- Disables saving m3u8 files (streaming can't be saved)

- Changes Error messages to not include stack traces and move them to a copy to clipboard action instead.
This commit is contained in:
Vitor Pamplona
2024-09-05 14:36:23 -04:00
parent 5af473870e
commit 010305fbeb
4 changed files with 82 additions and 50 deletions
@@ -20,9 +20,12 @@
*/ */
package com.vitorpamplona.amethyst.ui.actions package com.vitorpamplona.amethyst.ui.actions
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Done import androidx.compose.material.icons.outlined.Done
@@ -32,9 +35,14 @@ import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.Size16dp import com.vitorpamplona.amethyst.ui.theme.Size16dp
@@ -50,15 +58,11 @@ fun InformationDialog(
buttonColors: ButtonColors = ButtonDefaults.buttonColors(), buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
val stack = stringRes(id = R.string.stack) val str = textContent ?: throwable.localizedMessage ?: throwable.message ?: throwable.javaClass.simpleName
val str =
val stack =
remember(throwable) { remember(throwable) {
val writer = StringWriter() val writer = StringWriter()
textContent?.let {
writer.append(it)
writer.append("\n\n")
}
writer.append(stack)
writer.append("\n") writer.append("\n")
throwable.printStackTrace(PrintWriter(writer)) throwable.printStackTrace(PrintWriter(writer))
@@ -66,13 +70,14 @@ fun InformationDialog(
writer.toString() writer.toString()
} }
InformationDialog(title = title, textContent = str, buttonColors, onDismiss) InformationDialog(title = title, textContent = str, moreInfo = stack, buttonColors, onDismiss)
} }
@Composable @Composable
fun InformationDialog( fun InformationDialog(
title: String, title: String,
textContent: String, textContent: String,
moreInfo: String? = null,
buttonColors: ButtonColors = ButtonDefaults.buttonColors(), buttonColors: ButtonColors = ButtonDefaults.buttonColors(),
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
@@ -85,20 +90,37 @@ fun InformationDialog(
} }
}, },
confirmButton = { confirmButton = {
Button( Row(
onClick = onDismiss, modifier =
colors = buttonColors, Modifier
contentPadding = PaddingValues(horizontal = Size16dp), .padding(all = 8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
) { ) {
Row( moreInfo?.let {
verticalAlignment = Alignment.CenterVertically, val clipboardManager = LocalClipboardManager.current
TextButton(onClick = {
clipboardManager.setText(AnnotatedString(it))
}) {
Text(stringRes(R.string.copy_stack_to_clipboard))
}
}
Button(
onClick = onDismiss,
colors = buttonColors,
contentPadding = PaddingValues(horizontal = Size16dp),
) { ) {
Icon( Row(
imageVector = Icons.Outlined.Done, verticalAlignment = Alignment.CenterVertically,
contentDescription = null, ) {
) Icon(
Spacer(StdHorzSpacer) imageVector = Icons.Outlined.Done,
Text(stringRes(R.string.error_dialog_button_ok)) contentDescription = null,
)
Spacer(StdHorzSpacer)
Text(stringRes(R.string.error_dialog_button_ok))
}
} }
} }
}, },
@@ -826,12 +826,18 @@ private fun RenderVideoPlayer(
keepPlaying.value = newKeepPlaying keepPlaying.value = newKeepPlaying
} }
AnimatedSaveButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size110dp)) { context -> if (!videoUri.endsWith(".m3u8")) {
saveImage(videoUri, mimeType, context, accountViewModel) AnimatedSaveButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size110dp)) { context ->
} saveImage(videoUri, mimeType, context, accountViewModel)
}
AnimatedShareButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size165dp)) { popupExpanded, toggle -> AnimatedShareButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size165dp)) { popupExpanded, toggle ->
ShareImageAction(accountViewModel = accountViewModel, popupExpanded, videoUri, nostrUriCallback, null, null, null, mimeType, toggle) ShareImageAction(accountViewModel = accountViewModel, popupExpanded, videoUri, nostrUriCallback, null, null, null, mimeType, toggle)
}
} else {
AnimatedShareButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size110dp)) { popupExpanded, toggle ->
ShareImageAction(accountViewModel = accountViewModel, popupExpanded, videoUri, nostrUriCallback, null, null, null, mimeType, toggle)
}
} }
} else { } else {
controller.volume = 0f controller.volume = 0f
@@ -255,34 +255,36 @@ private fun DialogContent(
ShareImageAction(accountViewModel = accountViewModel, popupExpanded = popupExpanded, myContent, onDismiss = { popupExpanded.value = false }) ShareImageAction(accountViewModel = accountViewModel, popupExpanded = popupExpanded, myContent, onDismiss = { popupExpanded.value = false })
} }
val localContext = LocalContext.current if (myContent !is MediaUrlContent || !myContent.url.endsWith(".m3u8")) {
val localContext = LocalContext.current
val writeStoragePermissionState = val writeStoragePermissionState =
rememberPermissionState(Manifest.permission.WRITE_EXTERNAL_STORAGE) { isGranted -> rememberPermissionState(Manifest.permission.WRITE_EXTERNAL_STORAGE) { isGranted ->
if (isGranted) { if (isGranted) {
saveImage(myContent, localContext, accountViewModel) saveImage(myContent, localContext, accountViewModel)
}
} }
OutlinedButton(
onClick = {
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ||
writeStoragePermissionState.status.isGranted
) {
saveImage(myContent, localContext, accountViewModel)
} else {
writeStoragePermissionState.launchPermissionRequest()
}
},
contentPadding = PaddingValues(horizontal = Size5dp),
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
) {
Icon(
imageVector = Icons.Default.Download,
modifier = Size20Modifier,
contentDescription = stringRes(R.string.save_to_gallery),
)
} }
OutlinedButton(
onClick = {
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ||
writeStoragePermissionState.status.isGranted
) {
saveImage(myContent, localContext, accountViewModel)
} else {
writeStoragePermissionState.launchPermissionRequest()
}
},
contentPadding = PaddingValues(horizontal = Size5dp),
colors = ButtonDefaults.outlinedButtonColors().copy(containerColor = MaterialTheme.colorScheme.background),
) {
Icon(
imageVector = Icons.Default.Download,
modifier = Size20Modifier,
contentDescription = stringRes(R.string.save_to_gallery),
)
} }
} }
} }
+2
View File
@@ -602,6 +602,8 @@
<string name="automatically_show_url_preview_description">Show URL previews</string> <string name="automatically_show_url_preview_description">Show URL previews</string>
<string name="load_image_description">When to load images</string> <string name="load_image_description">When to load images</string>
<string name="copy_stack_to_clipboard">Copy Stack</string>
<string name="copy_to_clipboard">Copy to clipboard</string> <string name="copy_to_clipboard">Copy to clipboard</string>
<string name="copy_npub_to_clipboard">Copy npub to clipboard</string> <string name="copy_npub_to_clipboard">Copy npub to clipboard</string>
<string name="share_or_save">Share or Save</string> <string name="share_or_save">Share or Save</string>