feat: Add explanation to SaveFolderTile.kt for DCIM folder

This commit is contained in:
Myzel394 2024-01-05 21:57:49 +01:00
parent caeb966598
commit 42f8262796
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
3 changed files with 164 additions and 12 deletions

View File

@ -3,6 +3,10 @@ package app.myzel394.alibi.ui.components.SettingsScreen.Tiles
import android.Manifest import android.Manifest
import android.content.Intent import android.content.Intent
import android.net.Uri 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.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box 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.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons 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.Cancel
import androidx.compose.material.icons.filled.Folder import androidx.compose.material.icons.filled.Folder
import androidx.compose.material.icons.filled.InsertDriveFile import androidx.compose.material.icons.filled.InsertDriveFile
import androidx.compose.material.icons.filled.Lock 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.PermMedia
import androidx.compose.material.icons.filled.Warning import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
@ -55,10 +61,14 @@ import androidx.documentfile.provider.DocumentFile
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings 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.RECORDER_MEDIA_SELECTED_VALUE
import app.myzel394.alibi.ui.SHEET_BOTTOM_OFFSET 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_SAVING_VIDEOS_IN_CUSTOM_FOLDERS
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE 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.MessageBox
import app.myzel394.alibi.ui.components.atoms.MessageType import app.myzel394.alibi.ui.components.atoms.MessageType
import app.myzel394.alibi.ui.components.atoms.PermissionRequester 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( SettingsTile(
title = stringResource(R.string.ui_settings_option_saveFolder_title), title = stringResource(R.string.ui_settings_option_saveFolder_title),
description = stringResource(R.string.ui_settings_option_saveFolder_explanation), description = stringResource(R.string.ui_settings_option_saveFolder_explanation),
@ -181,9 +201,30 @@ fun SaveFolderTile(
when (settings.saveFolder) { when (settings.saveFolder) {
null -> {} null -> {}
RECORDER_MEDIA_SELECTED_VALUE -> {} RECORDER_MEDIA_SELECTED_VALUE -> {
Button(
onClick = {
showDCIMFolderHelpSheet = true
},
shape = MaterialTheme.shapes.small,
contentPadding = ButtonDefaults.TextButtonContentPadding,
colors = ButtonDefaults.filledTonalButtonColors(
contentColor = MaterialTheme.colorScheme.onTertiaryContainer,
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
),
) {
Text(
stringResource(R.string.ui_settings_option_saveFolder_explainMediaFolder_label),
fontSize = MaterialTheme.typography.bodySmall.fontSize,
)
}
}
// Custom folder // Custom folder
else -> 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( Button(
onClick = { onClick = {
openFolder( openFolder(
@ -212,6 +253,110 @@ fun SaveFolderTile(
) )
} }
@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) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SelectionSheet( fun SelectionSheet(

View File

@ -2,6 +2,7 @@ package app.myzel394.alibi.ui.effects
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.provider.DocumentsContract
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -10,7 +11,9 @@ fun rememberOpenUri(): (uri: Uri) -> Unit {
val context = LocalContext.current val context = LocalContext.current
return fun(uri: Uri) { 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) context.startActivity(intent)
} }

View File

@ -183,4 +183,8 @@
<string name="ui_severeError_fileSaverUnavailable_text">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.</string> <string name="ui_severeError_fileSaverUnavailable_text">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.</string>
<string name="ui_videoRecorder_state_recording_title">Recording Video</string> <string name="ui_videoRecorder_state_recording_title">Recording Video</string>
<string name="ui_settings_option_saveFolder_openFolder_label">Open Folder in Files</string> <string name="ui_settings_option_saveFolder_openFolder_label">Open Folder in Files</string>
<string name="ui_settings_option_saveFolder_explainMediaFolder_label">Where are my batches stored?</string>
<string name="ui_settings_option_saveFolder_explainMediaFolder_generalExplanation">To view your batches, open the Files app, go to the internal storage and then you will find your batches in following folders:</string>
<string name="ui_settings_option_saveFolder_explainMediaFolder_subfoldersExplanation">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.</string>
<string name="ui_settings_option_saveFolder_explainMediaFolder_openFolderExplanation">Tap on a folder to open it in the Files app</string>
</resources> </resources>