From c6932fd31dd6659978c3f874abcde20e8ac75b09 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:43:50 +0100 Subject: [PATCH] feat: Add progress bar; Closes #64 --- .../myzel394/alibi/helpers/BatchesFolder.kt | 9 +++++++- .../myzel394/alibi/helpers/MediaConverter.kt | 4 ---- .../atoms/RecorderProcessingDialog.kt | 6 ++--- .../molecules/AudioRecordingStart.kt | 23 +++++++++++++++---- .../molecules/VideoRecordingStart.kt | 7 +----- .../organisms/RecorderEventsHandler.kt | 2 +- .../components/atoms/PermissionRequester.kt | 23 ++++++++++++++++--- 7 files changed, 51 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt index 9b80a25..c1033f5 100644 --- a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt +++ b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt @@ -253,7 +253,7 @@ abstract class BatchesFolder( disableCache: Boolean = false, onNextParameterTry: (String) -> Unit = {}, durationPerBatchInMilliseconds: Long = 0, - onProgress: (Float) -> Unit = {}, + onProgress: (Float?) -> Unit = {}, ): String { if (!disableCache && checkIfOutputAlreadyExists(recordingStart, extension)) { return getOutputFileForFFmpeg( @@ -265,6 +265,7 @@ abstract class BatchesFolder( for (parameter in ffmpegParameters) { Log.i("Concatenation", "Trying parameter $parameter") onNextParameterTry(parameter) + onProgress(null) try { val filePaths = getBatchesForFFmpeg() @@ -293,7 +294,13 @@ abstract class BatchesFolder( parameter ) { time -> if (fullTime != null) { + println("**************** check24") + println(time) + println(fullTime) onProgress(time / fullTime!!) + } else { + onProgress(null) + println("----------------- nonono") } }.await() return outputFile diff --git a/app/src/main/java/app/myzel394/alibi/helpers/MediaConverter.kt b/app/src/main/java/app/myzel394/alibi/helpers/MediaConverter.kt index c9b3519..d3fd4dd 100644 --- a/app/src/main/java/app/myzel394/alibi/helpers/MediaConverter.kt +++ b/app/src/main/java/app/myzel394/alibi/helpers/MediaConverter.kt @@ -92,8 +92,6 @@ class MediaConverter { "-protocol_whitelist saf,concat,content,file,subfile" + " -i 'concat:$filePathsConcatenated'" + extraCommand + - " -nostats" + - " -loglevel error" + " -y" + " $outputFile" @@ -150,8 +148,6 @@ class MediaConverter { " -i ${listFile.absolutePath}" + extraCommand + " -strict normal" + - " -nostats" + - " -loglevel error" + " -y" + " $outputFile" diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/RecorderProcessingDialog.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/RecorderProcessingDialog.kt index 7c03ac6..25f8ce7 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/RecorderProcessingDialog.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/RecorderProcessingDialog.kt @@ -41,10 +41,10 @@ fun RecorderProcessingDialog( stringResource(R.string.ui_recorder_action_save_processing_dialog_description), ) Spacer(modifier = Modifier.height(32.dp)) - if (progress != null) - LinearProgressIndicator(progress = progress) - else + if (progress == null) LinearProgressIndicator() + else + LinearProgressIndicator(progress = progress) } }, confirmButton = {} diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/AudioRecordingStart.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/AudioRecordingStart.kt index 5b554e0..747c7c8 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/AudioRecordingStart.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/AudioRecordingStart.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -34,6 +35,10 @@ import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE import app.myzel394.alibi.ui.components.atoms.PermissionRequester import app.myzel394.alibi.ui.models.AudioRecorderModel import app.myzel394.alibi.ui.utils.PermissionHelper +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext @Composable fun AudioRecordingStart( @@ -54,6 +59,17 @@ fun AudioRecordingStart( } } + println("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww app: ${appSettings.saveFolder}") + val requiresExternalPerm = rememberSaveable { + appSettings.requiresExternalStoragePermission(context) + } + println("hasGranted ${requiresExternalPerm}") + val scope = rememberCoroutineScope() + + fun test() { + println("appSäääääääääääääääääääääääääääääääättings ${appSettings.saveFolder}") + } + PermissionRequester( permission = Manifest.permission.WRITE_EXTERNAL_STORAGE, icon = Icons.Default.InsertDriveFile, @@ -65,11 +81,8 @@ fun AudioRecordingStart( permission = Manifest.permission.RECORD_AUDIO, icon = Icons.Default.Mic, onPermissionAvailable = { - if (!SUPPORTS_SCOPED_STORAGE && !PermissionHelper.hasGranted( - context, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - ) { + test() + if (appSettings.requiresExternalStoragePermission(context)) { triggerExternalStorage() } else { startRecording = true diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/VideoRecordingStart.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/VideoRecordingStart.kt index 364cc3e..9716029 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/VideoRecordingStart.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/VideoRecordingStart.kt @@ -80,11 +80,6 @@ fun VideoRecordingStart( ) } - val hasGrantedStorage = SUPPORTS_SCOPED_STORAGE || PermissionHelper.hasGranted( - context, - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) - PermissionRequester( permission = Manifest.permission.WRITE_EXTERNAL_STORAGE, icon = Icons.Default.InsertDriveFile, @@ -112,7 +107,7 @@ fun VideoRecordingStart( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(color = MaterialTheme.colorScheme.primary), onClick = { - if (!hasGrantedStorage) { + if (appSettings.requiresExternalStoragePermission(context)) { triggerExternalStorage() return@combinedClickable } diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt index 727f1fa..30df7ee 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/RecorderEventsHandler.kt @@ -58,7 +58,7 @@ fun RecorderEventsHandler( var showRecorderError by remember { mutableStateOf(false) } var showBatchesInaccessibleError by remember { mutableStateOf(false) } - var processingProgress by remember { mutableFloatStateOf(0.0f) } + var processingProgress by remember { mutableStateOf(null) } val saveAudioFile = rememberFileSaverDialog(settings.audioRecorderSettings.getMimeType()) { if (settings.deleteRecordingsImmediately) { diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/atoms/PermissionRequester.kt b/app/src/main/java/app/myzel394/alibi/ui/components/atoms/PermissionRequester.kt index 59be983..7e98f79 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/atoms/PermissionRequester.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/atoms/PermissionRequester.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.runtime.getValue +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector @@ -45,15 +46,22 @@ fun PermissionRequester( var isGranted by remember { mutableStateOf(PermissionHelper.hasGranted(context, permission)) } var visibleDialog by remember { mutableStateOf(null) } + + var _runFunc by rememberSaveable { mutableStateOf(false) } + val requestPermission = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), onResult = { isPermissionGranted: Boolean -> isGranted = isPermissionGranted if (isGranted) { - onPermissionAvailable() + _runFunc = true } else { - if (ActivityCompat.shouldShowRequestPermissionRationale(context as Activity, permission)) { + if (ActivityCompat.shouldShowRequestPermissionRationale( + context as Activity, + permission + ) + ) { visibleDialog = VisibleDialog.REQUEST } else { visibleDialog = VisibleDialog.PERMANENTLY_DENIED @@ -64,12 +72,21 @@ fun PermissionRequester( fun callback() { if (isGranted) { - onPermissionAvailable() + _runFunc = true } else { requestPermission.launch(permission) } } + // No idea but this hacky way is required to make sure the callback + // `onPermissionAvailable` can access other values such as the app settings. + LaunchedEffect(_runFunc) { + if (_runFunc) { + _runFunc = false + onPermissionAvailable() + } + } + if (visibleDialog == VisibleDialog.REQUEST) { AlertDialog( onDismissRequest = {