Merge pull request #1843 from davotoula/bugfix-multiple-spinners-on-upload
Bugfix: multiple spinners on upload
This commit is contained in:
@@ -264,6 +264,7 @@ fun EditPostView(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
it,
|
it,
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = postViewModel.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
||||||
postViewModel.upload(alt, sensitiveContent, mediaQuality, false, server, accountViewModel.toastManager::toast, context)
|
postViewModel.upload(alt, sensitiveContent, mediaQuality, false, server, accountViewModel.toastManager::toast, context)
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
@@ -372,6 +373,7 @@ private fun BottomRowActions(postViewModel: EditPostViewModel) {
|
|||||||
) {
|
) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -379,7 +381,8 @@ private fun BottomRowActions(postViewModel: EditPostViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import com.vitorpamplona.amethyst.service.uploads.MediaCompressor
|
|||||||
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
||||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.UserSuggestionState
|
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.UserSuggestionState
|
||||||
@@ -79,7 +80,9 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
|
|
||||||
var message by mutableStateOf(TextFieldValue(""))
|
var message by mutableStateOf(TextFieldValue(""))
|
||||||
var urlPreview by mutableStateOf<String?>(null)
|
var urlPreview by mutableStateOf<String?>(null)
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -180,7 +183,7 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
val myAccount = account
|
val myAccount = account
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -243,7 +246,7 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +258,7 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
|
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
urlPreview = null
|
urlPreview = null
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
|
|
||||||
wantsInvoice = false
|
wantsInvoice = false
|
||||||
|
|
||||||
@@ -296,7 +299,7 @@ open class EditPostViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canPost() = message.text.isNotBlank() && !isUploadingImage && !wantsInvoice && multiOrchestrator == null
|
fun canPost() = message.text.isNotBlank() && !mediaUploadTracker.isUploading && !wantsInvoice && multiOrchestrator == null
|
||||||
|
|
||||||
fun selectImage(uris: ImmutableList<SelectedMedia>) {
|
fun selectImage(uris: ImmutableList<SelectedMedia>) {
|
||||||
multiOrchestrator = MultiOrchestrator(uris)
|
multiOrchestrator = MultiOrchestrator(uris)
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.actions.uploads
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
|
||||||
|
class MediaUploadTracker {
|
||||||
|
var isUploadingImage by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
var isUploadingFile by mutableStateOf(false)
|
||||||
|
private set
|
||||||
|
|
||||||
|
val isUploading: Boolean get() = isUploadingImage || isUploadingFile
|
||||||
|
|
||||||
|
fun startUpload(hasNonMedia: Boolean) {
|
||||||
|
if (hasNonMedia) {
|
||||||
|
isUploadingFile = true
|
||||||
|
} else {
|
||||||
|
isUploadingImage = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun finishUpload() {
|
||||||
|
isUploadingImage = false
|
||||||
|
isUploadingFile = false
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-2
@@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicBoolean
|
|||||||
@Composable
|
@Composable
|
||||||
fun SelectFromFiles(
|
fun SelectFromFiles(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
enabled: Boolean = true,
|
||||||
tint: Color,
|
tint: Color,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onFilesChosen: (ImmutableList<SelectedMedia>) -> Unit,
|
onFilesChosen: (ImmutableList<SelectedMedia>) -> Unit,
|
||||||
@@ -64,19 +65,20 @@ fun SelectFromFiles(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSelectButton(isUploading, tint, modifier) { showFileSelect = true }
|
FileSelectButton(isUploading, enabled, tint, modifier) { showFileSelect = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun FileSelectButton(
|
private fun FileSelectButton(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
enabled: Boolean,
|
||||||
tint: Color,
|
tint: Color,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
enabled = !isUploading,
|
enabled = enabled && !isUploading,
|
||||||
onClick = { onClick() },
|
onClick = { onClick() },
|
||||||
) {
|
) {
|
||||||
if (!isUploading) {
|
if (!isUploading) {
|
||||||
|
|||||||
+5
-3
@@ -69,6 +69,7 @@ class SelectedMedia(
|
|||||||
@Composable
|
@Composable
|
||||||
fun SelectFromGallery(
|
fun SelectFromGallery(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
enabled: Boolean = true,
|
||||||
tint: Color,
|
tint: Color,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onImageChosen: (ImmutableList<SelectedMedia>) -> Unit,
|
onImageChosen: (ImmutableList<SelectedMedia>) -> Unit,
|
||||||
@@ -85,7 +86,7 @@ fun SelectFromGallery(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
GallerySelectButton(isUploading, tint, modifier) { showGallerySelect = true }
|
GallerySelectButton(isUploading, enabled, tint, modifier) { showGallerySelect = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -107,19 +108,20 @@ fun SelectSingleFromGallery(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
GallerySelectButton(isUploading, tint, modifier) { showGallerySelect = true }
|
GallerySelectButton(isUploading, true, tint, modifier) { showGallerySelect = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun GallerySelectButton(
|
private fun GallerySelectButton(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
enabled: Boolean,
|
||||||
tint: Color,
|
tint: Color,
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
enabled = !isUploading,
|
enabled = enabled && !isUploading,
|
||||||
onClick = { onClick() },
|
onClick = { onClick() },
|
||||||
) {
|
) {
|
||||||
if (!isUploading) {
|
if (!isUploading) {
|
||||||
|
|||||||
+2
@@ -78,6 +78,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||||||
fun ImageVideoDescription(
|
fun ImageVideoDescription(
|
||||||
uris: MultiOrchestrator,
|
uris: MultiOrchestrator,
|
||||||
defaultServer: ServerName,
|
defaultServer: ServerName,
|
||||||
|
isUploading: Boolean,
|
||||||
onAdd: (String, ServerName, Boolean, Int, Boolean) -> Unit,
|
onAdd: (String, ServerName, Boolean, Int, Boolean) -> Unit,
|
||||||
onDelete: (SelectedMediaProcessing) -> Unit,
|
onDelete: (SelectedMediaProcessing) -> Unit,
|
||||||
onCancel: () -> Unit,
|
onCancel: () -> Unit,
|
||||||
@@ -319,6 +320,7 @@ fun ImageVideoDescription(
|
|||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 10.dp),
|
.padding(vertical = 10.dp),
|
||||||
|
enabled = !isUploading,
|
||||||
onClick = { onAdd(message, selectedServer, sensitiveContent, mediaQualitySlider, useH265Codec) },
|
onClick = { onAdd(message, selectedServer, sensitiveContent, mediaQualitySlider, useH265Codec) },
|
||||||
shape = QuoteBorder,
|
shape = QuoteBorder,
|
||||||
colors =
|
colors =
|
||||||
|
|||||||
+8
-5
@@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
|||||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
||||||
@@ -149,7 +150,9 @@ open class CommentPostViewModel :
|
|||||||
|
|
||||||
val urlPreviews = PreviewState()
|
val urlPreviews = PreviewState()
|
||||||
|
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -487,7 +490,7 @@ open class CommentPostViewModel :
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -551,7 +554,7 @@ open class CommentPostViewModel :
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,7 +567,7 @@ open class CommentPostViewModel :
|
|||||||
externalIdentity = null
|
externalIdentity = null
|
||||||
|
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
|
|
||||||
notifying = null
|
notifying = null
|
||||||
|
|
||||||
@@ -676,7 +679,7 @@ open class CommentPostViewModel :
|
|||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
!isUploadingImage &&
|
!mediaUploadTracker.isUploading &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
||||||
multiOrchestrator == null
|
multiOrchestrator == null
|
||||||
|
|||||||
+4
-1
@@ -300,6 +300,7 @@ private fun GenericCommentPostBody(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
it,
|
it,
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = postViewModel.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
@@ -391,6 +392,7 @@ private fun BottomRowActions(postViewModel: CommentPostViewModel) {
|
|||||||
) {
|
) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -398,7 +400,8 @@ private fun BottomRowActions(postViewModel: CommentPostViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+4
-2
@@ -141,7 +141,8 @@ class ChatNewMessageViewModel :
|
|||||||
|
|
||||||
val urlPreviews = PreviewState()
|
val urlPreviews = PreviewState()
|
||||||
|
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val isUploadingImage: Boolean get() = uploadState?.isUploadingImage ?: false
|
||||||
|
val isUploadingFile: Boolean get() = uploadState?.isUploadingFile ?: false
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -560,6 +561,7 @@ class ChatNewMessageViewModel :
|
|||||||
userSuggestionsMainMessage = null
|
userSuggestionsMainMessage = null
|
||||||
|
|
||||||
uploadsWaitingToBeSent = emptyList()
|
uploadsWaitingToBeSent = emptyList()
|
||||||
|
uploadState?.reset()
|
||||||
|
|
||||||
iMetaAttachments.reset()
|
iMetaAttachments.reset()
|
||||||
|
|
||||||
@@ -691,7 +693,7 @@ class ChatNewMessageViewModel :
|
|||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
uploadState?.isUploadingImage != true &&
|
uploadState?.mediaUploadTracker?.isUploading != true &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
||||||
(toUsers.text.isNotBlank()) &&
|
(toUsers.text.isNotBlank()) &&
|
||||||
|
|||||||
+4
-1
@@ -287,6 +287,7 @@ fun GroupDMScreenContent(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
selectedFiles,
|
selectedFiles,
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = uploading.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
||||||
postViewModel.uploadAndHold(
|
postViewModel.uploadAndHold(
|
||||||
accountViewModel.toastManager::toast,
|
accountViewModel.toastManager::toast,
|
||||||
@@ -386,6 +387,7 @@ private fun BottomRowActions(
|
|||||||
if (postViewModel.room != null) {
|
if (postViewModel.room != null) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -393,7 +395,8 @@ private fun BottomRowActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+4
-4
@@ -43,7 +43,7 @@ class ChatFileUploader(
|
|||||||
onceUploaded: suspend (List<SuccessfulUploads>) -> Unit,
|
onceUploaded: suspend (List<SuccessfulUploads>) -> Unit,
|
||||||
) {
|
) {
|
||||||
val orchestrator = viewState.multiOrchestrator ?: return
|
val orchestrator = viewState.multiOrchestrator ?: return
|
||||||
viewState.isUploadingImage = true
|
viewState.mediaUploadTracker.startUpload(orchestrator.hasNonMedia())
|
||||||
|
|
||||||
val cipher = AESGCM()
|
val cipher = AESGCM()
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ class ChatFileUploader(
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
viewState.isUploadingImage = false
|
viewState.mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------
|
// ------
|
||||||
@@ -90,7 +90,7 @@ class ChatFileUploader(
|
|||||||
onceUploaded: suspend (List<SuccessfulUploads>) -> Unit,
|
onceUploaded: suspend (List<SuccessfulUploads>) -> Unit,
|
||||||
) {
|
) {
|
||||||
val orchestrator = viewState.multiOrchestrator ?: return
|
val orchestrator = viewState.multiOrchestrator ?: return
|
||||||
viewState.isUploadingImage = true
|
viewState.mediaUploadTracker.startUpload(orchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
orchestrator.upload(
|
orchestrator.upload(
|
||||||
@@ -120,6 +120,6 @@ class ChatFileUploader(
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
viewState.isUploadingImage = false
|
viewState.mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -134,7 +134,8 @@ open class ChannelNewMessageViewModel :
|
|||||||
|
|
||||||
var message by mutableStateOf(TextFieldValue(""))
|
var message by mutableStateOf(TextFieldValue(""))
|
||||||
var urlPreview by mutableStateOf<String?>(null)
|
var urlPreview by mutableStateOf<String?>(null)
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val isUploadingImage: Boolean get() = uploadState?.isUploadingImage ?: false
|
||||||
|
val isUploadingFile: Boolean get() = uploadState?.isUploadingFile ?: false
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -337,7 +338,7 @@ open class ChannelNewMessageViewModel :
|
|||||||
|
|
||||||
val myMultiOrchestrator = uploadState.multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = uploadState.multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
uploadState.mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -378,7 +379,7 @@ open class ChannelNewMessageViewModel :
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
uploadState.mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,6 +547,8 @@ open class ChannelNewMessageViewModel :
|
|||||||
userSuggestions?.reset()
|
userSuggestions?.reset()
|
||||||
userSuggestionsMainMessage = null
|
userSuggestionsMainMessage = null
|
||||||
|
|
||||||
|
uploadState?.reset()
|
||||||
|
|
||||||
iMetaAttachments.reset()
|
iMetaAttachments.reset()
|
||||||
|
|
||||||
emojiSuggestions?.reset()
|
emojiSuggestions?.reset()
|
||||||
@@ -632,7 +635,7 @@ open class ChannelNewMessageViewModel :
|
|||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
uploadState?.isUploadingImage != true &&
|
uploadState?.mediaUploadTracker?.isUploading != true &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount != null) &&
|
(!wantsZapraiser || zapRaiserAmount != null) &&
|
||||||
uploadState?.multiOrchestrator == null
|
uploadState?.multiOrchestrator == null
|
||||||
|
|||||||
+6
-3
@@ -28,6 +28,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||||
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
@@ -36,7 +37,9 @@ import kotlinx.collections.immutable.ImmutableList
|
|||||||
class ChatFileUploadState(
|
class ChatFileUploadState(
|
||||||
val defaultServer: ServerName,
|
val defaultServer: ServerName,
|
||||||
) {
|
) {
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var selectedServer by mutableStateOf(defaultServer)
|
var selectedServer by mutableStateOf(defaultServer)
|
||||||
var caption by mutableStateOf("")
|
var caption by mutableStateOf("")
|
||||||
@@ -64,7 +67,7 @@ class ChatFileUploadState(
|
|||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
caption = ""
|
caption = ""
|
||||||
selectedServer = defaultServer
|
selectedServer = defaultServer
|
||||||
}
|
}
|
||||||
@@ -73,7 +76,7 @@ class ChatFileUploadState(
|
|||||||
multiOrchestrator?.remove(selected)
|
multiOrchestrator?.remove(selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun canPost(): Boolean = !isUploadingImage && multiOrchestrator != null
|
fun canPost(): Boolean = !mediaUploadTracker.isUploading && multiOrchestrator != null
|
||||||
|
|
||||||
fun hasPickedMedia() = multiOrchestrator != null
|
fun hasPickedMedia() = multiOrchestrator != null
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -269,6 +269,7 @@ private fun NewProductBody(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
uris = it,
|
uris = it,
|
||||||
defaultServer = accountViewModel.account.settings.defaultFileServer,
|
defaultServer = accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = postViewModel.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
@@ -359,6 +360,7 @@ private fun BottomRowActions(postViewModel: NewProductViewModel) {
|
|||||||
) {
|
) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -366,7 +368,8 @@ private fun BottomRowActions(postViewModel: NewProductViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+8
-5
@@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
|||||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
||||||
@@ -133,7 +134,9 @@ open class NewProductViewModel :
|
|||||||
|
|
||||||
val urlPreviews = PreviewState()
|
val urlPreviews = PreviewState()
|
||||||
|
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -399,7 +402,7 @@ open class NewProductViewModel :
|
|||||||
val myAccount = account ?: return@launch
|
val myAccount = account ?: return@launch
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -444,7 +447,7 @@ open class NewProductViewModel :
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +457,7 @@ open class NewProductViewModel :
|
|||||||
message = TextFieldValue("")
|
message = TextFieldValue("")
|
||||||
|
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
|
|
||||||
wantsInvoice = false
|
wantsInvoice = false
|
||||||
wantsZapraiser = false
|
wantsZapraiser = false
|
||||||
@@ -575,7 +578,7 @@ open class NewProductViewModel :
|
|||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
!isUploadingImage &&
|
!mediaUploadTracker.isUploading &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
||||||
title.text.isNotBlank() &&
|
title.text.isNotBlank() &&
|
||||||
|
|||||||
+4
-1
@@ -356,6 +356,7 @@ private fun NewPostScreenBody(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
it,
|
it,
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = postViewModel.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, useH265 ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, useH265 ->
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context, useH265)
|
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context, useH265)
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
@@ -494,6 +495,7 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) {
|
|||||||
) {
|
) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -501,7 +503,8 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+9
-6
@@ -49,6 +49,7 @@ import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
|||||||
import com.vitorpamplona.amethyst.service.uploads.UploadingState
|
import com.vitorpamplona.amethyst.service.uploads.UploadingState
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.RecordingResult
|
import com.vitorpamplona.amethyst.ui.actions.uploads.RecordingResult
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
@@ -178,7 +179,9 @@ open class ShortNotePostViewModel :
|
|||||||
|
|
||||||
val urlPreviews = PreviewState()
|
val urlPreviews = PreviewState()
|
||||||
|
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -829,7 +832,7 @@ open class ShortNotePostViewModel :
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -885,7 +888,7 @@ open class ShortNotePostViewModel :
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,7 +900,7 @@ open class ShortNotePostViewModel :
|
|||||||
forkedFromNote = null
|
forkedFromNote = null
|
||||||
|
|
||||||
multiOrchestrator = null
|
multiOrchestrator = null
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
voiceAnonymization.clear()
|
voiceAnonymization.clear()
|
||||||
deleteVoiceLocalFile()
|
deleteVoiceLocalFile()
|
||||||
voiceRecording = null
|
voiceRecording = null
|
||||||
@@ -1032,12 +1035,12 @@ open class ShortNotePostViewModel :
|
|||||||
fun canPost(): Boolean {
|
fun canPost(): Boolean {
|
||||||
// Voice messages can be posted without text (with either uploaded or pending recording)
|
// Voice messages can be posted without text (with either uploaded or pending recording)
|
||||||
if (voiceMetadata != null || voiceRecording != null) {
|
if (voiceMetadata != null || voiceRecording != null) {
|
||||||
return !isUploadingVoice && !isUploadingImage && processingPreset == null
|
return !isUploadingVoice && !mediaUploadTracker.isUploading && processingPreset == null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular text/media posts require text
|
// Regular text/media posts require text
|
||||||
return message.text.isNotBlank() &&
|
return message.text.isNotBlank() &&
|
||||||
!isUploadingImage &&
|
!mediaUploadTracker.isUploading &&
|
||||||
!isUploadingVoice &&
|
!isUploadingVoice &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapRaiser || zapRaiserAmount.value != null) &&
|
(!wantsZapRaiser || zapRaiserAmount.value != null) &&
|
||||||
|
|||||||
+4
-1
@@ -246,6 +246,7 @@ fun PublicMessageScreenContent(
|
|||||||
ImageVideoDescription(
|
ImageVideoDescription(
|
||||||
it,
|
it,
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
isUploading = postViewModel.mediaUploadTracker.isUploading,
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
onAdd = { alt, server, sensitiveContent, mediaQuality, _ ->
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
@@ -321,6 +322,7 @@ private fun BottomRowActions(
|
|||||||
) {
|
) {
|
||||||
SelectFromGallery(
|
SelectFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
enabled = !postViewModel.isUploadingFile,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
@@ -328,7 +330,8 @@ private fun BottomRowActions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SelectFromFiles(
|
SelectFromFiles(
|
||||||
isUploading = postViewModel.isUploadingImage,
|
isUploading = postViewModel.isUploadingFile,
|
||||||
|
enabled = !postViewModel.isUploadingImage,
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+9
-4
@@ -45,6 +45,7 @@ import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
|||||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.MediaUploadTracker
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
||||||
@@ -149,7 +150,9 @@ class NewPublicMessageViewModel :
|
|||||||
|
|
||||||
val urlPreviews = PreviewState()
|
val urlPreviews = PreviewState()
|
||||||
|
|
||||||
var isUploadingImage by mutableStateOf(false)
|
val mediaUploadTracker = MediaUploadTracker()
|
||||||
|
val isUploadingImage: Boolean get() = mediaUploadTracker.isUploadingImage
|
||||||
|
val isUploadingFile: Boolean get() = mediaUploadTracker.isUploadingFile
|
||||||
|
|
||||||
var userSuggestions: UserSuggestionState? = null
|
var userSuggestions: UserSuggestionState? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
@@ -439,7 +442,7 @@ class NewPublicMessageViewModel :
|
|||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
val myMultiOrchestrator = multiOrchestrator ?: return@launch
|
||||||
|
|
||||||
isUploadingImage = true
|
mediaUploadTracker.startUpload(myMultiOrchestrator.hasNonMedia())
|
||||||
|
|
||||||
val results =
|
val results =
|
||||||
myMultiOrchestrator.upload(
|
myMultiOrchestrator.upload(
|
||||||
@@ -494,7 +497,7 @@ class NewPublicMessageViewModel :
|
|||||||
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
onError(stringRes(context, R.string.failed_to_upload_media_no_details), errorMessages.joinToString(".\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
isUploadingImage = false
|
mediaUploadTracker.finishUpload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,6 +526,8 @@ class NewPublicMessageViewModel :
|
|||||||
userSuggestions?.reset()
|
userSuggestions?.reset()
|
||||||
userSuggestionsMainMessage = null
|
userSuggestionsMainMessage = null
|
||||||
|
|
||||||
|
mediaUploadTracker.finishUpload()
|
||||||
|
|
||||||
iMetaAttachments.reset()
|
iMetaAttachments.reset()
|
||||||
|
|
||||||
emojiSuggestions?.reset()
|
emojiSuggestions?.reset()
|
||||||
@@ -628,7 +633,7 @@ class NewPublicMessageViewModel :
|
|||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
message.text.isNotBlank() &&
|
message.text.isNotBlank() &&
|
||||||
!isUploadingImage &&
|
!mediaUploadTracker.isUploading &&
|
||||||
!wantsInvoice &&
|
!wantsInvoice &&
|
||||||
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
(!wantsZapraiser || zapRaiserAmount.value != null) &&
|
||||||
(toUsers.text.isNotBlank()) &&
|
(toUsers.text.isNotBlank()) &&
|
||||||
|
|||||||
Reference in New Issue
Block a user