feat: show "Replying to" label in quoted notes

Follow-up to #1723. When a quoted note is itself a reply, display a
compact "Replying to [username]" label above the content instead of
showing nothing. Uses the event's p-tags to resolve reply targets
directly, matching the Damus-style display.
This commit is contained in:
The Daniel
2026-02-28 18:53:32 -05:00
parent 3762c8d6c3
commit eb3b7077fd
3 changed files with 42 additions and 0 deletions
@@ -595,6 +595,7 @@ fun DisplayFullNote(
baseNote = note,
modifier = MaterialTheme.colorScheme.innerPostModifier,
isQuotedNote = true,
unPackReply = false,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
@@ -867,6 +868,7 @@ private fun DisplayNoteFromTag(
baseNote = baseNote,
modifier = MaterialTheme.colorScheme.innerPostModifier,
isQuotedNote = true,
unPackReply = false,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
@@ -116,6 +116,31 @@ fun ReplyInformationChannel(
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ReplyToLabel(
replyingDirectlyTo: Note,
accountViewModel: AccountViewModel,
nav: INav,
) {
val user = replyingDirectlyTo.author ?: return
FlowRow {
Text(
stringRes(id = R.string.replying_to),
fontSize = 13.sp,
color = MaterialTheme.colorScheme.placeholderText,
)
ReplyInfoMention(
user = user,
prefix = "",
accountViewModel = accountViewModel,
onUserTagClick = { nav.nav(routeFor(it)) },
)
}
}
@Composable
private fun ReplyInfoMention(
user: User,
@@ -42,6 +42,7 @@ import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContent
import com.vitorpamplona.amethyst.ui.note.ReplyInformationChannel
import com.vitorpamplona.amethyst.ui.note.ReplyNoteComposition
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -49,10 +50,13 @@ import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hasHashtags
import com.vitorpamplona.quartz.nip01Core.tags.people.hasAnyTaggedUser
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip14Subject.subject
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
@Composable
fun RenderTextEvent(
@@ -98,6 +102,17 @@ fun RenderTextEvent(
ReplyNoteComposition(replyingDirectlyTo, backgroundColor, accountViewModel, nav)
Spacer(modifier = StdVertSpacer)
}
} else if (!unPackReply && !makeItShort && noteEvent is BaseThreadedEvent && noteEvent.hasAnyTaggedUser()) {
val mentions =
remember(noteEvent) {
noteEvent.taggedUsers().map { it.pubKey }.toImmutableList()
}
ReplyInformationChannel(
replyTo = persistentListOf(note),
mentions = mentions,
accountViewModel = accountViewModel,
nav = nav,
)
}
// Check if this is an audio-only event (content is just an audio URL with waveform IMeta)