fix: cap quoted note nesting to prevent squashed action bars
Add quoteDepth parameter to RichContent, QuotedNote, PostCard, and GalleryCard. At depth >= 1 (already inside a quote), force compact preview rendering (avatar + name + snippet) instead of full PostCard with action bar. Prevents recursive nesting from crushing layouts.
This commit is contained in:
@@ -152,6 +152,7 @@ fun GalleryCard(
|
||||
onPin: () -> Unit = {},
|
||||
isPinned: Boolean = false,
|
||||
onDelete: () -> Unit = {},
|
||||
quoteDepth: Int = 0,
|
||||
modifier: Modifier = Modifier,
|
||||
showDivider: Boolean = true
|
||||
) {
|
||||
@@ -220,6 +221,7 @@ fun GalleryCard(
|
||||
onPin = onPin,
|
||||
isPinned = isPinned,
|
||||
onDelete = onDelete,
|
||||
quoteDepth = quoteDepth,
|
||||
modifier = modifier,
|
||||
showDivider = showDivider
|
||||
)
|
||||
|
||||
@@ -163,6 +163,7 @@ fun PostCard(
|
||||
onZapPollVote: (Int) -> Unit = {},
|
||||
translationState: TranslationState = TranslationState(),
|
||||
onTranslate: () -> Unit = {},
|
||||
quoteDepth: Int = 0,
|
||||
modifier: Modifier = Modifier,
|
||||
showDivider: Boolean = true
|
||||
) {
|
||||
@@ -570,7 +571,8 @@ fun PostCard(
|
||||
onProfileClick = onNavigateToProfile,
|
||||
onNoteClick = onQuotedNoteClick,
|
||||
noteActions = noteActions,
|
||||
authorPubkey = event.pubkey
|
||||
authorPubkey = event.pubkey,
|
||||
quoteDepth = quoteDepth
|
||||
)
|
||||
} else {
|
||||
// Collapsible content with max height (~1 viewport)
|
||||
@@ -603,7 +605,8 @@ fun PostCard(
|
||||
eventRepo = eventRepo,
|
||||
onProfileClick = onNavigateToProfile,
|
||||
onNoteClick = onQuotedNoteClick,
|
||||
noteActions = noteActions
|
||||
noteActions = noteActions,
|
||||
quoteDepth = quoteDepth
|
||||
)
|
||||
}
|
||||
|
||||
@@ -704,7 +707,8 @@ fun PostCard(
|
||||
eventRepo = eventRepo,
|
||||
onProfileClick = onNavigateToProfile,
|
||||
onNoteClick = onQuotedNoteClick,
|
||||
noteActions = noteActions
|
||||
noteActions = noteActions,
|
||||
quoteDepth = quoteDepth
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +525,9 @@ private fun LightningInvoiceCard(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(com.wisp.app.R.drawable.ic_bolt),
|
||||
painter = painterResource(
|
||||
if (com.wisp.app.ui.util.isFiatMode()) com.wisp.app.R.drawable.ic_coin_stack else com.wisp.app.R.drawable.ic_bolt
|
||||
),
|
||||
contentDescription = null,
|
||||
tint = primary,
|
||||
modifier = Modifier.size(20.dp)
|
||||
@@ -608,6 +610,7 @@ fun RichContent(
|
||||
onLiveStreamClick: ((String, String, String?) -> Unit)? = null,
|
||||
noteActions: NoteActions? = null,
|
||||
authorPubkey: String? = null,
|
||||
quoteDepth: Int = 0,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val segments = remember(content, emojiMap, imetaMap, plainLinks) { parseContent(content.trimEnd('\n', '\r'), emojiMap, imetaMap, trimBlankLines = !plainLinks) }
|
||||
@@ -839,7 +842,8 @@ fun RichContent(
|
||||
eventRepo = eventRepo,
|
||||
relayHints = segment.relayHints,
|
||||
onNoteClick = onNoteClick,
|
||||
noteActions = noteActions
|
||||
noteActions = noteActions,
|
||||
quoteDepth = quoteDepth
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
@@ -863,6 +867,7 @@ fun RichContent(
|
||||
onNoteClick = onNoteClick,
|
||||
onProfileClick = onProfileClick,
|
||||
noteActions = noteActions,
|
||||
quoteDepth = quoteDepth,
|
||||
style = style
|
||||
)
|
||||
} else {
|
||||
@@ -953,7 +958,8 @@ fun QuotedNote(
|
||||
eventRepo: EventRepository,
|
||||
relayHints: List<String> = emptyList(),
|
||||
onNoteClick: ((String) -> Unit)? = null,
|
||||
noteActions: NoteActions? = null
|
||||
noteActions: NoteActions? = null,
|
||||
quoteDepth: Int = 0
|
||||
) {
|
||||
// Observe versions so we recompose when data arrives from relays
|
||||
val version by eventRepo.quotedEventVersion.collectAsState()
|
||||
@@ -967,7 +973,10 @@ fun QuotedNote(
|
||||
}
|
||||
}
|
||||
|
||||
val effectiveNoteClick = noteActions?.onNoteClick ?: onNoteClick
|
||||
// Cap nesting: depth >= 1 means we're already inside a quoted note,
|
||||
// so force compact preview to avoid squashed action bars
|
||||
val effectiveActions = if (quoteDepth >= 1) null else noteActions
|
||||
val effectiveNoteClick = effectiveActions?.onNoteClick ?: noteActions?.onNoteClick ?: onNoteClick
|
||||
|
||||
// Fetch poll votes when quoted event is a poll
|
||||
LaunchedEffect(event?.id, event?.kind) {
|
||||
@@ -979,7 +988,7 @@ fun QuotedNote(
|
||||
}
|
||||
}
|
||||
|
||||
if (event != null && noteActions != null) {
|
||||
if (event != null && effectiveActions != null) {
|
||||
// Full rendering with all interactive features
|
||||
val reactionVersion by eventRepo.reactionVersion.collectAsState()
|
||||
val zapVersion by eventRepo.zapVersion.collectAsState()
|
||||
@@ -992,8 +1001,8 @@ fun QuotedNote(
|
||||
val zapSats = remember(zapVersion, eventId) { eventRepo.getZapSats(eventId) }
|
||||
val repostCount = remember(repostVersion, eventId) { eventRepo.getRepostCount(eventId) }
|
||||
val repostPubkeys = remember(repostVersion, eventId) { eventRepo.getReposterPubkeys(eventId) }
|
||||
val userEmojis = remember(reactionVersion, eventId, noteActions.userPubkey) {
|
||||
noteActions.userPubkey?.let { eventRepo.getUserReactionEmojis(eventId, it) } ?: emptySet()
|
||||
val userEmojis = remember(reactionVersion, eventId, effectiveActions.userPubkey) {
|
||||
effectiveActions.userPubkey?.let { eventRepo.getUserReactionEmojis(eventId, it) } ?: emptySet()
|
||||
}
|
||||
val hasUserReposted = remember(repostVersion, eventId) { eventRepo.hasUserReposted(eventId) }
|
||||
val hasUserZapped = remember(zapVersion, eventId) { eventRepo.hasUserZapped(eventId) }
|
||||
@@ -1035,17 +1044,17 @@ fun QuotedNote(
|
||||
GalleryCard(
|
||||
event = event,
|
||||
profile = profile,
|
||||
onReply = { noteActions.onReply(event) },
|
||||
onProfileClick = { noteActions.onProfileClick(event.pubkey) },
|
||||
onNavigateToProfile = noteActions.onProfileClick,
|
||||
onReply = { effectiveActions.onReply(event) },
|
||||
onProfileClick = { effectiveActions.onProfileClick(event.pubkey) },
|
||||
onNavigateToProfile = effectiveActions.onProfileClick,
|
||||
onNoteClick = { effectiveNoteClick?.invoke(eventId) },
|
||||
onReact = { emoji -> noteActions.onReact(event, emoji) },
|
||||
onReact = { emoji -> effectiveActions.onReact(event, emoji) },
|
||||
userReactionEmojis = userEmojis,
|
||||
onRepost = { noteActions.onRepost(event) },
|
||||
onQuote = { noteActions.onQuote(event) },
|
||||
onRepost = { effectiveActions.onRepost(event) },
|
||||
onQuote = { effectiveActions.onQuote(event) },
|
||||
hasUserReposted = hasUserReposted,
|
||||
repostCount = repostCount,
|
||||
onZap = { noteActions.onZap(event) },
|
||||
onZap = { effectiveActions.onZap(event) },
|
||||
hasUserZapped = hasUserZapped,
|
||||
likeCount = likeCount,
|
||||
replyCount = replyCount,
|
||||
@@ -1054,37 +1063,38 @@ fun QuotedNote(
|
||||
reactionDetails = reactionDetails,
|
||||
zapDetails = zapDetails,
|
||||
repostDetails = repostPubkeys,
|
||||
onNavigateToProfileFromDetails = noteActions.onProfileClick,
|
||||
onFollowAuthor = { noteActions.onFollowAuthor(event.pubkey) },
|
||||
onBlockAuthor = { noteActions.onBlockAuthor(event.pubkey) },
|
||||
isFollowingAuthor = noteActions.isFollowing(event.pubkey),
|
||||
isOwnEvent = event.pubkey == noteActions.userPubkey,
|
||||
nip05Repo = noteActions.nip05Repo,
|
||||
onAddToList = { noteActions.onAddToList(eventId) },
|
||||
onPin = { noteActions.onPin(eventId) },
|
||||
onNavigateToProfileFromDetails = effectiveActions.onProfileClick,
|
||||
onFollowAuthor = { effectiveActions.onFollowAuthor(event.pubkey) },
|
||||
onBlockAuthor = { effectiveActions.onBlockAuthor(event.pubkey) },
|
||||
isFollowingAuthor = effectiveActions.isFollowing(event.pubkey),
|
||||
isOwnEvent = event.pubkey == effectiveActions.userPubkey,
|
||||
nip05Repo = effectiveActions.nip05Repo,
|
||||
onAddToList = { effectiveActions.onAddToList(eventId) },
|
||||
onPin = { effectiveActions.onPin(eventId) },
|
||||
onQuotedNoteClick = effectiveNoteClick,
|
||||
noteActions = noteActions,
|
||||
noteActions = effectiveActions,
|
||||
reactionEmojiUrls = reactionEmojiUrls,
|
||||
resolvedEmojis = noteActions.resolvedEmojisProvider(),
|
||||
unicodeEmojis = noteActions.unicodeEmojisProvider(),
|
||||
onOpenEmojiLibrary = noteActions.onOpenEmojiLibrary,
|
||||
showDivider = false
|
||||
resolvedEmojis = effectiveActions.resolvedEmojisProvider(),
|
||||
unicodeEmojis = effectiveActions.unicodeEmojisProvider(),
|
||||
onOpenEmojiLibrary = effectiveActions.onOpenEmojiLibrary,
|
||||
showDivider = false,
|
||||
quoteDepth = quoteDepth + 1
|
||||
)
|
||||
} else {
|
||||
PostCard(
|
||||
event = event,
|
||||
profile = profile,
|
||||
onReply = { noteActions.onReply(event) },
|
||||
onProfileClick = { noteActions.onProfileClick(event.pubkey) },
|
||||
onNavigateToProfile = noteActions.onProfileClick,
|
||||
onReply = { effectiveActions.onReply(event) },
|
||||
onProfileClick = { effectiveActions.onProfileClick(event.pubkey) },
|
||||
onNavigateToProfile = effectiveActions.onProfileClick,
|
||||
onNoteClick = { effectiveNoteClick?.invoke(eventId) },
|
||||
onReact = { emoji -> noteActions.onReact(event, emoji) },
|
||||
onReact = { emoji -> effectiveActions.onReact(event, emoji) },
|
||||
userReactionEmojis = userEmojis,
|
||||
onRepost = { noteActions.onRepost(event) },
|
||||
onQuote = { noteActions.onQuote(event) },
|
||||
onRepost = { effectiveActions.onRepost(event) },
|
||||
onQuote = { effectiveActions.onQuote(event) },
|
||||
hasUserReposted = hasUserReposted,
|
||||
repostCount = repostCount,
|
||||
onZap = { noteActions.onZap(event) },
|
||||
onZap = { effectiveActions.onZap(event) },
|
||||
hasUserZapped = hasUserZapped,
|
||||
likeCount = likeCount,
|
||||
replyCount = replyCount,
|
||||
@@ -1093,28 +1103,29 @@ fun QuotedNote(
|
||||
reactionDetails = reactionDetails,
|
||||
zapDetails = zapDetails,
|
||||
repostDetails = repostPubkeys,
|
||||
onNavigateToProfileFromDetails = noteActions.onProfileClick,
|
||||
onFollowAuthor = { noteActions.onFollowAuthor(event.pubkey) },
|
||||
onBlockAuthor = { noteActions.onBlockAuthor(event.pubkey) },
|
||||
isFollowingAuthor = noteActions.isFollowing(event.pubkey),
|
||||
isOwnEvent = event.pubkey == noteActions.userPubkey,
|
||||
nip05Repo = noteActions.nip05Repo,
|
||||
onAddToList = { noteActions.onAddToList(eventId) },
|
||||
onPin = { noteActions.onPin(eventId) },
|
||||
onNavigateToProfileFromDetails = effectiveActions.onProfileClick,
|
||||
onFollowAuthor = { effectiveActions.onFollowAuthor(event.pubkey) },
|
||||
onBlockAuthor = { effectiveActions.onBlockAuthor(event.pubkey) },
|
||||
isFollowingAuthor = effectiveActions.isFollowing(event.pubkey),
|
||||
isOwnEvent = event.pubkey == effectiveActions.userPubkey,
|
||||
nip05Repo = effectiveActions.nip05Repo,
|
||||
onAddToList = { effectiveActions.onAddToList(eventId) },
|
||||
onPin = { effectiveActions.onPin(eventId) },
|
||||
onQuotedNoteClick = effectiveNoteClick,
|
||||
noteActions = noteActions,
|
||||
noteActions = effectiveActions,
|
||||
pollVoteCounts = pollVoteCounts,
|
||||
pollTotalVotes = pollTotalVotes,
|
||||
userPollVotes = userPollVotes,
|
||||
onPollVote = { optionIds -> noteActions.onPollVote(eventId, optionIds) },
|
||||
onPollVote = { optionIds -> effectiveActions.onPollVote(eventId, optionIds) },
|
||||
zapPollSatsCounts = zapPollSatsCounts,
|
||||
zapPollTotalSats = zapPollTotalSats,
|
||||
userZapPollVote = userZapPollVote,
|
||||
reactionEmojiUrls = reactionEmojiUrls,
|
||||
resolvedEmojis = noteActions.resolvedEmojisProvider(),
|
||||
unicodeEmojis = noteActions.unicodeEmojisProvider(),
|
||||
onOpenEmojiLibrary = noteActions.onOpenEmojiLibrary,
|
||||
showDivider = false
|
||||
resolvedEmojis = effectiveActions.resolvedEmojisProvider(),
|
||||
unicodeEmojis = effectiveActions.unicodeEmojisProvider(),
|
||||
onOpenEmojiLibrary = effectiveActions.onOpenEmojiLibrary,
|
||||
showDivider = false,
|
||||
quoteDepth = quoteDepth + 1
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1223,6 +1234,7 @@ private fun QuotedAddressableNote(
|
||||
onNoteClick: ((String) -> Unit)?,
|
||||
onProfileClick: ((String) -> Unit)?,
|
||||
noteActions: NoteActions?,
|
||||
quoteDepth: Int = 0,
|
||||
style: TextStyle
|
||||
) {
|
||||
val version by eventRepo.quotedEventVersion.collectAsState()
|
||||
@@ -1241,7 +1253,8 @@ private fun QuotedAddressableNote(
|
||||
eventId = event.id,
|
||||
eventRepo = eventRepo,
|
||||
onNoteClick = onNoteClick,
|
||||
noteActions = noteActions
|
||||
noteActions = noteActions,
|
||||
quoteDepth = quoteDepth
|
||||
)
|
||||
} else {
|
||||
// Loading state
|
||||
|
||||
Reference in New Issue
Block a user