feat: convert media context menu to M3 dialog

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
davotoula
2026-03-20 19:17:16 +01:00
parent b3a61ba288
commit 4e5d2e7d2a
@@ -32,15 +32,16 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Report import androidx.compose.material.icons.filled.Report
import androidx.compose.material3.DropdownMenu import androidx.compose.material.icons.outlined.Collections
import androidx.compose.material3.DropdownMenuItem import androidx.compose.material.icons.outlined.ContentCopy
import androidx.compose.material.icons.outlined.Link
import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -771,63 +772,54 @@ fun ShareMediaAction(
// Track if video is downloading - hoisted here to block menu dismiss during download // Track if video is downloading - hoisted here to block menu dismiss during download
val isDownloadingVideo = remember { mutableStateOf(false) } val isDownloadingVideo = remember { mutableStateOf(false) }
DropdownMenu( if (popupExpanded.value) {
expanded = popupExpanded.value, M3ActionDialog(
onDismissRequest = { if (!isDownloadingVideo.value) onDismiss() }, title = stringRes(R.string.media_actions_dialog_title),
onDismiss = { if (!isDownloadingVideo.value) onDismiss() },
) { ) {
val clipboardManager = LocalClipboardManager.current val clipboardManager = LocalClipboardManager.current
// Copy & Gallery section
M3ActionSection {
if (videoUri != null && !videoUri.startsWith("file")) { if (videoUri != null && !videoUri.startsWith("file")) {
DropdownMenuItem( M3ActionRow(icon = Icons.Outlined.Link, text = stringRes(R.string.copy_url_to_clipboard)) {
text = { Text(stringRes(R.string.copy_url_to_clipboard)) },
onClick = {
clipboardManager.setText(AnnotatedString(videoUri)) clipboardManager.setText(AnnotatedString(videoUri))
onDismiss() onDismiss()
},
)
} }
}
postNostrUri?.let { postNostrUri?.let {
DropdownMenuItem( M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_the_note_id_to_the_clipboard)) {
text = { Text(stringRes(R.string.copy_the_note_id_to_the_clipboard)) },
onClick = {
clipboardManager.setText(AnnotatedString(it)) clipboardManager.setText(AnnotatedString(it))
onDismiss() onDismiss()
},
)
} }
}
postNostrUri?.let { postNostrUri?.let {
DropdownMenuItem( M3ActionRow(icon = Icons.Outlined.Collections, text = stringRes(R.string.add_media_to_gallery)) {
text = { Text(stringRes(R.string.add_media_to_gallery)) },
onClick = {
if (videoUri != null) { if (videoUri != null) {
val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent
if (n19 != null) { if (n19 != null) {
accountViewModel.addMediaToGallery(n19.hex, videoUri, n19.relay.getOrNull(0), blurhash, dim, hash, mimeType) // TODO Whole list or first? accountViewModel.addMediaToGallery(n19.hex, videoUri, n19.relay.getOrNull(0), blurhash, dim, hash, mimeType)
accountViewModel.toastManager.toast(R.string.media_added, R.string.media_added_to_profile_gallery) accountViewModel.toastManager.toast(R.string.media_added, R.string.media_added_to_profile_gallery)
} }
} }
onDismiss() onDismiss()
}, }
) }
} }
// Share section
content?.let { content?.let {
val context = LocalContext.current val context = LocalContext.current
M3ActionSection {
when (content) { when (content) {
is MediaUrlImage -> { is MediaUrlImage -> {
videoUri?.let { videoUri?.let {
if (videoUri.isNotEmpty()) { if (videoUri.isNotEmpty()) {
DropdownMenuItem( M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_image)) {
text = { Text(stringRes(R.string.share_image)) },
onClick = {
scope.launch { shareImageFile(context, videoUri, mimeType) } scope.launch { shareImageFile(context, videoUri, mimeType) }
onDismiss() onDismiss()
}, }
)
} }
} }
} }
@@ -835,18 +827,11 @@ fun ShareMediaAction(
is MediaUrlVideo -> { is MediaUrlVideo -> {
videoUri?.let { videoUri?.let {
if (videoUri.isNotEmpty()) { if (videoUri.isNotEmpty()) {
DropdownMenuItem( M3ActionRow(
text = { icon = Icons.Outlined.Share,
Row(verticalAlignment = Alignment.CenterVertically) { text = stringRes(R.string.share_video),
Text(stringRes(R.string.share_video))
if (isDownloadingVideo.value) {
Spacer(modifier = Modifier.width(8.dp))
LoadingAnimation(indicatorSize = 16.dp, circleWidth = 2.dp)
}
}
},
enabled = !isDownloadingVideo.value, enabled = !isDownloadingVideo.value,
onClick = { ) {
isDownloadingVideo.value = true isDownloadingVideo.value = true
scope.launch { scope.launch {
shareVideoFile( shareVideoFile(
@@ -865,21 +850,17 @@ fun ShareMediaAction(
}, },
) )
} }
}, }
)
} }
} }
} }
is MediaLocalVideo -> { is MediaLocalVideo -> {
content.localFile?.let { localFile -> content.localFile?.let { localFile ->
DropdownMenuItem( M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_video)) {
text = { Text(stringRes(R.string.share_video)) },
onClick = {
scope.launch { shareLocalVideoFile(context, localFile, mimeType) } scope.launch { shareLocalVideoFile(context, localFile, mimeType) }
onDismiss() onDismiss()
}, }
)
} }
} }
@@ -887,6 +868,8 @@ fun ShareMediaAction(
} }
} }
} }
}
}
} }
private suspend fun shareImageFile( private suspend fun shareImageFile(