feat: Add QuickMaxDurationSelector; closes #57

This commit is contained in:
Myzel394 2023-12-15 22:05:04 +01:00
parent f462d5ff50
commit 39895bcd40
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
3 changed files with 153 additions and 13 deletions

View File

@ -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))
}
}
}

View File

@ -2,7 +2,6 @@ package app.myzel394.alibi.ui.components.RecorderScreen.organisms
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer 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.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn 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.Icons
import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.Button import androidx.compose.material3.Button
@ -22,21 +22,28 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics 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.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE 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.AudioRecordingStart
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.QuickMaxDurationSelector
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.VideoRecordingStart import app.myzel394.alibi.ui.components.RecorderScreen.molecules.VideoRecordingStart
import app.myzel394.alibi.ui.effects.rememberForceUpdateOnLifeCycleChange import app.myzel394.alibi.ui.effects.rememberForceUpdateOnLifeCycleChange
import app.myzel394.alibi.ui.models.AudioRecorderModel import app.myzel394.alibi.ui.models.AudioRecorderModel
@ -125,18 +132,51 @@ fun StartRecording(
.size(24.dp) .size(24.dp)
) )
Text( val label = stringResource(
stringResource( R.string.ui_audioRecorder_action_start_description_2,
R.string.ui_audioRecorder_action_start_description, appSettings.maxDuration / 1000 / 60
appSettings.maxDuration / 1000 / 60 )
), val annotatedDescription = buildAnnotatedString {
style = MaterialTheme.typography.bodySmall.copy( append(stringResource(R.string.ui_audioRecorder_action_start_description_1))
color = MaterialTheme.colorScheme.onSurfaceVariant,
), 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 modifier = Modifier
.widthIn(max = 300.dp) .widthIn(max = 300.dp)
.fillMaxWidth(), .fillMaxWidth(),
textAlign = TextAlign.Center, style = MaterialTheme.typography.bodySmall.copy(
color = MaterialTheme.colorScheme.onSurfaceVariant,
),
) )
} }
} }

View File

@ -26,7 +26,11 @@
<string name="ui_audioRecorder_action_pause_label">Pause</string> <string name="ui_audioRecorder_action_pause_label">Pause</string>
<string name="ui_audioRecorder_action_resume_label">Resume</string> <string name="ui_audioRecorder_action_resume_label">Resume</string>
<string name="ui_audioRecorder_action_save_label">Save Recording</string> <string name="ui_audioRecorder_action_save_label">Save Recording</string>
<string name="ui_audioRecorder_action_start_description">Alibi will continue recording in the background and store the last <xliff:g name="durationInMinutes">%s</xliff:g> minutes at your request</string>
<string name="ui_audioRecorder_action_start_description_1">Alibi will continue recording in the background and store the last\u0020</string>
<string name="ui_audioRecorder_action_start_description_2"><xliff:g name="durationInMinutes">%s</xliff:g> minutes</string>
<string name="ui_audioRecorder_action_start_description_3">\u0020at your request</string>
<string name="ui_audioRecorder_action_save_processing_dialog_title">Processing</string> <string name="ui_audioRecorder_action_save_processing_dialog_title">Processing</string>
<string name="ui_audioRecorder_action_save_processing_dialog_description">Processing your recording, do not close Alibi! You will automatically be prompted to save the file once it\'s ready</string> <string name="ui_audioRecorder_action_save_processing_dialog_description">Processing your recording, do not close Alibi! You will automatically be prompted to save the file once it\'s ready</string>
@ -151,4 +155,5 @@
<string name="ui_videoRecorder_action_torch_off">Disable Torch</string> <string name="ui_videoRecorder_action_torch_off">Disable Torch</string>
<string name="ui_videoRecorder_action_torch_on">Enable Torch</string> <string name="ui_videoRecorder_action_torch_on">Enable Torch</string>
<string name="ui_videoRecorder_action_configure_label">Press long for configuration</string> <string name="ui_videoRecorder_action_configure_label">Press long for configuration</string>
<string name="ui_recorder_action_changeMaxDuration_title">When stopped, save the last...</string>
</resources> </resources>