diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 2e26088071..7974342bf9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -322,8 +322,6 @@ object LocalCache : ILocalCache { fun getNoteIfExists(key: ETag): Note? = notes.get(key.eventId) - fun getChatroomListIfExists(key: String): ChatroomList? = chatroomList.get(key) - fun getPublicChatChannelIfExists(key: String): PublicChatChannel? = publicChatChannels.get(key) fun getEphemeralChatChannelIfExists(key: RoomId): EphemeralChatChannel? = ephemeralChannels.get(key) @@ -1571,6 +1569,8 @@ object LocalCache : ILocalCache { ): Boolean { val channelId = event.channelId() ?: return false + val new = consumeRegularEvent(event, relay, wasVerified) + val channel = checkGetOrCreatePublicChatChannel(channelId) if (channel == null) { Log.w("LocalCache", "Unable to create public chat channel for event ${event.toJson()}") @@ -1580,7 +1580,7 @@ object LocalCache : ILocalCache { val note = getOrCreateNote(event.id) channel.addNote(note, relay) - return consumeRegularEvent(event, relay, wasVerified) + return new } fun consume( @@ -1590,11 +1590,13 @@ object LocalCache : ILocalCache { ): Boolean { val roomId = event.roomId() ?: return false + val new = consumeRegularEvent(event, relay, wasVerified) + val note = getOrCreateNote(event.id) val channel = getOrCreateEphemeralChannel(roomId) channel.addNote(note, relay) - return consumeRegularEvent(event, relay, wasVerified) + return new } fun consume( @@ -1604,12 +1606,14 @@ object LocalCache : ILocalCache { ): Boolean { val activityAddress = event.activityAddress() ?: return false + val new = consumeRegularEvent(event, relay, wasVerified) + val channel = getOrCreateLiveChannel(activityAddress) val note = getOrCreateNote(event.id) channel.addNote(note, relay) - return consumeRegularEvent(event, relay, wasVerified) + return new } fun consume( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Loaders.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Loaders.kt index b1a1ed18b0..a834331c41 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Loaders.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Loaders.kt @@ -33,12 +33,14 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteOts import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserStatuses import com.vitorpamplona.amethyst.ui.components.GenericLoadable import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.Dispatchers @@ -172,6 +174,20 @@ fun LoadPublicChatChannel( channel.value?.let { content(it) } } +@Composable +fun LoadEphemeralChatChannel( + id: RoomId, + accountViewModel: AccountViewModel, + content: @Composable (EphemeralChatChannel) -> Unit, +) { + val channel = + produceStateIfNotNull(accountViewModel.getEphemeralChatChannelIfExists(id), id) { + value = accountViewModel.checkGetOrCreateEphemeralChatChannel(id) + } + + channel.value?.let { content(it) } +} + @Composable fun LoadLiveActivityChannel( id: Address, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/rooms/ChatroomHeaderCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/rooms/ChatroomHeaderCompose.kt index 57f5e6d7ab..8f2e7fe071 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/rooms/ChatroomHeaderCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/rooms/ChatroomHeaderCompose.kt @@ -55,6 +55,7 @@ import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.FeatureSetType import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannel import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteHasEvent @@ -72,11 +73,14 @@ import com.vitorpamplona.amethyst.ui.note.ObserveDraftEvent import com.vitorpamplona.amethyst.ui.note.timeAgo import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.header.RoomNameDisplay +import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.ephemChat.LoadEphemeralChatChannel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.ephemChat.header.loadRelayInfo import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.AccountPictureModifier import com.vitorpamplona.amethyst.ui.theme.Size55dp import com.vitorpamplona.amethyst.ui.theme.grayText import com.vitorpamplona.amethyst.ui.theme.placeholderText +import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent @@ -146,6 +150,13 @@ private fun ChatroomEntry( val room = baseNoteEvent.chatroomKey(accountViewModel.userProfile().pubkeyHex) UserRoomCompose(room, lastMessage, accountViewModel, nav) } + is EphemeralChatEvent -> { + baseNoteEvent.roomId()?.let { + LoadEphemeralChatChannel(it, accountViewModel) { channel -> + ChannelRoomCompose(lastMessage, channel, accountViewModel, nav) + } + } + } else -> BlankNote() } } @@ -191,6 +202,38 @@ private fun ChannelRoomCompose( ) } +@Composable +private fun ChannelRoomCompose( + lastMessage: Note, + channel: EphemeralChatChannel, + accountViewModel: AccountViewModel, + nav: INav, +) { + val authorName by observeUserName(lastMessage.author!!, accountViewModel) + val channelState by observeChannel(channel, accountViewModel) + + val channel = channelState?.channel as? EphemeralChatChannel ?: return + + val relayInfo by loadRelayInfo(channel.roomId.relayUrl, accountViewModel) + + val noteEvent = lastMessage.event + val description = noteEvent?.content?.take(200) + + val lastReadTime by accountViewModel.account.loadLastReadFlow("Channel/${channel.roomId.toKey()}").collectAsStateWithLifecycle() + + ChannelName( + channelIdHex = channel.roomId.toKey(), + channelPicture = relayInfo.icon, + channelTitle = { modifier -> ChannelTitleWithLabelInfo(channel.toBestDisplayName(), R.string.ephemeral_relay_chat, modifier) }, + channelLastTime = lastMessage.createdAt(), + channelLastContent = "$authorName: $description", + hasNewMessages = (noteEvent?.createdAt ?: Long.MIN_VALUE) > lastReadTime, + loadProfilePicture = accountViewModel.settings.showProfilePictures.value, + loadRobohash = accountViewModel.settings.featureSet != FeatureSetType.PERFORMANCE, + onClick = { nav.nav(routeFor(channel)) }, + ) +} + @Composable private fun ChannelTitleWithLabelInfo( channelName: String,