diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfo.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfo.kt index 3fac4efd4..1d2655ac1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfo.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfo.kt @@ -21,6 +21,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common import androidx.compose.runtime.Immutable +import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStat import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl @@ -31,6 +32,7 @@ data class BasicRelaySetupInfo( val relayStat: RelayStat, val paidRelay: Boolean = false, val forcesTor: Boolean = false, + val users: List = emptyList(), ) fun relaySetupInfoBuilder( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoClickableRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoClickableRow.kt index 98da2d921..ec65c11c5 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoClickableRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoClickableRow.kt @@ -22,26 +22,37 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.text.AnnotatedString +import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.model.LocalCache.users +import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav.nav +import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon +import com.vitorpamplona.amethyst.ui.note.UserPicture import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.ephemChat.header.loadRelayInfo +import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.HalfHorzPadding import com.vitorpamplona.amethyst.ui.theme.HalfStartPadding import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding +import com.vitorpamplona.amethyst.ui.theme.Height25Modifier import com.vitorpamplona.amethyst.ui.theme.LargeRelayIconModifier import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth +import com.vitorpamplona.amethyst.ui.theme.Size25dp import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl @OptIn(ExperimentalFoundationApi::class) @@ -53,6 +64,7 @@ fun BasicRelaySetupInfoClickableRow( onDelete: ((BasicRelaySetupInfo) -> Unit)?, onClick: () -> Unit, accountViewModel: AccountViewModel, + nav: INav, ) { val clipboardManager = LocalClipboardManager.current Column( @@ -90,6 +102,8 @@ fun BasicRelaySetupInfoClickableRow( ReactionRowHeightChatMaxWidth, ) + UsedBy(item, accountViewModel, nav) + Row( verticalAlignment = Alignment.CenterVertically, modifier = ReactionRowHeightChatMaxWidth, @@ -106,3 +120,56 @@ fun BasicRelaySetupInfoClickableRow( HorizontalDivider(thickness = DividerThickness) } } + +@OptIn(ExperimentalLayoutApi::class) +@Composable +fun UsedBy( + item: BasicRelaySetupInfo, + accountViewModel: AccountViewModel, + nav: INav, +) { + if (item.users.isNotEmpty()) { + Row(verticalAlignment = Alignment.CenterVertically) { + item.users.getOrNull(0)?.let { + UserPicture( + user = it, + size = Size25dp, + accountViewModel = accountViewModel, + nav = nav, + ) + } + item.users.getOrNull(1)?.let { + UserPicture( + user = it, + size = Size25dp, + accountViewModel = accountViewModel, + nav = nav, + ) + } + item.users.getOrNull(2)?.let { + UserPicture( + user = it, + size = Size25dp, + accountViewModel = accountViewModel, + nav = nav, + ) + } + item.users.getOrNull(3)?.let { + UserPicture( + user = it, + size = Size25dp, + accountViewModel = accountViewModel, + nav = nav, + ) + } + if (item.users.size > 4) { + Box(contentAlignment = Alignment.Center, modifier = Height25Modifier) { + Text( + text = stringRes(R.string.and_more, item.users.size - 4), + maxLines = 1, + ) + } + } + } + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoDialog.kt index e5b2b7b4a..6ca31d0b1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoDialog.kt @@ -44,5 +44,6 @@ fun BasicRelaySetupInfoDialog( onDelete = onDelete, accountViewModel = accountViewModel, onClick = { nav.nav(Route.RelayInfo(item.relay.url)) }, + nav = nav, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoModel.kt index 9f84c96d5..89875455a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/common/BasicRelaySetupInfoModel.kt @@ -83,22 +83,24 @@ abstract class BasicRelaySetupInfoModel : ViewModel() { } } - fun clear() { - _relays.update { - val relayList = getRelayList() ?: emptyList() + open fun relayListBuilder(): List { + val relayList = getRelayList() ?: emptyList() - relayList - .map { - relaySetupInfoBuilder( - normalized = it, - forcesTor = - account.torRelayState.flow.value - .useTor(it), - ) - }.distinctBy { it.relay } - .sortedBy { it.relayStat.receivedBytes } - .reversed() - } + return relayList + .map { + relaySetupInfoBuilder( + normalized = it, + forcesTor = + account.torRelayState.flow.value + .useTor(it), + ) + }.distinctBy { it.relay } + .sortedBy { it.relayStat.receivedBytes } + .reversed() + } + + fun clear() { + _relays.update { relayListBuilder() } } fun addRelay(relay: BasicRelaySetupInfo) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/connected/ConnectedRelayListViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/connected/ConnectedRelayListViewModel.kt index 975953387..a76ebe9ee 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/connected/ConnectedRelayListViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/connected/ConnectedRelayListViewModel.kt @@ -20,10 +20,34 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.connected +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfo import com.vitorpamplona.amethyst.ui.screen.loggedIn.relays.common.BasicRelaySetupInfoModel +import com.vitorpamplona.quartz.nip01Core.relay.client.stats.RelayStats import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class ConnectedRelayListViewModel : BasicRelaySetupInfoModel() { + override fun relayListBuilder(): List { + val relayList = getRelayList() + + return relayList + .map { + BasicRelaySetupInfo( + relay = it, + relayStat = RelayStats.get(it), + forcesTor = + account.torRelayState.flow.value + .useTor(it), + users = + account.followsPerRelay.value[it]?.mapNotNull { hex -> + LocalCache.checkGetOrCreateUser(hex) + } ?: emptyList(), + ) + }.distinctBy { it.relay } + .sortedBy { it.relayStat.receivedBytes } + .reversed() + } + override fun getRelayList(): List = account.client .relayStatusFlow() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt index 704938d0d..71568c03c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt @@ -189,6 +189,7 @@ val UserNameMaxRowHeight = Modifier.fillMaxWidth() val Height24dpModifier = Modifier.height(24.dp) val Height4dpModifier = Modifier.height(4.dp) +val Height25Modifier = Modifier.height(Size25dp) val Height24dpFilledModifier = Modifier.fillMaxWidth().height(24.dp) val Height4dpFilledModifier = Modifier.fillMaxWidth().height(4.dp)