diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Gallery.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Gallery.kt index 25f1c7e15..3bbf5b382 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Gallery.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/Gallery.kt @@ -38,8 +38,10 @@ import androidx.compose.ui.unit.sp import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor +import com.vitorpamplona.amethyst.ui.navigation.routes.routeForUser import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.Size25dp +import com.vitorpamplona.quartz.nip01Core.core.HexKey import kotlinx.collections.immutable.ImmutableList @OptIn(ExperimentalLayoutApi::class) @@ -81,3 +83,45 @@ fun Gallery( } } } + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun GalleryUnloaded( + users: ImmutableList, + modifier: Modifier, + accountViewModel: AccountViewModel, + nav: INav, + maxPictures: Int = 6, +) { + FlowRow( + modifier, + verticalArrangement = Arrangement.Center, + horizontalArrangement = Arrangement.spacedBy((-5).dp), + ) { + users.take(maxPictures).forEach { + ClickableUserPicture( + it, + Size25dp, + accountViewModel, + onClick = { + nav.nav { + routeForUser(it) + } + }, + ) + } + + if (users.size > maxPictures) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier.size(Size25dp).clip(shape = CircleShape).background(MaterialTheme.colorScheme.secondaryContainer), + ) { + Text( + text = "+" + showCount(users.size - maxPictures), + fontSize = 10.sp, + color = MaterialTheme.colorScheme.onSurface, + ) + } + } + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt index 405c31996..4a243c8ad 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UserProfilePicture.kt @@ -46,6 +46,7 @@ import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.LoadUser import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey @Composable @@ -175,6 +176,40 @@ fun ClickableUserPicture( BaseUserPicture(baseUser, size, accountViewModel, modifier, myModifier) } +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun ClickableUserPicture( + baseUserHex: HexKey, + size: Dp, + accountViewModel: AccountViewModel, + modifier: Modifier = Modifier, + onClick: ((HexKey) -> Unit)? = null, + onLongClick: ((HexKey) -> Unit)? = null, +) { + // BaseUser is the same reference as accountState.user + val myModifier = + remember(baseUserHex) { + if (onClick != null && onLongClick != null) { + Modifier + .size(size) + .combinedClickable( + onClick = { onClick(baseUserHex) }, + onLongClick = { onLongClick(baseUserHex) }, + ) + } else if (onClick != null) { + Modifier + .size(size) + .clickable( + onClick = { onClick(baseUserHex) }, + ) + } else { + Modifier.size(size) + } + } + + BaseUserPicture(baseUserHex, size, accountViewModel, modifier, myModifier) +} + @Composable fun NonClickableUserPictures( room: ChatroomKey, @@ -322,6 +357,34 @@ fun BaseUserPicture( } } +@Composable +fun BaseUserPicture( + baseUserHex: HexKey, + size: Dp, + accountViewModel: AccountViewModel, + innerModifier: Modifier = Modifier, + outerModifier: Modifier = Modifier.size(size), +) { + Box(outerModifier, contentAlignment = Alignment.TopEnd) { + LoadUserProfilePicture(baseUserHex, accountViewModel) { userProfilePicture, userName -> + InnerUserPicture( + userHex = baseUserHex, + userPicture = userProfilePicture, + userName = userName, + size = size, + modifier = innerModifier, + accountViewModel = accountViewModel, + ) + } + + WatchUserFollows(baseUserHex, accountViewModel) { newFollowingState -> + if (newFollowingState) { + FollowingIcon(Modifier.size(size.div(3.5f))) + } + } + } +} + @Composable fun LoadUserProfilePicture( baseUser: User, @@ -333,6 +396,23 @@ fun LoadUserProfilePicture( innerContent(userProfile?.profilePicture(), userProfile?.bestName()) } +@Composable +fun LoadUserProfilePicture( + baseUserHex: HexKey, + accountViewModel: AccountViewModel, + innerContent: @Composable (String?, String?) -> Unit, +) { + LoadUser(baseUserHex, accountViewModel) { + if (it != null) { + val userProfile by observeUserInfo(it, accountViewModel) + + innerContent(userProfile?.profilePicture(), userProfile?.bestName()) + } else { + innerContent(null, null) + } + } +} + @Composable fun InnerUserPicture( userHex: String,