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,119 +772,101 @@ 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
if (videoUri != null && !videoUri.startsWith("file")) { // Copy & Gallery section
DropdownMenuItem( M3ActionSection {
text = { Text(stringRes(R.string.copy_url_to_clipboard)) }, if (videoUri != null && !videoUri.startsWith("file")) {
onClick = { M3ActionRow(icon = Icons.Outlined.Link, text = stringRes(R.string.copy_url_to_clipboard)) {
clipboardManager.setText(AnnotatedString(videoUri)) clipboardManager.setText(AnnotatedString(videoUri))
onDismiss() onDismiss()
},
)
}
postNostrUri?.let {
DropdownMenuItem(
text = { Text(stringRes(R.string.copy_the_note_id_to_the_clipboard)) },
onClick = {
clipboardManager.setText(AnnotatedString(it))
onDismiss()
},
)
}
postNostrUri?.let {
DropdownMenuItem(
text = { Text(stringRes(R.string.add_media_to_gallery)) },
onClick = {
if (videoUri != null) {
val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent
if (n19 != null) {
accountViewModel.addMediaToGallery(n19.hex, videoUri, n19.relay.getOrNull(0), blurhash, dim, hash, mimeType) // TODO Whole list or first?
accountViewModel.toastManager.toast(R.string.media_added, R.string.media_added_to_profile_gallery)
}
}
onDismiss()
},
)
}
content?.let {
val context = LocalContext.current
when (content) {
is MediaUrlImage -> {
videoUri?.let {
if (videoUri.isNotEmpty()) {
DropdownMenuItem(
text = { Text(stringRes(R.string.share_image)) },
onClick = {
scope.launch { shareImageFile(context, videoUri, mimeType) }
onDismiss()
},
)
}
} }
} }
postNostrUri?.let {
M3ActionRow(icon = Icons.Outlined.ContentCopy, text = stringRes(R.string.copy_the_note_id_to_the_clipboard)) {
clipboardManager.setText(AnnotatedString(it))
onDismiss()
}
}
postNostrUri?.let {
M3ActionRow(icon = Icons.Outlined.Collections, text = stringRes(R.string.add_media_to_gallery)) {
if (videoUri != null) {
val n19 = Nip19Parser.uriToRoute(postNostrUri)?.entity as? NEvent
if (n19 != null) {
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)
}
}
onDismiss()
}
}
}
is MediaUrlVideo -> { // Share section
videoUri?.let { content?.let {
if (videoUri.isNotEmpty()) { val context = LocalContext.current
DropdownMenuItem(
text = { M3ActionSection {
Row(verticalAlignment = Alignment.CenterVertically) { when (content) {
Text(stringRes(R.string.share_video)) is MediaUrlImage -> {
if (isDownloadingVideo.value) { videoUri?.let {
Spacer(modifier = Modifier.width(8.dp)) if (videoUri.isNotEmpty()) {
LoadingAnimation(indicatorSize = 16.dp, circleWidth = 2.dp) M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_image)) {
scope.launch { shareImageFile(context, videoUri, mimeType) }
onDismiss()
}
}
}
}
is MediaUrlVideo -> {
videoUri?.let {
if (videoUri.isNotEmpty()) {
M3ActionRow(
icon = Icons.Outlined.Share,
text = stringRes(R.string.share_video),
enabled = !isDownloadingVideo.value,
) {
isDownloadingVideo.value = true
scope.launch {
shareVideoFile(
context = context,
videoUrl = videoUri,
mimeType = mimeType,
okHttpClient = { url ->
accountViewModel.httpClientBuilder.okHttpClientForVideo(url)
},
onComplete = {
isDownloadingVideo.value = false
onDismiss()
},
onError = {
isDownloadingVideo.value = false
},
)
} }
} }
}, }
enabled = !isDownloadingVideo.value, }
onClick = {
isDownloadingVideo.value = true
scope.launch {
shareVideoFile(
context = context,
videoUrl = videoUri,
mimeType = mimeType,
okHttpClient = { url ->
accountViewModel.httpClientBuilder.okHttpClientForVideo(url)
},
onComplete = {
isDownloadingVideo.value = false
onDismiss()
},
onError = {
isDownloadingVideo.value = false
},
)
}
},
)
} }
is MediaLocalVideo -> {
content.localFile?.let { localFile ->
M3ActionRow(icon = Icons.Outlined.Share, text = stringRes(R.string.share_video)) {
scope.launch { shareLocalVideoFile(context, localFile, mimeType) }
onDismiss()
}
}
}
else -> { /* No share option for other types */ }
} }
} }
is MediaLocalVideo -> {
content.localFile?.let { localFile ->
DropdownMenuItem(
text = { Text(stringRes(R.string.share_video)) },
onClick = {
scope.launch { shareLocalVideoFile(context, localFile, mimeType) }
onDismiss()
},
)
}
}
else -> { /* No share option for other types */ }
} }
} }
} }