From aad95595eb188ccd95e437f40f9854f2987d4945 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 17 Jun 2024 14:37:31 -0400 Subject: [PATCH] Quick Refactoring of the Author UI components. --- .../ui/note/ChatroomMessageCompose.kt | 8 +++- .../vitorpamplona/amethyst/ui/note/Icons.kt | 21 +++++++-- .../amethyst/ui/note/UserProfilePicture.kt | 45 ++++--------------- .../amethyst/ui/screen/FeedView.kt | 15 ------- .../ui/screen/loggedIn/ProfileScreen.kt | 37 +++++++-------- .../vitorpamplona/amethyst/ui/theme/Shape.kt | 3 +- .../vitorpamplona/amethyst/ui/theme/Theme.kt | 20 ++++++++- 7 files changed, 67 insertions(+), 82 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index 9f0ffe7e9..4144b4b00 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -78,7 +78,7 @@ import com.vitorpamplona.amethyst.ui.theme.RowColSpacing import com.vitorpamplona.amethyst.ui.theme.RowColSpacing5dp import com.vitorpamplona.amethyst.ui.theme.Size15Modifier import com.vitorpamplona.amethyst.ui.theme.Size20dp -import com.vitorpamplona.amethyst.ui.theme.Size5dp +import com.vitorpamplona.amethyst.ui.theme.Size5Modifier import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.StdTopPadding import com.vitorpamplona.amethyst.ui.theme.chatAuthorBox @@ -769,7 +769,11 @@ private fun WatchAndDisplayUser( accountViewModel = accountViewModel, ) - ObserveAndDisplayFollowingMark(author.pubkeyHex, Size5dp, accountViewModel) + WatchUserFollows(author.pubkeyHex, accountViewModel) { newFollowingState -> + if (newFollowingState) { + FollowingIcon(Size5Modifier) + } + } }, name = { if (userState != null) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt index 7796c6ad5..b193661e0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/Icons.kt @@ -87,10 +87,15 @@ fun AmethystIcon(iconSize: Dp) { @Composable fun FollowingIcon(iconSize: Dp) { + FollowingIcon(Modifier.size(iconSize)) +} + +@Composable +fun FollowingIcon(modifier: Modifier) { Icon( imageVector = Following, contentDescription = stringResource(id = R.string.following), - modifier = Modifier.size(iconSize), + modifier = modifier, tint = Color.Unspecified, ) } @@ -549,18 +554,26 @@ fun ZapSplitIcon( fun ZapSplitPreview() { Column(horizontalAlignment = Alignment.CenterHorizontally) { Box( - Modifier.height(20.dp).width(25.dp), + Modifier + .height(20.dp) + .width(25.dp), ) { Icon( imageVector = Icons.Outlined.Bolt, contentDescription = stringResource(id = R.string.zaps), - modifier = Modifier.size(20.dp).align(Alignment.CenterStart), + modifier = + Modifier + .size(20.dp) + .align(Alignment.CenterStart), tint = BitcoinOrange, ) Icon( imageVector = Icons.Outlined.ArrowForwardIos, contentDescription = stringResource(id = R.string.zaps), - modifier = Modifier.size(13.dp).align(Alignment.CenterEnd), + modifier = + Modifier + .size(13.dp) + .align(Alignment.CenterEnd), tint = BitcoinOrange, ) } 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 75749a607..75c763c31 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 @@ -20,9 +20,6 @@ */ package com.vitorpamplona.amethyst.ui.note -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable @@ -30,7 +27,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.remember @@ -40,7 +36,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.Dp import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.map @@ -161,23 +156,19 @@ fun ClickableUserPicture( .combinedClickable( onClick = { onClick(baseUser) }, onLongClick = { onLongClick(baseUser) }, - role = Role.Button, ) } else if (onClick != null) { Modifier .size(size) .clickable( onClick = { onClick(baseUser) }, - role = Role.Button, ) } else { Modifier.size(size) } } - Box(modifier = myModifier, contentAlignment = Alignment.TopEnd) { - BaseUserPicture(baseUser, size, accountViewModel, modifier) - } + BaseUserPicture(baseUser, size, accountViewModel, modifier, myModifier) } @Composable @@ -301,10 +292,8 @@ fun BaseUserPicture( size: Dp, accountViewModel: AccountViewModel, innerModifier: Modifier = Modifier, - outerModifier: Modifier = remember { Modifier.size(size) }, + outerModifier: Modifier = Modifier.size(size), ) { - val myIconSize by remember(size) { derivedStateOf { size.div(3.5f) } } - Box(outerModifier, contentAlignment = Alignment.TopEnd) { LoadUserProfilePicture(baseUser) { userProfilePicture, userName -> InnerUserPicture( @@ -317,7 +306,11 @@ fun BaseUserPicture( ) } - ObserveAndDisplayFollowingMark(baseUser.pubkeyHex, myIconSize, accountViewModel) + WatchUserFollows(baseUser.pubkeyHex, accountViewModel) { newFollowingState -> + if (newFollowingState) { + FollowingIcon(Modifier.size(size.div(3.5f))) + } + } } } @@ -345,11 +338,6 @@ fun InnerUserPicture( modifier.size(size).clip(shape = CircleShape) } - val automaticallyShowProfilePicture = - remember { - accountViewModel.settings.showProfilePictures.value - } - RobohashFallbackAsyncImage( robot = userHex, model = userPicture, @@ -361,27 +349,10 @@ fun InnerUserPicture( }, modifier = myImageModifier, contentScale = ContentScale.Crop, - loadProfilePicture = automaticallyShowProfilePicture, + loadProfilePicture = accountViewModel.settings.showProfilePictures.value, ) } -@Composable -fun ObserveAndDisplayFollowingMark( - userHex: String, - iconSize: Dp, - accountViewModel: AccountViewModel, -) { - WatchUserFollows(userHex, accountViewModel) { newFollowingState -> - AnimatedVisibility( - visible = newFollowingState, - enter = remember { fadeIn() }, - exit = remember { fadeOut() }, - ) { - FollowingIcon(iconSize) - } - } -} - @Composable fun WatchUserFollows( userHex: String, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedView.kt index 9c1299b90..8dd64290f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedView.kt @@ -77,21 +77,6 @@ fun RefresheableFeedView( } } -@Composable -fun DVMStatusView( - viewModel: FeedViewModel, - routeForLastRead: String?, - enablePullRefresh: Boolean = true, - scrollStateKey: String? = null, - accountViewModel: AccountViewModel, - nav: (String) -> Unit, -) { - viewModel.invalidateData() - SaveableFeedState(viewModel, scrollStateKey) { listState -> - RenderFeedState(viewModel, accountViewModel, listState, nav, routeForLastRead) - } -} - @Composable fun RefresheableBox( viewModel: InvalidatableViewModel, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index 62bfe7fda..5168253b5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.animation.core.tween import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.gestures.scrollBy @@ -159,6 +158,7 @@ import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonPadding import com.vitorpamplona.amethyst.ui.theme.DividerThickness +import com.vitorpamplona.amethyst.ui.theme.Size100dp import com.vitorpamplona.amethyst.ui.theme.Size15Modifier import com.vitorpamplona.amethyst.ui.theme.Size16Modifier import com.vitorpamplona.amethyst.ui.theme.Size25Modifier @@ -166,6 +166,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer import com.vitorpamplona.amethyst.ui.theme.ZeroPadding import com.vitorpamplona.amethyst.ui.theme.placeholderText +import com.vitorpamplona.amethyst.ui.theme.userProfileBorderModifier import com.vitorpamplona.quartz.events.AppDefinitionEvent import com.vitorpamplona.quartz.events.BadgeDefinitionEvent import com.vitorpamplona.quartz.events.BadgeProfilesEvent @@ -429,8 +430,7 @@ private fun RenderSurface( } } }, - ) - .fillMaxHeight() + ).fillMaxHeight() }, ) { RenderScreen( @@ -550,8 +550,7 @@ fun UpdateThreadsAndRepliesWhenBlockUnblock( accountViewModel.account.liveHiddenUsers .map { it.hiddenUsers.contains(baseUser.pubkeyHex) || it.spammers.contains(baseUser.pubkeyHex) - } - .observeAsState(accountViewModel.account.isHidden(baseUser)) + }.observeAsState(accountViewModel.account.isHidden(baseUser)) LaunchedEffect(key1 = isHidden) { threadsViewModel.invalidateData() @@ -597,7 +596,11 @@ private fun RelaysTabHeader(baseUser: User) { val userStateRelayInfo by baseUser.live().relayInfo.observeAsState() val userRelays = remember(userStateRelayInfo) { - userStateRelayInfo?.user?.latestContactList?.relays()?.size ?: "--" + userStateRelayInfo + ?.user + ?.latestContactList + ?.relays() + ?.size ?: "--" } Text(text = "$userRelaysBeingUsed / $userRelays ${stringResource(R.string.relays)}") @@ -780,13 +783,8 @@ private fun ProfileHeader( ClickableUserPicture( baseUser = baseUser, accountViewModel = accountViewModel, - size = 100.dp, - modifier = - Modifier.border( - 3.dp, - MaterialTheme.colorScheme.background, - CircleShape, - ), + size = Size100dp, + modifier = MaterialTheme.colorScheme.userProfileBorderModifier, onClick = { if (baseUser.profilePicture() != null) { zoomImageDialogOpen = true @@ -922,31 +920,28 @@ fun WatchIsHiddenUser( accountViewModel.account.liveHiddenUsers .map { it.hiddenUsers.contains(baseUser.pubkeyHex) || it.spammers.contains(baseUser.pubkeyHex) - } - .observeAsState(accountViewModel.account.isHidden(baseUser)) + }.observeAsState(accountViewModel.account.isHidden(baseUser)) content(isHidden) } -fun getIdentityClaimIcon(identity: IdentityClaim): Int { - return when (identity) { +fun getIdentityClaimIcon(identity: IdentityClaim): Int = + when (identity) { is TwitterIdentity -> R.drawable.twitter is TelegramIdentity -> R.drawable.telegram is MastodonIdentity -> R.drawable.mastodon is GitHubIdentity -> R.drawable.github else -> R.drawable.github } -} -fun getIdentityClaimDescription(identity: IdentityClaim): Int { - return when (identity) { +fun getIdentityClaimDescription(identity: IdentityClaim): Int = + when (identity) { is TwitterIdentity -> R.string.twitter is TelegramIdentity -> R.string.telegram is MastodonIdentity -> R.string.mastodon is GitHubIdentity -> R.string.github else -> R.drawable.github } -} @Composable private fun DrawAdditionalInfo( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt index 4a5ddcc9f..5f3bce586 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt @@ -97,6 +97,7 @@ val Size35dp = 35.dp val Size40dp = 40.dp val Size55dp = 55.dp val Size75dp = 75.dp +val Size100dp = 100.dp val Size110dp = 110.dp val Size165dp = 165.dp @@ -122,7 +123,7 @@ val VertPadding = Modifier.padding(vertical = 10.dp) val MaxWidthWithHorzPadding = Modifier.fillMaxWidth().padding(horizontal = 10.dp) -val Size6Modifier = Modifier.size(6.dp) +val Size5Modifier = Modifier.size(5.dp) val Size10Modifier = Modifier.size(10.dp) val Size15Modifier = Modifier.size(15.dp) val Size16Modifier = Modifier.size(16.dp) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt index d96062a03..440a16c1e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt @@ -191,6 +191,20 @@ val LightChannelNotePictureModifier = .clip(shape = CircleShape) .border(2.dp, LightColorPalette.background, CircleShape) +val LightProfilePictureBorder = + Modifier.border( + 3.dp, + DarkColorPalette.background, + CircleShape, + ) + +val DarkProfilePictureBorder = + Modifier.border( + 3.dp, + LightColorPalette.background, + CircleShape, + ) + val LightRelayIconModifier = Modifier .size(Size13dp) @@ -379,6 +393,9 @@ val ColorScheme.innerPostModifier: Modifier val ColorScheme.channelNotePictureModifier: Modifier get() = if (isLight) LightChannelNotePictureModifier else DarkChannelNotePictureModifier +val ColorScheme.userProfileBorderModifier: Modifier + get() = if (isLight) LightProfilePictureBorder else DarkProfilePictureBorder + val ColorScheme.relayIconModifier: Modifier get() = if (isLight) LightRelayIconModifier else DarkRelayIconModifier @@ -400,8 +417,7 @@ val ColorScheme.chartStyle: ChartStyle defaultColors.entity1Color, defaultColors.entity2Color, defaultColors.entity3Color, - ) - .map(::Color), + ).map(::Color), elevationOverlayColor = Color(defaultColors.elevationOverlayColor), ) }