feat: Add selection sheet for SaveFolderTile

This commit is contained in:
Myzel394 2023-12-31 21:07:34 +01:00
parent 1187d83e86
commit d6ab56f027
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
3 changed files with 138 additions and 48 deletions

View File

@ -4,6 +4,9 @@ import android.os.Build
import androidx.compose.ui.unit.dp
val BIG_PRIMARY_BUTTON_SIZE = 64.dp
// TODO: Add everywhere
val SHEET_BOTTOM_OFFSET = 56.dp
val MAX_AMPLITUDE = 20000
val SUPPORTS_DARK_MODE_NATIVELY = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
val RECORDER_SUBFOLDER_NAME = ".recordings"

View File

@ -2,26 +2,34 @@ package app.myzel394.alibi.ui.components.SettingsScreen.Tiles
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.AudioFile
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.PermMedia
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -30,21 +38,30 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE
import app.myzel394.alibi.ui.SHEET_BOTTOM_OFFSET
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE
import app.myzel394.alibi.ui.components.atoms.MessageBox
import app.myzel394.alibi.ui.components.atoms.MessageType
import app.myzel394.alibi.ui.components.atoms.SettingsTile
import app.myzel394.alibi.ui.utils.rememberFolderSelectorDialog
import com.maxkeppeker.sheets.core.models.base.SelectionButton
import kotlinx.coroutines.launch
import java.net.URLDecoder
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SaveFolderTile(
settings: AppSettings,
@ -138,33 +155,107 @@ fun SaveFolderTile(
)
}
var selectionVisible by remember { mutableStateOf(false) }
val selectionSheetState = rememberModalBottomSheetState(true)
fun hideSheet() {
scope.launch {
selectionSheetState.hide()
selectionVisible = false
}
}
if (selectionVisible) {
ModalBottomSheet(
sheetState = selectionSheetState,
onDismissRequest = ::hideSheet,
) {
Column(
modifier = Modifier
.padding(horizontal = 16.dp)
.padding(bottom = SHEET_BOTTOM_OFFSET),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(24.dp),
) {
Text(
stringResource(R.string.ui_settings_option_saveFolder_title),
style = MaterialTheme.typography.headlineMedium,
textAlign = TextAlign.Center,
)
SelectionButton(
label = stringResource(R.string.ui_settings_option_saveFolder_action_default_label),
icon = Icons.Default.Lock,
onClick = {
hideSheet()
updateValue(null)
},
)
Divider()
Column {
SelectionButton(
label = stringResource(R.string.ui_settings_option_saveFolder_action_custom_label),
icon = Icons.Default.Folder,
onClick = {
hideSheet()
showWarning = true
},
)
if (!SUPPORTS_SCOPED_STORAGE) {
Column(
modifier = Modifier.padding(horizontal = 32.dp, vertical = 12.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
MessageBox(
type = MessageType.INFO,
message = stringResource(R.string.ui_settings_option_saveFolder_videoUnsupported),
)
Text(
stringResource(R.string.ui_minApiRequired, 8, 26),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface,
)
}
}
}
Divider()
SelectionButton(
label = stringResource(R.string.ui_settings_option_saveFolder_action_dcim_label),
icon = Icons.Default.PermMedia,
onClick = {
hideSheet()
updateValue(RECORDER_MEDIA_SELECTED_VALUE)
},
)
}
}
}
SettingsTile(
title = stringResource(R.string.ui_settings_option_saveFolder_title),
description = stringResource(R.string.ui_settings_option_saveFolder_explanation),
leading = {
Icon(
Icons.Default.AudioFile,
Icons.Default.InsertDriveFile,
contentDescription = null,
)
},
trailing = {
Button(
onClick = {
showWarning = true
scope.launch {
selectionVisible = true
}
},
colors = ButtonDefaults.filledTonalButtonColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
),
shape = MaterialTheme.shapes.medium,
) {
Icon(
Icons.Default.Folder,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(
modifier = Modifier.size(ButtonDefaults.IconSpacing)
)
Text(
text = stringResource(R.string.ui_settings_option_saveFolder_action_select_label),
)
@ -218,48 +309,42 @@ fun SaveFolderTile(
modifier = Modifier.fillMaxWidth(),
)
}
if (!SUPPORTS_SCOPED_STORAGE) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 32.dp, vertical = 8.dp),
) {
Icon(
Icons.Default.Warning,
contentDescription = null,
tint = Color.Yellow,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
Text(
stringResource(R.string.ui_settings_option_saveFolder_videoUnsupported),
style = MaterialTheme.typography.bodySmall,
color = Color.Yellow,
)
Text(
stringResource(R.string.ui_minApiRequired, 8, 26),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface,
)
}
}
}
Button(
onClick = { updateValue(RECORDER_MEDIA_SELECTED_VALUE) }
) {
Text("Use Media")
}
}
}
)
}
@Composable
fun SelectionButton(
label: String,
icon: ImageVector,
onClick: () -> Unit,
) {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.clip(MaterialTheme.shapes.medium)
.semantics {
contentDescription = label
}
.clickable {
onClick()
}
.padding(horizontal = 16.dp)
) {
Icon(
icon,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Text(label)
Box {}
}
}
fun splitPath(path: String): List<String> {
return try {
URLDecoder

View File

@ -169,4 +169,6 @@
<string name="identityVerificationRequired_subtitle">You need to verify your identity to continue</string>
<string name="ui_settings_option_saveFolder_videoUnsupported">Custom folders for Video Recordings aren\'t supported by your Android version. Alibi will fallback to the internal folder instead for Video Recordings.</string>
<string name="ui_minApiRequired">You will need an Android phone running at least Android %s (API-Level: %s) to use this feature</string>
<string name="ui_settings_option_saveFolder_action_custom_label">Select a custom location</string>
<string name="ui_settings_option_saveFolder_action_dcim_label">Use the DCIM folder</string>
</resources>