From 0404ba983f3103f722c3a3d7520309138aeb8dea Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Thu, 3 Aug 2023 23:34:58 +0200 Subject: [PATCH] feat: Add BitrateTile --- app/build.gradle | 1 + .../myzel394/locationtest/db/AppSettings.kt | 13 +- .../SettingsScreen/atoms/BitrateTile.kt | 131 ++++++++++++++++++ .../locationtest/ui/screens/SettingsScreen.kt | 2 + 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/BitrateTile.kt diff --git a/app/build.gradle b/app/build.gradle index 3158691..7c1732c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,4 +83,5 @@ dependencies { implementation 'com.maxkeppeler.sheets-compose-dialogs:core:1.2.0' implementation 'com.maxkeppeler.sheets-compose-dialogs:duration:1.2.0' + implementation 'com.maxkeppeler.sheets-compose-dialogs:input:1.2.0' } \ No newline at end of file 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 31533f3..2cc7193 100644 --- a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt @@ -68,8 +68,9 @@ data class AudioRecorderSettings( } fun setBitRate(bitRate: Int): AudioRecorderSettings { - if (bitRate < 1000) { - throw Exception("Bit rate must be at least 1000") + println("bitRate: $bitRate") + if (bitRate !in 1000..320000) { + throw Exception("Bit rate must be between 1000 and 320000") } return copy(bitRate = bitRate) @@ -108,5 +109,13 @@ data class AudioRecorderSettings( 60 * 30 * 1000L, 60 * 60 * 1000L, ) + val EXAMPLE_BITRATE_VALUES = listOf( + 96 * 1000, + 128 * 1000, + 160 * 1000, + 192 * 1000, + 256 * 1000, + 320 * 1000, + ) } } diff --git a/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/BitrateTile.kt b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/BitrateTile.kt new file mode 100644 index 0000000..a5a8ffb --- /dev/null +++ b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/BitrateTile.kt @@ -0,0 +1,131 @@ +package app.myzel394.locationtest.ui.components.SettingsScreen.atoms + +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Mic +import androidx.compose.material.icons.filled.Tune +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.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +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.IconSource +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.input.InputDialog +import com.maxkeppeler.sheets.input.models.InputHeader +import com.maxkeppeler.sheets.input.models.InputSelection +import com.maxkeppeler.sheets.input.models.InputTextField +import com.maxkeppeler.sheets.input.models.InputTextFieldType +import com.maxkeppeler.sheets.input.models.ValidationResult +import kotlinx.coroutines.launch + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BitrateTile() { + val scope = rememberCoroutineScope() + val showDialog = rememberUseCaseState() + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + + InputDialog( + state = showDialog, + selection = InputSelection( + input = listOf( + InputTextField( + header = InputHeader( + title = "Set the bitrate for the audio recording", + icon = IconSource(Icons.Default.Tune), + ), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + ), + type = InputTextFieldType.OUTLINED, + text = (settings.audioRecorderSettings.bitRate / 1000).toString(), + validationListener = { text -> + val bitRate = text?.toIntOrNull() + + if (bitRate == null) { + ValidationResult.Invalid("Please enter a valid number") + } + + if (bitRate in 1..320) { + ValidationResult.Valid + } else { + ValidationResult.Invalid("Please enter a number between 1 and 320") + } + }, + key = "bitrate", + ) + ), + ) { result -> + val bitRate = result.getString("bitrate")?.toIntOrNull() ?: throw IllegalStateException("Bitrate is null") + + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setBitRate(bitRate * 1000) + ) + } + } + } + ) + SettingsTile( + title = "Bitrate", + description = "A higher bitrate means better quality but also larger file size", + leading = { + Icon( + Icons.Default.Tune, + contentDescription = null, + ) + }, + trailing = { + Button( + onClick = showDialog::show, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + shape = MaterialTheme.shapes.medium, + ) { + Text( + text = "${settings.audioRecorderSettings.bitRate / 1000} KB/s", + ) + } + }, + extra = { + ExampleListRoulette( + items = AudioRecorderSettings.EXAMPLE_BITRATE_VALUES, + onItemSelected = { bitRate -> + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setBitRate(bitRate) + ) + } + } + } + ) {bitRate -> + Text( + text = "${bitRate / 1000} KB/s", + ) + } + } + ) +} \ 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 ea8aa91..a8f8d39 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 @@ -31,6 +31,7 @@ import androidx.navigation.NavController 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.IntervalDurationTile import app.myzel394.locationtest.ui.components.atoms.GlobalSwitch import app.myzel394.locationtest.ui.components.atoms.SettingsTile @@ -91,6 +92,7 @@ fun SettingsScreen( AnimatedVisibility(visible = settings.showAdvancedSettings) { Column { IntervalDurationTile() + BitrateTile() } } }