From b86fb74a3a7671aeb2c1a2ea0129dc57da20136f Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Fri, 4 Aug 2023 00:36:51 +0200 Subject: [PATCH] feat: Add EncoderTile --- .../myzel394/locationtest/db/AppSettings.kt | 14 ++- .../SettingsScreen/atoms/EncoderTile.kt | 99 +++++++++++++++++++ .../locationtest/ui/screens/SettingsScreen.kt | 24 ++++- 3 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/EncoderTile.kt diff --git a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt index 6ddd6f7..9d0ed5a 100644 --- a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt @@ -105,8 +105,8 @@ data class AudioRecorderSettings( return copy(outputFormat = outputFormat) } - fun setEncoder(encoder: Int): AudioRecorderSettings { - if (encoder < 0 || encoder > 7) { + fun setEncoder(encoder: Int?): AudioRecorderSettings { + if (encoder != null && (encoder < 0 || encoder > 7)) { throw Exception("Encoder is not a MediaRecorder.AudioEncoder constant") } @@ -153,5 +153,15 @@ data class AudioRecorderSettings( 10 to "HEIF", 11 to "OGG", ) + val ENCODER_INDEX_TEXT_MAP = mapOf( + 0 to "Default", + 1 to "AMR_NB", + 2 to "AMR_WB", + 3 to "AAC", + 4 to "HE_AAC", + 5 to "AAC_ELD", + 6 to "VORBIS", + 7 to "OPUS", + ) } } diff --git a/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/EncoderTile.kt b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/EncoderTile.kt new file mode 100644 index 0000000..727c948 --- /dev/null +++ b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/EncoderTile.kt @@ -0,0 +1,99 @@ +package app.myzel394.locationtest.ui.components.SettingsScreen.atoms + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AudioFile +import androidx.compose.material.icons.filled.Memory +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.platform.LocalContext +import app.myzel394.locationtest.dataStore +import app.myzel394.locationtest.db.AppSettings +import app.myzel394.locationtest.db.AudioRecorderSettings +import app.myzel394.locationtest.ui.components.atoms.ExampleListRoulette +import app.myzel394.locationtest.ui.components.atoms.SettingsTile +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.list.ListDialog +import com.maxkeppeler.sheets.list.models.ListOption +import com.maxkeppeler.sheets.list.models.ListSelection +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun EncoderTile() { + val scope = rememberCoroutineScope() + val showDialog = rememberUseCaseState() + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + + fun updateValue(encoder: Int?) { + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setEncoder(encoder) + ) + } + } + } + + ListDialog( + state = showDialog, + selection = ListSelection.Single( + showRadioButtons = true, + options = IntRange(0, 7).map { index -> + ListOption( + titleText = AudioRecorderSettings.ENCODER_INDEX_TEXT_MAP[index]!!, + selected = settings.audioRecorderSettings.encoder == index, + ) + }.toList() + ) {index, option -> + updateValue(index) + }, + ) + SettingsTile( + title = "Encoder", + description = "Define the audio encoder.", + leading = { + Icon( + Icons.Default.Memory, + contentDescription = null, + ) + }, + trailing = { + Button( + onClick = showDialog::show, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + shape = MaterialTheme.shapes.medium, + ) { + Text( + text = if (settings.audioRecorderSettings.encoder == null) { + "Auto" + } else { + AudioRecorderSettings.ENCODER_INDEX_TEXT_MAP[settings.audioRecorderSettings.encoder]!! + } + ) + } + }, + extra = { + ExampleListRoulette( + items = listOf(null), + onItemSelected = ::updateValue, + ) { + Text( + text = "Auto" + ) + } + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt index 13ebd6e..4b84797 100644 --- a/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/locationtest/ui/screens/SettingsScreen.kt @@ -4,9 +4,12 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.Mic @@ -21,11 +24,14 @@ import androidx.compose.material3.LargeTopAppBar import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -33,6 +39,7 @@ import app.myzel394.locationtest.dataStore import app.myzel394.locationtest.db.AppSettings import app.myzel394.locationtest.db.AudioRecorderSettings import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.BitrateTile +import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.EncoderTile import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.IntervalDurationTile import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.OutputFormatTile import app.myzel394.locationtest.ui.components.SettingsScreen.atoms.SamplingRateTile @@ -51,6 +58,10 @@ import kotlinx.coroutines.launch fun SettingsScreen( navController: NavController ) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior( + rememberTopAppBarState() + ) + Scaffold( topBar = { LargeTopAppBar( @@ -64,14 +75,18 @@ fun SettingsScreen( contentDescription = "Back" ) } - } + }, + scrollBehavior = scrollBehavior, ) - } + }, + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) ) {padding -> Column( modifier = Modifier - .fillMaxWidth() - .padding(padding), + .fillMaxSize() + .padding(padding) + .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, ) { val scope = rememberCoroutineScope() @@ -98,6 +113,7 @@ fun SettingsScreen( BitrateTile() SamplingRateTile() OutputFormatTile() + EncoderTile() } } }