From 42f826279645df6dcc49d1f72badbf1e8ee6cb8d Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 5 Jan 2024 21:57:49 +0100 Subject: [PATCH] feat: Add explanation to SaveFolderTile.kt for DCIM folder --- .../SettingsScreen/Tiles/SaveFolderTile.kt | 167 ++++++++++++++++-- .../app/myzel394/alibi/ui/effects/open-uri.kt | 5 +- app/src/main/res/values/strings.xml | 4 + 3 files changed, 164 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt index 16b7547..bd8bd0c 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/SaveFolderTile.kt @@ -3,6 +3,10 @@ package app.myzel394.alibi.ui.components.SettingsScreen.Tiles import android.Manifest import android.content.Intent import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.MediaStore +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -15,10 +19,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CameraAlt import androidx.compose.material.icons.filled.Cancel import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.InsertDriveFile import androidx.compose.material.icons.filled.Lock +import androidx.compose.material.icons.filled.Mic import androidx.compose.material.icons.filled.PermMedia import androidx.compose.material.icons.filled.Warning import androidx.compose.material3.AlertDialog @@ -55,10 +61,14 @@ import androidx.documentfile.provider.DocumentFile import app.myzel394.alibi.R import app.myzel394.alibi.dataStore import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.helpers.AudioBatchesFolder +import app.myzel394.alibi.helpers.VideoBatchesFolder +import app.myzel394.alibi.ui.MEDIA_SUBFOLDER_NAME import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE import app.myzel394.alibi.ui.SHEET_BOTTOM_OFFSET import app.myzel394.alibi.ui.SUPPORTS_SAVING_VIDEOS_IN_CUSTOM_FOLDERS import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE +import app.myzel394.alibi.ui.components.SettingsScreen.atoms.FolderBreadcrumbs import app.myzel394.alibi.ui.components.atoms.MessageBox import app.myzel394.alibi.ui.components.atoms.MessageType import app.myzel394.alibi.ui.components.atoms.PermissionRequester @@ -129,6 +139,16 @@ fun SaveFolderTile( ) } + var showDCIMFolderHelpSheet by remember { mutableStateOf(false) } + + if (showDCIMFolderHelpSheet) { + MediaFoldersExplanationDialog( + onDismiss = { + showDCIMFolderHelpSheet = false + } + ) + } + SettingsTile( title = stringResource(R.string.ui_settings_option_saveFolder_title), description = stringResource(R.string.ui_settings_option_saveFolder_explanation), @@ -181,20 +201,12 @@ fun SaveFolderTile( when (settings.saveFolder) { null -> {} - RECORDER_MEDIA_SELECTED_VALUE -> {} - // Custom folder - else -> + RECORDER_MEDIA_SELECTED_VALUE -> { Button( onClick = { - openFolder( - DocumentFile.fromTreeUri( - context, - settings.saveFolder.toUri(), - )!!.uri - ) + showDCIMFolderHelpSheet = true }, shape = MaterialTheme.shapes.small, - // TODO: Adjust padding everywhere contentPadding = ButtonDefaults.TextButtonContentPadding, colors = ButtonDefaults.filledTonalButtonColors( contentColor = MaterialTheme.colorScheme.onTertiaryContainer, @@ -202,16 +214,149 @@ fun SaveFolderTile( ), ) { Text( - stringResource(R.string.ui_settings_option_saveFolder_openFolder_label), + stringResource(R.string.ui_settings_option_saveFolder_explainMediaFolder_label), fontSize = MaterialTheme.typography.bodySmall.fontSize, ) } + } + // Custom folder + else -> + // Doesn't seem to reliably work on all devices, 30 & 33 + // has been tested; so we just show the button for versions + // above 30 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + Button( + onClick = { + openFolder( + DocumentFile.fromTreeUri( + context, + settings.saveFolder.toUri(), + )!!.uri + ) + }, + shape = MaterialTheme.shapes.small, + // TODO: Adjust padding everywhere + contentPadding = ButtonDefaults.TextButtonContentPadding, + colors = ButtonDefaults.filledTonalButtonColors( + contentColor = MaterialTheme.colorScheme.onTertiaryContainer, + containerColor = MaterialTheme.colorScheme.tertiaryContainer, + ), + ) { + Text( + stringResource(R.string.ui_settings_option_saveFolder_openFolder_label), + fontSize = MaterialTheme.typography.bodySmall.fontSize, + ) + } } } } ) } +@Composable +fun MediaFoldersExplanationDialog( + onDismiss: () -> Unit, +) { + val context = LocalContext.current + val openFolder = rememberOpenUri() + + AlertDialog( + onDismissRequest = onDismiss, + icon = { + Icon( + Icons.Default.PermMedia, + contentDescription = null, + ) + }, + title = { + Text(stringResource(R.string.ui_settings_option_saveFolder_explainMediaFolder_label)) + }, + confirmButton = { + Button( + onClick = onDismiss, + ) { + Text(stringResource(R.string.dialog_close_neutral_label)) + } + }, + text = { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(32.dp), + ) { + Text( + stringResource(R.string.ui_settings_option_saveFolder_explainMediaFolder_generalExplanation), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface, + ) + // I tried adding support for opening the folder directly by tapping on the + // breadcrumbs, but couldn't get it to work. + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp) + .clip(MaterialTheme.shapes.medium) + .background(MaterialTheme.colorScheme.surfaceVariant) + .padding(16.dp) + ) { + Icon( + Icons.Default.Mic, + contentDescription = null, + ) + FolderBreadcrumbs( + folders = listOf( + if (SUPPORTS_SCOPED_STORAGE) + AudioBatchesFolder.BASE_SCOPED_STORAGE_RELATIVE_PATH + else + AudioBatchesFolder.BASE_LEGACY_STORAGE_FOLDER, + MEDIA_SUBFOLDER_NAME + ) + ) + Box {} + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp) + .clip(MaterialTheme.shapes.medium) + .background(MaterialTheme.colorScheme.surfaceVariant) + .padding(16.dp) + ) { + Icon( + Icons.Default.CameraAlt, + contentDescription = null, + ) + FolderBreadcrumbs( + folders = listOf( + if (SUPPORTS_SCOPED_STORAGE) + VideoBatchesFolder.BASE_SCOPED_STORAGE_RELATIVE_PATH + else + VideoBatchesFolder.BASE_LEGACY_STORAGE_FOLDER, + MEDIA_SUBFOLDER_NAME + ) + ) + Box {} + } + } + Text( + stringResource(R.string.ui_settings_option_saveFolder_explainMediaFolder_subfoldersExplanation), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurface, + ) + } + } + ) +} + @OptIn(ExperimentalMaterial3Api::class) @Composable fun SelectionSheet( diff --git a/app/src/main/java/app/myzel394/alibi/ui/effects/open-uri.kt b/app/src/main/java/app/myzel394/alibi/ui/effects/open-uri.kt index 9e0ef36..910679a 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/effects/open-uri.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/effects/open-uri.kt @@ -2,6 +2,7 @@ package app.myzel394.alibi.ui.effects import android.content.Intent import android.net.Uri +import android.provider.DocumentsContract import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext @@ -10,7 +11,9 @@ fun rememberOpenUri(): (uri: Uri) -> Unit { val context = LocalContext.current return fun(uri: Uri) { - val intent = Intent(Intent.ACTION_VIEW, uri) + val intent = Intent(Intent.ACTION_VIEW, uri).apply { + setDataAndType(uri, DocumentsContract.Document.MIME_TYPE_DIR) + } context.startActivity(intent) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b373d12..0e6cd29 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -183,4 +183,8 @@ Alibi couldn\'t find a file manager app on your phone. Please install a file manager app and try again. If this message still appears, you can try using a custom batches folder in the advanced settings section. Alibi may not fully work on your device. Recording Video Open Folder in Files + Where are my batches stored? + To view your batches, open the Files app, go to the internal storage and then you will find your batches in following folders: + The final merged recordings will be saved in those folders. Each recording creates a subfolder to store the short batches in ("%s" for audio recordings, "%s" for video recordings). To view the individual batches, you may need to enable hidden files in the Files app. + Tap on a folder to open it in the Files app \ No newline at end of file