From c7a9bd12265de7a94937128c31d09e7f2213fac3 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 20 Apr 2023 17:19:34 -0400 Subject: [PATCH] Using FlowRow to display relay icons. --- .../amethyst/ui/note/NoteCompose.kt | 141 +++++++++++------- 1 file changed, 86 insertions(+), 55 deletions(-) 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 a09fe58ca..f6d4f406c 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 @@ -5,8 +5,6 @@ import android.graphics.Bitmap import android.util.Log import androidx.compose.foundation.* import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -61,7 +59,6 @@ import com.vitorpamplona.amethyst.ui.theme.Following import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.math.BigDecimal -import kotlin.math.ceil import kotlin.time.ExperimentalTime import kotlin.time.measureTimedValue @@ -299,7 +296,7 @@ fun NoteComposeInner( } if (noteEvent is RepostEvent) { - note.replyTo?.lastOrNull()?.let { + baseNote.replyTo?.lastOrNull()?.let { RelayBadges(it) } } else { @@ -871,68 +868,102 @@ private fun LongFormHeader(noteEvent: LongTextNoteEvent, note: Note, loggedIn: U @Composable private fun RelayBadges(baseNote: Note) { val noteRelaysState by baseNote.live().relays.observeAsState() - val noteRelays = noteRelaysState?.note?.relays ?: emptySet() + val noteRelays = noteRelaysState?.note ?: return var expanded by remember { mutableStateOf(false) } + var showShowMore by remember { mutableStateOf(false) } + var lazyRelayList by remember { mutableStateOf(emptyList()) } - val relaysToDisplay = (if (expanded) noteRelays else noteRelays.take(3)).toList() - val height = (ceil(relaysToDisplay.size / 3.0f) * 17).dp + LaunchedEffect(key1 = noteRelaysState, key2 = expanded) { + withContext(Dispatchers.IO) { + val relayList = noteRelays.relays.map { + it.removePrefix("wss://").removePrefix("ws://") + } - val uri = LocalUriHandler.current + val relaysToDisplay = if (expanded) relayList else relayList.take(3) + val shouldListChange = lazyRelayList.size < 3 || lazyRelayList.size != relayList.size - Spacer(Modifier.height(10.dp)) + if (shouldListChange) { + lazyRelayList = relaysToDisplay + } - LazyVerticalGrid( - columns = GridCells.Fixed(3), - contentPadding = PaddingValues(start = 4.dp, end = 4.dp), - modifier = Modifier.height(height), - userScrollEnabled = false - ) { - items(relaysToDisplay.size) { - val url = relaysToDisplay[it].removePrefix("wss://").removePrefix("ws://") - - Box( - Modifier - .padding(1.dp) - .size(15.dp) - ) { - RobohashFallbackAsyncImage( - robot = "https://$url/favicon.ico", - robotSize = 15.dp, - model = "https://$url/favicon.ico", - contentDescription = stringResource(R.string.relay_icon), - colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) }), - modifier = Modifier - .width(13.dp) - .height(13.dp) - .clip(shape = CircleShape) - // .border(1.dp, Color.Red) - .background(MaterialTheme.colors.background) - .clickable(onClick = { uri.openUri("https://$url") }) - ) + val nextShowMore = relayList.size > 3 && !expanded + if (nextShowMore != showShowMore) { + // only triggers recomposition when actually different + showShowMore = nextShowMore } } } - if (noteRelays.size > 3 && !expanded) { - Row( - Modifier - .fillMaxWidth() - .height(25.dp), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.Top + Spacer(Modifier.height(10.dp)) + + VerticalRelayPanelWithFlow(lazyRelayList) + + if (showShowMore) { + ShowMoreRelaysButton { + expanded = true + } + } +} + +@Composable +@Stable +private fun VerticalRelayPanelWithFlow( + relays: List +) { + // FlowRow Seems to be a lot faster than LazyVerticalGrid + FlowRow() { + relays.forEach { url -> + RelayIconCompose(url) + } + } +} + +@Composable +@Stable +private fun RelayIconCompose(url: String) { + val uri = LocalUriHandler.current + + Box( + Modifier + .padding(1.dp) + .size(15.dp) + ) { + RobohashFallbackAsyncImage( + robot = "https://$url/favicon.ico", + robotSize = 15.dp, + model = "https://$url/favicon.ico", + contentDescription = stringResource(R.string.relay_icon), + colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) }), + modifier = Modifier + .width(13.dp) + .height(13.dp) + .clip(shape = CircleShape) + .background(MaterialTheme.colors.background) + .clickable(onClick = { uri.openUri("https://$url") }) + ) + } +} + +@Composable +private fun ShowMoreRelaysButton(onClick: () -> Unit) { + Row( + Modifier + .fillMaxWidth() + .height(25.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.Top + ) { + IconButton( + modifier = Modifier.then(Modifier.size(24.dp)), + onClick = onClick ) { - IconButton( - modifier = Modifier.then(Modifier.size(24.dp)), - onClick = { expanded = true } - ) { - Icon( - imageVector = Icons.Default.ExpandMore, - null, - modifier = Modifier.size(15.dp), - tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) - ) - } + Icon( + imageVector = Icons.Default.ExpandMore, + null, + modifier = Modifier.size(15.dp), + tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) + ) } } }