From 5255a82de29087e1d4e252173c6a2ca80ad61c28 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:30:04 +0100 Subject: [PATCH 01/37] Implement LegendaryCustomization data class --- .../compose/profile/model/ProfileDetailsUi.kt | 10 ++++------ .../compose/profile/model/UserProfileItemUi.kt | 5 +++++ .../premium/legend/LegendaryCustomization.kt | 16 ++++++++++++++++ .../profile/details/ui/ProfileDetailsHeader.kt | 4 ++-- .../profile/details/ui/ProfileTopCoverBar.kt | 10 +++++----- 5 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 app/src/main/kotlin/net/primal/android/premium/legend/LegendaryCustomization.kt diff --git a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt index af3bc2bbd..beb8b9e53 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt @@ -3,7 +3,9 @@ package net.primal.android.core.compose.profile.model import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.core.utils.usernameUiFriendly +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.db.ProfileData data class ProfileDetailsUi( @@ -20,9 +22,7 @@ data class ProfileDetailsUi( val website: String? = null, val primalName: String? = null, val lnUrlDecoded: String? = null, - val avatarGlow: Boolean = false, - val customBadge: Boolean = false, - val legendaryStyle: LegendaryStyle? = null, + val legendaryCustomization: LegendaryCustomization? = null, ) fun ProfileData.asProfileDetailsUi() = @@ -40,7 +40,5 @@ fun ProfileData.asProfileDetailsUi() = website = this.website, primalName = this.primalName, lnUrlDecoded = this.lnUrlDecoded, - avatarGlow = this.primalLegendProfile?.avatarGlow == true, - customBadge = this.primalLegendProfile?.customBadge == true, - legendaryStyle = LegendaryStyle.valueById(this.primalLegendProfile?.styleId), + legendaryCustomization = this.primalLegendProfile?.asLegendaryCustomization(), ) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/UserProfileItemUi.kt b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/UserProfileItemUi.kt index fde2beb8e..7929bd7fb 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/UserProfileItemUi.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/UserProfileItemUi.kt @@ -3,6 +3,8 @@ package net.primal.android.core.compose.profile.model import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.explore.domain.UserProfileSearchItem +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.db.ProfileData data class UserProfileItemUi( @@ -13,6 +15,7 @@ data class UserProfileItemUi( val followersCount: Int? = null, val score: Float? = null, val isFollowed: Boolean? = null, + val legendaryCustomization: LegendaryCustomization? = null, ) fun UserProfileSearchItem.mapAsUserProfileUi() = @@ -23,6 +26,7 @@ fun UserProfileSearchItem.mapAsUserProfileUi() = avatarCdnImage = this.metadata.avatarCdnImage, followersCount = this.followersCount, score = this.score, + legendaryCustomization = this.metadata.primalLegendProfile?.asLegendaryCustomization(), ) fun ProfileData.asUserProfileItemUi() = @@ -34,4 +38,5 @@ fun ProfileData.asUserProfileItemUi() = followersCount = null, score = null, isFollowed = null, + legendaryCustomization = this.primalLegendProfile?.asLegendaryCustomization(), ) diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/LegendaryCustomization.kt b/app/src/main/kotlin/net/primal/android/premium/legend/LegendaryCustomization.kt new file mode 100644 index 000000000..2c808eb39 --- /dev/null +++ b/app/src/main/kotlin/net/primal/android/premium/legend/LegendaryCustomization.kt @@ -0,0 +1,16 @@ +package net.primal.android.premium.legend + +import net.primal.android.profile.domain.PrimalLegendProfile + +data class LegendaryCustomization( + val avatarGlow: Boolean = false, + val customBadge: Boolean = false, + val legendaryStyle: LegendaryStyle? = null, +) + +fun PrimalLegendProfile.asLegendaryCustomization() = + LegendaryCustomization( + avatarGlow = avatarGlow, + customBadge = customBadge, + legendaryStyle = LegendaryStyle.valueById(id = styleId), + ) diff --git a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileDetailsHeader.kt b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileDetailsHeader.kt index 751870e77..95fc41e81 100644 --- a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileDetailsHeader.kt +++ b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileDetailsHeader.kt @@ -125,8 +125,8 @@ private fun ProfileHeaderDetails( displayName = state.profileDetails?.authorDisplayName ?: state.profileId.asEllipsizedNpub(), internetIdentifier = state.profileDetails?.internetIdentifier, isProfileFollowingMe = state.isProfileFollowingMe, - customBadge = state.profileDetails?.customBadge == true, - legendaryStyle = state.profileDetails?.legendaryStyle, + customBadge = state.profileDetails?.legendaryCustomization?.customBadge == true, + legendaryStyle = state.profileDetails?.legendaryCustomization?.legendaryStyle, ) if (state.profileDetails?.internetIdentifier?.isNotEmpty() == true) { diff --git a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt index bbc16d297..fbb2231f6 100644 --- a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt +++ b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt @@ -130,8 +130,8 @@ fun ProfileTopCoverBar( onClick = { state.profileDetails?.avatarCdnImage?.sourceUrl?.let { onMediaItemClick(it) } }, avatarCdnImage = state.profileDetails?.avatarCdnImage, hasBorder = true, - borderBrush = if (state.profileDetails?.legendaryStyle != null && state.profileDetails.avatarGlow) { - when (state.profileDetails.legendaryStyle) { + borderBrush = if (state.profileDetails?.legendaryCustomization?.legendaryStyle != null && state.profileDetails.legendaryCustomization.avatarGlow) { + when (state.profileDetails.legendaryCustomization.legendaryStyle) { LegendaryStyle.NO_CUSTOMIZATION -> Brush.linearGradient( listOf( Color.White, @@ -139,7 +139,7 @@ fun ProfileTopCoverBar( ), ) - else -> state.profileDetails.legendaryStyle.brush + else -> state.profileDetails.legendaryCustomization.legendaryStyle.brush } } else { Brush.linearGradient(listOf(Color.White, Color.White)) @@ -196,8 +196,8 @@ private fun ProfileTopAppBar( internetIdentifier = state.profileDetails?.internetIdentifier, internetIdentifierBadgeSize = 20.dp, internetIdentifierBadgeAlign = PlaceholderVerticalAlign.Center, - customBadgeStyle = if (state.profileDetails?.customBadge == true) { - state.profileDetails.legendaryStyle + customBadgeStyle = if (state.profileDetails?.legendaryCustomization?.customBadge == true) { + state.profileDetails.legendaryCustomization.legendaryStyle } else { null }, From 50b633f9dd822f14bc65b1ae5bad2f33d74ef134 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:31:19 +0100 Subject: [PATCH 02/37] Implement UniversalAvatarThumbnail Idea is to swap every AvatarThumbnail and AvatarThumbnailCustomBorder usage with this one and later do a refactor --- .../compose/AvatarThumbnailListItemImage.kt | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index c1326bd45..097929080 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -27,8 +27,45 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.AvatarDefault import net.primal.android.core.images.AvatarCoilImageLoader +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme +@Composable +fun UniversalAvatarThumbnail( + modifier: Modifier = Modifier, + avatarCdnImage: CdnImage? = null, + avatarSize: Dp = 48.dp, + hasBorder: Boolean = true, + hasGlowOverride: Boolean? = null, + fallbackBorderColor: Color = Color.Transparent, + legendaryCustomization: LegendaryCustomization? = null, + borderSize: Dp = 2.dp, + backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, + onClick: (() -> Unit)? = null, + defaultAvatar: @Composable () -> Unit = { DefaultAvatarThumbnailPlaceholderListItemImage() }, +) { + val variant = avatarCdnImage?.variants?.minByOrNull { it.width } + val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl + AvatarThumbnailListItemImage( + modifier = modifier, + avatarSize = avatarSize, + source = imageSource, + hasBorder = hasBorder, + borderBrush = legendaryCustomization?.legendaryStyle?.brush ?: Brush.linearGradient( + colors = listOf( + fallbackBorderColor, + fallbackBorderColor, + ), + ), + hasGlow = (hasGlowOverride ?: legendaryCustomization?.avatarGlow) == true, + borderSize = borderSize, + backgroundColor = backgroundColor, + onClick = onClick, + defaultAvatar = defaultAvatar, + ) +} + @Composable fun AvatarThumbnail( modifier: Modifier = Modifier, @@ -93,6 +130,7 @@ private fun AvatarThumbnailListItemImage( listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), ), borderSize: Dp = 2.dp, + hasGlow: Boolean = false, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, defaultAvatar: @Composable () -> Unit, From fcc4b9bcc5f15b16c031b3e11cc7073b8f73bc26 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:31:47 +0100 Subject: [PATCH 03/37] Use UniversalAvatarThumbnail on UserProfileListItem --- .../explore/search/ui/UserProfileListItem.kt | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt b/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt index b3e2fd1d0..67420a53f 100644 --- a/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt +++ b/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt @@ -24,11 +24,14 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import net.primal.android.R import net.primal.android.core.compose.AvatarThumbnail +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.FollowUnfollowButton import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.compose.profile.model.UserProfileItemUi import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.core.utils.shortened +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @Composable @@ -46,9 +49,10 @@ fun UserProfileListItem( modifier = Modifier.clickable { onClick(data) }, colors = colors, leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = data.avatarCdnImage, onClick = { onClick(data) }, + legendaryCustomization = data.legendaryCustomization, ) }, headlineContent = { @@ -108,6 +112,56 @@ fun UserProfileListItem( ) } +@Preview +@Composable +fun PreviewLegendaryUserProfileListItemWithFollow() { + PrimalPreview(primalTheme = net.primal.android.theme.domain.PrimalTheme.Sunset) { + Surface { + UserProfileListItem( + data = UserProfileItemUi( + profileId = "b10b0d5e5fae9c6c48a8c77f7e5abd42a79e9480e25a4094051d4ba4ce14456b", + displayName = "alex", + internetIdentifier = "alex@primal.net", + followersCount = 12345, + legendaryCustomization = LegendaryCustomization( + avatarGlow = true, + customBadge = true, + legendaryStyle = LegendaryStyle.GOLD, + ) + ), + followUnfollowVisibility = FollowUnfollowVisibility.Visible, + isFollowed = false, + onClick = {}, + ) + } + } +} + +@Preview +@Composable +fun PreviewLegendaryUserProfileListItemWithUnfollow() { + PrimalPreview(primalTheme = net.primal.android.theme.domain.PrimalTheme.Sunset) { + Surface { + UserProfileListItem( + data = UserProfileItemUi( + profileId = "b10b0d5e5fae9c6c48a8c77f7e5abd42a79e9480e25a4094051d4ba4ce14456b", + displayName = "alex", + internetIdentifier = "alex@primal.net", + followersCount = 12345, + legendaryCustomization = LegendaryCustomization( + avatarGlow = true, + customBadge = true, + legendaryStyle = LegendaryStyle.SUN_FIRE, + ) + ), + followUnfollowVisibility = FollowUnfollowVisibility.Visible, + isFollowed = true, + onClick = {}, + ) + } + } +} + @Preview @Composable fun PreviewUserProfileListItemWithFollow() { From 4191eb3fd7c6b861f015606c2ac358afe94e5dd3 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:41:35 +0100 Subject: [PATCH 04/37] Use UniversalAvatarThumbnail on MultipleUserPicker --- .../primal/android/explore/asearch/ui/MultipleUserPicker.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/explore/asearch/ui/MultipleUserPicker.kt b/app/src/main/kotlin/net/primal/android/explore/asearch/ui/MultipleUserPicker.kt index 1ecd8331e..d5f9b2c01 100644 --- a/app/src/main/kotlin/net/primal/android/explore/asearch/ui/MultipleUserPicker.kt +++ b/app/src/main/kotlin/net/primal/android/explore/asearch/ui/MultipleUserPicker.kt @@ -46,9 +46,9 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import kotlinx.coroutines.launch import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalIconTextField +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalLoadingButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.Search @@ -260,11 +260,12 @@ private fun SelectedUsersIndicator( modifier = Modifier.size(54.dp), contentAlignment = Alignment.BottomEnd, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.offset(x = (-6).dp, y = (-6).dp), avatarSize = 48.dp, avatarCdnImage = user.avatarCdnImage, onClick = { onUserClick(user) }, + legendaryCustomization = user.legendaryCustomization, ) Icon( modifier = Modifier From 060c1f37d99ad2c13d93299a0394605a37facdc9 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:51:59 +0100 Subject: [PATCH 05/37] Implement legendary customization to muted list --- .../primal/android/settings/muted/list/MutedSettingsScreen.kt | 4 +++- .../android/settings/muted/list/MutedSettingsViewModel.kt | 2 ++ .../primal/android/settings/muted/list/model/MutedUserUi.kt | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt index 7efb90500..7ff95c87f 100644 --- a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt @@ -27,6 +27,7 @@ import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack @@ -119,9 +120,10 @@ fun MutedUserListItem( containerColor = AppTheme.colorScheme.surfaceVariant, ), leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = item.avatarCdnImage, onClick = { onProfileClick(item.userId) }, + legendaryCustomization = item.legendaryCustomization, ) }, headlineContent = { diff --git a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsViewModel.kt b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsViewModel.kt index bff4823d0..fa72dc4f1 100644 --- a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsViewModel.kt @@ -15,6 +15,7 @@ import net.primal.android.core.utils.asEllipsizedNpub import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.networking.relays.errors.NostrPublishException import net.primal.android.networking.sockets.errors.WssException +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.settings.muted.db.MutedUser import net.primal.android.settings.muted.list.MutedSettingsContract.UiEvent import net.primal.android.settings.muted.list.MutedSettingsContract.UiState @@ -101,5 +102,6 @@ class MutedSettingsViewModel @Inject constructor( userId = this.mutedAccount.userId, avatarCdnImage = this.profileData?.avatarCdnImage, internetIdentifier = this.profileData?.internetIdentifier, + legendaryCustomization = this.profileData?.primalLegendProfile?.asLegendaryCustomization(), ) } diff --git a/app/src/main/kotlin/net/primal/android/settings/muted/list/model/MutedUserUi.kt b/app/src/main/kotlin/net/primal/android/settings/muted/list/model/MutedUserUi.kt index 569c34e83..3728af7ab 100644 --- a/app/src/main/kotlin/net/primal/android/settings/muted/list/model/MutedUserUi.kt +++ b/app/src/main/kotlin/net/primal/android/settings/muted/list/model/MutedUserUi.kt @@ -1,10 +1,12 @@ package net.primal.android.settings.muted.list.model import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization data class MutedUserUi( val userId: String, val displayName: String, val avatarCdnImage: CdnImage? = null, val internetIdentifier: String? = null, + val legendaryCustomization: LegendaryCustomization? = null, ) From e988fd1325884803f9e68a0789e8a83d862d0c16 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 11:52:07 +0100 Subject: [PATCH 06/37] Implement legendary customization to login screen --- .../kotlin/net/primal/android/auth/login/LoginScreen.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt b/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt index 007737484..b6acabbd8 100644 --- a/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt +++ b/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt @@ -57,6 +57,7 @@ import net.primal.android.core.compose.AppBarIcon import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.UiDensityMode +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.detectUiDensityModeFromMaxHeight import net.primal.android.core.compose.foundation.keyboardVisibilityAsState import net.primal.android.core.compose.icons.PrimalIcons @@ -397,11 +398,12 @@ private fun ProfileDetailsColumn( verticalArrangement = Arrangement.Bottom, ) { if (!(uiMode.isCompactOrLower() && keyboardVisible)) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = profileDetails.avatarCdnImage, avatarSize = 100.dp, hasBorder = profileDetails.avatarCdnImage != null, - borderColor = Color.White, + fallbackBorderColor = Color.White, + legendaryCustomization = profileDetails.legendaryCustomization, backgroundColor = defaultOnboardingAvatarBackground, defaultAvatar = { DefaultOnboardingAvatar() }, ) From 3a1498b20ecaecfc3218549967cf2486a21730c0 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:08:39 +0100 Subject: [PATCH 07/37] Use UniversalAvatarThumbnail on PremiumPurchase and BecomeLegendAmount stages --- .../android/premium/buying/purchase/PremiumPurchaseStage.kt | 5 +++-- .../premium/legend/become/amount/BecomeLegendAmountStage.kt | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/premium/buying/purchase/PremiumPurchaseStage.kt b/app/src/main/kotlin/net/primal/android/premium/buying/purchase/PremiumPurchaseStage.kt index b7d17c15a..6025e9dc8 100644 --- a/app/src/main/kotlin/net/primal/android/premium/buying/purchase/PremiumPurchaseStage.kt +++ b/app/src/main/kotlin/net/primal/android/premium/buying/purchase/PremiumPurchaseStage.kt @@ -40,10 +40,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalLoadingSpinner import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.findActivity import net.primal.android.core.compose.icons.PrimalIcons @@ -119,9 +119,10 @@ fun PremiumPurchaseStage( verticalArrangement = Arrangement.spacedBy(24.dp, Alignment.CenterVertically), ) { if (state.profile != null && state.primalName != null) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = state.profile.avatarCdnImage, avatarSize = 80.dp, + legendaryCustomization = state.profile.legendaryCustomization, ) NostrUserText( displayName = state.primalName, diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/become/amount/BecomeLegendAmountStage.kt b/app/src/main/kotlin/net/primal/android/premium/legend/become/amount/BecomeLegendAmountStage.kt index 33a380184..6f9d4e152 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/become/amount/BecomeLegendAmountStage.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/become/amount/BecomeLegendAmountStage.kt @@ -31,10 +31,10 @@ import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalSliderThumb import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.premium.legend.LegendaryStyle @@ -82,7 +82,7 @@ fun BecomeLegendAmountStage( Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = state.avatarCdnImage, avatarSize = 80.dp, ) From b815f2dc5fb77e8c80b9e415a518461bc220bc05 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:09:07 +0100 Subject: [PATCH 08/37] Use UniversalAvatarThumbnail on GenericReactionsLazyColumn --- .../android/stats/reactions/ui/GenericReactionsLazyColumn.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/GenericReactionsLazyColumn.kt b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/GenericReactionsLazyColumn.kt index 5ec05fe52..474593fd4 100644 --- a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/GenericReactionsLazyColumn.kt +++ b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/GenericReactionsLazyColumn.kt @@ -16,10 +16,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.unit.dp -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.heightAdjustableLoadingLazyListPlaceholder import net.primal.android.stats.reactions.EventActionUi import net.primal.android.theme.AppTheme @@ -75,10 +75,11 @@ private fun GenericReactionListItem( containerColor = AppTheme.colorScheme.surfaceVariant, ), leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = item.profile.avatarCdnImage, avatarSize = 42.dp, onClick = { onProfileClick(item.profile.pubkey) }, + legendaryCustomization = item.profile.legendaryCustomization, ) }, headlineContent = { From 482d042b51bd1edc89f0df1b280994c9fab3eb79 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:14:44 +0100 Subject: [PATCH 09/37] Use UniversalAvatarThumbnail on ExploreZaps --- .../primal/android/explore/home/zaps/ExploreZaps.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/explore/home/zaps/ExploreZaps.kt b/app/src/main/kotlin/net/primal/android/explore/home/zaps/ExploreZaps.kt index 5188bc67e..da98b76aa 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/zaps/ExploreZaps.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/zaps/ExploreZaps.kt @@ -34,9 +34,9 @@ import java.text.NumberFormat import java.time.Instant import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.HeightAdjustableLoadingLazyListPlaceholder import net.primal.android.core.compose.ListNoContent +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.LightningBoltFilled @@ -44,6 +44,7 @@ import net.primal.android.explore.home.zaps.ui.ExploreZapNoteUi import net.primal.android.notes.feed.model.NoteContentUi import net.primal.android.notes.feed.note.ui.NoteContent import net.primal.android.notes.feed.note.ui.events.NoteCallbacks +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.theme.AppTheme @Composable @@ -134,6 +135,7 @@ fun ZapListItem( senderCdnImage = zapData.sender?.avatarCdnImage, amountSats = zapData.amountSats, message = zapData.zapMessage, + senderLegendaryCustomization = zapData.sender?.legendaryCustomization, ) NoteSummary( noteContent = zapData.noteContentUi, @@ -143,6 +145,7 @@ fun ZapListItem( receiverCdnResource = zapData.receiver?.avatarCdnImage, receiverDisplayName = zapData.receiver?.authorDisplayName, onReceiverAvatarClick = { zapData.receiver?.pubkey?.let { noteCallbacks.onProfileClick?.invoke(it) } }, + receiverLegendaryCustomization = zapData.receiver?.legendaryCustomization, ) } } @@ -152,6 +155,7 @@ private fun NoteSummary( receiverDisplayName: String?, noteContent: NoteContentUi, receiverCdnResource: CdnImage?, + receiverLegendaryCustomization: LegendaryCustomization?, noteTimestamp: Instant, noteCallbacks: NoteCallbacks, onReceiverAvatarClick: () -> Unit, @@ -163,10 +167,11 @@ private fun NoteSummary( .padding(start = 2.dp, end = 8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = receiverCdnResource, avatarSize = 38.dp, onClick = onReceiverAvatarClick, + legendaryCustomization = receiverLegendaryCustomization, ) Column( verticalArrangement = Arrangement.spacedBy(4.dp), @@ -213,6 +218,7 @@ private fun NoteSummary( private fun ZapHeader( onSenderAvatarClick: () -> Unit, senderCdnImage: CdnImage?, + senderLegendaryCustomization: LegendaryCustomization?, amountSats: ULong, message: String?, ) { @@ -226,10 +232,11 @@ private fun ZapHeader( horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = senderCdnImage, avatarSize = 38.dp, onClick = onSenderAvatarClick, + legendaryCustomization = senderLegendaryCustomization, ) val numberFormat = NumberFormat.getNumberInstance() Row( From 98a851c9578c5e61bbda1c471080dcab33c2edf4 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:31:46 +0100 Subject: [PATCH 10/37] Add zap sender legendary customization to EventZap --- .../46.json | 1753 +++++++++++++++++ .../net/primal/android/db/PrimalDatabase.kt | 2 +- .../net/primal/android/stats/db/EventZap.kt | 3 + .../android/stats/ui/EventZapUiModel.kt | 4 + 4 files changed, 1761 insertions(+), 1 deletion(-) create mode 100644 app/schemas/net.primal.android.db.PrimalDatabase/46.json diff --git a/app/schemas/net.primal.android.db.PrimalDatabase/46.json b/app/schemas/net.primal.android.db.PrimalDatabase/46.json new file mode 100644 index 000000000..1719e6212 --- /dev/null +++ b/app/schemas/net.primal.android.db.PrimalDatabase/46.json @@ -0,0 +1,1753 @@ +{ + "formatVersion": 1, + "database": { + "version": 46, + "identityHash": "afb70ec74be5c0f7fc40491c8049abfb", + "entities": [ + { + "tableName": "PostData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`postId` TEXT NOT NULL, `authorId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `uris` TEXT NOT NULL, `hashtags` TEXT NOT NULL, `sig` TEXT NOT NULL, `raw` TEXT NOT NULL, `authorMetadataId` TEXT, `replyToPostId` TEXT, `replyToAuthorId` TEXT, PRIMARY KEY(`postId`))", + "fields": [ + { + "fieldPath": "postId", + "columnName": "postId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "authorId", + "columnName": "authorId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "uris", + "columnName": "uris", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hashtags", + "columnName": "hashtags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sig", + "columnName": "sig", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "authorMetadataId", + "columnName": "authorMetadataId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "replyToPostId", + "columnName": "replyToPostId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "replyToAuthorId", + "columnName": "replyToAuthorId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "postId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ProfileData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`ownerId` TEXT NOT NULL, `eventId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `raw` TEXT NOT NULL, `handle` TEXT, `displayName` TEXT, `internetIdentifier` TEXT, `lightningAddress` TEXT, `lnUrlDecoded` TEXT, `avatarCdnImage` TEXT, `bannerCdnImage` TEXT, `website` TEXT, `about` TEXT, `aboutUris` TEXT NOT NULL, `aboutHashtags` TEXT NOT NULL, `primalName` TEXT, `primalLegendProfile` TEXT, PRIMARY KEY(`ownerId`))", + "fields": [ + { + "fieldPath": "ownerId", + "columnName": "ownerId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "handle", + "columnName": "handle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "internetIdentifier", + "columnName": "internetIdentifier", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lightningAddress", + "columnName": "lightningAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "lnUrlDecoded", + "columnName": "lnUrlDecoded", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "avatarCdnImage", + "columnName": "avatarCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "bannerCdnImage", + "columnName": "bannerCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "website", + "columnName": "website", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "about", + "columnName": "about", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "aboutUris", + "columnName": "aboutUris", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "aboutHashtags", + "columnName": "aboutHashtags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "primalName", + "columnName": "primalName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "primalLegendProfile", + "columnName": "primalLegendProfile", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "ownerId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "RepostData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repostId` TEXT NOT NULL, `authorId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `tags` TEXT NOT NULL, `postId` TEXT NOT NULL, `postAuthorId` TEXT NOT NULL, `sig` TEXT NOT NULL, PRIMARY KEY(`repostId`))", + "fields": [ + { + "fieldPath": "repostId", + "columnName": "repostId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "authorId", + "columnName": "authorId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "tags", + "columnName": "tags", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "postId", + "columnName": "postId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "postAuthorId", + "columnName": "postAuthorId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sig", + "columnName": "sig", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repostId" + ] + }, + "indices": [ + { + "name": "index_RepostData_postId", + "unique": false, + "columnNames": [ + "postId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_RepostData_postId` ON `${TABLE_NAME}` (`postId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "EventStats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `likes` INTEGER NOT NULL, `replies` INTEGER NOT NULL, `mentions` INTEGER NOT NULL, `reposts` INTEGER NOT NULL, `zaps` INTEGER NOT NULL, `satsZapped` INTEGER NOT NULL, `score` INTEGER NOT NULL, `score24h` INTEGER NOT NULL, PRIMARY KEY(`eventId`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "likes", + "columnName": "likes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "replies", + "columnName": "replies", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mentions", + "columnName": "mentions", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reposts", + "columnName": "reposts", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "zaps", + "columnName": "zaps", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "satsZapped", + "columnName": "satsZapped", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "score", + "columnName": "score", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "score24h", + "columnName": "score24h", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "eventId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "EventZap", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `zapSenderId` TEXT NOT NULL, `zapReceiverId` TEXT NOT NULL, `zapRequestAt` INTEGER NOT NULL, `zapReceiptAt` INTEGER NOT NULL, `amountInBtc` REAL NOT NULL, `message` TEXT, `zapSenderDisplayName` TEXT, `zapSenderHandle` TEXT, `zapSenderInternetIdentifier` TEXT, `zapSenderAvatarCdnImage` TEXT, `zapSenderPrimalLegendProfile` TEXT, PRIMARY KEY(`zapSenderId`, `eventId`, `zapRequestAt`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "zapSenderId", + "columnName": "zapSenderId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "zapReceiverId", + "columnName": "zapReceiverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "zapRequestAt", + "columnName": "zapRequestAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "zapReceiptAt", + "columnName": "zapReceiptAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "amountInBtc", + "columnName": "amountInBtc", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "message", + "columnName": "message", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapSenderDisplayName", + "columnName": "zapSenderDisplayName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapSenderHandle", + "columnName": "zapSenderHandle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapSenderInternetIdentifier", + "columnName": "zapSenderInternetIdentifier", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapSenderAvatarCdnImage", + "columnName": "zapSenderAvatarCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapSenderPrimalLegendProfile", + "columnName": "zapSenderPrimalLegendProfile", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "zapSenderId", + "eventId", + "zapRequestAt" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "EventUserStats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `userId` TEXT NOT NULL, `replied` INTEGER NOT NULL, `liked` INTEGER NOT NULL, `reposted` INTEGER NOT NULL, `zapped` INTEGER NOT NULL, PRIMARY KEY(`eventId`, `userId`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "replied", + "columnName": "replied", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "liked", + "columnName": "liked", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "reposted", + "columnName": "reposted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "zapped", + "columnName": "zapped", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "eventId", + "userId" + ] + }, + "indices": [ + { + "name": "index_EventUserStats_eventId", + "unique": false, + "columnNames": [ + "eventId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_EventUserStats_eventId` ON `${TABLE_NAME}` (`eventId`)" + }, + { + "name": "index_EventUserStats_userId", + "unique": false, + "columnNames": [ + "userId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_EventUserStats_userId` ON `${TABLE_NAME}` (`userId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "NoteNostrUri", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`noteId` TEXT NOT NULL, `uri` TEXT NOT NULL, `refNote_postId` TEXT, `refNote_createdAt` INTEGER, `refNote_content` TEXT, `refNote_authorId` TEXT, `refNote_authorName` TEXT, `refNote_authorAvatarCdnImage` TEXT, `refNote_authorInternetIdentifier` TEXT, `refNote_authorLightningAddress` TEXT, `refNote_attachments` TEXT, `refNote_nostrUris` TEXT, `refArticle_naddr` TEXT, `refArticle_aTag` TEXT, `refArticle_eventId` TEXT, `refArticle_articleId` TEXT, `refArticle_articleTitle` TEXT, `refArticle_authorId` TEXT, `refArticle_authorName` TEXT, `refArticle_authorAvatarCdnImage` TEXT, `refArticle_createdAt` INTEGER, `refArticle_raw` TEXT, `refArticle_articleImageCdnImage` TEXT, `refArticle_articleReadingTimeInMinutes` INTEGER, `refUser_userId` TEXT, `refUser_handle` TEXT, PRIMARY KEY(`noteId`, `uri`))", + "fields": [ + { + "fieldPath": "noteId", + "columnName": "noteId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "uri", + "columnName": "uri", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "referencedNote.postId", + "columnName": "refNote_postId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.createdAt", + "columnName": "refNote_createdAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "referencedNote.content", + "columnName": "refNote_content", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.authorId", + "columnName": "refNote_authorId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.authorName", + "columnName": "refNote_authorName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.authorAvatarCdnImage", + "columnName": "refNote_authorAvatarCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.authorInternetIdentifier", + "columnName": "refNote_authorInternetIdentifier", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.authorLightningAddress", + "columnName": "refNote_authorLightningAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.attachments", + "columnName": "refNote_attachments", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedNote.nostrUris", + "columnName": "refNote_nostrUris", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.naddr", + "columnName": "refArticle_naddr", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.aTag", + "columnName": "refArticle_aTag", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.eventId", + "columnName": "refArticle_eventId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.articleId", + "columnName": "refArticle_articleId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.articleTitle", + "columnName": "refArticle_articleTitle", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.authorId", + "columnName": "refArticle_authorId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.authorName", + "columnName": "refArticle_authorName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.authorAvatarCdnImage", + "columnName": "refArticle_authorAvatarCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.createdAt", + "columnName": "refArticle_createdAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "referencedArticle.raw", + "columnName": "refArticle_raw", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.articleImageCdnImage", + "columnName": "refArticle_articleImageCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedArticle.articleReadingTimeInMinutes", + "columnName": "refArticle_articleReadingTimeInMinutes", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "referencedUser.userId", + "columnName": "refUser_userId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "referencedUser.handle", + "columnName": "refUser_handle", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "noteId", + "uri" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "NoteAttachment", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `url` TEXT NOT NULL, `type` TEXT NOT NULL, `mimeType` TEXT, `variants` TEXT, `title` TEXT, `description` TEXT, `thumbnail` TEXT, `authorAvatarUrl` TEXT, PRIMARY KEY(`eventId`, `url`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "mimeType", + "columnName": "mimeType", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "variants", + "columnName": "variants", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "thumbnail", + "columnName": "thumbnail", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "authorAvatarUrl", + "columnName": "authorAvatarUrl", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "eventId", + "url" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Feed", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`spec` TEXT NOT NULL, `specKind` TEXT NOT NULL, `feedKind` TEXT NOT NULL, `title` TEXT NOT NULL, `description` TEXT NOT NULL, `enabled` INTEGER NOT NULL, PRIMARY KEY(`spec`))", + "fields": [ + { + "fieldPath": "spec", + "columnName": "spec", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "specKind", + "columnName": "specKind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "feedKind", + "columnName": "feedKind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "description", + "columnName": "description", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "enabled", + "columnName": "enabled", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "spec" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "FeedPostDataCrossRef", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`feedSpec` TEXT NOT NULL, `eventId` TEXT NOT NULL, `orderIndex` INTEGER NOT NULL, PRIMARY KEY(`feedSpec`, `eventId`))", + "fields": [ + { + "fieldPath": "feedSpec", + "columnName": "feedSpec", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "orderIndex", + "columnName": "orderIndex", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "feedSpec", + "eventId" + ] + }, + "indices": [ + { + "name": "index_FeedPostDataCrossRef_feedSpec", + "unique": false, + "columnNames": [ + "feedSpec" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_FeedPostDataCrossRef_feedSpec` ON `${TABLE_NAME}` (`feedSpec`)" + }, + { + "name": "index_FeedPostDataCrossRef_eventId", + "unique": false, + "columnNames": [ + "eventId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_FeedPostDataCrossRef_eventId` ON `${TABLE_NAME}` (`eventId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "FeedPostRemoteKey", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `directive` TEXT NOT NULL, `sinceId` INTEGER NOT NULL, `untilId` INTEGER NOT NULL, `cachedAt` INTEGER NOT NULL, PRIMARY KEY(`eventId`, `directive`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "directive", + "columnName": "directive", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sinceId", + "columnName": "sinceId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "untilId", + "columnName": "untilId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "cachedAt", + "columnName": "cachedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "eventId", + "directive" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "NoteConversationCrossRef", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`noteId` TEXT NOT NULL, `replyNoteId` TEXT NOT NULL, PRIMARY KEY(`noteId`, `replyNoteId`))", + "fields": [ + { + "fieldPath": "noteId", + "columnName": "noteId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "replyNoteId", + "columnName": "replyNoteId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "noteId", + "replyNoteId" + ] + }, + "indices": [ + { + "name": "index_NoteConversationCrossRef_noteId", + "unique": false, + "columnNames": [ + "noteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_NoteConversationCrossRef_noteId` ON `${TABLE_NAME}` (`noteId`)" + }, + { + "name": "index_NoteConversationCrossRef_replyNoteId", + "unique": false, + "columnNames": [ + "replyNoteId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_NoteConversationCrossRef_replyNoteId` ON `${TABLE_NAME}` (`replyNoteId`)" + } + ], + "foreignKeys": [] + }, + { + "tableName": "ProfileStats", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`profileId` TEXT NOT NULL, `following` INTEGER, `followers` INTEGER, `notesCount` INTEGER, `readsCount` INTEGER, `mediaCount` INTEGER, `repliesCount` INTEGER, `relaysCount` INTEGER, `totalReceivedZaps` INTEGER, `contentZapCount` INTEGER, `totalReceivedSats` INTEGER, `joinedAt` INTEGER, PRIMARY KEY(`profileId`))", + "fields": [ + { + "fieldPath": "profileId", + "columnName": "profileId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "following", + "columnName": "following", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "followers", + "columnName": "followers", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "notesCount", + "columnName": "notesCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "readsCount", + "columnName": "readsCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "mediaCount", + "columnName": "mediaCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "repliesCount", + "columnName": "repliesCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "relaysCount", + "columnName": "relaysCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "totalReceivedZaps", + "columnName": "totalReceivedZaps", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "contentZapCount", + "columnName": "contentZapCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "totalReceivedSats", + "columnName": "totalReceivedSats", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "joinedAt", + "columnName": "joinedAt", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "profileId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "TrendingTopic", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`topic` TEXT NOT NULL, `score` REAL NOT NULL, PRIMARY KEY(`topic`))", + "fields": [ + { + "fieldPath": "topic", + "columnName": "topic", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "score", + "columnName": "score", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "topic" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "NotificationData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`notificationId` TEXT NOT NULL, `ownerId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `type` TEXT NOT NULL, `seenGloballyAt` INTEGER, `actionUserId` TEXT, `actionPostId` TEXT, `satsZapped` INTEGER, PRIMARY KEY(`notificationId`))", + "fields": [ + { + "fieldPath": "notificationId", + "columnName": "notificationId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerId", + "columnName": "ownerId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "seenGloballyAt", + "columnName": "seenGloballyAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "actionUserId", + "columnName": "actionUserId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "actionPostId", + "columnName": "actionPostId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "satsZapped", + "columnName": "satsZapped", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "notificationId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MutedUserData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `userMetadataEventId` TEXT, PRIMARY KEY(`userId`))", + "fields": [ + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "userMetadataEventId", + "columnName": "userMetadataEventId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "userId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "DirectMessageData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageId` TEXT NOT NULL, `senderId` TEXT NOT NULL, `receiverId` TEXT NOT NULL, `participantId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `content` TEXT NOT NULL, `uris` TEXT NOT NULL, `hashtags` TEXT NOT NULL, PRIMARY KEY(`messageId`))", + "fields": [ + { + "fieldPath": "messageId", + "columnName": "messageId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "senderId", + "columnName": "senderId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "receiverId", + "columnName": "receiverId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "participantId", + "columnName": "participantId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "uris", + "columnName": "uris", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hashtags", + "columnName": "hashtags", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "messageId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "MessageConversationData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`participantId` TEXT NOT NULL, `lastMessageId` TEXT NOT NULL, `lastMessageAt` INTEGER NOT NULL, `unreadMessagesCount` INTEGER NOT NULL, `relation` TEXT NOT NULL, `participantMetadataId` TEXT, PRIMARY KEY(`participantId`))", + "fields": [ + { + "fieldPath": "participantId", + "columnName": "participantId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastMessageId", + "columnName": "lastMessageId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastMessageAt", + "columnName": "lastMessageAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "unreadMessagesCount", + "columnName": "unreadMessagesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "relation", + "columnName": "relation", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "participantMetadataId", + "columnName": "participantMetadataId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "participantId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "WalletTransactionData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `walletLightningAddress` TEXT NOT NULL, `type` TEXT NOT NULL, `state` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `completedAt` INTEGER, `amountInBtc` REAL NOT NULL, `amountInUsd` REAL, `isZap` INTEGER NOT NULL, `isStorePurchase` INTEGER NOT NULL, `userId` TEXT NOT NULL, `userSubWallet` TEXT NOT NULL, `userLightningAddress` TEXT, `otherUserId` TEXT, `otherLightningAddress` TEXT, `note` TEXT, `invoice` TEXT, `totalFeeInBtc` TEXT, `exchangeRate` TEXT, `onChainAddress` TEXT, `onChainTxId` TEXT, `zapNoteId` TEXT, `zapNoteAuthorId` TEXT, `zappedByUserId` TEXT, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "walletLightningAddress", + "columnName": "walletLightningAddress", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "state", + "columnName": "state", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "completedAt", + "columnName": "completedAt", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "amountInBtc", + "columnName": "amountInBtc", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "amountInUsd", + "columnName": "amountInUsd", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "isZap", + "columnName": "isZap", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isStorePurchase", + "columnName": "isStorePurchase", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "userSubWallet", + "columnName": "userSubWallet", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "userLightningAddress", + "columnName": "userLightningAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "otherUserId", + "columnName": "otherUserId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "otherLightningAddress", + "columnName": "otherLightningAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "invoice", + "columnName": "invoice", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "totalFeeInBtc", + "columnName": "totalFeeInBtc", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "exchangeRate", + "columnName": "exchangeRate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "onChainAddress", + "columnName": "onChainAddress", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "onChainTxId", + "columnName": "onChainTxId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapNoteId", + "columnName": "zapNoteId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zapNoteAuthorId", + "columnName": "zapNoteAuthorId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "zappedByUserId", + "columnName": "zappedByUserId", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Relay", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `kind` TEXT NOT NULL, `url` TEXT NOT NULL, `read` INTEGER NOT NULL, `write` INTEGER NOT NULL, PRIMARY KEY(`userId`, `kind`, `url`))", + "fields": [ + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "write", + "columnName": "write", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "userId", + "kind", + "url" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "EventRelayHints", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` TEXT NOT NULL, `relays` TEXT NOT NULL, PRIMARY KEY(`eventId`))", + "fields": [ + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "relays", + "columnName": "relays", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "eventId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "PublicBookmark", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tagValue` TEXT NOT NULL, `tagType` TEXT NOT NULL, `bookmarkType` TEXT NOT NULL, `ownerId` TEXT NOT NULL, PRIMARY KEY(`tagValue`))", + "fields": [ + { + "fieldPath": "tagValue", + "columnName": "tagValue", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "tagType", + "columnName": "tagType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "bookmarkType", + "columnName": "bookmarkType", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "ownerId", + "columnName": "ownerId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "tagValue" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ProfileInteraction", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`profileId` TEXT NOT NULL, `lastInteractionAt` INTEGER NOT NULL, PRIMARY KEY(`profileId`))", + "fields": [ + { + "fieldPath": "profileId", + "columnName": "profileId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "lastInteractionAt", + "columnName": "lastInteractionAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "profileId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ArticleData", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`aTag` TEXT NOT NULL, `eventId` TEXT NOT NULL, `articleId` TEXT NOT NULL, `authorId` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `content` TEXT NOT NULL, `title` TEXT NOT NULL, `publishedAt` INTEGER NOT NULL, `raw` TEXT NOT NULL, `imageCdnImage` TEXT, `summary` TEXT, `authorMetadataId` TEXT, `wordsCount` INTEGER, `uris` TEXT NOT NULL, `hashtags` TEXT NOT NULL, PRIMARY KEY(`aTag`))", + "fields": [ + { + "fieldPath": "aTag", + "columnName": "aTag", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "eventId", + "columnName": "eventId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "articleId", + "columnName": "articleId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "authorId", + "columnName": "authorId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "title", + "columnName": "title", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "publishedAt", + "columnName": "publishedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "raw", + "columnName": "raw", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "imageCdnImage", + "columnName": "imageCdnImage", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "summary", + "columnName": "summary", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "authorMetadataId", + "columnName": "authorMetadataId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "wordsCount", + "columnName": "wordsCount", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "uris", + "columnName": "uris", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hashtags", + "columnName": "hashtags", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "aTag" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ArticleCommentCrossRef", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`articleId` TEXT NOT NULL, `articleAuthorId` TEXT NOT NULL, `commentNoteId` TEXT NOT NULL, PRIMARY KEY(`articleId`, `articleAuthorId`, `commentNoteId`))", + "fields": [ + { + "fieldPath": "articleId", + "columnName": "articleId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "articleAuthorId", + "columnName": "articleAuthorId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "commentNoteId", + "columnName": "commentNoteId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "articleId", + "articleAuthorId", + "commentNoteId" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "ArticleFeedCrossRef", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`spec` TEXT NOT NULL, `articleId` TEXT NOT NULL, `articleAuthorId` TEXT NOT NULL, PRIMARY KEY(`spec`, `articleId`, `articleAuthorId`))", + "fields": [ + { + "fieldPath": "spec", + "columnName": "spec", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "articleId", + "columnName": "articleId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "articleAuthorId", + "columnName": "articleAuthorId", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "spec", + "articleId", + "articleAuthorId" + ] + }, + "indices": [ + { + "name": "index_ArticleFeedCrossRef_spec", + "unique": false, + "columnNames": [ + "spec" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ArticleFeedCrossRef_spec` ON `${TABLE_NAME}` (`spec`)" + }, + { + "name": "index_ArticleFeedCrossRef_articleId", + "unique": false, + "columnNames": [ + "articleId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ArticleFeedCrossRef_articleId` ON `${TABLE_NAME}` (`articleId`)" + }, + { + "name": "index_ArticleFeedCrossRef_articleAuthorId", + "unique": false, + "columnNames": [ + "articleAuthorId" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `index_ArticleFeedCrossRef_articleAuthorId` ON `${TABLE_NAME}` (`articleAuthorId`)" + } + ], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'afb70ec74be5c0f7fc40491c8049abfb')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/net/primal/android/db/PrimalDatabase.kt b/app/src/main/kotlin/net/primal/android/db/PrimalDatabase.kt index 6f46b5ef4..8871254eb 100644 --- a/app/src/main/kotlin/net/primal/android/db/PrimalDatabase.kt +++ b/app/src/main/kotlin/net/primal/android/db/PrimalDatabase.kt @@ -89,7 +89,7 @@ import net.primal.android.wallet.db.WalletTransactionData ArticleCommentCrossRef::class, ArticleFeedCrossRef::class, ], - version = 45, + version = 46, exportSchema = true, ) @TypeConverters( diff --git a/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt b/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt index 513764fa6..fa08f0923 100644 --- a/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt +++ b/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt @@ -2,6 +2,8 @@ package net.primal.android.stats.db import androidx.room.Entity import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.profile.domain.PrimalLegendProfile @Entity( primaryKeys = [ @@ -22,4 +24,5 @@ data class EventZap( val zapSenderHandle: String? = null, val zapSenderInternetIdentifier: String? = null, val zapSenderAvatarCdnImage: CdnImage? = null, + val zapSenderPrimalLegendProfile: PrimalLegendProfile? = null, ) diff --git a/app/src/main/kotlin/net/primal/android/stats/ui/EventZapUiModel.kt b/app/src/main/kotlin/net/primal/android/stats/ui/EventZapUiModel.kt index 3928d0c9f..91679b32f 100644 --- a/app/src/main/kotlin/net/primal/android/stats/ui/EventZapUiModel.kt +++ b/app/src/main/kotlin/net/primal/android/stats/ui/EventZapUiModel.kt @@ -4,6 +4,8 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.core.utils.usernameUiFriendly +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.stats.db.EventZap import net.primal.android.wallet.utils.CurrencyConversionUtils.toSats @@ -17,6 +19,7 @@ data class EventZapUiModel( val amountInSats: ULong, val zapperInternetIdentifier: String? = null, val zapperAvatarCdnImage: CdnImage? = null, + val zapperLegendaryCustomization: LegendaryCustomization? = null, ) { companion object { val DefaultComparator = compareByDescending { it.amountInSats }.thenBy { it.zappedAt } @@ -34,4 +37,5 @@ fun EventZap.asEventZapUiModel() = zappedAt = this.zapRequestAt, message = this.message, amountInSats = this.amountInBtc.toBigDecimal().toSats(), + zapperLegendaryCustomization = this.zapSenderPrimalLegendProfile?.asLegendaryCustomization(), ) From 1fc13b8454326c9e31d54044170379776d060e0d Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:32:02 +0100 Subject: [PATCH 11/37] Use UniversalAvatarThumbnail on ReactionsZapsLazyColumn --- .../android/stats/reactions/ui/ReactionsZapsLazyColumn.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt index 9adb607d1..2862aabf5 100644 --- a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt +++ b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt @@ -24,6 +24,7 @@ import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.foundation.rememberLazyListStatePagingWorkaround import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.FeedZaps @@ -81,10 +82,11 @@ private fun NoteZapListItem(data: EventZapUiModel, onProfileClick: (profileId: S containerColor = AppTheme.colorScheme.surfaceVariant, ), leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = data.zapperAvatarCdnImage, avatarSize = 42.dp, onClick = { onProfileClick(data.zapperId) }, + legendaryCustomization = data.zapperLegendaryCustomization, ) }, headlineContent = { From 8ec17968eb6143d2b60132c977dfb4411a7053c3 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 12:48:31 +0100 Subject: [PATCH 12/37] Use UniversalAvatarThumbnail on ArticleTopZapsSection --- .../core/compose/zaps/ArticleTopZapsSection.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt index 08a14f333..11dd2c691 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt @@ -24,11 +24,13 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import java.text.NumberFormat import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.NavWalletBoltFilled import net.primal.android.core.compose.preview.PrimalPreview +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.theme.AppTheme @@ -86,11 +88,12 @@ private fun ArticleTopNoteZapRow(noteZap: EventZapUiModel, onClick: () -> Unit) .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(start = 2.dp), avatarCdnImage = noteZap.zapperAvatarCdnImage, avatarSize = 28.dp, onClick = onClick, + legendaryCustomization = noteZap.zapperLegendaryCustomization, ) IconText( @@ -134,11 +137,12 @@ private fun ArticleNoteZapListItem(noteZap: EventZapUiModel, onClick: () -> Unit .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(start = 2.dp), avatarCdnImage = noteZap.zapperAvatarCdnImage, avatarSize = 24.dp, onClick = onClick, + legendaryCustomization = noteZap.zapperLegendaryCustomization, ) Text( @@ -202,6 +206,11 @@ private fun PreviewArticleTopZapsSection() { zappedAt = 0, message = "Top zap message!!!", amountInSats = 21_21_21.toULong(), + zapperLegendaryCustomization = LegendaryCustomization( + avatarGlow = true, + customBadge = true, + legendaryStyle = LegendaryStyle.SUN_FIRE, + ) ), EventZapUiModel( id = "id", From e38287277ab0faa51f67fa3faf629a364ca02c4e Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 15:30:57 +0100 Subject: [PATCH 13/37] Refactor ActiveAccount to store PrimalLegendProfile instead of destructured arguments --- .../primal/android/articles/reads/ReadsViewModel.kt | 3 ++- .../android/explore/home/ExploreHomeViewModel.kt | 3 ++- .../net/primal/android/notes/home/HomeFeedViewModel.kt | 3 ++- .../notifications/list/NotificationsViewModel.kt | 3 ++- .../android/settings/keys/KeysSettingsContract.kt | 2 ++ .../primal/android/settings/keys/KeysSettingsScreen.kt | 10 ++++++++-- .../android/settings/keys/KeysSettingsViewModel.kt | 2 ++ .../net/primal/android/user/accounts/UserAccountExt.kt | 4 +--- .../primal/android/user/accounts/UserAccountFetcher.kt | 4 +--- .../net/primal/android/user/domain/UserAccount.kt | 6 +++--- .../wallet/dashboard/WalletDashboardViewModel.kt | 3 ++- 11 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt index 3c507d4ca..024df8415 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt @@ -16,6 +16,7 @@ import net.primal.android.feeds.list.ui.model.asFeedUi import net.primal.android.feeds.repository.FeedsRepository import net.primal.android.networking.primal.retryNetworkCall import net.primal.android.networking.sockets.errors.WssException +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import timber.log.Timber @@ -102,7 +103,7 @@ class ReadsViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = if (it.avatarRing) it.legendaryStyle else null, + activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), ) } } diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt index 1c734ba64..52a3479dd 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch import net.primal.android.explore.home.ExploreHomeContract.UiState +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager @@ -34,7 +35,7 @@ class ExploreHomeViewModel @Inject constructor( copy( activeAccountPubkey = it.pubkey, activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = if (it.avatarRing) it.legendaryStyle else null, + activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), ) } } diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt index 516554f60..82dcff556 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt @@ -20,6 +20,7 @@ import net.primal.android.networking.primal.retryNetworkCall import net.primal.android.networking.sockets.errors.WssException import net.primal.android.notes.home.HomeFeedContract.UiEvent import net.primal.android.notes.home.HomeFeedContract.UiState +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import net.primal.android.user.updater.UserDataUpdater @@ -116,7 +117,7 @@ class HomeFeedViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = if (it.avatarRing) it.legendaryStyle else null, + activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), ) } } diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt index 76c9ecd69..0089e2b32 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt @@ -30,6 +30,7 @@ import net.primal.android.notifications.list.NotificationsContract.UiEvent.Notif import net.primal.android.notifications.list.NotificationsContract.UiState import net.primal.android.notifications.list.ui.NotificationUi import net.primal.android.notifications.repository.NotificationRepository +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import timber.log.Timber @@ -77,7 +78,7 @@ class NotificationsViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = if (it.avatarRing) it.legendaryStyle else null, + activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), ) } } diff --git a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsContract.kt b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsContract.kt index 4d629e673..af8e985ae 100644 --- a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsContract.kt +++ b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsContract.kt @@ -1,11 +1,13 @@ package net.primal.android.settings.keys import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization interface KeysSettingsContract { data class UiState( val avatarCdnImage: CdnImage? = null, val nsec: String = "", val npub: String = "", + val legendaryCustomization: LegendaryCustomization? = null, ) } diff --git a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt index 2b822fe12..eb83ca1b2 100644 --- a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt @@ -43,11 +43,13 @@ import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalLoadingButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.core.compose.icons.primaliconpack.Key import net.primal.android.core.compose.preview.PrimalPreview +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme @@ -87,6 +89,7 @@ fun KeysSettingsScreen(state: KeysSettingsContract.UiState, onClose: () -> Unit) PublicKeySection( npub = state.npub, avatarCdnImage = state.avatarCdnImage, + legendaryCustomization = state.legendaryCustomization, ) } @@ -105,7 +108,7 @@ fun KeysSettingsScreen(state: KeysSettingsContract.UiState, onClose: () -> Unit) } @Composable -fun PublicKeySection(npub: String, avatarCdnImage: CdnImage?) { +fun PublicKeySection(npub: String, avatarCdnImage: CdnImage?, legendaryCustomization: LegendaryCustomization?) { val context = LocalContext.current Text( @@ -127,7 +130,10 @@ fun PublicKeySection(npub: String, avatarCdnImage: CdnImage?) { verticalAlignment = Alignment.CenterVertically, ) { Box(modifier = Modifier.padding(start = 16.dp)) { - AvatarThumbnail(avatarCdnImage = avatarCdnImage) + UniversalAvatarThumbnail( + avatarCdnImage = avatarCdnImage, + legendaryCustomization = legendaryCustomization, + ) } Text( modifier = Modifier.padding(all = 16.dp), diff --git a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsViewModel.kt b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsViewModel.kt index ec7302fce..e66c18931 100644 --- a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsViewModel.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch import net.primal.android.crypto.hexToNpubHrp +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.settings.keys.KeysSettingsContract.UiState import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.credentials.CredentialsStore @@ -36,6 +37,7 @@ class KeysSettingsViewModel @Inject constructor( avatarCdnImage = it.avatarCdnImage, nsec = credential.nsec, npub = credential.npub, + legendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountExt.kt b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountExt.kt index 6a89b7d96..03be4da8f 100644 --- a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountExt.kt +++ b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountExt.kt @@ -19,9 +19,7 @@ fun UserAccount.copyProfileIfNotNull(profile: UserAccount?): UserAccount { avatarCdnImage = profile.avatarCdnImage, internetIdentifier = profile.internetIdentifier, lightningAddress = profile.lightningAddress, - avatarRing = profile.avatarRing, - customBadge = profile.customBadge, - legendaryStyle = profile.legendaryStyle, + primalLegendProfile = profile.primalLegendProfile, ) } else { this diff --git a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt index 64a348b80..569271ed3 100644 --- a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt +++ b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt @@ -56,9 +56,7 @@ class UserAccountFetcher @Inject constructor( followingCount = profileStats?.following, notesCount = profileStats?.notesCount, repliesCount = profileStats?.repliesCount, - customBadge = profileData.primalLegendProfile?.customBadge == true, - avatarRing = profileData.primalLegendProfile?.avatarGlow == true, - legendaryStyle = LegendaryStyle.valueById(profileData.primalLegendProfile?.styleId), + primalLegendProfile = profileData.primalLegendProfile, ) } diff --git a/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt b/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt index 2c69338b0..b98630972 100644 --- a/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt +++ b/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt @@ -5,7 +5,9 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.asEllipsizedNpub import net.primal.android.nostr.model.primal.content.ContentAppSettings import net.primal.android.premium.domain.PremiumMembership +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.profile.domain.PrimalLegendProfile import net.primal.android.wallet.domain.WalletSettings import net.primal.android.wallet.domain.WalletState @@ -38,9 +40,7 @@ data class UserAccount( val cachingProxyEnabled: Boolean = false, val premiumMembership: PremiumMembership? = null, val lastBuyPremiumTimestampInMillis: Long? = null, - val avatarRing: Boolean = false, - val customBadge: Boolean = false, - val legendaryStyle: LegendaryStyle? = null, + val primalLegendProfile: PrimalLegendProfile? = null, ) { companion object { val EMPTY = UserAccount( diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt index 3faed9f57..35bc9c312 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.launch import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.networking.sockets.errors.NostrNoticeException import net.primal.android.networking.sockets.errors.WssException +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.domain.WalletPreference import net.primal.android.user.repository.UserRepository @@ -79,7 +80,7 @@ class WalletDashboardViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = if (it.avatarRing) it.legendaryStyle else null, + activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), primalWallet = it.primalWallet, walletPreference = it.walletPreference, walletBalance = it.primalWalletState.balanceInBtc?.toBigDecimal(), From 873a21be0d27d62bbf24e6b62462d6012e7d09f2 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 15:31:28 +0100 Subject: [PATCH 14/37] Use UniversalAvatarThumbnail on EventZapItem, DvmFeedListItem and ProfileQrCodeViewer --- .../net/primal/android/core/compose/zaps/EventZapItem.kt | 5 +++-- .../net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt | 4 ++-- .../net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/EventZapItem.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/EventZapItem.kt index 122e9e7ac..e38867d3a 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/EventZapItem.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/EventZapItem.kt @@ -15,8 +15,8 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import java.text.NumberFormat -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.FeedNewZapFilled import net.primal.android.stats.ui.EventZapUiModel @@ -44,11 +44,12 @@ fun EventZapItem( ), verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(start = 2.dp), avatarCdnImage = noteZap.zapperAvatarCdnImage, avatarSize = 24.dp, onClick = onClick, + legendaryCustomization = noteZap.zapperLegendaryCustomization, ) IconText( diff --git a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt index 7ebaed73b..c75fd031d 100644 --- a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt +++ b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt @@ -43,8 +43,8 @@ import java.text.NumberFormat import net.primal.android.R import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AvatarOverlap -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.AvatarThumbnailsRow +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.FeedLikes import net.primal.android.core.compose.icons.primaliconpack.FeedLikesFilled @@ -276,7 +276,7 @@ fun DvmFeedThumbnail( modifier = Modifier.size(avatarSize), contentAlignment = Alignment.BottomEnd, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = avatarCdnImage, avatarSize = avatarSize, ) diff --git a/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt b/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt index 5d7a33f64..7c78d4b4c 100644 --- a/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt +++ b/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt @@ -64,6 +64,7 @@ import net.primal.android.R import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.DefaultAvatarThumbnailPlaceholderListItemImage import net.primal.android.core.compose.PrimalLoadingSpinner +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.Copy import net.primal.android.core.compose.profile.model.ProfileDetailsUi @@ -86,11 +87,12 @@ fun ProfileQrCodeViewer( .padding(paddingValues), horizontalAlignment = Alignment.CenterHorizontally, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.size(108.dp), avatarCdnImage = profileDetails?.avatarCdnImage, hasBorder = true, - borderColor = Color.White, + fallbackBorderColor = Color.White, + legendaryCustomization = profileDetails?.legendaryCustomization, defaultAvatar = { DefaultAvatarThumbnailPlaceholderListItemImage( backgroundColor = Color.White, From 366d80b6fda8c2dfa5bde4ea4ffacf7ec24ad3a6 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 15:31:52 +0100 Subject: [PATCH 15/37] Implement no ring option on UniversalAvatarThumbnail --- .../android/core/compose/AvatarThumbnailListItemImage.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index 097929080..9484d30da 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -47,12 +47,19 @@ fun UniversalAvatarThumbnail( ) { val variant = avatarCdnImage?.variants?.minByOrNull { it.width } val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl + + val borderBrush = if (legendaryCustomization?.avatarGlow == true) { + legendaryCustomization.legendaryStyle?.brush + } else { + null + } + AvatarThumbnailListItemImage( modifier = modifier, avatarSize = avatarSize, source = imageSource, hasBorder = hasBorder, - borderBrush = legendaryCustomization?.legendaryStyle?.brush ?: Brush.linearGradient( + borderBrush = borderBrush ?: Brush.linearGradient( colors = listOf( fallbackBorderColor, fallbackBorderColor, From cd4b5b0504ce636dc3a55491b8887cfa6c0b5e12 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 15:54:08 +0100 Subject: [PATCH 16/37] Use UniversalAvatarThumbnail on PrimalTopAppBar --- .../net/primal/android/articles/reads/ReadsScreen.kt | 7 ++++--- .../android/articles/reads/ReadsScreenContract.kt | 3 ++- .../primal/android/articles/reads/ReadsViewModel.kt | 3 ++- .../primal/android/core/compose/PrimalTopAppBar.kt | 11 ++++------- .../net/primal/android/messages/chat/ChatScreen.kt | 4 +++- .../conversation/MessageConversationListScreen.kt | 6 ++++-- .../conversation/MessageConversationListViewModel.kt | 2 ++ .../conversation/model/MessageConversationUi.kt | 2 ++ .../net/primal/android/notes/home/HomeFeedContract.kt | 3 ++- .../net/primal/android/notes/home/HomeFeedScreen.kt | 7 ++++--- .../primal/android/notes/home/HomeFeedViewModel.kt | 3 ++- .../notifications/list/NotificationsContract.kt | 3 ++- .../android/notifications/list/NotificationsScreen.kt | 2 +- .../notifications/list/NotificationsViewModel.kt | 3 ++- .../wallet/dashboard/WalletDashboardContract.kt | 3 ++- .../android/wallet/dashboard/WalletDashboardScreen.kt | 2 +- .../wallet/dashboard/WalletDashboardViewModel.kt | 3 ++- 17 files changed, 41 insertions(+), 26 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt index 1fdb4a538..b3d4c1f13 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt @@ -53,6 +53,7 @@ import net.primal.android.drawer.PrimalDrawerScaffold import net.primal.android.feeds.domain.FeedSpecKind import net.primal.android.feeds.list.FeedsBottomSheet import net.primal.android.feeds.list.ui.model.FeedUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle @Composable @@ -129,7 +130,7 @@ private fun ReadsScreen( title = activeFeed?.title ?: "", activeFeed = activeFeed, avatarCdnImage = state.activeAccountAvatarCdnImage, - avatarLegendaryStyle = state.activeAccountLegendaryStyle, + avatarLegendaryCustomization = state.activeAccountLegendaryCustomization, onAvatarClick = { uiScope.launch { drawerState.open() } }, onSearchClick = onSearchClick, onFeedChanged = { feed -> @@ -195,7 +196,7 @@ private fun ArticleFeedTopAppBar( onSearchClick: () -> Unit, activeFeed: FeedUi?, onFeedChanged: (FeedUi) -> Unit, - avatarLegendaryStyle: LegendaryStyle? = null, + avatarLegendaryCustomization: LegendaryCustomization? = null, scrollBehavior: TopAppBarScrollBehavior? = null, ) { var feedPickerVisible by rememberSaveable { mutableStateOf(false) } @@ -222,7 +223,7 @@ private fun ArticleFeedTopAppBar( } }, avatarCdnImage = avatarCdnImage, - avatarLegendaryStyle = avatarLegendaryStyle, + legendaryCustomization = avatarLegendaryCustomization, navigationIcon = PrimalIcons.AvatarDefault, onNavigationIconClick = onAvatarClick, actions = { diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt index 7d1346bf0..9b3a56790 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt @@ -2,6 +2,7 @@ package net.primal.android.articles.reads import net.primal.android.attachments.domain.CdnImage import net.primal.android.feeds.list.ui.model.FeedUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges @@ -9,7 +10,7 @@ interface ReadsScreenContract { data class UiState( val feeds: List = emptyList(), val activeAccountAvatarCdnImage: CdnImage? = null, - val activeAccountLegendaryStyle: LegendaryStyle? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val badges: Badges = Badges(), val loading: Boolean = false, ) diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt index 024df8415..d0e7a32d7 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt @@ -17,6 +17,7 @@ import net.primal.android.feeds.repository.FeedsRepository import net.primal.android.networking.primal.retryNetworkCall import net.primal.android.networking.sockets.errors.WssException import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import timber.log.Timber @@ -103,7 +104,7 @@ class ReadsViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), + activeAccountLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt b/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt index 19f92905e..a27cb40b5 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @@ -53,7 +54,7 @@ fun PrimalTopAppBar( onNavigationIconClick: (() -> Unit)? = null, autoCloseKeyboardOnNavigationIconClick: Boolean = true, avatarCdnImage: CdnImage? = null, - avatarLegendaryStyle: LegendaryStyle? = null, + legendaryCustomization: LegendaryCustomization? = null, actions: (@Composable RowScope.() -> Unit)? = null, showDivider: Boolean = true, scrollBehavior: TopAppBarScrollBehavior? = null, @@ -77,15 +78,11 @@ fun PrimalTopAppBar( .padding(horizontal = 8.dp) .clip(CircleShape), ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarCdnImage = avatarCdnImage, modifier = Modifier.size(32.dp), onClick = onNavigationIconClick, - hasBorder = avatarLegendaryStyle != null, - borderBrush = avatarLegendaryStyle?.brush - ?: Brush.linearGradient( - listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), - ), + legendaryCustomization = legendaryCustomization, ) } } else if (navigationIcon != null) { diff --git a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt index 4336f453b..c8808f3bf 100644 --- a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt +++ b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt @@ -59,6 +59,7 @@ import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.compose.foundation.rememberLazyListStatePagingWorkaround import net.primal.android.core.compose.heightAdjustableLoadingLazyListPlaceholder @@ -138,10 +139,11 @@ fun ChatScreen( .padding(horizontal = 8.dp) .clip(CircleShape), ) { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = state.participantProfile?.avatarCdnImage, modifier = Modifier.size(32.dp), onClick = { noteCallbacks.onProfileClick?.invoke(state.participantId) }, + legendaryCustomization = state.participantProfile?.legendaryCustomization, ) } }, diff --git a/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListScreen.kt b/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListScreen.kt index 7e0ddf4c7..3d18bd4b2 100644 --- a/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListScreen.kt +++ b/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListScreen.kt @@ -60,11 +60,11 @@ import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.itemContentType import androidx.paging.compose.itemKey import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.compose.foundation.rememberLazyListStatePagingWorkaround import net.primal.android.core.compose.heightAdjustableLoadingLazyListPlaceholder @@ -280,9 +280,10 @@ private fun ConversationListItem( }, colors = ListItemDefaults.colors(containerColor = AppTheme.colorScheme.surfaceVariant), leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = conversation.participantAvatarCdnImage, onClick = { onProfileClick(conversation.participantId) }, + legendaryCustomization = conversation.participantLegendaryCustomization, ) }, headlineContent = { @@ -311,6 +312,7 @@ private fun ConversationListItem( displayName = conversation.participantUsername, internetIdentifier = conversation.participantInternetIdentifier, annotatedStringSuffixBuilder = { append(suffixText) }, + customBadgeStyle = conversation.participantLegendaryCustomization?.legendaryStyle, style = AppTheme.typography.bodyMedium, ) } diff --git a/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListViewModel.kt b/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListViewModel.kt index dbc7e0927..29122713b 100644 --- a/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/messages/conversation/MessageConversationListViewModel.kt @@ -26,6 +26,7 @@ import net.primal.android.messages.domain.ConversationRelation import net.primal.android.messages.repository.MessageRepository import net.primal.android.networking.sockets.errors.WssException import net.primal.android.notes.feed.model.asNoteNostrUriUi +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import timber.log.Timber @@ -139,6 +140,7 @@ class MessageConversationListViewModel @Inject constructor( isLastMessageFromUser = this.lastMessage?.senderId == activeUserId, participantInternetIdentifier = this.participant?.internetIdentifier, participantAvatarCdnImage = this.participant?.avatarCdnImage, + participantLegendaryCustomization = this.participant?.primalLegendProfile?.asLegendaryCustomization(), unreadMessagesCount = this.data.unreadMessagesCount, ) } diff --git a/app/src/main/kotlin/net/primal/android/messages/conversation/model/MessageConversationUi.kt b/app/src/main/kotlin/net/primal/android/messages/conversation/model/MessageConversationUi.kt index 701d6687f..86a424ee8 100644 --- a/app/src/main/kotlin/net/primal/android/messages/conversation/model/MessageConversationUi.kt +++ b/app/src/main/kotlin/net/primal/android/messages/conversation/model/MessageConversationUi.kt @@ -4,6 +4,7 @@ import java.time.Instant import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.attachment.model.NoteAttachmentUi import net.primal.android.notes.feed.model.NoteNostrUriUi +import net.primal.android.premium.legend.LegendaryCustomization data class MessageConversationUi( val participantId: String, @@ -16,5 +17,6 @@ data class MessageConversationUi( val isLastMessageFromUser: Boolean, val participantInternetIdentifier: String? = null, val participantAvatarCdnImage: CdnImage? = null, + val participantLegendaryCustomization: LegendaryCustomization? = null, val unreadMessagesCount: Int = 0, ) diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt index 0b8ff105f..f1f5cf00b 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt @@ -2,6 +2,7 @@ package net.primal.android.notes.home import net.primal.android.attachments.domain.CdnImage import net.primal.android.feeds.list.ui.model.FeedUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges @@ -10,7 +11,7 @@ interface HomeFeedContract { data class UiState( val feeds: List = emptyList(), val activeAccountAvatarCdnImage: CdnImage? = null, - val activeAccountLegendaryStyle: LegendaryStyle? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val badges: Badges = Badges(), val loading: Boolean = true, ) diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt index 02bfbfe7a..9ce14cb10 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt @@ -67,6 +67,7 @@ import net.primal.android.feeds.list.ui.model.FeedUi import net.primal.android.notes.feed.list.NoteFeedList import net.primal.android.notes.feed.note.ui.events.NoteCallbacks import net.primal.android.notes.home.HomeFeedContract.UiEvent +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @@ -166,7 +167,7 @@ fun HomeFeedScreen( title = activeFeed?.title ?: "", activeFeed = activeFeed, avatarCdnImage = state.activeAccountAvatarCdnImage, - avatarLegendaryStyle = state.activeAccountLegendaryStyle, + avatarLegendaryCustomization = state.activeAccountLegendaryCustomization, onAvatarClick = { uiScope.launch { drawerState.open() } }, onSearchClick = onSearchClick, onFeedChanged = { feed -> @@ -255,7 +256,7 @@ private fun NoteFeedTopAppBar( onSearchClick: () -> Unit, activeFeed: FeedUi?, onFeedChanged: (FeedUi) -> Unit, - avatarLegendaryStyle: LegendaryStyle? = null, + avatarLegendaryCustomization: LegendaryCustomization? = null, scrollBehavior: TopAppBarScrollBehavior? = null, onGoToWallet: (() -> Unit)? = null, ) { @@ -284,7 +285,7 @@ private fun NoteFeedTopAppBar( } }, avatarCdnImage = avatarCdnImage, - avatarLegendaryStyle = avatarLegendaryStyle, + legendaryCustomization = avatarLegendaryCustomization, navigationIcon = PrimalIcons.AvatarDefault, onNavigationIconClick = onAvatarClick, actions = { diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt index 82dcff556..07eebad8b 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt @@ -21,6 +21,7 @@ import net.primal.android.networking.sockets.errors.WssException import net.primal.android.notes.home.HomeFeedContract.UiEvent import net.primal.android.notes.home.HomeFeedContract.UiState import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import net.primal.android.user.updater.UserDataUpdater @@ -117,7 +118,7 @@ class HomeFeedViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), + activeAccountLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt index 84258a270..6b288f203 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt @@ -4,6 +4,7 @@ import androidx.paging.PagingData import kotlinx.coroutines.flow.Flow import net.primal.android.attachments.domain.CdnImage import net.primal.android.notifications.list.ui.NotificationUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges @@ -13,7 +14,7 @@ interface NotificationsContract { val seenNotifications: Flow>, val unseenNotifications: List> = emptyList(), val activeAccountAvatarCdnImage: CdnImage? = null, - val activeAccountLegendaryStyle: LegendaryStyle? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val badges: Badges = Badges(), ) diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsScreen.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsScreen.kt index 54c7bb899..5ef6a8239 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsScreen.kt @@ -158,7 +158,7 @@ fun NotificationsScreen( PrimalTopAppBar( title = stringResource(id = R.string.notifications_title), avatarCdnImage = state.activeAccountAvatarCdnImage, - avatarLegendaryStyle = state.activeAccountLegendaryStyle, + legendaryCustomization = state.activeAccountLegendaryCustomization, navigationIcon = PrimalIcons.AvatarDefault, onNavigationIconClick = { uiScope.launch { drawerState.open() } diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt index 0089e2b32..98542a7cf 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt @@ -31,6 +31,7 @@ import net.primal.android.notifications.list.NotificationsContract.UiState import net.primal.android.notifications.list.ui.NotificationUi import net.primal.android.notifications.repository.NotificationRepository import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager import timber.log.Timber @@ -78,7 +79,7 @@ class NotificationsViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), + activeAccountLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt index ddf315e80..662bad01c 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt @@ -4,6 +4,7 @@ import androidx.paging.PagingData import java.math.BigDecimal import kotlinx.coroutines.flow.Flow import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges import net.primal.android.user.domain.PrimalWallet @@ -14,7 +15,7 @@ interface WalletDashboardContract { data class UiState( val transactions: Flow>, val activeAccountAvatarCdnImage: CdnImage? = null, - val activeAccountLegendaryStyle: LegendaryStyle? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val badges: Badges = Badges(), val primalWallet: PrimalWallet? = null, val walletPreference: WalletPreference = WalletPreference.Undefined, diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardScreen.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardScreen.kt index 4f06d6203..d71962814 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardScreen.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardScreen.kt @@ -180,7 +180,7 @@ fun WalletDashboardScreen( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, title = stringResource(id = R.string.wallet_title), avatarCdnImage = state.activeAccountAvatarCdnImage, - avatarLegendaryStyle = state.activeAccountLegendaryStyle, + legendaryCustomization = state.activeAccountLegendaryCustomization, navigationIcon = PrimalIcons.AvatarDefault, onNavigationIconClick = { uiScope.launch { drawerState.open() } diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt index 35bc9c312..4013fab8b 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt @@ -18,6 +18,7 @@ import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.networking.sockets.errors.NostrNoticeException import net.primal.android.networking.sockets.errors.WssException import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.domain.WalletPreference import net.primal.android.user.repository.UserRepository @@ -80,7 +81,7 @@ class WalletDashboardViewModel @Inject constructor( setState { copy( activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), + activeAccountLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), primalWallet = it.primalWallet, walletPreference = it.walletPreference, walletBalance = it.primalWalletState.balanceInBtc?.toBigDecimal(), From 90af9a424884b763e8c58141e216dfad4e57988c Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 15:58:52 +0100 Subject: [PATCH 17/37] Use UniversalAvatarThumbnail on TransactionListItem --- .../android/wallet/dashboard/WalletDashboardViewModel.kt | 1 + .../wallet/transactions/list/TransactionListItem.kt | 7 ++++++- .../wallet/transactions/list/TransactionListItemDataUi.kt | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt index 4013fab8b..7efeecb64 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt @@ -164,6 +164,7 @@ class WalletDashboardViewModel @Inject constructor( otherUserId = this.data.otherUserId, otherUserAvatarCdnImage = this.otherProfileData?.avatarCdnImage, otherUserDisplayName = this.otherProfileData?.authorNameUiFriendly(), + otherUserLegendaryCustomization = this.otherProfileData?.primalLegendProfile?.asLegendaryCustomization(), isZap = this.data.isZap, isStorePurchase = this.data.isStorePurchase, isOnChainPayment = this.data.onChainAddress != null, diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt index 51cd8f08c..ee6f9029d 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt @@ -47,6 +47,7 @@ import net.primal.android.R import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.WrappedContentWithSuffix import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.WalletBitcoinPayment @@ -54,6 +55,7 @@ import net.primal.android.core.compose.icons.primaliconpack.WalletLightningPayme import net.primal.android.core.compose.icons.primaliconpack.WalletPay import net.primal.android.core.compose.icons.primaliconpack.WalletReceive import net.primal.android.core.compose.preview.PrimalPreview +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.theme.AppTheme import net.primal.android.wallet.domain.TxState import net.primal.android.wallet.domain.TxType @@ -97,6 +99,7 @@ fun TransactionListItem( isPending = data.txState.isPending(), otherUserId = data.otherUserId, otherUserAvatarCdnImage = data.otherUserAvatarCdnImage, + otherUserLegendaryCustomization = data.otherUserLegendaryCustomization, onAvatarClick = onAvatarClick, ) }, @@ -133,13 +136,15 @@ private fun TransactionLeadingContent( isPending: Boolean, otherUserId: String?, otherUserAvatarCdnImage: CdnImage?, + otherUserLegendaryCustomization: LegendaryCustomization?, onAvatarClick: (String) -> Unit, ) { when { otherUserId != null -> { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = otherUserAvatarCdnImage, onClick = { onAvatarClick(otherUserId) }, + legendaryCustomization = otherUserLegendaryCustomization, ) } diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItemDataUi.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItemDataUi.kt index eb7738984..5e87086ed 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItemDataUi.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItemDataUi.kt @@ -2,6 +2,7 @@ package net.primal.android.wallet.transactions.list import java.time.Instant import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.wallet.domain.TxState import net.primal.android.wallet.domain.TxType @@ -20,4 +21,5 @@ data class TransactionListItemDataUi( val otherUserId: String? = null, val otherUserAvatarCdnImage: CdnImage? = null, val otherUserDisplayName: String? = null, + val otherUserLegendaryCustomization: LegendaryCustomization? = null, ) From 0783a5b82754409adfa933d474fd53ebb936aab7 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 16:12:15 +0100 Subject: [PATCH 18/37] Use UniversalAvatarThumbnail on NoteEditor, TransationEditor and ExplorePeople --- .../kotlin/net/primal/android/editor/NoteEditorContract.kt | 2 ++ .../kotlin/net/primal/android/editor/NoteEditorViewModel.kt | 3 +++ .../kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt | 4 +++- .../net/primal/android/explore/home/people/ExplorePeople.kt | 5 +++-- .../transactions/send/create/CreateTransactionContract.kt | 2 ++ .../transactions/send/create/CreateTransactionViewModel.kt | 3 +++ .../wallet/transactions/send/create/ui/TransactionEditor.kt | 4 +++- 7 files changed, 19 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/editor/NoteEditorContract.kt b/app/src/main/kotlin/net/primal/android/editor/NoteEditorContract.kt index 5560e38d2..704faa06c 100644 --- a/app/src/main/kotlin/net/primal/android/editor/NoteEditorContract.kt +++ b/app/src/main/kotlin/net/primal/android/editor/NoteEditorContract.kt @@ -9,6 +9,7 @@ import net.primal.android.core.compose.profile.model.UserProfileItemUi import net.primal.android.editor.domain.NoteAttachment import net.primal.android.editor.domain.NoteTaggedUser import net.primal.android.notes.feed.model.FeedPostUi +import net.primal.android.premium.legend.LegendaryCustomization interface NoteEditorContract { @@ -19,6 +20,7 @@ interface NoteEditorContract { val publishing: Boolean = false, val error: NoteEditorError? = null, val activeAccountAvatarCdnImage: CdnImage? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val uploadingAttachments: Boolean = false, val attachments: List = emptyList(), val taggedUsers: List = emptyList(), diff --git a/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt b/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt index 6f13d9218..daf59960f 100644 --- a/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt @@ -51,6 +51,7 @@ import net.primal.android.nostr.utils.Naddr import net.primal.android.nostr.utils.Nip19TLV import net.primal.android.notes.feed.model.asFeedPostUi import net.primal.android.notes.repository.FeedRepository +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.repository.ProfileRepository import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.accounts.active.ActiveUserAccountState @@ -169,6 +170,8 @@ class NoteEditorViewModel @AssistedInject constructor( setState { copy( activeAccountAvatarCdnImage = it.data.avatarCdnImage, + activeAccountLegendaryCustomization = + it.data.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt index 21a0705f5..4b098b8bb 100644 --- a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt +++ b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt @@ -69,6 +69,7 @@ import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar import net.primal.android.core.compose.ReplyingToText import net.primal.android.core.compose.TakePhotoIconButton +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalLoadingButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ImportPhotoFromCamera @@ -310,7 +311,7 @@ private fun NoteEditor( } Row { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier .drawWithCache { onDrawBehind { @@ -335,6 +336,7 @@ private fun NoteEditor( .padding(top = 8.dp), avatarSize = avatarSizeDp, avatarCdnImage = state.activeAccountAvatarCdnImage, + legendaryCustomization = state.activeAccountLegendaryCustomization, ) NoteOutlinedTextField( diff --git a/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt b/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt index cbab29990..3fff032e1 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt @@ -36,10 +36,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.HeightAdjustableLoadingLazyListPlaceholder import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.FollowUnfollowButton import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.compose.profile.model.ProfileDetailsUi @@ -154,11 +154,12 @@ private fun ExplorePersonListItem( modifier = Modifier.padding(horizontal = 12.dp), verticalArrangement = Arrangement.Top, ) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(bottom = 24.dp), avatarSize = 64.dp, avatarCdnImage = person.profile.avatarCdnImage, onClick = onItemClick, + legendaryCustomization = person.profile.legendaryCustomization, ) } diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionContract.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionContract.kt index 2730f2a70..554c47c91 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionContract.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionContract.kt @@ -1,6 +1,7 @@ package net.primal.android.wallet.transactions.send.create import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.wallet.domain.DraftTx import net.primal.android.wallet.transactions.send.create.ui.model.MiningFeeUi @@ -16,6 +17,7 @@ interface CreateTransactionContract { val profileAvatarCdnImage: CdnImage? = null, val profileDisplayName: String? = null, val profileLightningAddress: String? = null, + val profileLegendaryCustomization: LegendaryCustomization? = null, ) { fun isNotInvoice() = transaction.lnInvoice == null && transaction.onChainInvoice == null } diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionViewModel.kt index f8c212ab1..720599441 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/CreateTransactionViewModel.kt @@ -16,6 +16,7 @@ import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.navigation.draftTransaction import net.primal.android.navigation.lnbc import net.primal.android.networking.sockets.errors.WssException +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.db.ProfileData import net.primal.android.profile.repository.ProfileRepository import net.primal.android.scanner.analysis.WalletTextParser @@ -191,6 +192,8 @@ class CreateTransactionViewModel @Inject constructor( setState { copy( profileAvatarCdnImage = this@updateStateWithProfileData.avatarCdnImage, + profileLegendaryCustomization = this@updateStateWithProfileData + .primalLegendProfile?.asLegendaryCustomization(), profileDisplayName = this@updateStateWithProfileData.authorNameUiFriendly(), profileLightningAddress = transaction.targetLud16 ?: this@updateStateWithProfileData.lightningAddress, transaction = if (transaction.targetLud16 == null && diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt index 44afe715c..76c565874 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt @@ -56,6 +56,7 @@ import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.PrimalLoadingSpinner import net.primal.android.core.compose.UiDensityMode +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalLoadingButton import net.primal.android.core.compose.detectUiDensityModeFromMaxHeight import net.primal.android.core.compose.foundation.keyboardVisibilityAsState @@ -388,10 +389,11 @@ private fun TransactionHeaderColumn( ) } } else { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(vertical = verticalPadding.value), avatarCdnImage = state.profileAvatarCdnImage, avatarSize = avatarSize.value, + legendaryCustomization = state.profileLegendaryCustomization, ) } From b05483281bd3125df68b0ea80a43fcb3b0d0c9aa Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 16:19:56 +0100 Subject: [PATCH 19/37] Use UniversalAvatarThumbnail and add custom badge to ChangePrimalNameScreen --- .../manage/nameChange/ConfirmNameChangeStage.kt | 12 ++++++++++-- .../nameChange/PremiumChangePrimalNameContract.kt | 2 ++ .../nameChange/PremiumChangePrimalNameScreen.kt | 1 + .../nameChange/PremiumChangePrimalNameViewModel.kt | 2 ++ 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/ConfirmNameChangeStage.kt b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/ConfirmNameChangeStage.kt index 761da5cb8..de8bc843f 100644 --- a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/ConfirmNameChangeStage.kt +++ b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/ConfirmNameChangeStage.kt @@ -15,8 +15,9 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.NostrUserText +import net.primal.android.core.compose.UniversalAvatarThumbnail +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.ui.PremiumPrimalNameTable import net.primal.android.theme.AppTheme @@ -25,6 +26,7 @@ fun ConfirmNameChangeStage( modifier: Modifier = Modifier, primalName: String, profileAvatarCdnImage: CdnImage?, + profileLegendaryCustomization: LegendaryCustomization?, contentPadding: PaddingValues, ) { Column( @@ -34,15 +36,21 @@ fun ConfirmNameChangeStage( ) { Spacer(modifier = Modifier.height(48.dp)) - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = profileAvatarCdnImage, avatarSize = 80.dp, + legendaryCustomization = profileLegendaryCustomization, ) NostrUserText( displayName = primalName, internetIdentifier = "$primalName@primal.net", internetIdentifierBadgeSize = 24.dp, fontSize = 20.sp, + customBadgeStyle = if (profileLegendaryCustomization?.customBadge == true) { + profileLegendaryCustomization.legendaryStyle + } else { + null + }, ) Text( modifier = Modifier.padding(horizontal = 12.dp), diff --git a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameContract.kt b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameContract.kt index 5a5ae23fb..78a853777 100644 --- a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameContract.kt +++ b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameContract.kt @@ -1,12 +1,14 @@ package net.primal.android.premium.manage.nameChange import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization interface PremiumChangePrimalNameContract { data class UiState( val stage: ChangePrimalNameStage = ChangePrimalNameStage.PickNew, val primalName: String? = null, val profileAvatarCdnImage: CdnImage? = null, + val profileLegendaryCustomization: LegendaryCustomization? = null, val changingName: Boolean = false, val error: NameChangeError? = null, ) diff --git a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameScreen.kt b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameScreen.kt index 4212ac6ad..527b6c855 100644 --- a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameScreen.kt +++ b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameScreen.kt @@ -166,6 +166,7 @@ private fun ChangePremiumNameConfirmationStage( contentPadding = paddingValues, primalName = state.primalName, profileAvatarCdnImage = state.profileAvatarCdnImage, + profileLegendaryCustomization = state.profileLegendaryCustomization, ) } } diff --git a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameViewModel.kt b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameViewModel.kt index 1f5f1f162..b2b013373 100644 --- a/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/premium/manage/nameChange/PremiumChangePrimalNameViewModel.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import net.primal.android.networking.sockets.errors.WssException +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.premium.manage.nameChange.PremiumChangePrimalNameContract.ChangePrimalNameStage import net.primal.android.premium.manage.nameChange.PremiumChangePrimalNameContract.SideEffect import net.primal.android.premium.manage.nameChange.PremiumChangePrimalNameContract.UiEvent @@ -91,6 +92,7 @@ class PremiumChangePrimalNameViewModel @Inject constructor( copy( primalName = it.premiumMembership?.premiumName, profileAvatarCdnImage = it.avatarCdnImage, + profileLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } From fd4e6d83f227d98240351dbea4ef15225104cdc6 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 16:20:15 +0100 Subject: [PATCH 20/37] UseUniversalAvatarThumbnail on ZappersAvatarThumbnailRow --- .../core/compose/zaps/ZappersAvatarThumbnailRow.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt index 3028b139c..31da5791d 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt @@ -15,7 +15,10 @@ import androidx.compose.ui.unit.times import java.util.* import kotlinx.datetime.Clock import net.primal.android.core.compose.AvatarThumbnail +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.preview.PrimalPreview +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme @@ -30,13 +33,14 @@ fun ZappersAvatarThumbnailRow(zaps: List, onClick: (() -> Unit) repeat(times = zaps.size) { index -> val zap = reversed[index] key(zap.id) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.padding(end = index.times(18.dp)), avatarSize = 24.dp, avatarCdnImage = zap.zapperAvatarCdnImage, hasBorder = true, borderSize = 1.dp, - borderColor = AppTheme.colorScheme.surface, + fallbackBorderColor = AppTheme.colorScheme.surface, + legendaryCustomization = zap.zapperLegendaryCustomization, onClick = onClick, ) } @@ -62,6 +66,10 @@ private fun PreviewZappersAvatarThumbnailRow() { zapperHandle = "zapper", zapperId = "zapperId", zapperName = "Zapper", + zapperLegendaryCustomization = LegendaryCustomization( + avatarGlow = true, + legendaryStyle = LegendaryStyle.SUN_FIRE, + ) ), EventZapUiModel( id = UUID.randomUUID().toString(), From 3af2c48064e37b73d93b53bb1be8be7e272778fa Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 16:59:09 +0100 Subject: [PATCH 21/37] Use Universal AvatarThumbnail on AvatarThumbnailsRow --- .../android/core/compose/AvatarThumbnailsRow.kt | 7 +++++-- .../explore/asearch/AdvancedSearchScreen.kt | 1 + .../android/feeds/dvm/ui/DvmFeedListItem.kt | 1 + .../primal/android/feeds/dvm/ui/DvmFeedUi.kt | 2 ++ .../feeds/repository/DvmFeedListHandler.kt | 11 ++++++++--- .../android/notes/feed/list/NoteFeedList.kt | 1 + .../notes/feed/list/NoteFeedViewModel.kt | 17 +++++++++++++---- .../notes/feed/model/FeedPostsSyncStats.kt | 2 ++ .../list/NotificationsViewModel.kt | 1 + .../list/ui/NotificationListItem.kt | 8 ++++++++ .../notifications/list/ui/NotificationUi.kt | 2 ++ .../profile/details/ui/ProfileDetailsHeader.kt | 1 + 12 files changed, 45 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt index 7e8872ccb..bb9b3011f 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt @@ -19,12 +19,14 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.theme.AppTheme @Composable fun AvatarThumbnailsRow( modifier: Modifier = Modifier, avatarCdnImages: List, + avatarLegendaryCustomizations: List, avatarOverlap: AvatarOverlap = AvatarOverlap.End, hasAvatarBorder: Boolean = true, avatarBorderSize: Dp = 2.dp, @@ -70,11 +72,12 @@ fun AvatarThumbnailsRow( } AvatarSpacer(width = (layoutIndex * avatarVisibleWidth.value).dp) { - AvatarThumbnail( + UniversalAvatarThumbnail( modifier = Modifier.size(avatarSize), avatarCdnImage = imageCdnImage, hasBorder = hasAvatarBorder, - borderColor = avatarBorderColor, + legendaryCustomization = runCatching { avatarLegendaryCustomizations[layoutIndex] }.getOrNull(), + fallbackBorderColor = avatarBorderColor, borderSize = avatarBorderSize, onClick = { onClick(layoutIndex) }, ) diff --git a/app/src/main/kotlin/net/primal/android/explore/asearch/AdvancedSearchScreen.kt b/app/src/main/kotlin/net/primal/android/explore/asearch/AdvancedSearchScreen.kt index b1a3cec7c..d9747532c 100644 --- a/app/src/main/kotlin/net/primal/android/explore/asearch/AdvancedSearchScreen.kt +++ b/app/src/main/kotlin/net/primal/android/explore/asearch/AdvancedSearchScreen.kt @@ -437,6 +437,7 @@ private fun MultipleUserPickerOptionListItem( } else { AvatarThumbnailsRow( avatarCdnImages = selectedUsers.map { it.avatarCdnImage }, + avatarLegendaryCustomizations = selectedUsers.map { it.legendaryCustomization }, onClick = {}, avatarOverlap = AvatarOverlap.None, maxAvatarsToShow = 4, diff --git a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt index c75fd031d..96774fca0 100644 --- a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt +++ b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedListItem.kt @@ -247,6 +247,7 @@ private fun DvmFeedListItem( height = profileAvatarSize, ), avatarCdnImages = dvmFeed.actionUserAvatars, + avatarLegendaryCustomizations = dvmFeed.actionUserLegendaryCustomizations, onClick = {}, maxAvatarsToShow = MaxAvatarsToShow, displayAvatarOverflowIndicator = false, diff --git a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedUi.kt b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedUi.kt index 9d3a3cb76..10b0be374 100644 --- a/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedUi.kt +++ b/app/src/main/kotlin/net/primal/android/feeds/dvm/ui/DvmFeedUi.kt @@ -2,6 +2,7 @@ package net.primal.android.feeds.dvm.ui import net.primal.android.attachments.domain.CdnImage import net.primal.android.feeds.domain.DvmFeed +import net.primal.android.premium.legend.LegendaryCustomization data class DvmFeedUi( val data: DvmFeed, @@ -10,4 +11,5 @@ data class DvmFeedUi( val totalLikes: Long? = null, val totalSatsZapped: Long? = null, val actionUserAvatars: List = emptyList(), + val actionUserLegendaryCustomizations: List = emptyList(), ) diff --git a/app/src/main/kotlin/net/primal/android/feeds/repository/DvmFeedListHandler.kt b/app/src/main/kotlin/net/primal/android/feeds/repository/DvmFeedListHandler.kt index 2cfdfc2bb..072e2b1f1 100644 --- a/app/src/main/kotlin/net/primal/android/feeds/repository/DvmFeedListHandler.kt +++ b/app/src/main/kotlin/net/primal/android/feeds/repository/DvmFeedListHandler.kt @@ -8,6 +8,7 @@ import net.primal.android.core.ext.asMapByKey import net.primal.android.feeds.domain.FeedSpecKind import net.primal.android.feeds.dvm.ui.DvmFeedUi import net.primal.android.networking.primal.retryNetworkCall +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.repository.ProfileRepository import net.primal.android.stats.repository.EventRepository @@ -33,15 +34,19 @@ class DvmFeedListHandler @Inject constructor( .asMapByKey { it.eventId } var feeds = dvmFeeds.map { dvmFeed -> + val actionUsers = profileRepository.findProfilesData(profileIds = dvmFeed.actionUserIds) + val avatarLegendaryCustomizationPair = actionUsers + .filter { it.avatarCdnImage != null } + .map { Pair(it.avatarCdnImage, it.primalLegendProfile?.asLegendaryCustomization()) } + DvmFeedUi( data = dvmFeed, userLiked = userStats[dvmFeed.eventId]?.liked, userZapped = userStats[dvmFeed.eventId]?.zapped, totalLikes = stats[dvmFeed.eventId]?.likes, totalSatsZapped = stats[dvmFeed.eventId]?.satsZapped, - actionUserAvatars = profileRepository - .findProfilesData(profileIds = dvmFeed.actionUserIds) - .mapNotNull { it.avatarCdnImage }, + actionUserAvatars = avatarLegendaryCustomizationPair.mapNotNull { it.first }, + actionUserLegendaryCustomizations = avatarLegendaryCustomizationPair.map { it.second }, ) } update(feeds) diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedList.kt b/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedList.kt index 7452eb53f..ff6aff7e7 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedList.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedList.kt @@ -329,6 +329,7 @@ private fun NewPostsButton(syncStats: FeedPostsSyncStats, onClick: () -> Unit) { AvatarThumbnailsRow( modifier = Modifier.padding(start = 6.dp), avatarCdnImages = syncStats.latestAvatarCdnImages, + avatarLegendaryCustomizations = syncStats.latestLegendaryCustomizations, onClick = { onClick() }, ) diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedViewModel.kt b/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedViewModel.kt index 5820e6069..7f0756aca 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/list/NoteFeedViewModel.kt @@ -39,6 +39,7 @@ import net.primal.android.notes.feed.list.NoteFeedContract.UiState import net.primal.android.notes.feed.model.FeedPostsSyncStats import net.primal.android.notes.feed.model.asFeedPostUi import net.primal.android.notes.repository.FeedRepository +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import timber.log.Timber @@ -182,15 +183,23 @@ class NoteFeedViewModel @AssistedInject constructor( primalUserNames = primalUserNames, primalLegendProfiles = primalLegendProfiles, ) - val avatarCdnImages = allNotes - .mapNotNull { note -> profiles.find { it.ownerId == note.pubKey }?.avatarCdnImage } + val avatarCdnImagesAndLegendaryCustomizations = allNotes + .mapNotNull { note -> profiles.find { it.ownerId == note.pubKey } } + .filter { profileData -> profileData.avatarCdnImage != null } + .map { profileData -> + Pair( + profileData.avatarCdnImage, + profileData.primalLegendProfile?.asLegendaryCustomization(), + ) + } .distinct() - val limit = if (avatarCdnImages.count() <= MAX_AVATARS) avatarCdnImages.count() else MAX_AVATARS + val limit = avatarCdnImagesAndLegendaryCustomizations.count().coerceAtMost(MAX_AVATARS) val newSyncStats = FeedPostsSyncStats( latestNoteIds = allNotes.map { it.id }, - latestAvatarCdnImages = avatarCdnImages.take(limit), + latestAvatarCdnImages = avatarCdnImagesAndLegendaryCustomizations.mapNotNull { it.first }.take(limit), + latestLegendaryCustomizations = avatarCdnImagesAndLegendaryCustomizations.map { it.second }.take(limit), ) if (newSyncStats.isTopVisibleNoteTheLatestNote()) { diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostsSyncStats.kt b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostsSyncStats.kt index 005ce9105..5bfd3018c 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostsSyncStats.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostsSyncStats.kt @@ -1,8 +1,10 @@ package net.primal.android.notes.feed.model import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization data class FeedPostsSyncStats( val latestNoteIds: List = emptyList(), val latestAvatarCdnImages: List = emptyList(), + val latestLegendaryCustomizations: List = emptyList(), ) diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt index 98542a7cf..5330cb142 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt @@ -154,6 +154,7 @@ class NotificationsViewModel @Inject constructor( ?: this.data.actionUserId?.asEllipsizedNpub(), actionUserInternetIdentifier = this.actionByUser?.internetIdentifier, actionUserAvatarCdnImage = this.actionByUser?.avatarCdnImage, + actionUserLegendaryCustomization = this.actionByUser?.primalLegendProfile?.asLegendaryCustomization(), actionUserSatsZapped = this.data.satsZapped, actionPost = this.extractFeedPostUi(), ) diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/ui/NotificationListItem.kt b/app/src/main/kotlin/net/primal/android/notifications/list/ui/NotificationListItem.kt index 139600fb2..26436deaa 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/ui/NotificationListItem.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/ui/NotificationListItem.kt @@ -48,6 +48,8 @@ import net.primal.android.notes.feed.note.ui.FeedNoteActionsRow import net.primal.android.notes.feed.note.ui.NoteContent import net.primal.android.notes.feed.note.ui.events.NoteCallbacks import net.primal.android.notifications.domain.NotificationType +import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme.Sunset @@ -331,6 +333,7 @@ private fun NotificationsGroupHeader( AvatarThumbnailsRow( modifier = Modifier.fillMaxWidth(), avatarCdnImages = notifications.map { it.actionUserAvatarCdnImage }, + avatarLegendaryCustomizations = notifications.map { it.actionUserLegendaryCustomization }, avatarOverlap = AvatarOverlap.None, hasAvatarBorder = false, onClick = { index -> @@ -385,6 +388,7 @@ private fun HeaderContent( if (showAvatars) { AvatarThumbnailsRow( avatarCdnImages = notifications.map { it.actionUserAvatarCdnImage }, + avatarLegendaryCustomizations = notifications.map { it.actionUserLegendaryCustomization }, avatarOverlap = AvatarOverlap.None, hasAvatarBorder = false, onClick = { index -> @@ -559,6 +563,10 @@ private class NotificationsParameterProvider : PreviewParameterProvider Date: Fri, 29 Nov 2024 17:01:12 +0100 Subject: [PATCH 22/37] Auto-format code --- .../net/primal/android/articles/reads/ReadsScreen.kt | 1 - .../primal/android/articles/reads/ReadsScreenContract.kt | 1 - .../net/primal/android/articles/reads/ReadsViewModel.kt | 1 - .../kotlin/net/primal/android/auth/login/LoginScreen.kt | 1 - .../android/core/compose/AvatarThumbnailListItemImage.kt | 1 - .../net/primal/android/core/compose/PrimalTopAppBar.kt | 2 -- .../android/core/compose/profile/model/ProfileDetailsUi.kt | 1 - .../android/core/compose/zaps/ArticleTopZapsSection.kt | 2 +- .../android/core/compose/zaps/ZappersAvatarThumbnailRow.kt | 3 +-- .../net/primal/android/editor/NoteEditorViewModel.kt | 2 +- .../net/primal/android/editor/ui/NoteEditorScreen.kt | 1 - .../android/explore/search/ui/UserProfileListItem.kt | 5 ++--- .../kotlin/net/primal/android/messages/chat/ChatScreen.kt | 1 - .../net/primal/android/notes/home/HomeFeedContract.kt | 1 - .../kotlin/net/primal/android/notes/home/HomeFeedScreen.kt | 1 - .../net/primal/android/notes/home/HomeFeedViewModel.kt | 1 - .../android/notifications/list/NotificationsContract.kt | 1 - .../android/notifications/list/NotificationsViewModel.kt | 1 - .../android/profile/details/ui/ProfileTopCoverBar.kt | 4 +++- .../primal/android/profile/qr/ui/ProfileQrCodeViewer.kt | 1 - .../net/primal/android/settings/keys/KeysSettingsScreen.kt | 7 +++++-- .../android/settings/muted/list/MutedSettingsScreen.kt | 1 - .../main/kotlin/net/primal/android/stats/db/EventZap.kt | 1 - .../android/stats/reactions/ui/ReactionsZapsLazyColumn.kt | 1 - .../net/primal/android/user/accounts/UserAccountFetcher.kt | 1 - .../kotlin/net/primal/android/user/domain/UserAccount.kt | 2 -- .../android/wallet/dashboard/WalletDashboardContract.kt | 1 - .../android/wallet/dashboard/WalletDashboardViewModel.kt | 1 - .../wallet/transactions/list/TransactionListItem.kt | 1 - .../transactions/send/create/ui/TransactionEditor.kt | 1 - 30 files changed, 13 insertions(+), 36 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt index b3d4c1f13..9266654a6 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreen.kt @@ -54,7 +54,6 @@ import net.primal.android.feeds.domain.FeedSpecKind import net.primal.android.feeds.list.FeedsBottomSheet import net.primal.android.feeds.list.ui.model.FeedUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle @Composable fun ReadsScreen( diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt index 9b3a56790..4d4ed06a0 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsScreenContract.kt @@ -3,7 +3,6 @@ package net.primal.android.articles.reads import net.primal.android.attachments.domain.CdnImage import net.primal.android.feeds.list.ui.model.FeedUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges interface ReadsScreenContract { diff --git a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt index d0e7a32d7..cee0d03f5 100644 --- a/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/articles/reads/ReadsViewModel.kt @@ -16,7 +16,6 @@ import net.primal.android.feeds.list.ui.model.asFeedUi import net.primal.android.feeds.repository.FeedsRepository import net.primal.android.networking.primal.retryNetworkCall import net.primal.android.networking.sockets.errors.WssException -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager diff --git a/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt b/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt index b6acabbd8..9d690c673 100644 --- a/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt +++ b/app/src/main/kotlin/net/primal/android/auth/login/LoginScreen.kt @@ -54,7 +54,6 @@ import net.primal.android.auth.compose.DefaultOnboardingAvatar import net.primal.android.auth.compose.OnboardingButton import net.primal.android.auth.compose.defaultOnboardingAvatarBackground import net.primal.android.core.compose.AppBarIcon -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.UiDensityMode import net.primal.android.core.compose.UniversalAvatarThumbnail diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index 9484d30da..18577c240 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -28,7 +28,6 @@ import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.AvatarDefault import net.primal.android.core.images.AvatarCoilImageLoader import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @Composable diff --git a/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt b/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt index a27cb40b5..53e41b73e 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/PrimalTopAppBar.kt @@ -27,7 +27,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalSoftwareKeyboardController @@ -36,7 +35,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @OptIn(ExperimentalFoundationApi::class) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt index beb8b9e53..2532665d7 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/profile/model/ProfileDetailsUi.kt @@ -4,7 +4,6 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.core.utils.usernameUiFriendly import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.db.ProfileData diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt index 11dd2c691..bc32f079f 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ArticleTopZapsSection.kt @@ -210,7 +210,7 @@ private fun PreviewArticleTopZapsSection() { avatarGlow = true, customBadge = true, legendaryStyle = LegendaryStyle.SUN_FIRE, - ) + ), ), EventZapUiModel( id = "id", diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt index 31da5791d..33cc7cdff 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt @@ -14,7 +14,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.times import java.util.* import kotlinx.datetime.Clock -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.premium.legend.LegendaryCustomization @@ -69,7 +68,7 @@ private fun PreviewZappersAvatarThumbnailRow() { zapperLegendaryCustomization = LegendaryCustomization( avatarGlow = true, legendaryStyle = LegendaryStyle.SUN_FIRE, - ) + ), ), EventZapUiModel( id = UUID.randomUUID().toString(), diff --git a/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt b/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt index daf59960f..ea93b9854 100644 --- a/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/editor/NoteEditorViewModel.kt @@ -171,7 +171,7 @@ class NoteEditorViewModel @AssistedInject constructor( copy( activeAccountAvatarCdnImage = it.data.avatarCdnImage, activeAccountLegendaryCustomization = - it.data.primalLegendProfile?.asLegendaryCustomization(), + it.data.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt index 4b098b8bb..0a22b0a81 100644 --- a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt +++ b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt @@ -62,7 +62,6 @@ import androidx.compose.ui.unit.sp import java.util.* import net.primal.android.R import net.primal.android.articles.feed.ui.FeedArticleListItem -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ImportPhotosIconButton import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.PrimalDivider diff --git a/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt b/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt index 67420a53f..3d3a1c270 100644 --- a/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt +++ b/app/src/main/kotlin/net/primal/android/explore/search/ui/UserProfileListItem.kt @@ -23,7 +23,6 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.FollowUnfollowButton import net.primal.android.core.compose.preview.PrimalPreview @@ -127,7 +126,7 @@ fun PreviewLegendaryUserProfileListItemWithFollow() { avatarGlow = true, customBadge = true, legendaryStyle = LegendaryStyle.GOLD, - ) + ), ), followUnfollowVisibility = FollowUnfollowVisibility.Visible, isFollowed = false, @@ -152,7 +151,7 @@ fun PreviewLegendaryUserProfileListItemWithUnfollow() { avatarGlow = true, customBadge = true, legendaryStyle = LegendaryStyle.SUN_FIRE, - ) + ), ), followUnfollowVisibility = FollowUnfollowVisibility.Visible, isFollowed = true, diff --git a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt index c8808f3bf..06b87b1c5 100644 --- a/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt +++ b/app/src/main/kotlin/net/primal/android/messages/chat/ChatScreen.kt @@ -54,7 +54,6 @@ import java.time.Instant import kotlin.time.Duration.Companion.minutes import net.primal.android.R import net.primal.android.core.compose.AppBarIcon -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.PrimalDivider diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt index f1f5cf00b..2978816e2 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedContract.kt @@ -3,7 +3,6 @@ package net.primal.android.notes.home import net.primal.android.attachments.domain.CdnImage import net.primal.android.feeds.list.ui.model.FeedUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges interface HomeFeedContract { diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt index 9ce14cb10..eaae05a84 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedScreen.kt @@ -68,7 +68,6 @@ import net.primal.android.notes.feed.list.NoteFeedList import net.primal.android.notes.feed.note.ui.events.NoteCallbacks import net.primal.android.notes.home.HomeFeedContract.UiEvent import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @Composable diff --git a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt index 07eebad8b..4404dd9e0 100644 --- a/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notes/home/HomeFeedViewModel.kt @@ -20,7 +20,6 @@ import net.primal.android.networking.primal.retryNetworkCall import net.primal.android.networking.sockets.errors.WssException import net.primal.android.notes.home.HomeFeedContract.UiEvent import net.primal.android.notes.home.HomeFeedContract.UiState -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt index 6b288f203..aae820747 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsContract.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.Flow import net.primal.android.attachments.domain.CdnImage import net.primal.android.notifications.list.ui.NotificationUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges interface NotificationsContract { diff --git a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt index 5330cb142..5608eb4bd 100644 --- a/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/notifications/list/NotificationsViewModel.kt @@ -30,7 +30,6 @@ import net.primal.android.notifications.list.NotificationsContract.UiEvent.Notif import net.primal.android.notifications.list.NotificationsContract.UiState import net.primal.android.notifications.list.ui.NotificationUi import net.primal.android.notifications.repository.NotificationRepository -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager diff --git a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt index fbb2231f6..8b187fdf3 100644 --- a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt +++ b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt @@ -130,7 +130,9 @@ fun ProfileTopCoverBar( onClick = { state.profileDetails?.avatarCdnImage?.sourceUrl?.let { onMediaItemClick(it) } }, avatarCdnImage = state.profileDetails?.avatarCdnImage, hasBorder = true, - borderBrush = if (state.profileDetails?.legendaryCustomization?.legendaryStyle != null && state.profileDetails.legendaryCustomization.avatarGlow) { + borderBrush = if (state.profileDetails?.legendaryCustomization?.legendaryStyle != null && + state.profileDetails.legendaryCustomization.avatarGlow + ) { when (state.profileDetails.legendaryCustomization.legendaryStyle) { LegendaryStyle.NO_CUSTOMIZATION -> Brush.linearGradient( listOf( diff --git a/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt b/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt index 7c78d4b4c..542b36748 100644 --- a/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt +++ b/app/src/main/kotlin/net/primal/android/profile/qr/ui/ProfileQrCodeViewer.kt @@ -61,7 +61,6 @@ import com.wajahatkarim.flippable.Flippable import com.wajahatkarim.flippable.FlippableState import com.wajahatkarim.flippable.rememberFlipController import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.DefaultAvatarThumbnailPlaceholderListItemImage import net.primal.android.core.compose.PrimalLoadingSpinner import net.primal.android.core.compose.UniversalAvatarThumbnail diff --git a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt index eb83ca1b2..7c4505659 100644 --- a/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/settings/keys/KeysSettingsScreen.kt @@ -39,7 +39,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopAppBar @@ -108,7 +107,11 @@ fun KeysSettingsScreen(state: KeysSettingsContract.UiState, onClose: () -> Unit) } @Composable -fun PublicKeySection(npub: String, avatarCdnImage: CdnImage?, legendaryCustomization: LegendaryCustomization?) { +fun PublicKeySection( + npub: String, + avatarCdnImage: CdnImage?, + legendaryCustomization: LegendaryCustomization?, +) { val context = LocalContext.current Text( diff --git a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt index 7ff95c87f..f5c793f75 100644 --- a/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/settings/muted/list/MutedSettingsScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider diff --git a/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt b/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt index fa08f0923..ffff39cb4 100644 --- a/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt +++ b/app/src/main/kotlin/net/primal/android/stats/db/EventZap.kt @@ -2,7 +2,6 @@ package net.primal.android.stats.db import androidx.room.Entity import net.primal.android.attachments.domain.CdnImage -import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.profile.domain.PrimalLegendProfile @Entity( diff --git a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt index 2862aabf5..50efa1960 100644 --- a/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt +++ b/app/src/main/kotlin/net/primal/android/stats/reactions/ui/ReactionsZapsLazyColumn.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.unit.dp import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.itemKey import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.ListNoContent import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider diff --git a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt index 569271ed3..ca688523a 100644 --- a/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt +++ b/app/src/main/kotlin/net/primal/android/user/accounts/UserAccountFetcher.kt @@ -13,7 +13,6 @@ import net.primal.android.nostr.ext.asProfileStatsPO import net.primal.android.nostr.ext.flatMapNotNullAsCdnResource import net.primal.android.nostr.ext.parseAndMapPrimalLegendProfiles import net.primal.android.nostr.ext.parseAndMapPrimalUserNames -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.api.UsersApi import net.primal.android.user.domain.UserAccount import net.primal.android.user.domain.asUserAccountFromFollowListEvent diff --git a/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt b/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt index b98630972..6eee88e91 100644 --- a/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt +++ b/app/src/main/kotlin/net/primal/android/user/domain/UserAccount.kt @@ -5,8 +5,6 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.asEllipsizedNpub import net.primal.android.nostr.model.primal.content.ContentAppSettings import net.primal.android.premium.domain.PremiumMembership -import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.profile.domain.PrimalLegendProfile import net.primal.android.wallet.domain.WalletSettings import net.primal.android.wallet.domain.WalletState diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt index 662bad01c..5b1e065d5 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardContract.kt @@ -5,7 +5,6 @@ import java.math.BigDecimal import kotlinx.coroutines.flow.Flow import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges import net.primal.android.user.domain.PrimalWallet import net.primal.android.user.domain.WalletPreference diff --git a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt index 7efeecb64..487b4aab3 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/dashboard/WalletDashboardViewModel.kt @@ -17,7 +17,6 @@ import kotlinx.coroutines.launch import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.networking.sockets.errors.NostrNoticeException import net.primal.android.networking.sockets.errors.WssException -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.domain.WalletPreference diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt index ee6f9029d..f53f16b7b 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/list/TransactionListItem.kt @@ -45,7 +45,6 @@ import java.time.format.DateTimeFormatter import kotlin.time.Duration.Companion.seconds import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.IconText import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.WrappedContentWithSuffix diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt index 76c565874..d89b99034 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/send/create/ui/TransactionEditor.kt @@ -52,7 +52,6 @@ import androidx.compose.ui.unit.sp import java.math.BigDecimal import java.text.NumberFormat import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.PrimalDefaults import net.primal.android.core.compose.PrimalLoadingSpinner import net.primal.android.core.compose.UiDensityMode From a0ecca99689b81958bc16e4f4bf0c22a2ea2a7be Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 17:14:40 +0100 Subject: [PATCH 23/37] Use UniversalAvatarThumbnail on ExploreHomeTopBar and FeedNoteCard --- .../explore/home/ExploreHomeContract.kt | 3 +- .../android/explore/home/ExploreHomeScreen.kt | 14 +++---- .../explore/home/ExploreHomeViewModel.kt | 3 +- .../android/notes/feed/model/FeedPostUi.kt | 10 ++--- .../android/notes/feed/note/FeedNoteCard.kt | 13 ++---- .../android/notes/feed/note/ui/NoteHeader.kt | 20 +++++----- .../notes/feed/note/ui/ReferencedNoteCard.kt | 1 + .../articles/details/ArticleDetailsScreen.kt | 4 +- .../articles/details/ui/ArticleAuthorRow.kt | 40 ++++++++++++++----- .../articles/details/ui/ArticleDetailsUi.kt | 10 ++--- 10 files changed, 64 insertions(+), 54 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt index a75fbd7eb..fee4efb6a 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt @@ -1,13 +1,14 @@ package net.primal.android.explore.home import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges interface ExploreHomeContract { data class UiState( val activeAccountAvatarCdnImage: CdnImage? = null, - val activeAccountLegendaryStyle: LegendaryStyle? = null, + val activeAccountLegendaryCustomization: LegendaryCustomization? = null, val activeAccountPubkey: String? = null, val badges: Badges = Badges(), ) diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt index b5f9e6de6..4ed918f24 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt @@ -57,6 +57,7 @@ import net.primal.android.core.compose.IconText import net.primal.android.core.compose.InvisibleAppBarIcon import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalTopLevelDestination +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.AdvancedSearch import net.primal.android.core.compose.icons.primaliconpack.AvatarDefault @@ -79,6 +80,7 @@ import net.primal.android.explore.home.zaps.ExploreZaps import net.primal.android.feeds.domain.exploreMediaFeedSpec import net.primal.android.notes.feed.grid.MediaFeedGrid import net.primal.android.notes.feed.note.ui.events.NoteCallbacks +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme @@ -143,7 +145,7 @@ private fun ExploreHomeScreen( pagerState = pagerState, actionIcon = PrimalIcons.AdvancedSearch, avatarCdnImage = state.activeAccountAvatarCdnImage, - avatarLegendaryStyle = state.activeAccountLegendaryStyle, + avatarLegendaryCustomization = state.activeAccountLegendaryCustomization, navigationIcon = PrimalIcons.AvatarDefault, onNavigationIconClick = { uiScope.launch { drawerState.open() } @@ -233,7 +235,7 @@ fun ExploreTopAppBar( onNavigationIconClick: () -> Unit, onActionIconClick: () -> Unit, onSearchClick: () -> Unit, - avatarLegendaryStyle: LegendaryStyle? = null, + avatarLegendaryCustomization: LegendaryCustomization? = null, navigationIconTintColor: Color = LocalContentColor.current, scrollBehavior: TopAppBarScrollBehavior? = null, ) { @@ -257,15 +259,11 @@ fun ExploreTopAppBar( .padding(horizontal = 8.dp) .clip(CircleShape), ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarCdnImage = avatarCdnImage, modifier = Modifier.size(32.dp), onClick = onNavigationIconClick, - hasBorder = avatarLegendaryStyle != null, - borderBrush = avatarLegendaryStyle?.brush - ?: Brush.linearGradient( - listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), - ), + legendaryCustomization = avatarLegendaryCustomization, ) } } else if (navigationIcon != null) { diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt index 52a3479dd..4319f592b 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt @@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch import net.primal.android.explore.home.ExploreHomeContract.UiState import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager @@ -35,7 +36,7 @@ class ExploreHomeViewModel @Inject constructor( copy( activeAccountPubkey = it.pubkey, activeAccountAvatarCdnImage = it.avatarCdnImage, - activeAccountLegendaryStyle = LegendaryStyle.valueById(it.primalLegendProfile?.styleId), + activeAccountLegendaryCustomization = it.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt index 0bda3cbf3..6dd36ca21 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt @@ -9,7 +9,9 @@ import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.core.utils.usernameUiFriendly import net.primal.android.notes.db.FeedPost +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.stats.ui.asEventZapUiModel @@ -33,9 +35,7 @@ data class FeedPostUi( val replyToAuthorHandle: String? = null, val isBookmarked: Boolean = false, val eventZaps: List = emptyList(), - val authorLegendAvatarGlow: Boolean = false, - val authorLegendCustomBadge: Boolean = false, - val authorLegendaryStyle: LegendaryStyle? = null, + val authorLegendaryCustomization: LegendaryCustomization? = null, ) fun FeedPost.asFeedPostUi(): FeedPostUi { @@ -61,8 +61,6 @@ fun FeedPost.asFeedPostUi(): FeedPostUi { eventZaps = this.eventZaps .map { it.asEventZapUiModel() } .sortedWith(EventZapUiModel.DefaultComparator), - authorLegendAvatarGlow = this.author?.primalLegendProfile?.avatarGlow == true, - authorLegendCustomBadge = this.author?.primalLegendProfile?.customBadge == true, - authorLegendaryStyle = LegendaryStyle.valueById(this.author?.primalLegendProfile?.styleId), + authorLegendaryCustomization = this.author?.primalLegendProfile?.asLegendaryCustomization(), ) } diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt index 194c3a601..44366351a 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt @@ -46,6 +46,7 @@ import net.primal.android.LocalContentDisplaySettings import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.PrimalDivider +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.errors.UiError import net.primal.android.core.ext.openUriSafely @@ -413,20 +414,16 @@ private fun FeedNote( Row { if (!fullWidthContent) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( modifier = Modifier.padding(avatarPaddingValues), avatarSize = avatarSizeDp, avatarCdnImage = data.authorAvatarCdnImage, + legendaryCustomization = data.authorLegendaryCustomization, onClick = if (noteCallbacks.onProfileClick != null) { { noteCallbacks.onProfileClick.invoke(data.authorId) } } else { null }, - hasBorder = data.authorLegendAvatarGlow && data.authorLegendaryStyle != null, - borderBrush = when { - data.authorLegendaryStyle != null -> data.authorLegendaryStyle.brush - else -> Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, ) } @@ -445,9 +442,7 @@ private fun FeedNote( authorDisplayName = data.authorName, authorAvatarCdnImage = data.authorAvatarCdnImage, authorInternetIdentifier = data.authorInternetIdentifier, - authorLegendAvatarGlow = data.authorLegendAvatarGlow, - authorLegendCustomBadge = data.authorLegendCustomBadge, - authorLegendaryStyle = data.authorLegendaryStyle, + authorLegendaryCustomization = data.authorLegendaryCustomization, replyToAuthor = if (showReplyTo) data.replyToAuthorHandle else null, onAuthorAvatarClick = if (noteCallbacks.onProfileClick != null) { { noteCallbacks.onProfileClick.invoke(data.authorId) } diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt index 6f1a52054..ae6d2ec6c 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt @@ -30,9 +30,11 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.ReplyingToText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.WrappedContentWithSuffix import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.utils.formatNip05Identifier +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme import net.primal.android.theme.PrimalTheme @@ -49,9 +51,7 @@ fun FeedNoteHeader( authorAvatarVisible: Boolean = true, authorAvatarCdnImage: CdnImage? = null, authorInternetIdentifier: String? = null, - authorLegendAvatarGlow: Boolean = false, - authorLegendCustomBadge: Boolean = false, - authorLegendaryStyle: LegendaryStyle? = null, + authorLegendaryCustomization: LegendaryCustomization? = null, replyToAuthor: String? = null, label: String? = authorInternetIdentifier, labelStyle: TextStyle? = null, @@ -68,15 +68,11 @@ fun FeedNoteHeader( verticalAlignment = Alignment.CenterVertically, ) { if (authorAvatarVisible) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarCdnImage = authorAvatarCdnImage, avatarSize = authorAvatarSize, onClick = onAuthorAvatarClick, - hasBorder = authorLegendAvatarGlow && authorLegendaryStyle != null, - borderBrush = when { - authorLegendaryStyle != null -> authorLegendaryStyle.brush - else -> Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, + legendaryCustomization = authorLegendaryCustomization, ) } @@ -107,7 +103,11 @@ fun FeedNoteHeader( style = topRowTextStyle, internetIdentifierBadgeSize = topRowTextStyle.fontSize.value.dp, overflow = TextOverflow.Ellipsis, - customBadgeStyle = if (authorLegendCustomBadge) authorLegendaryStyle else null, + customBadgeStyle = if (authorLegendaryCustomization?.customBadge == true) { + authorLegendaryCustomization.legendaryStyle + } else { + null + }, ) }, suffixFixedContent = { diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/ReferencedNoteCard.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/ReferencedNoteCard.kt index e6aa52f0c..7e22ba00c 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/ReferencedNoteCard.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/ReferencedNoteCard.kt @@ -55,6 +55,7 @@ fun ReferencedNoteCard( singleLine = true, authorAvatarSize = 30.dp, authorAvatarCdnImage = data.authorAvatarCdnImage, + authorLegendaryCustomization = data.authorLegendaryCustomization, authorInternetIdentifier = data.authorInternetIdentifier, onAuthorAvatarClick = { noteCallbacks.onProfileClick?.invoke(data.authorId) }, ) diff --git a/app/src/main/kotlin/net/primal/android/thread/articles/details/ArticleDetailsScreen.kt b/app/src/main/kotlin/net/primal/android/thread/articles/details/ArticleDetailsScreen.kt index 0a1cb1153..94297615a 100644 --- a/app/src/main/kotlin/net/primal/android/thread/articles/details/ArticleDetailsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/thread/articles/details/ArticleDetailsScreen.kt @@ -447,9 +447,7 @@ private fun ArticleContentWithComments( authorCdnImage = state.article.authorAvatarCdnImage, authorDisplayName = state.article.authorDisplayName, authorInternetIdentifier = state.article.authorInternetIdentifier, - authorLegendAvatarGlow = state.article.authorLegendAvatarGlow, - authorLegendCustomBadge = state.article.authorLegendCustomBadge, - authorLegendaryStyle = state.article.authorLegendaryStyle, + authorLegendaryCustomization = state.article.authorLegendaryCustomization, onAuthorAvatarClick = { noteCallbacks.onProfileClick?.invoke(state.article.authorId) }, onFollowUnfollowClick = onFollowUnfollowClick, ) diff --git a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt index 9778ff614..6eda3478c 100644 --- a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt +++ b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt @@ -32,8 +32,10 @@ import net.primal.android.R import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.preview.PrimalPreview +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @@ -44,9 +46,7 @@ fun ArticleAuthorRow( authorDisplayName: String, authorCdnImage: CdnImage? = null, authorInternetIdentifier: String? = null, - authorLegendAvatarGlow: Boolean = false, - authorLegendCustomBadge: Boolean = false, - authorLegendaryStyle: LegendaryStyle? = null, + authorLegendaryCustomization: LegendaryCustomization? = null, onAuthorAvatarClick: (() -> Unit)? = null, onFollowUnfollowClick: (() -> Unit)? = null, ) { @@ -54,15 +54,11 @@ fun ArticleAuthorRow( modifier = modifier, verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarSize = 42.dp, avatarCdnImage = authorCdnImage, onClick = onAuthorAvatarClick, - hasBorder = authorLegendAvatarGlow && authorLegendaryStyle != null, - borderBrush = when { - authorLegendaryStyle != null -> authorLegendaryStyle.brush - else -> Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, + legendaryCustomization = authorLegendaryCustomization, ) Column( @@ -78,7 +74,11 @@ fun ArticleAuthorRow( fontSize = 16.sp, lineHeight = 16.sp, ), - customBadgeStyle = if (authorLegendCustomBadge) authorLegendaryStyle else null, + customBadgeStyle = if (authorLegendaryCustomization?.customBadge == true) { + authorLegendaryCustomization.legendaryStyle + } else { + null + }, ) if (!authorInternetIdentifier.isNullOrBlank()) { @@ -206,3 +206,23 @@ fun PreviewArticleAuthorRow() { } } } + +@Preview +@Composable +fun PreviewArticleLegendaryAuthorRow() { + PrimalPreview(primalTheme = net.primal.android.theme.domain.PrimalTheme.Sunset) { + Surface(modifier = Modifier.fillMaxWidth()) { + ArticleAuthorRow( + modifier = Modifier.fillMaxWidth(), + authorFollowed = true, + authorDisplayName = "miljan", + authorInternetIdentifier = "miljan@primal.net", + authorLegendaryCustomization = LegendaryCustomization( + avatarGlow = true, + customBadge = true, + legendaryStyle = LegendaryStyle.SUN_FIRE, + ) + ) + } + } +} diff --git a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt index f4db6efc4..95d056113 100644 --- a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt +++ b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt @@ -6,7 +6,9 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.utils.asEllipsizedNpub import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.notes.feed.model.EventStatsUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization data class ArticleDetailsUi( val aTag: String, @@ -26,9 +28,7 @@ data class ArticleDetailsUi( val hashtags: List = emptyList(), val isBookmarked: Boolean = false, val eventStatsUi: EventStatsUi = EventStatsUi(), - val authorLegendAvatarGlow: Boolean = false, - val authorLegendCustomBadge: Boolean = false, - val authorLegendaryStyle: LegendaryStyle? = null, + val authorLegendaryCustomization: LegendaryCustomization? = null, ) fun Article.mapAsArticleDetailsUi(): ArticleDetailsUi { @@ -50,8 +50,6 @@ fun Article.mapAsArticleDetailsUi(): ArticleDetailsUi { hashtags = this.data.hashtags, isBookmarked = this.bookmark != null, eventStatsUi = EventStatsUi.from(eventStats = this.eventStats, userStats = this.userEventStats), - authorLegendAvatarGlow = this.author?.primalLegendProfile?.avatarGlow == true, - authorLegendCustomBadge = this.author?.primalLegendProfile?.customBadge == true, - authorLegendaryStyle = LegendaryStyle.valueById(this.author?.primalLegendProfile?.styleId), + authorLegendaryCustomization = this.author?.primalLegendProfile?.asLegendaryCustomization(), ) } From 91b27c22e3978bc123fcfe88b80c797d18b1617f Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 17:37:21 +0100 Subject: [PATCH 24/37] Use UniversalAvatarThumbnail on FeedArticleListItem, PrimalDrawer, PremiumHome and ProfileTopCoverBar --- .../articles/feed/ui/FeedArticleListItem.kt | 9 +++----- .../android/articles/feed/ui/FeedArticleUi.kt | 10 ++++----- .../net/primal/android/drawer/PrimalDrawer.kt | 10 ++++----- .../premium/home/PremiumHomeContract.kt | 5 ++--- .../android/premium/home/PremiumHomeScreen.kt | 18 ++++++++++----- .../premium/home/PremiumHomeViewModel.kt | 6 ++--- .../profile/details/ui/ProfileTopCoverBar.kt | 22 ++++--------------- 7 files changed, 31 insertions(+), 49 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt index d057d857a..71fe138b2 100644 --- a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt +++ b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt @@ -47,6 +47,7 @@ import net.primal.android.R import net.primal.android.attachments.domain.findNearestOrNull import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.IconText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.WrappedContentWithSuffix import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.compose.icons.PrimalIcons @@ -161,14 +162,10 @@ private fun ListItemHeader( .padding(end = overflowIconSizeDp - 4.dp), verticalAlignment = Alignment.CenterVertically, ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarSize = 24.dp, avatarCdnImage = data.authorAvatarCdnImage, - hasBorder = data.authorLegendAvatarGlow && data.authorLegendaryStyle != null, - borderBrush = when { - data.authorLegendaryStyle != null -> data.authorLegendaryStyle.brush - else -> Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, + legendaryCustomization = data.authorLegendaryCustomization, ) Box(modifier = Modifier.fillMaxWidth()) { diff --git a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt index 2d720587a..39fe5a0f3 100644 --- a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt +++ b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt @@ -9,7 +9,9 @@ import net.primal.android.nostr.model.NostrEventKind import net.primal.android.nostr.utils.Naddr import net.primal.android.nostr.utils.Nip19TLV.toNaddrString import net.primal.android.notes.feed.model.EventStatsUi +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.stats.ui.asEventZapUiModel @@ -29,9 +31,7 @@ data class FeedArticleUi( val imageCdnImage: CdnImage? = null, val readingTimeInMinutes: Int? = null, val eventZaps: List = emptyList(), - val authorLegendAvatarGlow: Boolean = false, - val authorLegendCustomBadge: Boolean = false, - val authorLegendaryStyle: LegendaryStyle? = null, + val authorLegendaryCustomization: LegendaryCustomization? = null, ) fun Article.mapAsFeedArticleUi(): FeedArticleUi { @@ -51,9 +51,7 @@ fun Article.mapAsFeedArticleUi(): FeedArticleUi { stats = EventStatsUi.from(eventStats = this.eventStats, userStats = null), readingTimeInMinutes = this.data.wordsCount.wordsCountToReadingTime(), eventZaps = this.eventZaps.map { it.asEventZapUiModel() }, - authorLegendAvatarGlow = this.author?.primalLegendProfile?.avatarGlow == true, - authorLegendCustomBadge = this.author?.primalLegendProfile?.customBadge == true, - authorLegendaryStyle = LegendaryStyle.valueById(this.author?.primalLegendProfile?.styleId), + authorLegendaryCustomization = this.author?.primalLegendProfile?.asLegendaryCustomization(), ) } diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt index 41e9cd1f1..45a50fe90 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt @@ -50,6 +50,7 @@ import kotlinx.coroutines.launch import net.primal.android.R import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.DarkMode import net.primal.android.core.compose.icons.primaliconpack.DrawerBookmarks @@ -63,6 +64,7 @@ import net.primal.android.core.compose.icons.primaliconpack.QrCode import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme import net.primal.android.user.domain.Badges @@ -163,18 +165,14 @@ private fun DrawerHeader( val startGuideline = createGuidelineFromStart(24.dp) val (avatarRef, usernameRef, iconRef, identifierRef, statsRef) = createRefs() - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( modifier = Modifier.constrainAs(avatarRef) { start.linkTo(startGuideline) top.linkTo(parent.top, margin = 16.dp) }, avatarSize = 52.dp, avatarCdnImage = userAccount?.avatarCdnImage, - hasBorder = avatarGlow && legendaryStyle != null, - borderBrush = when { - legendaryStyle != null -> legendaryStyle.brush - else -> Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, + legendaryCustomization = userAccount?.primalLegendProfile?.asLegendaryCustomization(), ) NostrUserText( diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt index 4dd292d19..3e70f4bcf 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt @@ -3,6 +3,7 @@ package net.primal.android.premium.home import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.domain.MembershipError import net.primal.android.premium.domain.PremiumMembership +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle interface PremiumHomeContract { @@ -13,9 +14,7 @@ interface PremiumHomeContract { val profileLightningAddress: String? = null, val membership: PremiumMembership? = null, val showSupportUsNotice: Boolean = false, - val legendaryStyle: LegendaryStyle = LegendaryStyle.NO_CUSTOMIZATION, - val avatarGlow: Boolean = false, - val customBadge: Boolean = false, + val avatarLegendaryCustomization: LegendaryCustomization? = null, val error: MembershipError? = null, ) diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt index 884f5c59b..c066c8cb1 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt @@ -36,10 +36,12 @@ import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalTopAppBar import net.primal.android.core.compose.SnackbarErrorHandler +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.core.compose.runtime.DisposableLifecycleObserverEffect +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.ui.PremiumBadge import net.primal.android.premium.ui.PrimalPremiumTable import net.primal.android.premium.ui.toHumanReadableString @@ -133,11 +135,10 @@ private fun PremiumHomeScreen( Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarCdnImage = state.avatarCdnImage, avatarSize = 80.dp, - hasBorder = state.avatarGlow, - borderBrush = state.legendaryStyle.brush, + legendaryCustomization = state.avatarLegendaryCustomization, ) Spacer(modifier = Modifier.height(16.dp)) val primalName = state.membership?.premiumName ?: "" @@ -147,7 +148,11 @@ private fun PremiumHomeScreen( internetIdentifier = "$primalName@primal.net", internetIdentifierBadgeSize = 24.dp, fontSize = 20.sp, - customBadgeStyle = if (state.customBadge) state.legendaryStyle else null, + customBadgeStyle = if (state.avatarLegendaryCustomization?.customBadge == true) { + state.avatarLegendaryCustomization.legendaryStyle + } else { + null + }, ) } @@ -156,9 +161,10 @@ private fun PremiumHomeScreen( firstCohort = state.membership.cohort1, secondCohort = state.membership.cohort2, membershipExpired = state.membership.isExpired(), - legendaryStyle = state.legendaryStyle, + legendaryStyle = state.avatarLegendaryCustomization?.legendaryStyle + ?: LegendaryStyle.NO_CUSTOMIZATION, - ) + ) if (state.membership.cohort2.isPremiumFree()) { Text( diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt index 124a68460..2ff3284a4 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt @@ -15,6 +15,7 @@ import net.primal.android.premium.domain.MembershipError import net.primal.android.premium.home.PremiumHomeContract.UiEvent import net.primal.android.premium.home.PremiumHomeContract.UiState import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.premium.repository.PremiumRepository import net.primal.android.premium.utils.isPrimalLegend import net.primal.android.profile.repository.ProfileRepository @@ -76,10 +77,7 @@ class PremiumHomeViewModel @Inject constructor( profileRepository.observeProfile(profileId = activeAccountStore.activeUserId()).collect { setState { copy( - avatarGlow = it.metadata?.primalLegendProfile?.avatarGlow == true, - customBadge = it.metadata?.primalLegendProfile?.customBadge == true, - legendaryStyle = LegendaryStyle.valueById(it.metadata?.primalLegendProfile?.styleId) - ?: LegendaryStyle.NO_CUSTOMIZATION, + avatarLegendaryCustomization = it.metadata?.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt index 8b187fdf3..6bb2f30f7 100644 --- a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt +++ b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt @@ -40,6 +40,7 @@ import net.primal.android.attachments.domain.findNearestOrNull import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.core.compose.icons.primaliconpack.Search @@ -118,7 +119,7 @@ fun ProfileTopCoverBar( .offset(y = avatarValues.avatarOffsetY, x = avatarValues.avatarOffsetX) .padding(horizontal = 16.dp), ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( modifier = Modifier .size(avatarValues.avatarSize) .padding( @@ -129,23 +130,8 @@ fun ProfileTopCoverBar( ), onClick = { state.profileDetails?.avatarCdnImage?.sourceUrl?.let { onMediaItemClick(it) } }, avatarCdnImage = state.profileDetails?.avatarCdnImage, - hasBorder = true, - borderBrush = if (state.profileDetails?.legendaryCustomization?.legendaryStyle != null && - state.profileDetails.legendaryCustomization.avatarGlow - ) { - when (state.profileDetails.legendaryCustomization.legendaryStyle) { - LegendaryStyle.NO_CUSTOMIZATION -> Brush.linearGradient( - listOf( - Color.White, - Color.White, - ), - ) - - else -> state.profileDetails.legendaryCustomization.legendaryStyle.brush - } - } else { - Brush.linearGradient(listOf(Color.White, Color.White)) - }, + fallbackBorderColor = Color.White, + legendaryCustomization = state.profileDetails?.legendaryCustomization, ) } } From 361ad479a098e3bb3217c307549c3fa99b787dee Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 17:38:11 +0100 Subject: [PATCH 25/37] Use UniversalAvatarThumbnail on LegendaryProfileCustomization --- .../LegendaryProfileCustomizationContract.kt | 5 +-- .../LegendaryProfileCustomizationScreen.kt | 43 +++++++++++-------- .../LegendaryProfileCustomizationViewModel.kt | 6 +-- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationContract.kt b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationContract.kt index f000d2d3c..f7922d7e5 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationContract.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationContract.kt @@ -2,6 +2,7 @@ package net.primal.android.premium.legend.custimization import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.domain.PremiumMembership +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle interface LegendaryProfileCustomizationContract { @@ -9,9 +10,7 @@ interface LegendaryProfileCustomizationContract { data class UiState( val avatarCdnImage: CdnImage? = null, val membership: PremiumMembership? = null, - val customBadge: Boolean = false, - val avatarGlow: Boolean = false, - val legendaryStyle: LegendaryStyle = LegendaryStyle.NO_CUSTOMIZATION, + val avatarLegendaryCustomization: LegendaryCustomization? = null, val applyingChanges: Boolean = false, ) diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt index 912610052..690031409 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt @@ -45,10 +45,12 @@ import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalSwitch import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.core.compose.icons.primaliconpack.LegendaryProfileNoCustomization +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.ui.PremiumBadge import net.primal.android.theme.AppTheme @@ -80,9 +82,15 @@ fun LegendaryProfileCustomizationScreen( onClose: () -> Unit, ) { val snackbarHostState = remember { SnackbarHostState() } - var customBadge by remember(state.customBadge) { mutableStateOf(state.customBadge) } - var avatarGlow by remember(state.avatarGlow) { mutableStateOf(state.avatarGlow) } - var selectedStyle by remember(state.legendaryStyle) { mutableStateOf(state.legendaryStyle) } + var customBadge by remember(state.avatarLegendaryCustomization?.customBadge) { + mutableStateOf(state.avatarLegendaryCustomization?.customBadge) + } + var avatarGlow by remember(state.avatarLegendaryCustomization?.avatarGlow) { + mutableStateOf(state.avatarLegendaryCustomization?.avatarGlow) + } + var selectedStyle by remember(state.avatarLegendaryCustomization?.legendaryStyle) { + mutableStateOf(state.avatarLegendaryCustomization?.legendaryStyle) + } Scaffold( topBar = { @@ -98,9 +106,9 @@ fun LegendaryProfileCustomizationScreen( onClick = { eventPublisher( LegendaryProfileCustomizationContract.UiEvent.ApplyCustomization( - customBadge = customBadge, - avatarGlow = avatarGlow, - style = selectedStyle, + customBadge = customBadge ?: false, + avatarGlow = avatarGlow ?: false, + style = selectedStyle ?: LegendaryStyle.NO_CUSTOMIZATION, ), ) }, @@ -123,15 +131,14 @@ fun LegendaryProfileCustomizationScreen( Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - AvatarThumbnailCustomBorder( + UniversalAvatarThumbnail( avatarCdnImage = state.avatarCdnImage, avatarSize = 80.dp, - hasBorder = true, - borderBrush = if (avatarGlow) { - selectedStyle.brush - } else { - Brush.linearGradient(listOf(Color.Transparent, Color.Transparent)) - }, + legendaryCustomization = LegendaryCustomization( + avatarGlow = avatarGlow == true, + customBadge = customBadge == true, + legendaryStyle = selectedStyle, + ), ) Spacer(modifier = Modifier.height(16.dp)) val primalName = state.membership?.premiumName ?: "" @@ -140,7 +147,7 @@ fun LegendaryProfileCustomizationScreen( displayName = primalName, internetIdentifier = "$primalName@primal.net", internetIdentifierBadgeSize = 24.dp, - customBadgeStyle = if (customBadge) selectedStyle else null, + customBadgeStyle = if (customBadge == true) selectedStyle else null, fontSize = 20.sp, ) } @@ -150,7 +157,7 @@ fun LegendaryProfileCustomizationScreen( firstCohort = state.membership.cohort1, secondCohort = state.membership.cohort2, membershipExpired = state.membership.isExpired(), - legendaryStyle = selectedStyle, + legendaryStyle = selectedStyle ?: LegendaryStyle.NO_CUSTOMIZATION, ) PrimalDivider(modifier = Modifier.padding(top = 16.dp)) @@ -159,7 +166,7 @@ fun LegendaryProfileCustomizationScreen( modifier = Modifier .fillMaxWidth() .padding(horizontal = 32.dp, vertical = 8.dp), - activeLegendaryStyle = selectedStyle, + activeLegendaryStyle = selectedStyle ?: LegendaryStyle.NO_CUSTOMIZATION, onStyleChanged = { selectedStyle = it }, ) @@ -167,9 +174,9 @@ fun LegendaryProfileCustomizationScreen( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp), - avatarRing = avatarGlow, + avatarRing = avatarGlow == true, onAvatarRingChanged = { avatarGlow = it }, - customBadge = customBadge, + customBadge = customBadge == true, onCustomBadgeChanged = { customBadge = it }, ) diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt index d006a84bc..3cb2440a7 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import net.primal.android.networking.sockets.errors.WssException import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.premium.legend.custimization.LegendaryProfileCustomizationContract.SideEffect import net.primal.android.premium.legend.custimization.LegendaryProfileCustomizationContract.UiEvent import net.primal.android.premium.legend.custimization.LegendaryProfileCustomizationContract.UiState @@ -99,10 +100,7 @@ class LegendaryProfileCustomizationViewModel @Inject constructor( profileRepository.observeProfile(profileId = activeAccountStore.activeUserId()).collect { setState { copy( - avatarGlow = it.metadata?.primalLegendProfile?.avatarGlow == true, - customBadge = it.metadata?.primalLegendProfile?.customBadge == true, - legendaryStyle = LegendaryStyle.valueById(it.metadata?.primalLegendProfile?.styleId) - ?: LegendaryStyle.NO_CUSTOMIZATION, + avatarLegendaryCustomization = it.metadata?.primalLegendProfile?.asLegendaryCustomization(), ) } } From 7499fb5edd37f06dfecd3b9386ad38059cacca95 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 17:38:29 +0100 Subject: [PATCH 26/37] Mark AvatarThumbnail and AvatarThumbnailCustomBorder as deprecated --- .../android/core/compose/AvatarThumbnailListItemImage.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index 18577c240..a3c8851b7 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -72,6 +72,10 @@ fun UniversalAvatarThumbnail( ) } +@Deprecated( + message = "This component is deprecated in favor of UniversalAvatarThumbnail", + replaceWith = ReplaceWith("UniversalAvatarThumbnail"), +) @Composable fun AvatarThumbnail( modifier: Modifier = Modifier, @@ -97,6 +101,10 @@ fun AvatarThumbnail( ) } +@Deprecated( + message = "This component is deprecated in favor of UniversalAvatarThumbnail", + replaceWith = ReplaceWith("UniversalAvatarThumbnail"), +) @Composable fun AvatarThumbnailCustomBorder( modifier: Modifier = Modifier, From 23622d88bc348ef835ad289f1f51199a93839c6e Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 17:39:00 +0100 Subject: [PATCH 27/37] Auto-format code --- .../primal/android/articles/feed/ui/FeedArticleListItem.kt | 2 -- .../net/primal/android/articles/feed/ui/FeedArticleUi.kt | 1 - app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt | 3 --- .../net/primal/android/explore/home/ExploreHomeContract.kt | 1 - .../net/primal/android/explore/home/ExploreHomeScreen.kt | 3 --- .../net/primal/android/explore/home/ExploreHomeViewModel.kt | 1 - .../kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt | 1 - .../kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt | 3 --- .../net/primal/android/notes/feed/note/ui/NoteHeader.kt | 4 ---- .../net/primal/android/premium/home/PremiumHomeContract.kt | 1 - .../net/primal/android/premium/home/PremiumHomeScreen.kt | 3 +-- .../net/primal/android/premium/home/PremiumHomeViewModel.kt | 1 - .../custimization/LegendaryProfileCustomizationScreen.kt | 2 -- .../custimization/LegendaryProfileCustomizationViewModel.kt | 1 - .../primal/android/profile/details/ui/ProfileTopCoverBar.kt | 3 --- .../android/thread/articles/details/ui/ArticleAuthorRow.kt | 4 +--- .../android/thread/articles/details/ui/ArticleDetailsUi.kt | 1 - 17 files changed, 2 insertions(+), 33 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt index 71fe138b2..535742da6 100644 --- a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt +++ b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleListItem.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalDensity @@ -45,7 +44,6 @@ import coil.compose.SubcomposeAsyncImage import java.time.Instant import net.primal.android.R import net.primal.android.attachments.domain.findNearestOrNull -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.IconText import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.WrappedContentWithSuffix diff --git a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt index 39fe5a0f3..158291868 100644 --- a/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt +++ b/app/src/main/kotlin/net/primal/android/articles/feed/ui/FeedArticleUi.kt @@ -10,7 +10,6 @@ import net.primal.android.nostr.utils.Naddr import net.primal.android.nostr.utils.Nip19TLV.toNaddrString import net.primal.android.notes.feed.model.EventStatsUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.stats.ui.asEventZapUiModel diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt index 45a50fe90..f63fd9325 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt @@ -30,8 +30,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource @@ -48,7 +46,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import java.text.NumberFormat import kotlinx.coroutines.launch import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.icons.PrimalIcons diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt index fee4efb6a..3afefb523 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeContract.kt @@ -2,7 +2,6 @@ package net.primal.android.explore.home import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges interface ExploreHomeContract { diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt index 4ed918f24..3309b45f5 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeScreen.kt @@ -39,7 +39,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext @@ -52,7 +51,6 @@ import net.primal.android.LocalContentDisplaySettings import net.primal.android.R import net.primal.android.attachments.domain.CdnImage import net.primal.android.core.compose.AppBarIcon -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.IconText import net.primal.android.core.compose.InvisibleAppBarIcon import net.primal.android.core.compose.PrimalDivider @@ -81,7 +79,6 @@ import net.primal.android.feeds.domain.exploreMediaFeedSpec import net.primal.android.notes.feed.grid.MediaFeedGrid import net.primal.android.notes.feed.note.ui.events.NoteCallbacks import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme diff --git a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt index 4319f592b..eccff7ce1 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/ExploreHomeViewModel.kt @@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch import net.primal.android.explore.home.ExploreHomeContract.UiState -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.user.accounts.active.ActiveAccountStore import net.primal.android.user.subscriptions.SubscriptionsManager diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt index 6dd36ca21..3a31fb3d3 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/model/FeedPostUi.kt @@ -10,7 +10,6 @@ import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.core.utils.usernameUiFriendly import net.primal.android.notes.db.FeedPost import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.stats.ui.EventZapUiModel import net.primal.android.stats.ui.asEventZapUiModel diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt index 44366351a..ebb54331d 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/FeedNoteCard.kt @@ -28,8 +28,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalUriHandler @@ -44,7 +42,6 @@ import java.time.temporal.ChronoUnit import kotlinx.coroutines.launch import net.primal.android.LocalContentDisplaySettings import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.preview.PrimalPreview diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt index ae6d2ec6c..5c925dc90 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt @@ -11,8 +11,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle @@ -27,7 +25,6 @@ import java.time.Instant import kotlin.time.Duration.Companion.seconds import net.primal.android.LocalContentDisplaySettings import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.ReplyingToText import net.primal.android.core.compose.UniversalAvatarThumbnail @@ -35,7 +32,6 @@ import net.primal.android.core.compose.WrappedContentWithSuffix import net.primal.android.core.compose.asBeforeNowFormat import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme import net.primal.android.theme.PrimalTheme import net.primal.android.theme.domain.PrimalTheme diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt index 3e70f4bcf..a024140a1 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeContract.kt @@ -4,7 +4,6 @@ import net.primal.android.attachments.domain.CdnImage import net.primal.android.premium.domain.MembershipError import net.primal.android.premium.domain.PremiumMembership import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle interface PremiumHomeContract { diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt index c066c8cb1..6d3e9ab79 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeScreen.kt @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.Lifecycle import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalTopAppBar import net.primal.android.core.compose.SnackbarErrorHandler @@ -164,7 +163,7 @@ private fun PremiumHomeScreen( legendaryStyle = state.avatarLegendaryCustomization?.legendaryStyle ?: LegendaryStyle.NO_CUSTOMIZATION, - ) + ) if (state.membership.cohort2.isPremiumFree()) { Text( diff --git a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt index 2ff3284a4..296714d18 100644 --- a/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/premium/home/PremiumHomeViewModel.kt @@ -14,7 +14,6 @@ import net.primal.android.networking.sockets.errors.WssException import net.primal.android.premium.domain.MembershipError import net.primal.android.premium.home.PremiumHomeContract.UiEvent import net.primal.android.premium.home.PremiumHomeContract.UiState -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.premium.repository.PremiumRepository import net.primal.android.premium.utils.isPrimalLegend diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt index 690031409..b8b0a6a45 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationScreen.kt @@ -32,7 +32,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -40,7 +39,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.PrimalSwitch diff --git a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt index 3cb2440a7..ad6fd38bc 100644 --- a/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/premium/legend/custimization/LegendaryProfileCustomizationViewModel.kt @@ -12,7 +12,6 @@ import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import net.primal.android.networking.sockets.errors.WssException -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.premium.legend.custimization.LegendaryProfileCustomizationContract.SideEffect import net.primal.android.premium.legend.custimization.LegendaryProfileCustomizationContract.UiEvent diff --git a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt index 6bb2f30f7..4ea90967f 100644 --- a/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt +++ b/app/src/main/kotlin/net/primal/android/profile/details/ui/ProfileTopCoverBar.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawWithCache -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalDensity @@ -37,7 +36,6 @@ import androidx.compose.ui.unit.dp import coil.compose.SubcomposeAsyncImage import net.primal.android.R import net.primal.android.attachments.domain.findNearestOrNull -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalDivider import net.primal.android.core.compose.UniversalAvatarThumbnail @@ -45,7 +43,6 @@ import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack import net.primal.android.core.compose.icons.primaliconpack.Search import net.primal.android.core.utils.asEllipsizedNpub -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.profile.details.ProfileDetailsContract import net.primal.android.theme.AppTheme diff --git a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt index 6eda3478c..22c48f380 100644 --- a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt +++ b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleAuthorRow.kt @@ -20,7 +20,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -30,7 +29,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import net.primal.android.R import net.primal.android.attachments.domain.CdnImage -import net.primal.android.core.compose.AvatarThumbnailCustomBorder import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton @@ -221,7 +219,7 @@ fun PreviewArticleLegendaryAuthorRow() { avatarGlow = true, customBadge = true, legendaryStyle = LegendaryStyle.SUN_FIRE, - ) + ), ) } } diff --git a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt index 95d056113..7130dd08e 100644 --- a/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt +++ b/app/src/main/kotlin/net/primal/android/thread/articles/details/ui/ArticleDetailsUi.kt @@ -7,7 +7,6 @@ import net.primal.android.core.utils.asEllipsizedNpub import net.primal.android.core.utils.authorNameUiFriendly import net.primal.android.notes.feed.model.EventStatsUi import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization data class ArticleDetailsUi( From 71801b3402a60bad54e99875c7e9de5d04702531 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 19:26:33 +0100 Subject: [PATCH 28/37] Fix some detekt issues --- .../compose/AvatarThumbnailListItemImage.kt | 2 +- .../net/primal/android/drawer/PrimalDrawer.kt | 17 ++-- .../android/drawer/PrimalDrawerContract.kt | 5 +- .../android/drawer/PrimalDrawerViewModel.kt | 5 +- .../android/notes/feed/note/ui/NoteHeader.kt | 81 ++++++++++++------- 5 files changed, 65 insertions(+), 45 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index a3c8851b7..d4b4a380a 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -144,7 +144,7 @@ private fun AvatarThumbnailListItemImage( listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), ), borderSize: Dp = 2.dp, - hasGlow: Boolean = false, + @Suppress("UnusedParameter") hasGlow: Boolean = false, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, defaultAvatar: @Composable () -> Unit, diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt index f63fd9325..f0d3a10e3 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt @@ -60,6 +60,7 @@ import net.primal.android.core.compose.icons.primaliconpack.LightMode import net.primal.android.core.compose.icons.primaliconpack.QrCode import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.utils.formatNip05Identifier +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.theme.AppTheme @@ -118,10 +119,8 @@ fun PrimalDrawer( ) { DrawerHeader( userAccount = state.activeUserAccount, - customBadge = state.customBadge, - avatarGlow = state.avatarGlow, - legendaryStyle = state.legendaryStyle, onQrCodeClick = onQrCodeClick, + legendaryCustomization = state.legendaryCustomization, ) DrawerMenu( @@ -150,9 +149,7 @@ fun PrimalDrawer( @Composable private fun DrawerHeader( userAccount: UserAccount?, - customBadge: Boolean, - avatarGlow: Boolean, - legendaryStyle: LegendaryStyle?, + legendaryCustomization: LegendaryCustomization?, onQrCodeClick: () -> Unit, ) { val numberFormat = remember { NumberFormat.getNumberInstance() } @@ -169,7 +166,7 @@ private fun DrawerHeader( }, avatarSize = 52.dp, avatarCdnImage = userAccount?.avatarCdnImage, - legendaryCustomization = userAccount?.primalLegendProfile?.asLegendaryCustomization(), + legendaryCustomization = legendaryCustomization, ) NostrUserText( @@ -181,7 +178,11 @@ private fun DrawerHeader( top.linkTo(avatarRef.bottom, margin = 16.dp) width = Dimension.preferredValue(220.dp) }, - customBadgeStyle = if (customBadge) legendaryStyle else null, + customBadgeStyle = if (legendaryCustomization?.customBadge == true) { + legendaryCustomization.legendaryStyle + } else { + null + }, ) IconButton( diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt index 50aa083ee..043b8bf5b 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt @@ -1,5 +1,6 @@ package net.primal.android.drawer +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges import net.primal.android.user.domain.UserAccount @@ -12,9 +13,7 @@ interface PrimalDrawerContract { val activeUserAccount: UserAccount? = null, val badges: Badges = Badges(), val showPremiumBadge: Boolean = false, - val customBadge: Boolean = false, - val avatarGlow: Boolean = false, - val legendaryStyle: LegendaryStyle? = null, + val legendaryCustomization: LegendaryCustomization? = null, ) sealed class UiEvent { diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt index e19e570b7..1ef372607 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch import net.primal.android.premium.legend.LegendaryStyle +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.repository.ProfileRepository import net.primal.android.theme.active.ActiveThemeStore import net.primal.android.theme.domain.PrimalTheme @@ -82,9 +83,7 @@ class PrimalDrawerViewModel @Inject constructor( profileRepository.observeProfile(profileId = activeAccountStore.activeUserId()).collect { setState { copy( - avatarGlow = it.metadata?.primalLegendProfile?.avatarGlow == true, - customBadge = it.metadata?.primalLegendProfile?.customBadge == true, - legendaryStyle = LegendaryStyle.valueById(it.metadata?.primalLegendProfile?.styleId), + legendaryCustomization = it.metadata?.primalLegendProfile?.asLegendaryCustomization(), ) } } diff --git a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt index 5c925dc90..b071b079a 100644 --- a/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt +++ b/app/src/main/kotlin/net/primal/android/notes/feed/note/ui/NoteHeader.kt @@ -88,36 +88,14 @@ fun FeedNoteHeader( ) } - WrappedContentWithSuffix( - wrappedContent = { - NostrUserText( - displayName = authorDisplayName, - internetIdentifier = authorInternetIdentifier, - annotatedStringSuffixBuilder = { - append(suffixText) - }, - style = topRowTextStyle, - internetIdentifierBadgeSize = topRowTextStyle.fontSize.value.dp, - overflow = TextOverflow.Ellipsis, - customBadgeStyle = if (authorLegendaryCustomization?.customBadge == true) { - authorLegendaryCustomization.legendaryStyle - } else { - null - }, - ) - }, - suffixFixedContent = { - if (postTimestamp != null) { - Text( - text = " • ${postTimestamp.asBeforeNowFormat()}", - textAlign = TextAlign.Center, - maxLines = 1, - style = topRowTextStyle, - fontSize = (displaySettings.contentAppearance.noteUsernameSize.value).sp, - color = AppTheme.extraColorScheme.onSurfaceVariantAlt2, - ) - } - }, + NoteAuthorBadgeAndTimestampSection( + authorDisplayName = authorDisplayName, + authorInternetIdentifier = authorInternetIdentifier, + suffixText = suffixText, + topRowTextStyle = topRowTextStyle, + authorLegendaryCustomization = authorLegendaryCustomization, + postTimestamp = postTimestamp, + displaySettings = displaySettings, ) if (!label.isNullOrEmpty() && !singleLine) { @@ -142,6 +120,49 @@ fun FeedNoteHeader( } } +@Composable +private fun NoteAuthorBadgeAndTimestampSection( + authorDisplayName: String, + authorInternetIdentifier: String?, + suffixText: AnnotatedString, + topRowTextStyle: TextStyle, + authorLegendaryCustomization: LegendaryCustomization?, + postTimestamp: Instant?, + displaySettings: ContentDisplaySettings, +) { + WrappedContentWithSuffix( + wrappedContent = { + NostrUserText( + displayName = authorDisplayName, + internetIdentifier = authorInternetIdentifier, + annotatedStringSuffixBuilder = { + append(suffixText) + }, + style = topRowTextStyle, + internetIdentifierBadgeSize = topRowTextStyle.fontSize.value.dp, + overflow = TextOverflow.Ellipsis, + customBadgeStyle = if (authorLegendaryCustomization?.customBadge == true) { + authorLegendaryCustomization.legendaryStyle + } else { + null + }, + ) + }, + suffixFixedContent = { + if (postTimestamp != null) { + Text( + text = " • ${postTimestamp.asBeforeNowFormat()}", + textAlign = TextAlign.Center, + maxLines = 1, + style = topRowTextStyle, + fontSize = (displaySettings.contentAppearance.noteUsernameSize.value).sp, + color = AppTheme.extraColorScheme.onSurfaceVariantAlt2, + ) + } + }, + ) +} + @Preview @Composable fun PreviewLightNoteHeader() { From db0d73cb405dfd5b34f000b01d9a91635197f67b Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 19:27:15 +0100 Subject: [PATCH 29/37] Update detekt baseline --- app/detekt-baseline.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml index 59e18a72d..c29699e2b 100644 --- a/app/detekt-baseline.xml +++ b/app/detekt-baseline.xml @@ -62,7 +62,6 @@ LongMethod:NoteDropdownMenu.kt$@Composable fun NoteDropdownMenuIcon( modifier: Modifier, noteId: String, noteContent: String, noteRawData: String, authorId: String, isBookmarked: Boolean, enabled: Boolean = true, onBookmarkClick: (() -> Unit)? = null, onMuteUserClick: (() -> Unit)? = null, onReportContentClick: (() -> Unit)? = null, ) LongMethod:NoteEditorScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun NoteEditorBox( state: NoteEditorContract.UiState, eventPublisher: (UiEvent) -> Unit, modifier: Modifier = Modifier, contentPadding: PaddingValues, ) LongMethod:NoteFeedLazyColumn.kt$@ExperimentalMaterial3Api @ExperimentalFoundationApi @Composable fun NoteFeedLazyColumn( modifier: Modifier = Modifier, pagingItems: LazyPagingItems<FeedPostUi>, listState: LazyListState, showPaywall: Boolean, noteCallbacks: NoteCallbacks, onGoToWallet: () -> Unit, showTopZaps: Boolean = false, shouldShowLoadingState: Boolean = true, shouldShowNoContentState: Boolean = true, showReplyTo: Boolean = true, noContentVerticalArrangement: Arrangement.Vertical = Arrangement.Center, noContentPaddingValues: PaddingValues = PaddingValues(all = 0.dp), noContentText: String = stringResource(id = R.string.feed_no_content), contentPadding: PaddingValues = PaddingValues(all = 0.dp), header: @Composable (LazyItemScope.() -> Unit)? = null, stickyHeader: @Composable (LazyItemScope.() -> Unit)? = null, onUiError: ((UiError) -> Unit)? = null, ) - LongMethod:NoteHeader.kt$@Composable fun FeedNoteHeader( modifier: Modifier = Modifier, authorDisplayName: String, singleLine: Boolean = false, postTimestamp: Instant? = null, authorAvatarSize: Dp = 42.dp, authorAvatarVisible: Boolean = true, authorAvatarCdnImage: CdnImage? = null, authorInternetIdentifier: String? = null, authorLegendAvatarGlow: Boolean = false, authorLegendCustomBadge: Boolean = false, authorLegendaryStyle: LegendaryStyle? = null, replyToAuthor: String? = null, label: String? = authorInternetIdentifier, labelStyle: TextStyle? = null, onAuthorAvatarClick: (() -> Unit)? = null, ) LongMethod:NoteVideoLinkPreview.kt$@Composable fun NoteVideoLinkPreview( url: String, title: String?, thumbnailUrl: String?, thumbnailImageSize: DpSize, type: NoteAttachmentType, onClick: (() -> Unit)? = null, ) LongMethod:NotificationListItem.kt$@Composable private fun NotificationType.toSuffixText(usersZappedCount: Int = 0, totalSatsZapped: String? = null): String LongMethod:NotificationsScreen.kt$@ExperimentalMaterial3Api @Composable private fun NotificationsList( state: NotificationsContract.UiState, noteState: NoteContract.UiState, listState: LazyListState, seenPagingItems: LazyPagingItems<NotificationUi>, paddingValues: PaddingValues, noteCallbacks: NoteCallbacks, onGoToWallet: () -> Unit, onPostLikeClick: (FeedPostUi) -> Unit, onRepostClick: (FeedPostUi) -> Unit, onZapClick: (FeedPostUi, ULong?, String?) -> Unit, onPostQuoteClick: (FeedPostUi) -> Unit, onBookmarkClick: (FeedPostUi) -> Unit, ) @@ -76,11 +75,11 @@ LongMethod:PremiumOrderHistoryScreen.kt$@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable private fun PremiumOrderHistoryScreen( state: PremiumOrderHistoryContract.UiState, eventPublisher: (PremiumOrderHistoryContract.UiEvent) -> Unit, onExtendSubscription: (primalName: String) -> Unit, onClose: () -> Unit, ) LongMethod:PremiumPurchaseStage.kt$@ExperimentalMaterial3Api @Composable fun PremiumPurchaseStage( state: PremiumBuyingContract.UiState, onBack: () -> Unit, onLearnMoreClick: () -> Unit, eventPublisher: (PremiumBuyingContract.UiEvent) -> Unit, ) LongMethod:PrimalAppNavigation.kt$@OptIn(ExperimentalSharedTransitionApi::class) @Composable fun SharedTransitionScope.PrimalAppNavigation() - LongMethod:PrimalDrawer.kt$@Composable private fun DrawerHeader( userAccount: UserAccount?, customBadge: Boolean, avatarGlow: Boolean, legendaryStyle: LegendaryStyle?, onQrCodeClick: () -> Unit, ) + LongMethod:PrimalDrawer.kt$@Composable private fun DrawerHeader( userAccount: UserAccount?, legendaryCustomization: LegendaryCustomization?, onQrCodeClick: () -> Unit, ) LongMethod:PrimalDrawerScaffold.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun PrimalDrawerScaffold( modifier: Modifier = Modifier, drawerState: DrawerState, activeDestination: PrimalTopLevelDestination, onPrimaryDestinationChanged: (PrimalTopLevelDestination) -> Unit, onDrawerDestinationClick: (DrawerScreenDestination) -> Unit, onDrawerQrCodeClick: () -> Unit, badges: Badges = Badges(), onActiveDestinationClick: () -> Unit = {}, topAppBarState: TopAppBarState = remember { TopAppBarState( initialHeightOffsetLimit = -Float.MAX_VALUE, initialHeightOffset = 0f, initialContentOffset = 0f, ) }, topAppBar: @Composable (TopAppBarScrollBehavior?) -> Unit = {}, content: @Composable (PaddingValues) -> Unit = {}, floatingNewDataHost: @Composable () -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, snackbarHost: @Composable () -> Unit = {}, focusModeEnabled: Boolean = true, ) LongMethod:PrimalNavigationBar.kt$@Composable fun PrimalNavigationBarLightningBolt( modifier: Modifier = Modifier, activeDestination: PrimalTopLevelDestination, onTopLevelDestinationChanged: (PrimalTopLevelDestination) -> Unit, onActiveDestinationClick: (() -> Unit)? = null, badges: Badges = Badges(), ) LongMethod:PrimalOutlinedTextField.kt$@Composable fun PrimalOutlinedTextField( header: String?, value: String, onValueChange: (String) -> Unit, forceFocus: Boolean = false, isRequired: Boolean = false, prefix: String? = null, isMultiline: Boolean = false, fontSize: TextUnit = 16.sp, textAlign: TextAlign = TextAlign.Start, isError: Boolean = false, ) - LongMethod:PrimalTopAppBar.kt$@OptIn(ExperimentalFoundationApi::class) @ExperimentalMaterial3Api @Composable fun PrimalTopAppBar( modifier: Modifier = Modifier, title: String = "", subtitle: String? = null, titleTrailingIcon: ImageVector? = null, textColor: Color = LocalContentColor.current, navigationIcon: ImageVector? = null, navigationIconTintColor: Color = LocalContentColor.current, navigationIconContentDescription: String? = null, onNavigationIconClick: (() -> Unit)? = null, autoCloseKeyboardOnNavigationIconClick: Boolean = true, avatarCdnImage: CdnImage? = null, avatarLegendaryStyle: LegendaryStyle? = null, actions: (@Composable RowScope.() -> Unit)? = null, showDivider: Boolean = true, scrollBehavior: TopAppBarScrollBehavior? = null, onTitleClick: (() -> Unit)? = null, onTitleLongClick: (() -> Unit)? = null, colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors( containerColor = AppTheme.colorScheme.surface, scrolledContainerColor = AppTheme.colorScheme.surface, ), footer: @Composable () -> Unit = {}, ) + LongMethod:PrimalTopAppBar.kt$@OptIn(ExperimentalFoundationApi::class) @ExperimentalMaterial3Api @Composable fun PrimalTopAppBar( modifier: Modifier = Modifier, title: String = "", subtitle: String? = null, titleTrailingIcon: ImageVector? = null, textColor: Color = LocalContentColor.current, navigationIcon: ImageVector? = null, navigationIconTintColor: Color = LocalContentColor.current, navigationIconContentDescription: String? = null, onNavigationIconClick: (() -> Unit)? = null, autoCloseKeyboardOnNavigationIconClick: Boolean = true, avatarCdnImage: CdnImage? = null, legendaryCustomization: LegendaryCustomization? = null, actions: (@Composable RowScope.() -> Unit)? = null, showDivider: Boolean = true, scrollBehavior: TopAppBarScrollBehavior? = null, onTitleClick: (() -> Unit)? = null, onTitleLongClick: (() -> Unit)? = null, colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors( containerColor = AppTheme.colorScheme.surface, scrolledContainerColor = AppTheme.colorScheme.surface, ), footer: @Composable () -> Unit = {}, ) LongMethod:ReactionsScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ReactionsScreen( state: ReactionsContract.UiState, onClose: () -> Unit, onProfileClick: (profileId: String) -> Unit, ) LongMethod:ReadsScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ReadsScreen( state: ReadsScreenContract.UiState, onTopLevelDestinationChanged: (PrimalTopLevelDestination) -> Unit, onDrawerScreenClick: (DrawerScreenDestination) -> Unit, onDrawerQrCodeClick: () -> Unit, onSearchClick: () -> Unit, onArticleClick: (naddr: String) -> Unit, onGetPremiumClick: () -> Unit, eventPublisher: (ReadsScreenContract.UiEvent) -> Unit, ) LongMethod:ReceivePaymentScreen.kt$@Composable private fun ReceivePaymentViewer( paddingValues: PaddingValues, state: UiState, onBuyPremium: () -> Unit, onCopyClick: () -> Unit, onEditClick: () -> Unit, ) From ae54ef78729e04db297ae5ec153c4cba76efe0f6 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Fri, 29 Nov 2024 19:46:26 +0100 Subject: [PATCH 30/37] Auto-format code --- app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt | 2 -- .../kotlin/net/primal/android/drawer/PrimalDrawerContract.kt | 1 - .../kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt | 1 - 3 files changed, 4 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt index f0d3a10e3..7855fab06 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawer.kt @@ -61,8 +61,6 @@ import net.primal.android.core.compose.icons.primaliconpack.QrCode import net.primal.android.core.compose.preview.PrimalPreview import net.primal.android.core.utils.formatNip05Identifier import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle -import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.theme.AppTheme import net.primal.android.theme.domain.PrimalTheme import net.primal.android.user.domain.Badges diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt index 043b8bf5b..904fadd4a 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerContract.kt @@ -1,7 +1,6 @@ package net.primal.android.drawer import net.primal.android.premium.legend.LegendaryCustomization -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.user.domain.Badges import net.primal.android.user.domain.UserAccount diff --git a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt index 1ef372607..a128a5152 100644 --- a/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/drawer/PrimalDrawerViewModel.kt @@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.launch -import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.profile.repository.ProfileRepository import net.primal.android.theme.active.ActiveThemeStore From 71d98e8377bdc18f79358c76b0a6ba1703599172 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Sat, 30 Nov 2024 11:40:34 +0100 Subject: [PATCH 31/37] Use UniversalAvatarThumbnail on NoteEditorScreen and TransactionDetailsScreen --- .../kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt | 1 + .../wallet/transactions/details/TransactionDetailDataUi.kt | 2 ++ .../wallet/transactions/details/TransactionDetailsScreen.kt | 3 +-- .../wallet/transactions/details/TransactionDetailsViewModel.kt | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt index 0a22b0a81..0fa7f4257 100644 --- a/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt +++ b/app/src/main/kotlin/net/primal/android/editor/ui/NoteEditorScreen.kt @@ -478,6 +478,7 @@ private fun ReplyToNote(replyToNote: FeedPostUi, connectionLineColor: Color) { postTimestamp = replyToNote.timestamp, authorAvatarCdnImage = replyToNote.authorAvatarCdnImage, authorInternetIdentifier = replyToNote.authorInternetIdentifier, + authorLegendaryCustomization = replyToNote.authorLegendaryCustomization, onAuthorAvatarClick = {}, ) diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailDataUi.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailDataUi.kt index 641b855ac..2c42eb825 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailDataUi.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailDataUi.kt @@ -2,6 +2,7 @@ package net.primal.android.wallet.transactions.details import java.time.Instant import net.primal.android.attachments.domain.CdnImage +import net.primal.android.premium.legend.LegendaryCustomization import net.primal.android.wallet.domain.TxState import net.primal.android.wallet.domain.TxType @@ -25,4 +26,5 @@ data class TransactionDetailDataUi( val otherUserInternetIdentifier: String? = null, val otherUserDisplayName: String? = null, val otherUserLightningAddress: String? = null, + val otherUserLegendaryCustomization: LegendaryCustomization? = null, ) diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt index 187cc7882..a89309b7f 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsScreen.kt @@ -135,8 +135,6 @@ fun TransactionDetailsScreen( onClose: () -> Unit, noteCallbacks: NoteCallbacks, ) { - val context = LocalContext.current - val uiScope = rememberCoroutineScope() val scrollState = rememberScrollState() val showTopBarDivider by remember { derivedStateOf { scrollState.value > 0 } } val snackbarHostState = remember { SnackbarHostState() } @@ -397,6 +395,7 @@ private fun TransactionCard(txData: TransactionDetailDataUi, onProfileClick: (St authorDisplayName = txData.otherUserDisplayName, authorAvatarCdnImage = txData.otherUserAvatarCdnImage, authorInternetIdentifier = txData.otherUserInternetIdentifier, + authorLegendaryCustomization = txData.otherUserLegendaryCustomization, onAuthorAvatarClick = { txData.otherUserId?.let(onProfileClick) }, label = txData.otherUserLightningAddress, labelStyle = AppTheme.typography.bodyMedium, diff --git a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsViewModel.kt b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsViewModel.kt index f25929706..4b2875504 100644 --- a/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsViewModel.kt +++ b/app/src/main/kotlin/net/primal/android/wallet/transactions/details/TransactionDetailsViewModel.kt @@ -21,6 +21,7 @@ import net.primal.android.navigation.transactionIdOrThrow import net.primal.android.networking.sockets.errors.WssException import net.primal.android.notes.feed.model.asFeedPostUi import net.primal.android.notes.repository.FeedRepository +import net.primal.android.premium.legend.asLegendaryCustomization import net.primal.android.wallet.db.WalletTransaction import net.primal.android.wallet.repository.WalletRepository import net.primal.android.wallet.transactions.details.TransactionDetailsContract.UiState @@ -128,6 +129,7 @@ class TransactionDetailsViewModel @Inject constructor( otherUserDisplayName = this.otherProfileData?.authorNameUiFriendly(), otherUserInternetIdentifier = this.otherProfileData?.internetIdentifier, otherUserLightningAddress = this.data.otherLightningAddress, + otherUserLegendaryCustomization = this.otherProfileData?.primalLegendProfile?.asLegendaryCustomization(), isZap = this.data.isZap, isStorePurchase = this.data.isStorePurchase, ) From 4ba85a7ff71fcef0f4390f928a7dd589fe4c1db1 Mon Sep 17 00:00:00 2001 From: Marko Kocic Date: Tue, 3 Dec 2024 00:35:07 +0100 Subject: [PATCH 32/37] Adjust borderSize based on avatarSize and draw border on the outside --- .../compose/AvatarThumbnailListItemImage.kt | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index d4b4a380a..4c4b88626 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Icon @@ -65,7 +66,7 @@ fun UniversalAvatarThumbnail( ), ), hasGlow = (hasGlowOverride ?: legendaryCustomization?.avatarGlow) == true, - borderSize = borderSize, + borderSize = avatarSize.mapAvatarSizeToBorderSize(), backgroundColor = backgroundColor, onClick = onClick, defaultAvatar = defaultAvatar, @@ -189,20 +190,38 @@ fun Modifier.adjustAvatarBackground( ): Modifier { return if (hasBorder) { this - .size(size + borderSize) + .size(size + borderSize * 2) .border( width = borderSize, brush = borderBrush, shape = CircleShape, ) + .padding(borderSize) .clip(CircleShape) } else { this - .size(size) + .size(size + borderSize * 2) + .border( + width = borderSize, + brush = Brush.linearGradient( + listOf(Color.Transparent, Color.Transparent), + ), + shape = CircleShape, + ) + .padding(borderSize) .clip(CircleShape) } } +private fun Dp.mapAvatarSizeToBorderSize(): Dp = + when { + this >= 112.dp -> 4.dp + this >= 80.dp -> 3.dp + this >= 32.dp -> 2.dp + this >= 24.dp -> (1.5).dp + else -> 1.dp + } + @Composable fun DefaultAvatarThumbnailPlaceholderListItemImage( backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, From c5e1699b8cc7cbdd6c1e03b098cc626310577868 Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Tue, 3 Dec 2024 13:51:49 +0100 Subject: [PATCH 33/37] Remove deprecated AvatarThumbnails --- .../ui/OnboardingProfileFollowsScreen.kt | 4 +- .../compose/AvatarThumbnailListItemImage.kt | 64 +------------------ 2 files changed, 3 insertions(+), 65 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/auth/onboarding/account/ui/OnboardingProfileFollowsScreen.kt b/app/src/main/kotlin/net/primal/android/auth/onboarding/account/ui/OnboardingProfileFollowsScreen.kt index 69a408cbf..764c2b8f7 100644 --- a/app/src/main/kotlin/net/primal/android/auth/onboarding/account/ui/OnboardingProfileFollowsScreen.kt +++ b/app/src/main/kotlin/net/primal/android/auth/onboarding/account/ui/OnboardingProfileFollowsScreen.kt @@ -54,9 +54,9 @@ import net.primal.android.auth.onboarding.account.OnboardingContract import net.primal.android.auth.onboarding.account.OnboardingStep import net.primal.android.auth.onboarding.account.ui.model.FollowGroup import net.primal.android.auth.onboarding.account.ui.model.FollowGroupMember -import net.primal.android.core.compose.AvatarThumbnail import net.primal.android.core.compose.NostrUserText import net.primal.android.core.compose.PrimalTopAppBar +import net.primal.android.core.compose.UniversalAvatarThumbnail import net.primal.android.core.compose.button.PrimalFilledButton import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.ArrowBack @@ -373,7 +373,7 @@ private fun FollowGroupMemberListItem(member: FollowGroupMember, onClick: () -> containerColor = Color.White, ), leadingContent = { - AvatarThumbnail( + UniversalAvatarThumbnail( avatarCdnImage = member.metadata?.picture?.let { CdnImage(sourceUrl = it) }, ) }, diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index 4c4b88626..c3ebdd025 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -73,68 +73,6 @@ fun UniversalAvatarThumbnail( ) } -@Deprecated( - message = "This component is deprecated in favor of UniversalAvatarThumbnail", - replaceWith = ReplaceWith("UniversalAvatarThumbnail"), -) -@Composable -fun AvatarThumbnail( - modifier: Modifier = Modifier, - avatarCdnImage: CdnImage? = null, - avatarSize: Dp = 48.dp, - hasBorder: Boolean = false, - borderColor: Color = AppTheme.colorScheme.primary, - borderSize: Dp = 2.dp, - backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, - onClick: (() -> Unit)? = null, - defaultAvatar: @Composable () -> Unit = { DefaultAvatarThumbnailPlaceholderListItemImage() }, -) { - AvatarThumbnailCustomBorder( - modifier = modifier, - avatarCdnImage = avatarCdnImage, - avatarSize = avatarSize, - hasBorder = hasBorder, - borderBrush = Brush.linearGradient(listOf(borderColor, borderColor)), - borderSize = borderSize, - backgroundColor = backgroundColor, - onClick = onClick, - defaultAvatar = defaultAvatar, - ) -} - -@Deprecated( - message = "This component is deprecated in favor of UniversalAvatarThumbnail", - replaceWith = ReplaceWith("UniversalAvatarThumbnail"), -) -@Composable -fun AvatarThumbnailCustomBorder( - modifier: Modifier = Modifier, - avatarCdnImage: CdnImage? = null, - avatarSize: Dp = 48.dp, - hasBorder: Boolean = false, - borderBrush: Brush = Brush.linearGradient( - listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), - ), - borderSize: Dp = 2.dp, - backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, - onClick: (() -> Unit)? = null, - defaultAvatar: @Composable () -> Unit = { DefaultAvatarThumbnailPlaceholderListItemImage() }, -) { - val variant = avatarCdnImage?.variants?.minByOrNull { it.width } - val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl - AvatarThumbnailListItemImage( - modifier = modifier, - avatarSize = avatarSize, - source = imageSource, - hasBorder = hasBorder, - borderBrush = borderBrush, - borderSize = borderSize, - backgroundColor = backgroundColor, - onClick = onClick, - defaultAvatar = defaultAvatar, - ) -} - @Composable private fun AvatarThumbnailListItemImage( source: Any?, @@ -145,7 +83,7 @@ private fun AvatarThumbnailListItemImage( listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), ), borderSize: Dp = 2.dp, - @Suppress("UnusedParameter") hasGlow: Boolean = false, + hasGlow: Boolean = false, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, defaultAvatar: @Composable () -> Unit, From c7c4aa465e66ba91651b2c6b237dcc5aec2df2e2 Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Tue, 3 Dec 2024 13:59:13 +0100 Subject: [PATCH 34/37] Change borderSize argument to borderSizeOverride --- .../android/core/compose/AvatarThumbnailListItemImage.kt | 4 ++-- .../net/primal/android/core/compose/AvatarThumbnailsRow.kt | 2 +- .../android/core/compose/zaps/ZappersAvatarThumbnailRow.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index c3ebdd025..f8b329d80 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -40,7 +40,7 @@ fun UniversalAvatarThumbnail( hasGlowOverride: Boolean? = null, fallbackBorderColor: Color = Color.Transparent, legendaryCustomization: LegendaryCustomization? = null, - borderSize: Dp = 2.dp, + borderSizeOverride: Dp? = null, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, defaultAvatar: @Composable () -> Unit = { DefaultAvatarThumbnailPlaceholderListItemImage() }, @@ -66,7 +66,7 @@ fun UniversalAvatarThumbnail( ), ), hasGlow = (hasGlowOverride ?: legendaryCustomization?.avatarGlow) == true, - borderSize = avatarSize.mapAvatarSizeToBorderSize(), + borderSize = borderSizeOverride ?: avatarSize.mapAvatarSizeToBorderSize(), backgroundColor = backgroundColor, onClick = onClick, defaultAvatar = defaultAvatar, diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt index bb9b3011f..2cc3e4f9c 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailsRow.kt @@ -78,7 +78,7 @@ fun AvatarThumbnailsRow( hasBorder = hasAvatarBorder, legendaryCustomization = runCatching { avatarLegendaryCustomizations[layoutIndex] }.getOrNull(), fallbackBorderColor = avatarBorderColor, - borderSize = avatarBorderSize, + borderSizeOverride = avatarBorderSize, onClick = { onClick(layoutIndex) }, ) } diff --git a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt index 33cc7cdff..2f8bf9a3f 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/zaps/ZappersAvatarThumbnailRow.kt @@ -37,7 +37,7 @@ fun ZappersAvatarThumbnailRow(zaps: List, onClick: (() -> Unit) avatarSize = 24.dp, avatarCdnImage = zap.zapperAvatarCdnImage, hasBorder = true, - borderSize = 1.dp, + borderSizeOverride = 1.dp, fallbackBorderColor = AppTheme.colorScheme.surface, legendaryCustomization = zap.zapperLegendaryCustomization, onClick = onClick, From 6d6f2b99c5ad701e834fdfe6c301bbe5dcdc9b1f Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Tue, 3 Dec 2024 14:29:05 +0100 Subject: [PATCH 35/37] Remove hasGlow argument; Update borderBrush resolving; --- .../core/compose/AvatarThumbnailListItemImage.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index f8b329d80..5b12eb941 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -29,6 +29,7 @@ import net.primal.android.core.compose.icons.PrimalIcons import net.primal.android.core.compose.icons.primaliconpack.AvatarDefault import net.primal.android.core.images.AvatarCoilImageLoader import net.primal.android.premium.legend.LegendaryCustomization +import net.primal.android.premium.legend.LegendaryStyle import net.primal.android.theme.AppTheme @Composable @@ -37,9 +38,8 @@ fun UniversalAvatarThumbnail( avatarCdnImage: CdnImage? = null, avatarSize: Dp = 48.dp, hasBorder: Boolean = true, - hasGlowOverride: Boolean? = null, - fallbackBorderColor: Color = Color.Transparent, legendaryCustomization: LegendaryCustomization? = null, + fallbackBorderColor: Color = Color.Transparent, borderSizeOverride: Dp? = null, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, @@ -48,7 +48,9 @@ fun UniversalAvatarThumbnail( val variant = avatarCdnImage?.variants?.minByOrNull { it.width } val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl - val borderBrush = if (legendaryCustomization?.avatarGlow == true) { + val borderBrush = if (legendaryCustomization?.avatarGlow == true + && legendaryCustomization.legendaryStyle != LegendaryStyle.NO_CUSTOMIZATION + ) { legendaryCustomization.legendaryStyle?.brush } else { null @@ -65,7 +67,6 @@ fun UniversalAvatarThumbnail( fallbackBorderColor, ), ), - hasGlow = (hasGlowOverride ?: legendaryCustomization?.avatarGlow) == true, borderSize = borderSizeOverride ?: avatarSize.mapAvatarSizeToBorderSize(), backgroundColor = backgroundColor, onClick = onClick, @@ -83,7 +84,6 @@ private fun AvatarThumbnailListItemImage( listOf(AppTheme.colorScheme.primary, AppTheme.colorScheme.primary), ), borderSize: Dp = 2.dp, - hasGlow: Boolean = false, backgroundColor: Color = AppTheme.extraColorScheme.surfaceVariantAlt1, onClick: (() -> Unit)? = null, defaultAvatar: @Composable () -> Unit, From d943b65241afd4ba5089f688d31f9c66482d9005 Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Tue, 3 Dec 2024 14:31:17 +0100 Subject: [PATCH 36/37] Format code & fix detekt --- .../android/core/compose/AvatarThumbnailListItemImage.kt | 5 +++-- .../android/premium/buying/name/PremiumPrimalNameStage.kt | 4 +--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt index 5b12eb941..42af14585 100644 --- a/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt +++ b/app/src/main/kotlin/net/primal/android/core/compose/AvatarThumbnailListItemImage.kt @@ -48,8 +48,8 @@ fun UniversalAvatarThumbnail( val variant = avatarCdnImage?.variants?.minByOrNull { it.width } val imageSource = variant?.mediaUrl ?: avatarCdnImage?.sourceUrl - val borderBrush = if (legendaryCustomization?.avatarGlow == true - && legendaryCustomization.legendaryStyle != LegendaryStyle.NO_CUSTOMIZATION + val borderBrush = if (legendaryCustomization?.avatarGlow == true && + legendaryCustomization.legendaryStyle != LegendaryStyle.NO_CUSTOMIZATION ) { legendaryCustomization.legendaryStyle?.brush } else { @@ -151,6 +151,7 @@ fun Modifier.adjustAvatarBackground( } } +@Suppress("MagicNumber") private fun Dp.mapAvatarSizeToBorderSize(): Dp = when { this >= 112.dp -> 4.dp diff --git a/app/src/main/kotlin/net/primal/android/premium/buying/name/PremiumPrimalNameStage.kt b/app/src/main/kotlin/net/primal/android/premium/buying/name/PremiumPrimalNameStage.kt index 5c855a7ba..a306fcad4 100644 --- a/app/src/main/kotlin/net/primal/android/premium/buying/name/PremiumPrimalNameStage.kt +++ b/app/src/main/kotlin/net/primal/android/premium/buying/name/PremiumPrimalNameStage.kt @@ -100,9 +100,7 @@ private fun PremiumPrimalNameStage( .fillMaxWidth() .navigationBarsPadding() .padding(32.dp), - onClick = { - eventPublisher(PremiumPrimalNameContract.UiEvent.CheckPrimalName(primalName.text)) - }, + onClick = { eventPublisher(PremiumPrimalNameContract.UiEvent.CheckPrimalName(primalName.text)) }, ) { Text( text = stringResource(id = R.string.premium_primal_name_search_button), From d1027be16c32486d3b24e98e23e217a76acf4281 Mon Sep 17 00:00:00 2001 From: Aleksandar Ilic Date: Tue, 3 Dec 2024 15:07:59 +0100 Subject: [PATCH 37/37] Fix missing badge style in Explore People --- .../android/explore/home/people/ExplorePeople.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt b/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt index 498b4d8ff..a6d3e650a 100644 --- a/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt +++ b/app/src/main/kotlin/net/primal/android/explore/home/people/ExplorePeople.kt @@ -199,6 +199,11 @@ private fun ExplorePersonListItem( NostrUserText( displayName = person.profile.userDisplayName, internetIdentifier = person.profile.internetIdentifier, + customBadgeStyle = if (person.profile.legendaryCustomization?.customBadge == true) { + person.profile.legendaryCustomization.legendaryStyle + } else { + null + }, ) person.profile.internetIdentifier?.let { Text( @@ -234,13 +239,7 @@ private fun ExplorePersonListItem( fontSize = 12.sp, fontWeight = FontWeight.SemiBold, ), - onClick = { - if (isFollowed) { - onUnfollowClick() - } else { - onFollowClick() - } - }, + onClick = { if (isFollowed) onUnfollowClick() else onFollowClick() }, ) FollowersIndicator(