diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt index a56dd41af..b06ba8382 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostScreen.kt @@ -62,11 +62,13 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.ui.actions.StrippingFailureDialog import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromFiles import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.SelectSingleFromGallery import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton +import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton import com.vitorpamplona.amethyst.ui.components.markdown.RenderContentAsMarkdown import com.vitorpamplona.amethyst.ui.navigation.navs.Nav import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar @@ -114,6 +116,8 @@ fun LongFormPostScreen( WatchAndLoadMyEmojiList(accountViewModel) + StrippingFailureDialog(postViewModel.strippingFailureConfirmation) + BackHandler { accountViewModel.launchSigner { postViewModel.sendDraftSync() @@ -388,8 +392,9 @@ private fun MarkdownPostScreenBody( ImageVideoDescription( it, accountViewModel.account.settings.defaultFileServer, - onAdd = { alt, server, sensitiveContent, mediaQuality, useH265 -> - postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context, useH265) + isUploading = postViewModel.mediaUploadTracker.isUploading, + onAdd = { alt, server, sensitiveContent, mediaQuality, useH265, stripMetadata -> + postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context, useH265, stripMetadata) accountViewModel.account.settings.changeDefaultFileServer(server) }, onDelete = postViewModel::deleteMediaToUpload, @@ -488,6 +493,7 @@ private fun MarkdownBottomRowActions(postViewModel: LongFormPostViewModel) { ) { SelectFromGallery( isUploading = postViewModel.isUploadingImage, + enabled = !postViewModel.isUploadingFile, tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier, ) { @@ -495,7 +501,8 @@ private fun MarkdownBottomRowActions(postViewModel: LongFormPostViewModel) { } SelectFromFiles( - isUploading = postViewModel.isUploadingImage, + isUploading = postViewModel.isUploadingFile, + enabled = !postViewModel.isUploadingImage, tint = MaterialTheme.colorScheme.onBackground, modifier = Modifier, ) { @@ -508,6 +515,12 @@ private fun MarkdownBottomRowActions(postViewModel: LongFormPostViewModel) { }, ) + TakeVideoButton( + onVideoTaken = { + postViewModel.selectImage(it) + }, + ) + ForwardZapToButton(postViewModel.wantsForwardZapTo) { postViewModel.wantsForwardZapTo = !postViewModel.wantsForwardZapTo } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt index a9da009eb..3c5e16928 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormPostViewModel.kt @@ -43,12 +43,14 @@ import com.vitorpamplona.amethyst.service.location.LocationState import com.vitorpamplona.amethyst.service.uploads.CompressorQuality import com.vitorpamplona.amethyst.service.uploads.MediaCompressor import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator +import com.vitorpamplona.amethyst.service.uploads.SuspendableConfirmation import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.blossom.BlossomUploader import com.vitorpamplona.amethyst.service.uploads.nip96.Nip96Uploader import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType +import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState @@ -151,9 +153,15 @@ class LongFormPostViewModel : val iMetaAttachments = IMetaAttachments() - var isUploadingImage by mutableStateOf(false) + val mediaUploadTracker = MediaUploadTracker() + val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage + val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile + var multiOrchestrator by mutableStateOf(null) + // Stripping failure dialog + val strippingFailureConfirmation = SuspendableConfirmation() + var userSuggestions: UserSuggestionState? = null var userSuggestionsMainMessage: UserSuggestionAnchor? = null @@ -467,8 +475,9 @@ class LongFormPostViewModel : onError: (title: String, message: String) -> Unit, context: Context, useH265: Boolean, + stripMetadata: Boolean = true, ) = try { - uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context, useH265) + uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context, useH265, stripMetadata) } catch (_: SignerExceptions.ReadOnlyException) { onError( stringRes(context, R.string.read_only_user), @@ -484,11 +493,12 @@ class LongFormPostViewModel : onError: (title: String, message: String) -> Unit, context: Context, useH265: Boolean, + stripMetadata: Boolean = true, ) { viewModelScope.launch(Dispatchers.IO) { val myMultiOrchestrator = multiOrchestrator ?: return@launch - isUploadingImage = true + mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia()) val results = myMultiOrchestrator.upload( @@ -499,6 +509,8 @@ class LongFormPostViewModel : account, context, useH265, + stripMetadata, + onStrippingFailed = strippingFailureConfirmation::awaitConfirmation, ) if (results.allGood) { @@ -534,7 +546,7 @@ class LongFormPostViewModel : onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n")) } - isUploadingImage = false + mediaUploadTracker.finishUpload() } } @@ -552,7 +564,7 @@ class LongFormPostViewModel : existingDTag = null multiOrchestrator = null - isUploadingImage = false + mediaUploadTracker.finishUpload() wantsInvoice = false wantsZapRaiser = false @@ -568,10 +580,11 @@ class LongFormPostViewModel : forwardZapTo.value = SplitBuilder() forwardZapToEditting.value = TextFieldValue("") - iMetaAttachments.reset() - userSuggestions?.reset() userSuggestionsMainMessage = null + + iMetaAttachments.reset() + emojiSuggestions?.reset() }