mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-08 23:54:39 +00:00
fix(desktop): discoverable note moderation — right-click menu + ⋮ overflow
Manual testing showed the note moderation actions were hard to find: - Provide LocalDesktopIAccount on MainContent's own (non-null) provider so every deck/feed/profile/settings surface reliably resolves the account. - Add a right-click ContextMenuArea on feed notes: Mute user / Report… / Copy text (moderation items for other authors on a writeable account). - Swap the note action-row Share icon for a MoreVert (⋮) overflow — the menu it opens already carries copy/broadcast + mute/report, matching the profile ⋮. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2bad8f6a77
commit
df442bf7b5
@@ -2051,6 +2051,7 @@ fun MainContent(
|
||||
CompositionLocalProvider(
|
||||
LocalRelayCategories provides relayCategories,
|
||||
LocalBlossomServers provides iAccount.blossomServerList.flow,
|
||||
com.vitorpamplona.amethyst.desktop.model.LocalDesktopIAccount provides iAccount,
|
||||
com.vitorpamplona.amethyst.desktop.ui.relay.LocalAccountRelays provides accountRelays,
|
||||
com.vitorpamplona.amethyst.desktop.ui.deck.LocalDesktopCache provides localCache,
|
||||
com.vitorpamplona.amethyst.desktop.ui.deck.LocalRelayManager provides relayManager,
|
||||
|
||||
@@ -28,6 +28,8 @@ import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.ContextMenuArea
|
||||
import androidx.compose.foundation.ContextMenuItem
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.TooltipArea
|
||||
import androidx.compose.foundation.background
|
||||
@@ -202,32 +204,71 @@ fun FeedNoteCard(
|
||||
forceReveal: Boolean = false,
|
||||
) {
|
||||
val event = note.event ?: return
|
||||
val moderationAccount = com.vitorpamplona.amethyst.desktop.model.LocalDesktopIAccount.current
|
||||
val ctxScope = rememberCoroutineScope()
|
||||
var showReportDialog by remember(note.idHex) { mutableStateOf(false) }
|
||||
val canModerate = moderationAccount != null && moderationAccount.isWriteable() && event.pubKey != moderationAccount.pubKey
|
||||
|
||||
SpamCheckedNoteRender(
|
||||
note = note,
|
||||
localCache = localCache,
|
||||
forceReveal = forceReveal,
|
||||
) {
|
||||
FeedNoteCardBody(
|
||||
note = note,
|
||||
event = event,
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
account = account,
|
||||
nwcConnection = nwcConnection,
|
||||
onReply = onReply,
|
||||
onZapFeedback = onZapFeedback,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
onNavigateToThread = onNavigateToThread,
|
||||
onImageClick = onImageClick,
|
||||
onMediaClick = onMediaClick,
|
||||
onHashtagClick = onHashtagClick,
|
||||
followedUsers = followedUsers,
|
||||
myPubKeyHex = myPubKeyHex,
|
||||
onFollow = onFollow,
|
||||
// Right-click context menu (Compose Desktop). Mute/Report are only added
|
||||
// for other authors on a writeable account; Copy is always available.
|
||||
ContextMenuArea(items = {
|
||||
buildList {
|
||||
add(ContextMenuItem("Copy text") { copyTextToClipboard(event.content) })
|
||||
if (canModerate && moderationAccount != null) {
|
||||
add(ContextMenuItem("Mute user") { ctxScope.launch { moderationAccount.hideUser(event.pubKey) } })
|
||||
add(ContextMenuItem("Report…") { showReportDialog = true })
|
||||
}
|
||||
}
|
||||
}) {
|
||||
FeedNoteCardBody(
|
||||
note = note,
|
||||
event = event,
|
||||
relayManager = relayManager,
|
||||
localCache = localCache,
|
||||
account = account,
|
||||
nwcConnection = nwcConnection,
|
||||
onReply = onReply,
|
||||
onZapFeedback = onZapFeedback,
|
||||
onNavigateToProfile = onNavigateToProfile,
|
||||
onNavigateToThread = onNavigateToThread,
|
||||
onImageClick = onImageClick,
|
||||
onMediaClick = onMediaClick,
|
||||
onHashtagClick = onHashtagClick,
|
||||
followedUsers = followedUsers,
|
||||
myPubKeyHex = myPubKeyHex,
|
||||
onFollow = onFollow,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showReportDialog && moderationAccount != null) {
|
||||
com.vitorpamplona.amethyst.desktop.ui.note.ReportNoteDialog(
|
||||
onDismiss = { showReportDialog = false },
|
||||
onReport = { type, comment ->
|
||||
ctxScope.launch { moderationAccount.reportEvent(event, type, comment) }
|
||||
},
|
||||
onBlockAndReport = { type, comment ->
|
||||
ctxScope.launch {
|
||||
moderationAccount.reportEvent(event, type, comment)
|
||||
moderationAccount.hideUser(event.pubKey)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyTextToClipboard(text: String) {
|
||||
java.awt.Toolkit
|
||||
.getDefaultToolkit()
|
||||
.systemClipboard
|
||||
.setContents(java.awt.datatransfer.StringSelection(text), null)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FeedNoteCardBody(
|
||||
note: Note,
|
||||
|
||||
@@ -1311,7 +1311,7 @@ fun NoteActionsRow(
|
||||
)
|
||||
}
|
||||
|
||||
// Share menu
|
||||
// Overflow menu: copy / broadcast / share links + mute / report.
|
||||
val shareMenuState = rememberShareMenuState()
|
||||
Box {
|
||||
IconButton(
|
||||
@@ -1319,8 +1319,8 @@ fun NoteActionsRow(
|
||||
modifier = Modifier.size(32.dp),
|
||||
) {
|
||||
Icon(
|
||||
MaterialSymbols.Share,
|
||||
contentDescription = "Share",
|
||||
MaterialSymbols.MoreVert,
|
||||
contentDescription = "More actions",
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user