From 8722f37fa5779140eca4a0b310b03e8b4ce0cd45 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 5 Mar 2025 16:56:34 -0500 Subject: [PATCH] Improving the UI of the Custom Emoji page. --- .../ui/note/UpdateReactionTypeDialog.kt | 189 ++++++++++-------- .../amethyst/ui/note/types/Emoji.kt | 26 ++- .../selection/EmojiPackSelectionEvent.kt | 5 +- 3 files changed, 123 insertions(+), 97 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt index 7730ba8244..e356b11b56 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/UpdateReactionTypeDialog.kt @@ -30,6 +30,7 @@ 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.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding @@ -44,10 +45,13 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue @@ -77,6 +81,7 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.service.firstFullChar import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer +import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge import com.vitorpamplona.amethyst.ui.navigation.INav import com.vitorpamplona.amethyst.ui.navigation.routeFor import com.vitorpamplona.amethyst.ui.note.types.RenderEmojiPack @@ -85,9 +90,9 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton import com.vitorpamplona.amethyst.ui.screen.loggedIn.SaveButton import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.ButtonBorder +import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer +import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.placeholderText -import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address -import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag import com.vitorpamplona.quartz.nip30CustomEmoji.selection.EmojiPackSelectionEvent @@ -157,7 +162,7 @@ fun UpdateReactionTypeDialog( UpdateReactionTypeDialog(postViewModel, onClose, accountViewModel, nav) } -@OptIn(ExperimentalLayoutApi::class) +@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class) @Composable fun UpdateReactionTypeDialog( postViewModel: UpdateReactionTypeViewModel, @@ -174,98 +179,112 @@ fun UpdateReactionTypeDialog( decorFitsSystemWindows = false, ), ) { - Surface( - modifier = Modifier.fillMaxWidth(), - ) { - Column( - modifier = Modifier.padding(10.dp).imePadding(), + SetDialogToEdgeToEdge() + + Scaffold( + topBar = { + TopAppBar( + actions = { + SaveButton( + onPost = { + postViewModel.sendPost() + onClose() + }, + isActive = postViewModel.hasChanged(), + ) + Spacer(modifier = StdHorzSpacer) + }, + title = {}, + navigationIcon = { + Row { + Spacer(modifier = StdHorzSpacer) + CloseButton( + onPress = { + postViewModel.cancel() + onClose() + }, + ) + } + }, + ) + }, + ) { pad -> + Surface( + modifier = + Modifier + .padding(pad) + .consumeWindowInsets(pad) + .imePadding(), ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, + Column( + modifier = Modifier.padding(10.dp), ) { - CloseButton( - onPress = { - postViewModel.cancel() - onClose() - }, - ) - - SaveButton( - onPost = { - postViewModel.sendPost() - onClose() - }, - isActive = postViewModel.hasChanged(), - ) - } - - Spacer(modifier = Modifier.height(10.dp)) - - Row( - modifier = Modifier.fillMaxWidth(), - ) { - Column( - modifier = Modifier.verticalScroll(rememberScrollState()), + Row( + modifier = Modifier.fillMaxWidth(), ) { - Row(modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.animateContentSize()) { - FlowRow( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center, - ) { - postViewModel.reactionSet.forEach { reactionType -> - RenderReactionOption(reactionType, postViewModel) + Column( + modifier = Modifier.verticalScroll(rememberScrollState()), + ) { + Row(modifier = Modifier.fillMaxWidth()) { + Column(modifier = Modifier.animateContentSize()) { + FlowRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + ) { + postViewModel.reactionSet.forEach { reactionType -> + RenderReactionOption(reactionType, postViewModel) + } } } } - } - Spacer(modifier = Modifier.height(10.dp)) + Spacer(modifier = Modifier.height(10.dp)) - Row( - modifier = Modifier.fillMaxWidth().padding(vertical = 5.dp), - verticalAlignment = Alignment.CenterVertically, - ) { - OutlinedTextField( - label = { Text(text = stringRes(R.string.new_reaction_symbol)) }, - value = postViewModel.nextChoice, - onValueChange = { postViewModel.nextChoice = it }, - keyboardOptions = - KeyboardOptions.Default.copy( - capitalization = KeyboardCapitalization.None, - keyboardType = KeyboardType.Text, - ), - placeholder = { - Text( - text = "\uD83D\uDCAF, \uD83C\uDF89, \uD83D\uDC4E", - color = MaterialTheme.colorScheme.placeholderText, - ) - }, - singleLine = true, - modifier = Modifier.padding(end = 10.dp).weight(1f), - ) - - Button( - onClick = { postViewModel.addChoice() }, - shape = ButtonBorder, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - ), + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 5.dp), + verticalAlignment = Alignment.CenterVertically, ) { - Text(text = stringRes(R.string.add), color = Color.White) + OutlinedTextField( + label = { Text(text = stringRes(R.string.new_reaction_symbol)) }, + value = postViewModel.nextChoice, + onValueChange = { postViewModel.nextChoice = it }, + keyboardOptions = + KeyboardOptions.Default.copy( + capitalization = KeyboardCapitalization.None, + keyboardType = KeyboardType.Text, + ), + placeholder = { + Text( + text = "\uD83D\uDCAF, \uD83C\uDF89, \uD83D\uDC4E", + color = MaterialTheme.colorScheme.placeholderText, + ) + }, + singleLine = true, + modifier = Modifier.padding(end = 10.dp).weight(1f), + ) + + Button( + onClick = { postViewModel.addChoice() }, + shape = ButtonBorder, + colors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, + ), + ) { + Text(text = stringRes(R.string.add), color = Color.White) + } } } } - } - EmojiSelector( - accountViewModel = accountViewModel, - nav = nav, - ) { - postViewModel.addChoice(it) + Spacer(StdVertSpacer) + + EmojiSelector( + accountViewModel = accountViewModel, + nav = nav, + ) { + postViewModel.addChoice(it) + } } } } @@ -348,11 +367,11 @@ private fun EmojiSelector( usersEmojiList .live() .metadata - .map { (it.note.event as? EmojiPackSelectionEvent)?.taggedAddresses()?.toImmutableList() } + .map { (it.note.event as? EmojiPackSelectionEvent)?.emojiPackIds()?.toImmutableList() } .distinctUntilChanged() .observeAsState( (usersEmojiList.event as? EmojiPackSelectionEvent) - ?.taggedAddresses() + ?.emojiPackIds() ?.toImmutableList(), ) @@ -363,7 +382,7 @@ private fun EmojiSelector( @Composable fun EmojiCollectionGallery( - emojiCollections: ImmutableList
, + emojiCollections: ImmutableList, accountViewModel: AccountViewModel, nav: INav, onClick: ((EmojiUrlTag) -> Unit)? = null, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Emoji.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Emoji.kt index 708e3df980..df9712d1d1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Emoji.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Emoji.kt @@ -21,14 +21,15 @@ package com.vitorpamplona.amethyst.ui.note.types import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Arrangement.spacedBy import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState @@ -40,6 +41,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -112,7 +114,7 @@ public fun RenderEmojiPack( allEmojis.take(60) } - Row(verticalAlignment = Alignment.CenterVertically) { + Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(top = 10.dp)) { Text( text = remember(noteEvent) { "#${noteEvent.dTag()}" }, fontWeight = FontWeight.Bold, @@ -131,16 +133,19 @@ public fun RenderEmojiPack( } Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.TopCenter) { - FlowRow(modifier = Modifier.padding(top = 5.dp)) { + FlowRow( + modifier = Modifier.padding(top = 5.dp), + verticalArrangement = spacedBy(1.dp), + horizontalArrangement = spacedBy(1.dp), + ) { emojisToShow.forEach { emoji -> if (onClick != null) { - IconButton(onClick = { onClick(emoji) }, modifier = Size35Modifier) { - AsyncImage( - model = emoji.url, - contentDescription = emoji.code, - modifier = Size35Modifier, - ) - } + AsyncImage( + model = emoji.url, + contentDescription = emoji.code, + modifier = Size35Modifier.clickable { onClick(emoji) }, + contentScale = ContentScale.Crop, + ) } else { Box( modifier = Size35Modifier, @@ -150,6 +155,7 @@ public fun RenderEmojiPack( model = emoji.url, contentDescription = emoji.code, modifier = Size35Modifier, + contentScale = ContentScale.Crop, ) } } diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt index 10c565b704..a49bb75161 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip30CustomEmoji/selection/EmojiPackSelectionEvent.kt @@ -30,7 +30,6 @@ import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate import com.vitorpamplona.quartz.nip01Core.signers.eventUpdate import com.vitorpamplona.quartz.nip01Core.tags.addressables.ATag import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address -import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedATags import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent import com.vitorpamplona.quartz.nip31Alts.alt import com.vitorpamplona.quartz.utils.TimeUtils @@ -47,7 +46,9 @@ class EmojiPackSelectionEvent( AddressHintProvider { override fun addressHints() = tags.mapNotNull(ATag::parseAsHint) - fun emojiPacks() = taggedATags() + fun emojiPacks() = tags.mapNotNull(ATag::parseAddress) + + fun emojiPackIds() = tags.mapNotNull(ATag::parseAddressId) companion object { const val KIND = 10030