diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/QuickMaxDurationSelector.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/QuickMaxDurationSelector.kt new file mode 100644 index 0000000..7330ec1 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/molecules/QuickMaxDurationSelector.kt @@ -0,0 +1,95 @@ +package app.myzel394.alibi.ui.components.RecorderScreen.molecules + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +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.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +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.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +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.db.AudioRecorderSettings.Companion.EXAMPLE_MAX_DURATIONS +import app.myzel394.alibi.ui.utils.formatDuration +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun QuickMaxDurationSelector( + settings: AppSettings, + onDismiss: () -> Unit, +) { + val scope = rememberCoroutineScope() + val dataStore = LocalContext.current.dataStore + + val sheetState = rememberModalBottomSheetState(true) + + ModalBottomSheet( + onDismissRequest = onDismiss, + sheetState = sheetState, + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Box( + modifier = Modifier + .widthIn(max = 400.dp) + .padding(16.dp), + ) { + Text( + stringResource(R.string.ui_recorder_action_changeMaxDuration_title), + style = MaterialTheme.typography.headlineMedium, + textAlign = TextAlign.Center, + ) + } + + Column { + for (duration in EXAMPLE_MAX_DURATIONS) { + Button( + onClick = { + scope.launch { + // TODO: Add hide to microphone selection + sheetState.hide() + onDismiss() + } + scope.launch { + dataStore.updateData { + it.setMaxDuration(duration) + } + } + }, + colors = ButtonDefaults.textButtonColors(), + modifier = Modifier + .fillMaxWidth() + .height(64.dp), + ) { + Text( + formatDuration(duration) + ) + } + } + } + + Spacer(modifier = Modifier.height(32.dp)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt index 63bc8eb..c2a9d62 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt @@ -2,7 +2,6 @@ package app.myzel394.alibi.ui.components.RecorderScreen.organisms import androidx.compose.foundation.Image 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 @@ -13,7 +12,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn -import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.ClickableText import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Save import androidx.compose.material3.Button @@ -22,21 +22,28 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import app.myzel394.alibi.R import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE import app.myzel394.alibi.ui.components.RecorderScreen.molecules.AudioRecordingStart +import app.myzel394.alibi.ui.components.RecorderScreen.molecules.QuickMaxDurationSelector import app.myzel394.alibi.ui.components.RecorderScreen.molecules.VideoRecordingStart import app.myzel394.alibi.ui.effects.rememberForceUpdateOnLifeCycleChange import app.myzel394.alibi.ui.models.AudioRecorderModel @@ -125,18 +132,51 @@ fun StartRecording( .size(24.dp) ) - Text( - stringResource( - R.string.ui_audioRecorder_action_start_description, - appSettings.maxDuration / 1000 / 60 - ), - style = MaterialTheme.typography.bodySmall.copy( - color = MaterialTheme.colorScheme.onSurfaceVariant, - ), + val label = stringResource( + R.string.ui_audioRecorder_action_start_description_2, + appSettings.maxDuration / 1000 / 60 + ) + val annotatedDescription = buildAnnotatedString { + append(stringResource(R.string.ui_audioRecorder_action_start_description_1)) + + withStyle(SpanStyle(background = MaterialTheme.colorScheme.surfaceVariant)) { + pushStringAnnotation( + tag = "minutes", + annotation = label, + ) + append(label) + } + + append(stringResource(R.string.ui_audioRecorder_action_start_description_3)) + } + + var showQuickMaxDurationSelector by rememberSaveable { + mutableStateOf(false) + } + + if (showQuickMaxDurationSelector) { + QuickMaxDurationSelector( + settings = appSettings, + onDismiss = { + showQuickMaxDurationSelector = false + }, + ) + } + ClickableText( + text = annotatedDescription, + onClick = { textIndex -> + if (annotatedDescription.getStringAnnotations(textIndex, textIndex) + .firstOrNull()?.tag == "minutes" + ) { + showQuickMaxDurationSelector = true + } + }, modifier = Modifier .widthIn(max = 300.dp) .fillMaxWidth(), - textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodySmall.copy( + color = MaterialTheme.colorScheme.onSurfaceVariant, + ), ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1c17b12..12ccdd6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,7 +26,11 @@ Pause Resume Save Recording - Alibi will continue recording in the background and store the last %s minutes at your request + + Alibi will continue recording in the background and store the last\u0020 + %s minutes + \u0020at your request + Processing Processing your recording, do not close Alibi! You will automatically be prompted to save the file once it\'s ready @@ -151,4 +155,5 @@ Disable Torch Enable Torch Press long for configuration + When stopped, save the last... \ No newline at end of file