From ca8d32b83770525fdd3ce1dcc0b231da79d2b8eb Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 14 Jun 2024 08:22:24 -0400 Subject: [PATCH] Moves chatroom user group away from immutable sets --- .../service/NostrChatroomDataSource.kt | 5 +- .../amethyst/ui/navigation/AppTopBar.kt | 59 +++++++++++++------ .../amethyst/ui/note/ChatroomHeaderCompose.kt | 10 +++- .../amethyst/ui/note/UserProfilePicture.kt | 29 ++++----- .../ui/screen/loggedIn/ChatroomScreen.kt | 2 +- .../quartz/events/ChatMessageEvent.kt | 10 ++-- 6 files changed, 69 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt index b6680fc9b..ecb0efe56 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/NostrChatroomDataSource.kt @@ -52,7 +52,7 @@ object NostrChatroomDataSource : NostrDataSource("ChatroomFeed") { filter = JsonFilter( kinds = listOf(PrivateDmEvent.KIND), - authors = myPeer.users.map { it }, + authors = myPeer.users.toList(), tags = mapOf("p" to listOf(account.userProfile().pubkeyHex)), since = latestEOSEs.users[account.userProfile()] @@ -103,7 +103,6 @@ object NostrChatroomDataSource : NostrDataSource("ChatroomFeed") { listOfNotNull( createMessagesToMeFilter(), createMessagesFromMeFilter(), - ) - .ifEmpty { null } + ).ifEmpty { null } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt index c038dd117..9fca1d6ff 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt @@ -167,7 +167,12 @@ fun AppTopBar( ) { val currentRoute by remember(navEntryState.value) { - derivedStateOf { navEntryState.value?.destination?.route?.substringBefore("?") } + derivedStateOf { + navEntryState.value + ?.destination + ?.route + ?.substringBefore("?") + } } val id by @@ -397,7 +402,7 @@ private fun RenderRoomTopBar( FlexibleTopBarWithBackButton( title = { NonClickableUserPictures( - users = room.users, + room = room, accountViewModel = accountViewModel, size = Size34dp, ) @@ -577,7 +582,11 @@ private fun LoggedInUserPictureDrawer( onClick: () -> Unit, ) { val profilePicture by - accountViewModel.account.userProfile().live().profilePictureChanges.observeAsState() + accountViewModel.account + .userProfile() + .live() + .profilePictureChanges + .observeAsState() IconButton(onClick = onClick) { RobohashFallbackAsyncImage( @@ -633,32 +642,48 @@ abstract class Name { open fun name(context: Context) = name() } -class GeoHashName(val geoHashTag: String) : Name() { +class GeoHashName( + val geoHashTag: String, +) : Name() { override fun name() = "/g/$geoHashTag" } -class HashtagName(val hashTag: String) : Name() { +class HashtagName( + val hashTag: String, +) : Name() { override fun name() = "#$hashTag" } -class ResourceName(val resourceId: Int) : Name() { +class ResourceName( + val resourceId: Int, +) : Name() { override fun name() = " $resourceId " // Space to make sure it goes first override fun name(context: Context) = context.getString(resourceId) } -class PeopleListName(val note: AddressableNote) : Name() { +class PeopleListName( + val note: AddressableNote, +) : Name() { override fun name() = (note.event as? PeopleListEvent)?.nameOrTitle() ?: note.dTag() ?: "" } -class CommunityName(val note: AddressableNote) : Name() { +class CommunityName( + val note: AddressableNote, +) : Name() { override fun name() = "/n/${(note.dTag() ?: "")}" } -@Immutable data class CodeName(val code: String, val name: Name, val type: CodeNameType) +@Immutable data class CodeName( + val code: String, + val name: Name, + val type: CodeNameType, +) @Stable -class FollowListViewModel(val account: Account) : ViewModel() { +class FollowListViewModel( + val account: Account, +) : ViewModel() { val kind3Follow = CodeName(KIND3_FOLLOWS, ResourceName(R.string.follow_list_kind3follows), CodeNameType.HARDCODED) val globalFollow = @@ -699,8 +724,7 @@ class FollowListViewModel(val account: Account) : ViewModel() { } else { null } - } - .sortedBy { it.name.name() } + }.sortedBy { it.name.name() } emit(newFollowLists) } @@ -757,10 +781,10 @@ class FollowListViewModel(val account: Account) : ViewModel() { val kind3GlobalPeople = _kind3GlobalPeople.stateIn(viewModelScope, SharingStarted.Eagerly, defaultLists) - class Factory(val account: Account) : ViewModelProvider.Factory { - override fun create(modelClass: Class): FollowListViewModel { - return FollowListViewModel(account) as FollowListViewModel - } + class Factory( + val account: Account, + ) : ViewModelProvider.Factory { + override fun create(modelClass: Class): FollowListViewModel = FollowListViewModel(account) as FollowListViewModel } } @@ -942,7 +966,8 @@ fun AmethystClickableIcon() { } fun debugState(context: Context) { - Client.allSubscriptions() + Client + .allSubscriptions() .forEach { Log.d("STATE DUMP", "${it.key} ${it.value.joinToString { it.filter.toJson() }}") } NostrAccountDataSource.printCounter() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt index 8d95ec241..61501fbd6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomHeaderCompose.kt @@ -164,7 +164,10 @@ private fun ChannelRoomCompose( accountViewModel: AccountViewModel, nav: (String) -> Unit, ) { - val authorState by note.author!!.live().metadata.observeAsState() + val authorState by note.author!! + .live() + .metadata + .observeAsState() val authorName = remember(note, authorState) { authorState?.user?.toBestDisplayName() } val chanHex = remember { channel.idHex } @@ -273,7 +276,7 @@ private fun UserRoomCompose( ChannelName( channelPicture = { NonClickableUserPictures( - users = room.users, + room = room, accountViewModel = accountViewModel, size = Size55dp, ) @@ -536,7 +539,8 @@ private fun TimeAgo(channelLastTime: Long?) { fun NewItemsBubble() { Box( modifier = - Modifier.padding(start = 3.dp) + Modifier + .padding(start = 3.dp) .width(10.dp) .height(10.dp) .clip(shape = CircleShape) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt index d92af538b..75749a607 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt @@ -50,8 +50,7 @@ import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.quartz.encoders.HexKey -import kotlinx.collections.immutable.ImmutableSet +import com.vitorpamplona.quartz.events.ChatroomKey @Composable fun NoteAuthorPicture( @@ -157,14 +156,16 @@ fun ClickableUserPicture( val myModifier = remember { if (onClick != null && onLongClick != null) { - Modifier.size(size) + Modifier + .size(size) .combinedClickable( onClick = { onClick(baseUser) }, onLongClick = { onLongClick(baseUser) }, role = Role.Button, ) } else if (onClick != null) { - Modifier.size(size) + Modifier + .size(size) .clickable( onClick = { onClick(baseUser) }, role = Role.Button, @@ -181,15 +182,13 @@ fun ClickableUserPicture( @Composable fun NonClickableUserPictures( - users: ImmutableSet, + room: ChatroomKey, size: Dp, accountViewModel: AccountViewModel, ) { - val myBoxModifier = remember { Modifier.size(size) } - - Box(myBoxModifier, contentAlignment = Alignment.TopEnd) { - val userList = remember(users) { users.toList() } + val userList = remember(room) { room.users.toList() } + Box(Modifier.size(size), contentAlignment = Alignment.TopEnd) { when (userList.size) { 0 -> {} 1 -> @@ -395,13 +394,11 @@ fun WatchUserFollows( .map { it.user.isFollowingCached(userHex) || (userHex == accountViewModel.account.userProfile().pubkeyHex) - } - .distinctUntilChanged() - } - .observeAsState( - accountViewModel.account.userProfile().isFollowingCached(userHex) || - (userHex == accountViewModel.account.userProfile().pubkeyHex), - ) + }.distinctUntilChanged() + }.observeAsState( + accountViewModel.account.userProfile().isFollowingCached(userHex) || + (userHex == accountViewModel.account.userProfile().pubkeyHex), + ) onFollowChanges(showFollowingMark) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index a20b27c8f..aedacc4ed 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -672,7 +672,7 @@ fun GroupChatroomHeader( ) { Row(verticalAlignment = Alignment.CenterVertically) { NonClickableUserPictures( - users = room.users, + room = room, accountViewModel = accountViewModel, size = Size34dp, ) diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt index 934fb001c..0ca280e80 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/events/ChatMessageEvent.kt @@ -26,7 +26,6 @@ import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.Nip92MediaAttachments import com.vitorpamplona.quartz.signers.NostrSigner import com.vitorpamplona.quartz.utils.TimeUtils -import kotlinx.collections.immutable.ImmutableSet import kotlinx.collections.immutable.toImmutableSet @Immutable @@ -37,7 +36,8 @@ class ChatMessageEvent( tags: Array>, content: String, sig: HexKey, -) : WrappedEvent(id, pubKey, createdAt, KIND, tags, content, sig), ChatroomKeyable { +) : WrappedEvent(id, pubKey, createdAt, KIND, tags, content, sig), + ChatroomKeyable { /** Recipients intended to receive this conversation */ fun recipientsPubKey() = tags.mapNotNull { if (it.size > 1 && it[0] == "p") it[1] else null } @@ -61,9 +61,7 @@ class ChatMessageEvent( return result } - override fun chatroomKey(toRemove: String): ChatroomKey { - return ChatroomKey(talkingWith(toRemove).toImmutableSet()) - } + override fun chatroomKey(toRemove: String): ChatroomKey = ChatroomKey(talkingWith(toRemove).toImmutableSet()) companion object { const val KIND = 14 @@ -122,5 +120,5 @@ interface ChatroomKeyable { @Stable data class ChatroomKey( - val users: ImmutableSet, + val users: Set, )