Improves upload of music and documents.
This commit is contained in:
+1
-1
@@ -79,7 +79,7 @@ class BlossomServerListState(
|
|||||||
emptyList(),
|
emptyList(),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun mergeServerList(blossom: List<String>?): List<ServerName> = blossom?.map { ServerName(host(it), it, ServerType.Blossom) } ?: emptyList()
|
fun mergeServerList(blossom: List<String>?): List<ServerName> = blossom?.map { ServerName(host(it), it, ServerType.Blossom) }?.ifEmpty { DEFAULT_MEDIA_SERVERS } ?: DEFAULT_MEDIA_SERVERS
|
||||||
|
|
||||||
val hostNameFlow: StateFlow<List<ServerName>> =
|
val hostNameFlow: StateFlow<List<ServerName>> =
|
||||||
flow
|
flow
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ class MultiOrchestrator(
|
|||||||
|
|
||||||
fun hasVideo() = list.any { it.media.mimeType?.startsWith("video", ignoreCase = true) == true }
|
fun hasVideo() = list.any { it.media.mimeType?.startsWith("video", ignoreCase = true) == true }
|
||||||
|
|
||||||
|
fun hasNonMedia() = list.any { it.media.isNotMedia() }
|
||||||
|
|
||||||
suspend fun upload(
|
suspend fun upload(
|
||||||
alt: String?,
|
alt: String?,
|
||||||
contentWarningReason: String?,
|
contentWarningReason: String?,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
||||||
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
||||||
@@ -204,7 +205,8 @@ fun ImageVideoPost(
|
|||||||
fileServers
|
fileServers
|
||||||
.firstOrNull { it == accountViewModel.account.settings.defaultFileServer }
|
.firstOrNull { it == accountViewModel.account.settings.defaultFileServer }
|
||||||
?.name
|
?.name
|
||||||
?: fileServers[0].name,
|
?: fileServers.firstOrNull()?.name
|
||||||
|
?: DEFAULT_MEDIA_SERVERS[0].name,
|
||||||
options = fileServerOptions,
|
options = fileServerOptions,
|
||||||
onSelect = { postViewModel.selectedServer = fileServers[it] },
|
onSelect = { postViewModel.selectedServer = fileServers[it] },
|
||||||
)
|
)
|
||||||
|
|||||||
+5
@@ -58,6 +58,11 @@ class SelectedMedia(
|
|||||||
|
|
||||||
fun isAudio() = mimeType?.startsWith("audio")
|
fun isAudio() = mimeType?.startsWith("audio")
|
||||||
|
|
||||||
|
fun isNotMedia() =
|
||||||
|
mimeType?.let {
|
||||||
|
!(it.startsWith("image") || it.startsWith("video") || it.startsWith("audio"))
|
||||||
|
} ?: true
|
||||||
|
|
||||||
fun isDocument() = mimeType == "application/pdf"
|
fun isDocument() = mimeType == "application/pdf"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-32
@@ -129,7 +129,7 @@ fun ShowImageGallery(
|
|||||||
icon = Icons.Default.AudioFile,
|
icon = Icons.Default.AudioFile,
|
||||||
label = media.mimeType ?: "audio/*",
|
label = media.mimeType ?: "audio/*",
|
||||||
)
|
)
|
||||||
} else if (media.isDocument() == true) {
|
} else if (media.isDocument()) {
|
||||||
FilePreviewPlaceholder(
|
FilePreviewPlaceholder(
|
||||||
icon = Icons.Default.PictureAsPdf,
|
icon = Icons.Default.PictureAsPdf,
|
||||||
label = media.mimeType ?: "application/pdf",
|
label = media.mimeType ?: "application/pdf",
|
||||||
@@ -236,39 +236,44 @@ fun UploadingState(
|
|||||||
progress: Double,
|
progress: Double,
|
||||||
progressState: UploadingState,
|
progressState: UploadingState,
|
||||||
) {
|
) {
|
||||||
Box(Modifier.size(55.dp), contentAlignment = Alignment.Center) {
|
Box(
|
||||||
val animatedProgress by animateFloatAsState(
|
contentAlignment = Alignment.Center,
|
||||||
targetValue = progress.toFloat(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
) {
|
||||||
)
|
Box(Modifier.size(55.dp), contentAlignment = Alignment.Center) {
|
||||||
|
val animatedProgress by animateFloatAsState(
|
||||||
|
targetValue = progress.toFloat(),
|
||||||
|
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||||
|
)
|
||||||
|
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
progress = { animatedProgress },
|
progress = { animatedProgress },
|
||||||
modifier =
|
modifier =
|
||||||
Size55Modifier
|
Size55Modifier
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.background(MaterialTheme.colorScheme.background),
|
.background(MaterialTheme.colorScheme.background),
|
||||||
strokeWidth = 5.dp,
|
strokeWidth = 5.dp,
|
||||||
)
|
)
|
||||||
|
|
||||||
val txt =
|
val txt =
|
||||||
when (progressState) {
|
when (progressState) {
|
||||||
is UploadingState.Ready -> stringRes(R.string.uploading_state_ready)
|
is UploadingState.Ready -> stringRes(R.string.uploading_state_ready)
|
||||||
is UploadingState.Compressing -> stringRes(R.string.uploading_state_compressing)
|
is UploadingState.Compressing -> stringRes(R.string.uploading_state_compressing)
|
||||||
is UploadingState.Uploading -> stringRes(R.string.uploading_state_uploading)
|
is UploadingState.Uploading -> stringRes(R.string.uploading_state_uploading)
|
||||||
is UploadingState.ServerProcessing -> stringRes(R.string.uploading_state_server_processing)
|
is UploadingState.ServerProcessing -> stringRes(R.string.uploading_state_server_processing)
|
||||||
is UploadingState.Downloading -> stringRes(R.string.uploading_state_downloading)
|
is UploadingState.Downloading -> stringRes(R.string.uploading_state_downloading)
|
||||||
is UploadingState.Hashing -> stringRes(R.string.uploading_state_hashing)
|
is UploadingState.Hashing -> stringRes(R.string.uploading_state_hashing)
|
||||||
is UploadingState.Finished -> stringRes(R.string.uploading_state_finished)
|
is UploadingState.Finished -> stringRes(R.string.uploading_state_finished)
|
||||||
is UploadingState.Error -> stringRes(R.string.uploading_state_error)
|
is UploadingState.Error -> stringRes(R.string.uploading_state_error)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
txt,
|
txt,
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
fontSize = 10.sp,
|
fontSize = 10.sp,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +285,7 @@ fun FilePreviewPlaceholder(
|
|||||||
Box(
|
Box(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxSize()
|
||||||
.background(MaterialTheme.colorScheme.surfaceVariant),
|
.background(MaterialTheme.colorScheme.surfaceVariant),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
|
|||||||
+30
-22
@@ -57,6 +57,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
import com.vitorpamplona.amethyst.service.uploads.MultiOrchestrator
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
||||||
@@ -92,14 +93,16 @@ fun ImageVideoDescription(
|
|||||||
|
|
||||||
var selectedServer by remember {
|
var selectedServer by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
fileServers.firstOrNull { it == defaultServer } ?: fileServers[0],
|
fileServers.firstOrNull { it == defaultServer } ?: fileServers.firstOrNull() ?: DEFAULT_MEDIA_SERVERS[0],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
var message by remember { mutableStateOf("") }
|
var message by remember { mutableStateOf("") }
|
||||||
var sensitiveContent by remember { mutableStateOf(false) }
|
var sensitiveContent by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
// 0 = Low, 1 = Medium, 2 = High, 3=UNCOMPRESSED
|
// 0 = Low, 1 = Medium, 2 = High, 3=UNCOMPRESSED
|
||||||
var mediaQualitySlider by remember { mutableIntStateOf(1) }
|
var mediaQualitySlider by remember {
|
||||||
|
mutableIntStateOf(if (uris.hasNonMedia()) 3 else 1)
|
||||||
|
}
|
||||||
|
|
||||||
// Codec selection: false = H264, true = H265
|
// Codec selection: false = H264, true = H265
|
||||||
var useH265Codec by remember { mutableStateOf(false) }
|
var useH265Codec by remember { mutableStateOf(false) }
|
||||||
@@ -189,7 +192,8 @@ fun ImageVideoDescription(
|
|||||||
fileServers
|
fileServers
|
||||||
.firstOrNull { it == defaultServer }
|
.firstOrNull { it == defaultServer }
|
||||||
?.name
|
?.name
|
||||||
?: fileServers[0].name,
|
?: fileServers.firstOrNull()?.name
|
||||||
|
?: DEFAULT_MEDIA_SERVERS[0].name,
|
||||||
options = fileServerOptions,
|
options = fileServerOptions,
|
||||||
onSelect = { selectedServer = fileServers[it] },
|
onSelect = { selectedServer = fileServers[it] },
|
||||||
modifier =
|
modifier =
|
||||||
@@ -270,27 +274,31 @@ fun ImageVideoDescription(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
val firstMedia = uris.first().media
|
||||||
Box(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
Text(
|
if (firstMedia.isVideo() == true || firstMedia.isImage() == true || firstMedia.isAudio() == true) {
|
||||||
text =
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
when (mediaQualitySlider) {
|
Box(modifier = Modifier.fillMaxWidth()) {
|
||||||
0 -> stringRes(R.string.media_compression_quality_low)
|
Text(
|
||||||
1 -> stringRes(R.string.media_compression_quality_medium)
|
text =
|
||||||
2 -> stringRes(R.string.media_compression_quality_high)
|
when (mediaQualitySlider) {
|
||||||
3 -> stringRes(R.string.media_compression_quality_uncompressed)
|
0 -> stringRes(R.string.media_compression_quality_low)
|
||||||
else -> stringRes(R.string.media_compression_quality_medium)
|
1 -> stringRes(R.string.media_compression_quality_medium)
|
||||||
},
|
2 -> stringRes(R.string.media_compression_quality_high)
|
||||||
modifier = Modifier.align(Alignment.Center),
|
3 -> stringRes(R.string.media_compression_quality_uncompressed)
|
||||||
|
else -> stringRes(R.string.media_compression_quality_medium)
|
||||||
|
},
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider(
|
||||||
|
value = mediaQualitySlider.toFloat(),
|
||||||
|
onValueChange = { mediaQualitySlider = it.toInt() },
|
||||||
|
valueRange = 0f..3f,
|
||||||
|
steps = 2,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Slider(
|
|
||||||
value = mediaQualitySlider.toFloat(),
|
|
||||||
onValueChange = { mediaQualitySlider = it.toInt() },
|
|
||||||
valueRange = 0f..3f,
|
|
||||||
steps = 2,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uris.first().media.isVideo() == true) {
|
if (uris.first().media.isVideo() == true) {
|
||||||
|
|||||||
+3
-1
@@ -55,6 +55,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
import com.vitorpamplona.amethyst.ui.actions.uploads.ShowImageUploadGallery
|
||||||
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
||||||
import com.vitorpamplona.amethyst.ui.components.TextSpinner
|
import com.vitorpamplona.amethyst.ui.components.TextSpinner
|
||||||
@@ -196,7 +197,8 @@ private fun ImageVideoPostChat(
|
|||||||
fileServers
|
fileServers
|
||||||
.firstOrNull { it == accountViewModel.account.settings.defaultFileServer }
|
.firstOrNull { it == accountViewModel.account.settings.defaultFileServer }
|
||||||
?.name
|
?.name
|
||||||
?: fileServers[0].name,
|
?: fileServers.firstOrNull()?.name
|
||||||
|
?: DEFAULT_MEDIA_SERVERS[0].name,
|
||||||
options = fileServerOptions,
|
options = fileServerOptions,
|
||||||
onSelect = { fileUploadState.selectedServer = fileServers[it] },
|
onSelect = { fileUploadState.selectedServer = fileServers[it] },
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user