Improves edge to edge margins and colors for the RelayInfoDialog

This commit is contained in:
Vitor Pamplona
2025-05-15 11:49:25 -04:00
parent 42e20efaa5
commit afe04969ee
11 changed files with 151 additions and 106 deletions
@@ -23,27 +23,38 @@ package com.vitorpamplona.amethyst.ui.components
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.DialogWindowProvider
import androidx.core.view.WindowCompat
import com.vitorpamplona.amethyst.ui.theme.isLight
@Composable
fun SetDialogToEdgeToEdge() {
val activityWindow = getActivityWindow()
val dialogWindow = (LocalView.current.parent as? DialogWindowProvider)?.window
val parentView = LocalView.current.parent as View
val isLight = MaterialTheme.colorScheme.isLight
SideEffect {
if (activityWindow != null && dialogWindow != null) {
val attributes = WindowManager.LayoutParams()
attributes.copyFrom(activityWindow.attributes)
attributes.type = dialogWindow.attributes.type
dialogWindow.attributes = attributes
dialogWindow.statusBarColor
parentView.layoutParams =
FrameLayout.LayoutParams(
activityWindow.decorView.width,
activityWindow.decorView.height,
)
val insets = WindowCompat.getInsetsController(dialogWindow, parentView)
insets.isAppearanceLightNavigationBars = isLight
insets.isAppearanceLightStatusBars = isLight
}
}
}
@@ -121,18 +121,20 @@ fun RenderRelay(
accountViewModel: AccountViewModel,
nav: INav,
) {
val relayInfo = loadRelayInfo(relay.url, accountViewModel)
val relayInfo by loadRelayInfo(relay.url, accountViewModel)
var openRelayDialog by remember { mutableStateOf(false) }
if (openRelayDialog && relayInfo != null) {
RelayInformationDialog(
onClose = { openRelayDialog = false },
relayInfo = relayInfo,
relayBriefInfo = relay,
accountViewModel = accountViewModel,
nav = nav,
)
if (openRelayDialog) {
relayInfo?.let {
RelayInformationDialog(
onClose = { openRelayDialog = false },
relayInfo = it,
relayBriefInfo = relay,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
val clipboardManager = LocalClipboardManager.current
@@ -238,7 +238,7 @@ fun RenderRelayLinePublicChat(
nav: INav,
) {
@Suppress("ProduceStateDoesNotAssignValue")
val relayInfo = loadRelayInfo(dirtyUrl, accountViewModel)
val relayInfo by loadRelayInfo(dirtyUrl, accountViewModel)
var openRelayDialog by remember { mutableStateOf(false) }
@@ -247,14 +247,16 @@ fun RenderRelayLinePublicChat(
RelayBriefInfoCache.get(RelayUrlFormatter.normalize(dirtyUrl))
}
if (openRelayDialog && relayInfo != null) {
RelayInformationDialog(
onClose = { openRelayDialog = false },
relayInfo = relayInfo!!,
relayBriefInfo = info,
accountViewModel = accountViewModel,
nav = nav,
)
if (openRelayDialog) {
relayInfo?.let {
RelayInformationDialog(
onClose = { openRelayDialog = false },
relayInfo = it,
relayBriefInfo = info,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
val clipboardManager = LocalClipboardManager.current
@@ -27,6 +27,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
@@ -57,21 +58,22 @@ import com.vitorpamplona.quartz.nip65RelayList.RelayUrlFormatter
fun loadRelayInfo(
relayUrl: String,
accountViewModel: AccountViewModel,
): Nip11RelayInformation? {
): State<Nip11RelayInformation?> {
@Suppress("ProduceStateDoesNotAssignValue")
val relayInfo by produceStateIfNotNull(
Nip11CachedRetriever.getFromCache(relayUrl),
relayUrl,
) {
accountViewModel.retrieveRelayDocument(
val relayInfo =
produceStateIfNotNull(
Nip11CachedRetriever.getFromCache(relayUrl),
relayUrl,
onInfo = {
value = it
},
onError = { url, errorCode, exceptionMessage ->
},
)
}
) {
accountViewModel.retrieveRelayDocument(
relayUrl,
onInfo = {
value = it
},
onError = { url, errorCode, exceptionMessage ->
},
)
}
return relayInfo
}
@@ -121,7 +123,7 @@ private fun DrawRelayIcon(
channel: EphemeralChatChannel,
accountViewModel: AccountViewModel,
) {
val relayInfo = loadRelayInfo(channel.roomId.relayUrl, accountViewModel)
val relayInfo by loadRelayInfo(channel.roomId.relayUrl, accountViewModel)
val info =
remember(channel.roomId.relayUrl) {
RelayBriefInfoCache.get(RelayUrlFormatter.normalize(channel.roomId.relayUrl))
@@ -228,7 +228,7 @@ private fun ChannelRoomCompose(
val authorName by observeUserName(note.author!!, accountViewModel)
val channelState by observeChannel(channel, accountViewModel)
val relayInfo = loadRelayInfo(channel.roomId.relayUrl, accountViewModel)
val relayInfo by loadRelayInfo(channel.roomId.relayUrl, accountViewModel)
val info =
remember(channel.roomId.relayUrl) {
RelayBriefInfoCache.get(RelayUrlFormatter.normalize(channel.roomId.relayUrl))
@@ -27,15 +27,17 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -61,21 +63,25 @@ import com.vitorpamplona.amethyst.ui.note.RenderRelayIcon
import com.vitorpamplona.amethyst.ui.note.UserCompose
import com.vitorpamplona.amethyst.ui.note.timeAgo
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.LoadUser
import com.vitorpamplona.amethyst.ui.screen.loggedIn.qrcode.BackButton
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.HalfVertSpacer
import com.vitorpamplona.amethyst.ui.theme.LargeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.Size10dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
import com.vitorpamplona.ammolite.relays.RelayBriefInfoCache
import com.vitorpamplona.ammolite.relays.RelayStats
import com.vitorpamplona.quartz.nip01Core.relay.RelayDebugMessage
import com.vitorpamplona.quartz.nip02FollowList.EmptyTagList
import com.vitorpamplona.quartz.nip11RelayInfo.Nip11RelayInformation
import kotlinx.collections.immutable.toImmutableList
@OptIn(ExperimentalLayoutApi::class)
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
fun RelayInformationDialog(
onClose: () -> Unit,
@@ -106,29 +112,34 @@ fun RelayInformationDialog(
),
) {
SetDialogToEdgeToEdge()
Surface {
val color =
remember {
mutableStateOf(Color.Transparent)
}
val context = LocalContext.current
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
TopAppBar(
actions = {},
title = {
Text(relayBriefInfo.displayUrl)
},
navigationIcon = {
Row {
Spacer(modifier = StdHorzSpacer)
BackButton(
onPress = { onClose() },
)
}
},
)
},
) { pad ->
LazyColumn(
modifier =
Modifier
.padding(10.dp)
.padding(pad)
.consumeWindowInsets(pad)
.padding(bottom = Size10dp, start = Size10dp, end = Size10dp)
.fillMaxSize(),
) {
item {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
CloseButton(onPress = { onClose() })
}
}
item {
Row(
verticalAlignment = Alignment.CenterVertically,
@@ -142,7 +153,7 @@ fun RelayInformationDialog(
loadProfilePicture = accountViewModel.settings.showProfilePictures.value,
loadRobohash = accountViewModel.settings.featureSet != FeatureSetType.PERFORMANCE,
RelayStats.get(url = relayBriefInfo.url).pingInMs,
iconModifier = MaterialTheme.colorScheme.largeRelayIconModifier,
iconModifier = LargeRelayIconModifier,
)
}
@@ -150,10 +161,16 @@ fun RelayInformationDialog(
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Title(relayInfo.name?.trim() ?: "")
SubtitleContent(relayInfo.description?.trim() ?: "")
Spacer(modifier = HalfVertSpacer)
SubtitleContent(relayBriefInfo.url)
}
}
}
item {
Section(stringRes(R.string.description))
SectionContent(relayInfo.description?.trim() ?: "")
}
item {
Section(stringRes(R.string.owner))
@@ -161,15 +178,6 @@ fun RelayInformationDialog(
DisplayOwnerInformation(it, accountViewModel, newNav)
}
}
item {
Section(stringRes(R.string.software))
DisplaySoftwareInformation(relayInfo)
Section(stringRes(R.string.version))
SectionContent(relayInfo.version ?: "")
}
item {
Section(stringRes(R.string.contact))
@@ -185,6 +193,15 @@ fun RelayInformationDialog(
}
}
}
item {
Section(stringRes(R.string.software))
DisplaySoftwareInformation(relayInfo)
Section(stringRes(R.string.version))
SectionContent(relayInfo.version ?: "")
}
item {
Section(stringRes(R.string.supports))
@@ -290,22 +307,7 @@ fun RelayInformationDialog(
items(messages) { msg ->
Row {
SelectionContainer {
TranslatableRichTextViewer(
content =
remember {
"${timeAgo(msg.time, context)}, ${msg.type.name}: ${msg.message}"
},
canPreview = false,
quotesLeft = 0,
modifier = Modifier.fillMaxWidth(),
tags = EmptyTagList,
backgroundColor = color,
id = msg.hashCode().toString(),
accountViewModel = accountViewModel,
nav = newNav,
)
}
RenderDebugMessage(msg, accountViewModel, newNav)
}
Spacer(modifier = StdVertSpacer)
@@ -315,6 +317,35 @@ fun RelayInformationDialog(
}
}
@Composable
private fun RenderDebugMessage(
msg: RelayDebugMessage,
accountViewModel: AccountViewModel,
newNav: INav,
) {
SelectionContainer {
val context = LocalContext.current
val color =
remember {
mutableStateOf(Color.Transparent)
}
TranslatableRichTextViewer(
content =
remember {
"${timeAgo(msg.time, context)}, ${msg.type.name}: ${msg.message}"
},
canPreview = false,
quotesLeft = 0,
modifier = Modifier.fillMaxWidth(),
tags = EmptyTagList,
backgroundColor = color,
id = msg.hashCode().toString(),
accountViewModel = accountViewModel,
nav = newNav,
)
}
}
@Composable
@OptIn(ExperimentalLayoutApi::class)
private fun DisplaySupportedNips(relayInfo: Nip11RelayInformation) {
@@ -27,8 +27,8 @@ 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.MaterialTheme
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
@@ -40,8 +40,8 @@ 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.LargeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -68,15 +68,15 @@ fun BasicRelaySetupInfoClickableRow(
verticalAlignment = Alignment.CenterVertically,
modifier = HalfVertPadding,
) {
val iconUrlFromRelayInfoDoc = loadRelayInfo(item.url, accountViewModel)?.icon
val iconUrlFromRelayInfoDoc by loadRelayInfo(item.url, accountViewModel)
RenderRelayIcon(
item.briefInfo.displayUrl,
iconUrlFromRelayInfoDoc ?: item.briefInfo.favIcon,
iconUrlFromRelayInfoDoc?.icon ?: item.briefInfo.favIcon,
loadProfilePicture,
loadRobohash,
item.relayStat.pingInMs,
MaterialTheme.colorScheme.largeRelayIconModifier,
LargeRelayIconModifier,
)
Spacer(modifier = HalfHorzPadding)
@@ -86,13 +86,13 @@ import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import com.vitorpamplona.amethyst.ui.theme.HalfHorzPadding
import com.vitorpamplona.amethyst.ui.theme.HalfStartPadding
import com.vitorpamplona.amethyst.ui.theme.LargeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth
import com.vitorpamplona.amethyst.ui.theme.Size30Modifier
import com.vitorpamplona.amethyst.ui.theme.Size35dp
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.WarningColor
import com.vitorpamplona.amethyst.ui.theme.allGoodColor
import com.vitorpamplona.amethyst.ui.theme.largeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.warningColor
import com.vitorpamplona.ammolite.relays.Constants.activeTypesGlobalChats
@@ -334,7 +334,7 @@ fun ClickableRelayItem(
loadProfilePicture,
loadRobohash,
item.relayStat.pingInMs,
MaterialTheme.colorScheme.largeRelayIconModifier,
LargeRelayIconModifier,
)
Spacer(modifier = HalfHorzPadding)
@@ -39,6 +39,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
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.text.style.TextOverflow
@@ -56,11 +57,11 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
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.LargeRelayIconModifier
import com.vitorpamplona.amethyst.ui.theme.ReactionRowHeightChatMaxWidth
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.largeRelayIconModifier
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.quartz.nip01Core.relay.RelayStat
@@ -84,7 +85,7 @@ fun Kind3RelaySetupInfoProposalRow(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(vertical = 5.dp),
) {
val relayInfo = loadRelayInfo(item.url, accountViewModel)
val relayInfo by loadRelayInfo(item.url, accountViewModel)
RenderRelayIcon(
item.briefInfo.displayUrl,
@@ -92,7 +93,7 @@ fun Kind3RelaySetupInfoProposalRow(
loadProfilePicture,
loadRobohash,
item.relayStat.pingInMs,
MaterialTheme.colorScheme.largeRelayIconModifier,
LargeRelayIconModifier,
)
Spacer(modifier = HalfHorzPadding)
@@ -323,3 +323,13 @@ val SettingsCategorySpacingModifier = Modifier.padding(top = 24.dp, bottom = 8.d
val SquaredQuoteBorderModifier = Modifier.aspectRatio(1f).clip(shape = QuoteBorder)
val FillWidthQuoteBorderModifier = Modifier.fillMaxWidth().clip(shape = QuoteBorder)
val MediumRelayIconModifier =
Modifier
.size(Size35dp)
.clip(shape = CircleShape)
val LargeRelayIconModifier =
Modifier
.size(Size55dp)
.clip(shape = CircleShape)
@@ -248,16 +248,6 @@ val DarkRelayIconModifier =
.size(Size13dp)
.clip(shape = CircleShape)
val LightLargeRelayIconModifier =
Modifier
.size(Size55dp)
.clip(shape = CircleShape)
val DarkLargeRelayIconModifier =
Modifier
.size(Size55dp)
.clip(shape = CircleShape)
val darkLargeProfilePictureModifier =
Modifier
.width(120.dp)
@@ -449,10 +439,6 @@ val ColorScheme.userProfileBorderModifier: Modifier
val ColorScheme.relayIconModifier: Modifier
get() = if (isLight) LightRelayIconModifier else DarkRelayIconModifier
@Suppress("ModifierFactoryExtensionFunction")
val ColorScheme.largeRelayIconModifier: Modifier
get() = if (isLight) LightLargeRelayIconModifier else DarkLargeRelayIconModifier
@Suppress("ModifierFactoryExtensionFunction")
val ColorScheme.selectedReactionBoxModifier: Modifier
get() = if (isLight) LightSelectedReactionBoxModifier else DarkSelectedReactionBoxModifier