From 4d8be5e272928aeff946949b581cbb1dc37dc230 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 14:51:39 +0000 Subject: [PATCH 1/3] feat: scroll to replied message when clicking reply preview in chat When a user clicks on the reply preview (inner quote) in a chat message, the chat feed now scrolls to the original replied-to message in the same screen instead of doing nothing. https://claude.ai/code/session_01UF4VxoWGvvvwtLYBLBYw9w --- .../ui/screen/loggedIn/chats/feed/ChatFeedView.kt | 13 +++++++++++++ .../loggedIn/chats/feed/ChatMessageCompose.kt | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatFeedView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatFeedView.kt index 7c9846dd1..d7538f47f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatFeedView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatFeedView.kt @@ -28,6 +28,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.vitorpamplona.amethyst.commons.ui.feeds.FeedContentState @@ -43,6 +44,7 @@ import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent +import kotlinx.coroutines.launch @Composable fun RefreshingChatroomFeedView( @@ -131,6 +133,16 @@ fun ChatFeedLoaded( } } + val scope = rememberCoroutineScope() + val onScrollToNote: (Note) -> Unit = { note -> + val index = items.list.indexOfFirst { it.idHex == note.idHex } + if (index >= 0) { + scope.launch { + listState.animateScrollToItem(index) + } + } + } + LazyColumn( contentPadding = FeedPadding, modifier = Modifier.fillMaxSize(), @@ -147,6 +159,7 @@ fun ChatFeedLoaded( nav = nav, onWantsToReply = onWantsToReply, onWantsToEditDraft = onWantsToEditDraft, + onScrollToNote = onScrollToNote, ) NewDateOrSubjectDivisor(items.list.getOrNull(index + 1), item) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt index 3aeb9d13a..7cb452712 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/feed/ChatMessageCompose.kt @@ -95,6 +95,7 @@ fun ChatroomMessageCompose( nav: INav, onWantsToReply: (Note) -> Unit, onWantsToEditDraft: (Note) -> Unit, + onScrollToNote: ((Note) -> Unit)? = null, ) { WatchNoteEvent(baseNote = baseNote, accountViewModel = accountViewModel, nav) { WatchBlockAndReport( @@ -114,6 +115,7 @@ fun ChatroomMessageCompose( nav, onWantsToReply, onWantsToEditDraft, + onScrollToNote, ) } } @@ -130,6 +132,7 @@ fun NormalChatNote( nav: INav, onWantsToReply: (Note) -> Unit, onWantsToEditDraft: (Note) -> Unit, + onScrollToNote: ((Note) -> Unit)? = null, ) { val isLoggedInUser = remember(note.author) { @@ -171,6 +174,9 @@ fun NormalChatNote( if (note.event is ChannelCreateEvent) { nav.nav(Route.PublicChatChannel(note.idHex)) true + } else if (innerQuote && onScrollToNote != null) { + onScrollToNote(note) + true } else { false } @@ -253,6 +259,7 @@ fun NormalChatNote( canPreview, accountViewModel, nav, + onScrollToNote, ) } } @@ -288,6 +295,7 @@ private fun MessageBubbleLines( canPreview: Boolean, accountViewModel: AccountViewModel, nav: INav, + onScrollToNote: ((Note) -> Unit)? = null, ) { if (baseNote.event !is DraftWrapEvent) { RenderReplyRow( @@ -298,6 +306,7 @@ private fun MessageBubbleLines( nav = nav, onWantsToReply = onWantsToReply, onWantsToEditDraft = onWantsToEditDraft, + onScrollToNote = onScrollToNote, ) } @@ -334,9 +343,10 @@ fun RenderReplyRow( nav: INav, onWantsToReply: (Note) -> Unit, onWantsToEditDraft: (Note) -> Unit, + onScrollToNote: ((Note) -> Unit)? = null, ) { if (!innerQuote && note.replyTo?.lastOrNull() != null) { - RenderReply(note, bgColor, accountViewModel, nav, onWantsToReply, onWantsToEditDraft) + RenderReply(note, bgColor, accountViewModel, nav, onWantsToReply, onWantsToEditDraft, onScrollToNote) } } @@ -348,6 +358,7 @@ private fun RenderReply( nav: INav, onWantsToReply: (Note) -> Unit, onWantsToEditDraft: (Note) -> Unit, + onScrollToNote: ((Note) -> Unit)? = null, ) { Row(verticalAlignment = Alignment.CenterVertically) { @Suppress("ProduceStateDoesNotAssignValue") @@ -368,6 +379,7 @@ private fun RenderReply( nav = nav, onWantsToReply = onWantsToReply, onWantsToEditDraft = onWantsToEditDraft, + onScrollToNote = onScrollToNote, ) } } From 88042f06d4d5b0afbbbc36658f209f4d315a21bc Mon Sep 17 00:00:00 2001 From: Crowdin Bot Date: Tue, 24 Mar 2026 17:40:05 +0000 Subject: [PATCH 2/3] New Crowdin translations by GitHub Action --- amethyst/src/main/res/values-hu-rHU/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/amethyst/src/main/res/values-hu-rHU/strings.xml b/amethyst/src/main/res/values-hu-rHU/strings.xml index db98abc09..9f9daaf1e 100644 --- a/amethyst/src/main/res/values-hu-rHU/strings.xml +++ b/amethyst/src/main/res/values-hu-rHU/strings.xml @@ -290,6 +290,7 @@ Nostr-cím soha most + másodperc ó p n @@ -447,6 +448,8 @@ Maximum Zap Együttműködés (0–100)% + Egyetlen lehetőség + Több lehetőség Szavazás lezárásának dátuma és ideje A szavazás lezárul %1$s múlva Szavazás lezárása From bcdaf8630c748c75ec370413e87bf9c68485d284 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 20:34:01 +0000 Subject: [PATCH 3/3] feat: make relay rows clickable to open relay info dialog on profile page Adds onClick parameter to RelayCompose and navigates to RelayInformationScreen when a relay row is tapped in the profile relay tab. https://claude.ai/code/session_01PBFQz53xzXoFsEHD5Ghyqr --- .../java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt | 4 +++- .../ui/screen/loggedIn/profile/relays/RelayFeedView.kt | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt index b8ef58269..26e539624 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/RelayCompose.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.ui.note +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -59,11 +60,12 @@ fun RelayCompose( accountViewModel: AccountViewModel, onAddRelay: () -> Unit, onRemoveRelay: () -> Unit, + onClick: (() -> Unit)? = null, ) { val context = LocalContext.current Row( - modifier = StdPadding, + modifier = StdPadding.then(if (onClick != null) Modifier.clickable(onClick = onClick) else Modifier), verticalAlignment = Alignment.CenterVertically, ) { Column( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/relays/RelayFeedView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/relays/RelayFeedView.kt index 55b70ca2c..1bc249e05 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/relays/RelayFeedView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/profile/relays/RelayFeedView.kt @@ -105,6 +105,9 @@ private fun RenderRelayRow( onRemoveRelay = { nav.nav(Route.EditRelays) }, + onClick = { + nav.nav(Route.RelayInfo(relay.url.url)) + }, ) HorizontalDivider( thickness = DividerThickness,