From 157802142cdfd886d35f0e66d7ce8764c68d6a7d Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 21 Jun 2023 14:51:44 -0400 Subject: [PATCH] Reorganizing Relay Info Page --- README.md | 4 +- .../amethyst/ui/actions/NewRelayListView.kt | 58 +-- .../ui/actions/RelayInformationDialog.kt | 370 ++++++++---------- .../ui/note/ChatroomMessageCompose.kt | 42 +- .../amethyst/ui/note/NoteCompose.kt | 16 +- .../amethyst/ui/note/UserCompose.kt | 26 +- .../ui/screen/loggedIn/VideoScreen.kt | 6 +- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 233 insertions(+), 291 deletions(-) diff --git a/README.md b/README.md index 31fd58e45..472cdcf6d 100644 --- a/README.md +++ b/README.md @@ -65,12 +65,12 @@ Or get the latest APK from the [Releases Section](https://github.com/vitorpamplo - [x] Recommended Application Handlers (NIP-89) - [x] Events with a Subject (NIP-14) - [x] Generic Reposts (kind:16) -- [x] Live Activities (NIP-102) +- [x] Live Activities & Live Chats (NIP-102) +- [x] Relay Pages (NIP-11) - [ ] Marketplace (NIP-15) - [ ] Image/Video Capture in the app - [ ] Local Database - [ ] Bookmarks, Pinned Posts, Muted Events (NIP-51) -- [ ] Relay Pages (NIP-11) - [ ] Proof of Work in the Phone (NIP-13, NIP-20) - [ ] Workspaces - [ ] Expiration Support (NIP-40) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt index a26776310..142b502c8 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewRelayListView.kt @@ -54,21 +54,14 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.RelayInformation import com.vitorpamplona.amethyst.model.RelaySetupInfo -import com.vitorpamplona.amethyst.service.HttpClient -import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource import com.vitorpamplona.amethyst.service.relays.FeedType import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.placeholderText import kotlinx.coroutines.launch -import okhttp3.Call -import okhttp3.Callback -import okhttp3.Request -import okhttp3.Response import java.lang.Math.round @Composable @@ -242,17 +235,11 @@ fun ServerConfig( var relayInfo: RelayInformation? by remember { mutableStateOf(null) } if (relayInfo != null) { - val user = LocalCache.getOrCreateUser(relayInfo!!.pubkey ?: "") - NostrUserProfileDataSource.loadUserProfile(user) - NostrUserProfileDataSource.start() RelayInformationDialog( onClose = { relayInfo = null - NostrUserProfileDataSource.loadUserProfile(null) - NostrUserProfileDataSource.stop() }, relayInfo = relayInfo!!, - user, accountViewModel, nav ) @@ -286,48 +273,9 @@ fun ServerConfig( modifier = Modifier .weight(1f) .clickable { - val client = HttpClient.getHttpClient() - val url = item.url - .replace("wss://", "https://") - .replace("ws://", "http://") - val request: Request = Request - .Builder() - .header("Accept", "application/nostr+json") - .url(url) - .build() - client - .newCall(request) - .enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - response.use { - if (it.isSuccessful) { - relayInfo = - RelayInformation.fromJson(it.body.string()) - } else { - scope.launch { - Toast - .makeText( - context, - context.getString(R.string.an_error_ocurred_trying_to_get_relay_information), - Toast.LENGTH_SHORT - ).show() - } - } - } - } - - override fun onFailure(call: Call, e: java.io.IOException) { - e.printStackTrace() - scope.launch { - Toast - .makeText( - context, - context.getString(R.string.an_error_ocurred_trying_to_get_relay_information), - Toast.LENGTH_SHORT - ).show() - } - } - }) + loadRelayInfo(item.url, context, scope) { + relayInfo = it + } }, maxLines = 1, overflow = TextOverflow.Ellipsis diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt index da8277af9..d9c0ff289 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/RelayInformationDialog.kt @@ -1,6 +1,7 @@ package com.vitorpamplona.amethyst.ui.actions -import androidx.compose.foundation.border +import android.content.Context +import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -10,83 +11,45 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Icon -import androidx.compose.material.LocalTextStyle -import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Downloading -import androidx.compose.material.icons.filled.Report import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.RelayInformation -import com.vitorpamplona.amethyst.model.User +import com.vitorpamplona.amethyst.service.HttpClient import com.vitorpamplona.amethyst.ui.components.ClickableEmail import com.vitorpamplona.amethyst.ui.components.ClickableUrl -import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji -import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer -import com.vitorpamplona.amethyst.ui.components.nip05VerificationAsAState -import com.vitorpamplona.amethyst.ui.note.UserPicture +import com.vitorpamplona.amethyst.ui.note.LoadUser +import com.vitorpamplona.amethyst.ui.note.UserCompose import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisplayLNAddress -import com.vitorpamplona.amethyst.ui.theme.Nip05 -import com.vitorpamplona.amethyst.ui.theme.placeholderText - -@Composable -fun Section(text: String) { - Spacer(modifier = Modifier.height(10.dp)) - Text( - text = text, - fontWeight = FontWeight.Bold, - fontSize = 25.sp - ) - Spacer(modifier = Modifier.height(10.dp)) -} - -@Composable -fun SectionContent(text: String) { - Text( - modifier = Modifier.padding(start = 10.dp), - text = text - ) -} +import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import okhttp3.Call +import okhttp3.Callback +import okhttp3.Request +import okhttp3.Response +import java.io.IOException @OptIn(ExperimentalLayoutApi::class) @Composable -fun RelayInformationDialog(onClose: () -> Unit, relayInfo: RelayInformation, baseUser: User, accountViewModel: AccountViewModel, nav: (String) -> Unit) { - val userState by baseUser.live().metadata.observeAsState() - val user = remember(userState) { userState?.user } ?: return - val tags = remember(userState) { userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() } - val lud16 = remember(userState) { user.info?.lud16?.trim() ?: user.info?.lud06?.trim() } - val pubkeyHex = remember { baseUser.pubkeyHex } - val uri = LocalUriHandler.current - val scrollState = rememberScrollState() - +fun RelayInformationDialog( + onClose: () -> Unit, + relayInfo: RelayInformation, + accountViewModel: AccountViewModel, + nav: (String) -> Unit +) { Dialog( onDismissRequest = { onClose() }, properties = DialogProperties( @@ -95,6 +58,8 @@ fun RelayInformationDialog(onClose: () -> Unit, relayInfo: RelayInformation, bas ) ) { Surface { + val scrollState = rememberScrollState() + Column( modifier = Modifier .padding(10.dp) @@ -112,141 +77,28 @@ fun RelayInformationDialog(onClose: () -> Unit, relayInfo: RelayInformation, bas } Row( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center ) { - Section(relayInfo.name ?: "") + Title(relayInfo.name ?: "") } - SectionContent(relayInfo.description ?: "") + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + SectionContent(relayInfo.description ?: "") + } Section(stringResource(R.string.owner)) - Row { - UserPicture( - baseUser = user, - accountViewModel = accountViewModel, - size = 100.dp, - modifier = Modifier.border( - 3.dp, - MaterialTheme.colors.background, - CircleShape - ), - onClick = { - nav("User/${user.pubkeyHex}") - } - ) - - Column(Modifier.padding(start = 10.dp)) { - (user.bestDisplayName() ?: user.bestUsername())?.let { - Row(verticalAlignment = Alignment.Bottom, modifier = Modifier.padding(top = 7.dp)) { - CreateTextWithEmoji( - text = it, - tags = tags, - fontWeight = FontWeight.Bold, - fontSize = 25.sp - ) - } - } - - if (user.bestDisplayName() != null) { - user.bestUsername()?.let { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(top = 1.dp, bottom = 1.dp) - ) { - CreateTextWithEmoji( - text = "@$it", - tags = tags, - color = MaterialTheme.colors.placeholderText - ) - } - } - } - - user.nip05()?.let { nip05 -> - if (nip05.split("@").size == 2) { - val nip05Verified by nip05VerificationAsAState(user.info!!, user.pubkeyHex) - Row(verticalAlignment = Alignment.CenterVertically) { - if (nip05Verified == null) { - Icon( - tint = Color.Yellow, - imageVector = Icons.Default.Downloading, - contentDescription = "Downloading", - modifier = Modifier.size(16.dp) - ) - } else if (nip05Verified == true) { - Icon( - painter = painterResource(R.drawable.ic_verified), - "NIP-05 Verified", - tint = Nip05, - modifier = Modifier.size(16.dp) - ) - } else { - Icon( - tint = Color.Red, - imageVector = Icons.Default.Report, - contentDescription = "Invalid Nip05", - modifier = Modifier.size(16.dp) - ) - } - - var domainPadStart = 5.dp - - if (nip05.split("@")[0] != "_") { - Text( - text = AnnotatedString(nip05.split("@")[0] + "@"), - modifier = Modifier.padding(top = 1.dp, bottom = 1.dp, start = 5.dp), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - domainPadStart = 0.dp - } - - ClickableText( - text = AnnotatedString(nip05.split("@")[1]), - onClick = { nip05.let { runCatching { uri.openUri("https://${it.split("@")[1]}") } } }, - style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary), - modifier = Modifier.padding(top = 1.dp, bottom = 1.dp, start = domainPadStart), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - } - - DisplayLNAddress(lud16, pubkeyHex, accountViewModel.account) - - user.info?.about?.let { - Row( - modifier = Modifier.padding(top = 5.dp, bottom = 5.dp) - ) { - val defaultBackground = MaterialTheme.colors.background - val background = remember { - mutableStateOf(defaultBackground) - } - - TranslatableRichTextViewer( - content = it, - canPreview = false, - tags = remember { ImmutableListOfLists(emptyList()) }, - backgroundColor = background, - accountViewModel = accountViewModel, - nav = nav - ) - } - } - } + relayInfo.pubkey?.let { + DisplayOwnerInformation(it, accountViewModel, nav) } Section(stringResource(R.string.software)) - val url = (relayInfo.software ?: "").replace("git+", "") - Box(modifier = Modifier.padding(start = 10.dp)) { - ClickableUrl( - urlText = url, - url = url - ) - } + DisplaySoftwareInformation(relayInfo) Section(stringResource(R.string.version)) @@ -260,27 +112,7 @@ fun RelayInformationDialog(onClose: () -> Unit, relayInfo: RelayInformation, bas Section(stringResource(R.string.supports)) - FlowRow { - relayInfo.supported_nips?.forEach { item -> - val text = item.toString().padStart(2, '0') - Box(Modifier.padding(10.dp)) { - ClickableUrl( - urlText = "Nip-$text", - url = "https://github.com/nostr-protocol/nips/blob/master/$text.md" - ) - } - } - - relayInfo.supported_nip_extensions?.forEach { item -> - val text = item.padStart(2, '0') - Box(Modifier.padding(10.dp)) { - ClickableUrl( - urlText = "Nip-$text", - url = "https://github.com/nostr-protocol/nips/blob/master/$text.md" - ) - } - } - } + DisplaySupportedNips(relayInfo) relayInfo.fees?.admission?.let { if (it.isNotEmpty()) { @@ -368,3 +200,137 @@ fun RelayInformationDialog(onClose: () -> Unit, relayInfo: RelayInformation, bas } } } + +@Composable +@OptIn(ExperimentalLayoutApi::class) +private fun DisplaySupportedNips(relayInfo: RelayInformation) { + FlowRow { + relayInfo.supported_nips?.forEach { item -> + val text = item.toString().padStart(2, '0') + Box(Modifier.padding(10.dp)) { + ClickableUrl( + urlText = "$text", + url = "https://github.com/nostr-protocol/nips/blob/master/$text.md" + ) + } + } + + relayInfo.supported_nip_extensions?.forEach { item -> + val text = item.padStart(2, '0') + Box(Modifier.padding(10.dp)) { + ClickableUrl( + urlText = "$text", + url = "https://github.com/nostr-protocol/nips/blob/master/$text.md" + ) + } + } + } +} + +@Composable +private fun DisplaySoftwareInformation(relayInfo: RelayInformation) { + val url = (relayInfo.software ?: "").replace("git+", "") + Box(modifier = Modifier.padding(start = 10.dp)) { + ClickableUrl( + urlText = url, + url = url + ) + } +} + +@Composable +private fun DisplayOwnerInformation( + userHex: String, + accountViewModel: AccountViewModel, + nav: (String) -> Unit +) { + LoadUser(baseUserHex = userHex) { + UserCompose(baseUser = it, accountViewModel = accountViewModel, showDiviser = false, nav = nav) + } +} + +@Composable +fun Title(text: String) { + Spacer(modifier = DoubleVertSpacer) + Text( + text = text, + fontWeight = FontWeight.Bold, + fontSize = 24.sp + ) + Spacer(modifier = DoubleVertSpacer) +} + +@Composable +fun Section(text: String) { + Spacer(modifier = DoubleVertSpacer) + Text( + text = text, + fontWeight = FontWeight.Bold, + fontSize = 20.sp + ) + Spacer(modifier = DoubleVertSpacer) +} + +@Composable +fun SectionContent(text: String) { + Text( + modifier = Modifier.padding(start = 10.dp), + text = text + ) +} + +fun loadRelayInfo( + dirtyUrl: String, + context: Context, + scope: CoroutineScope, + onInfo: (RelayInformation) -> Unit +) { + val url = if (dirtyUrl.contains("://")) { + dirtyUrl + .replace("wss://", "https://") + .replace("ws://", "http://") + } else { + "https://$dirtyUrl" + } + + val request: Request = Request + .Builder() + .header("Accept", "application/nostr+json") + .url(url) + .build() + + HttpClient.getHttpClient() + .newCall(request) + .enqueue( + object : Callback { + override fun onResponse(call: Call, response: Response) { + response.use { + if (it.isSuccessful) { + onInfo(RelayInformation.fromJson(it.body.string())) + } else { + scope.launch { + Toast + .makeText( + context, + context.getString(R.string.an_error_ocurred_trying_to_get_relay_information), + Toast.LENGTH_SHORT + ).show() + } + } + } + } + + override fun onFailure(call: Call, e: IOException) { + e.printStackTrace() + scope.launch { + Toast + .makeText( + context, + context.getString(R.string.an_error_ocurred_trying_to_get_relay_information), + Toast.LENGTH_SHORT + ).show() + } + } + } + ) +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index f5001d4ed..8e3627422 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -33,6 +33,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -44,7 +45,6 @@ import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.IntSize @@ -52,11 +52,14 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.model.RelayInformation import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent import com.vitorpamplona.amethyst.service.model.PrivateDmEvent import com.vitorpamplona.amethyst.ui.actions.ImmutableListOfLists +import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog +import com.vitorpamplona.amethyst.ui.actions.loadRelayInfo import com.vitorpamplona.amethyst.ui.actions.toImmutableListOfLists import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji import com.vitorpamplona.amethyst.ui.components.CreateTextWithEmoji @@ -433,6 +436,7 @@ private fun MessageBubbleLines( StatusRow( baseNote = baseNote, accountViewModel = accountViewModel, + nav = nav, onWantsToReply = onWantsToReply ) } @@ -545,12 +549,13 @@ private fun ConstrainedStatusRow( private fun StatusRow( baseNote: Note, accountViewModel: AccountViewModel, + nav: (String) -> Unit, onWantsToReply: (Note) -> Unit ) { Column { Row(verticalAlignment = Alignment.CenterVertically) { ChatTimeAgo(baseNote) - RelayBadges(baseNote) + RelayBadges(baseNote, accountViewModel, nav = nav) Spacer(modifier = DoubleHorzSpacer) } } @@ -800,7 +805,7 @@ data class RelayBadgesState( @OptIn(ExperimentalLayoutApi::class) @Composable -private fun RelayBadges(baseNote: Note) { +private fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) { val noteRelaysState by baseNote.live().relays.observeAsState() val state: RelayBadgesState by remember(noteRelaysState) { @@ -821,7 +826,7 @@ private fun RelayBadges(baseNote: Note) { FlowRow(Modifier.padding(start = 10.dp)) { relaysToDisplay.forEach { - RenderRelay(it) + RenderRelay(it, accountViewModel, nav) } } @@ -841,22 +846,37 @@ private fun RelayBadges(baseNote: Note) { } @Composable -fun RenderRelay(dirtyUrl: String) { - val uri = LocalUriHandler.current - val website = remember(dirtyUrl) { - val cleanUrl = dirtyUrl.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/") - "https://$cleanUrl" - } +fun RenderRelay(dirtyUrl: String, accountViewModel: AccountViewModel, nav: (String) -> Unit) { val iconUrl = remember(dirtyUrl) { val cleanUrl = dirtyUrl.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/") "https://$cleanUrl/favicon.ico" } + var relayInfo: RelayInformation? by remember { mutableStateOf(null) } + + if (relayInfo != null) { + RelayInformationDialog( + onClose = { + relayInfo = null + }, + relayInfo = relayInfo!!, + accountViewModel, + nav + ) + } + + val context = LocalContext.current + val scope = rememberCoroutineScope() + val clickableModifier = remember(dirtyUrl) { Modifier .padding(1.dp) .size(15.dp) - .clickable(onClick = { uri.openUri(website) }) + .clickable(onClick = { + loadRelayInfo(dirtyUrl, context, scope) { + relayInfo = it + } + }) } val backgroundColor = MaterialTheme.colors.background diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index c99f11af3..f4e9e2090 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -1872,10 +1872,10 @@ private fun DrawAuthorImages(baseNote: Note, accountViewModel: AccountViewModel, baseNote.replyTo?.lastOrNull() } baseReply?.let { - RelayBadges(it) + RelayBadges(it, accountViewModel, nav) } } else { - RelayBadges(baseNote) + RelayBadges(baseNote, accountViewModel, nav) } } } @@ -2691,7 +2691,7 @@ private fun CreateImageHeader( } @Composable -private fun RelayBadges(baseNote: Note) { +private fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) { var expanded by remember { mutableStateOf(false) } var showShowMore by remember { mutableStateOf(false) } @@ -2714,9 +2714,9 @@ private fun RelayBadges(baseNote: Note) { Spacer(DoubleVertSpacer) if (expanded) { - VerticalRelayPanelWithFlow(lazyRelayList) + VerticalRelayPanelWithFlow(lazyRelayList, accountViewModel, nav) } else { - VerticalRelayPanelWithFlow(shortRelayList) + VerticalRelayPanelWithFlow(shortRelayList, accountViewModel, nav) } if (showShowMore && !expanded) { @@ -2745,12 +2745,14 @@ private fun WatchRelayLists(baseNote: Note, onListChanges: (ImmutableList + relays: ImmutableList, + accountViewModel: AccountViewModel, + nav: (String) -> Unit ) { // FlowRow Seems to be a lot faster than LazyVerticalGrid FlowRow() { relays.forEach { url -> - RenderRelay(url) + RenderRelay(url, accountViewModel, nav) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt index 6ada9d00c..e16dc87fd 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/UserCompose.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.Divider import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -16,12 +17,15 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @Composable fun UserCompose( baseUser: User, - overallModifier: Modifier = Modifier - .padding( - start = 12.dp, - end = 12.dp, - top = 10.dp - ), + overallModifier: Modifier = remember { + Modifier + .padding( + start = 12.dp, + end = 12.dp, + top = 10.dp + ) + }, + showDiviser: Boolean = true, accountViewModel: AccountViewModel, nav: (String) -> Unit ) { @@ -50,9 +54,11 @@ fun UserCompose( } } - Divider( - modifier = Modifier.padding(top = 10.dp), - thickness = 0.25.dp - ) + if (showDiviser) { + Divider( + modifier = Modifier.padding(top = 10.dp), + thickness = 0.25.dp + ) + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt index 66a3f41d7..90e3c1f70 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt @@ -319,7 +319,7 @@ private fun RenderVideoOrPicture( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = 2.dp) ) { - RelayBadges(baseNote = note) + RelayBadges(baseNote = note, accountViewModel, nav) } } } @@ -354,7 +354,7 @@ private fun VideoUserOptionAction( @OptIn(ExperimentalLayoutApi::class) @Composable -private fun RelayBadges(baseNote: Note) { +private fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) { val noteRelaysState by baseNote.live().relays.observeAsState() val noteRelays = remember(noteRelaysState) { noteRelaysState?.note?.relays ?: emptySet() @@ -362,7 +362,7 @@ private fun RelayBadges(baseNote: Note) { FlowRow() { noteRelays.forEach { dirtyUrl -> - RenderRelay(dirtyUrl) + RenderRelay(dirtyUrl, accountViewModel, nav) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 51f7e4f2e..f78d10a78 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -430,7 +430,7 @@ Version Software Contact - Supports + Supported NIPs Admission Fees Payments url Limitations