Fixes the centralization of the "and more" part of relay recommendations

This commit is contained in:
Vitor Pamplona
2024-08-14 18:50:26 -04:00
parent 7478899388
commit d6d8719c8d
6 changed files with 80 additions and 22 deletions

View File

@@ -55,7 +55,7 @@ data class Kind3RelayProposalSetupInfo(
val feedTypes: Set<FeedType>, val feedTypes: Set<FeedType>,
val relayStat: RelayStat, val relayStat: RelayStat,
val paidRelay: Boolean = false, val paidRelay: Boolean = false,
val users: Set<HexKey>, val users: List<HexKey>,
) { ) {
val briefInfo: RelayBriefInfoCache.RelayBriefInfo = RelayBriefInfoCache.RelayBriefInfo(url) val briefInfo: RelayBriefInfoCache.RelayBriefInfo = RelayBriefInfoCache.RelayBriefInfo(url)
} }

View File

@@ -164,7 +164,7 @@ class Kind3RelayListViewModel : ViewModel() {
write = false, write = false,
feedTypes = setOf(FeedType.FOLLOWS), feedTypes = setOf(FeedType.FOLLOWS),
relayStat = RelayStats.get(it.url), relayStat = RelayStats.get(it.url),
users = it.users, users = it.users.sorted(),
) )
} else { } else {
null null

View File

@@ -22,12 +22,14 @@ package com.vitorpamplona.amethyst.ui.actions.relays
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@@ -40,21 +42,26 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.Nip11CachedRetriever import com.vitorpamplona.amethyst.service.Nip11CachedRetriever
import com.vitorpamplona.amethyst.ui.components.mockAccountViewModel
import com.vitorpamplona.amethyst.ui.note.AddRelayButton import com.vitorpamplona.amethyst.ui.note.AddRelayButton
import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon
import com.vitorpamplona.amethyst.ui.note.UserPicture import com.vitorpamplona.amethyst.ui.note.UserPicture
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.HalfHorzPadding import com.vitorpamplona.amethyst.ui.theme.HalfHorzPadding
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth
import com.vitorpamplona.amethyst.ui.theme.Size25dp import com.vitorpamplona.amethyst.ui.theme.Size25dp
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
import com.vitorpamplona.amethyst.ui.theme.allGoodColor import com.vitorpamplona.amethyst.ui.theme.allGoodColor
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.RelayStat
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
@@ -111,23 +118,9 @@ fun Kind3RelaySetupInfoProposalRow(
) )
} }
} }
}
FlowRow(verticalArrangement = Arrangement.Center) { UsedBy(item, accountViewModel, nav)
item.users.take(3).forEach {
UserPicture(
userHex = it,
size = Size25dp,
accountViewModel = accountViewModel,
nav = nav,
)
}
if (item.users.size > 3) {
Text(
text = stringResource(R.string.and_more),
)
}
}
}
Column( Column(
Modifier Modifier
@@ -140,3 +133,68 @@ fun Kind3RelaySetupInfoProposalRow(
HorizontalDivider(thickness = DividerThickness) HorizontalDivider(thickness = DividerThickness)
} }
} }
@Preview
@Composable
fun UsedByPreview() {
val accountViewModel = mockAccountViewModel()
ThemeComparisonColumn {
UsedBy(
item =
Kind3RelayProposalSetupInfo(
"wss://nos.lol",
true,
true,
COMMON_FEED_TYPES,
relayStat = RelayStat(),
paidRelay = false,
users = listOf("User1", "User2", "User3", "User4"),
),
accountViewModel = accountViewModel,
) {
}
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun UsedBy(
item: Kind3RelayProposalSetupInfo,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
FlowRow(verticalArrangement = Arrangement.Center) {
item.users.getOrNull(0)?.let {
UserPicture(
userHex = it,
size = Size25dp,
accountViewModel = accountViewModel,
nav = nav,
)
}
item.users.getOrNull(1)?.let {
UserPicture(
userHex = it,
size = Size25dp,
accountViewModel = accountViewModel,
nav = nav,
)
}
item.users.getOrNull(2)?.let {
UserPicture(
userHex = it,
size = Size25dp,
accountViewModel = accountViewModel,
nav = nav,
)
}
if (item.users.size > 3) {
Box(contentAlignment = Alignment.Center, modifier = Modifier.height(Size25dp)) {
Text(
text = stringRes(R.string.and_more, item.users.size - 3),
maxLines = 1,
)
}
}
}
}

View File

@@ -805,5 +805,5 @@
<string name="add_a_nip96_server">Dodaj serwer NIP-96</string> <string name="add_a_nip96_server">Dodaj serwer NIP-96</string>
<string name="delete_all">Usuń wszystko</string> <string name="delete_all">Usuń wszystko</string>
<string name="delete_all_drafts_confirmation">Czy na pewno chcesz usunąć wszystkie wersje robocze?</string> <string name="delete_all_drafts_confirmation">Czy na pewno chcesz usunąć wszystkie wersje robocze?</string>
<string name="and_more">" ... i więcej"</string> <string name="and_more">" ... i %1$s więcej"</string>
</resources> </resources>

View File

@@ -805,5 +805,5 @@
<string name="add_a_nip96_server">添加 NIP-96 服务器</string> <string name="add_a_nip96_server">添加 NIP-96 服务器</string>
<string name="delete_all">删除所有</string> <string name="delete_all">删除所有</string>
<string name="delete_all_drafts_confirmation">确定要删除所有草稿吗?</string> <string name="delete_all_drafts_confirmation">确定要删除所有草稿吗?</string>
<string name="and_more">" ... 和更多"</string> <string name="and_more">" ... 和 %1$s 更多"</string>
</resources> </resources>

View File

@@ -951,5 +951,5 @@
<string name="add_a_nip96_server">Add a NIP-96 Server</string> <string name="add_a_nip96_server">Add a NIP-96 Server</string>
<string name="delete_all">Delete all</string> <string name="delete_all">Delete all</string>
<string name="delete_all_drafts_confirmation">Are you sure you want to delete all drafts?</string> <string name="delete_all_drafts_confirmation">Are you sure you want to delete all drafts?</string>
<string name="and_more">" ... and more"</string> <string name="and_more">" ... and %1$s more"</string>
</resources> </resources>