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 2cc7193..aa45019 100644 --- a/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/locationtest/db/AppSettings.kt @@ -76,8 +76,8 @@ data class AudioRecorderSettings( return copy(bitRate = bitRate) } - fun setSamplingRate(samplingRate: Int): AudioRecorderSettings { - if (samplingRate < 1000) { + fun setSamplingRate(samplingRate: Int?): AudioRecorderSettings { + if (samplingRate != null && samplingRate < 1000) { throw Exception("Sampling rate must be at least 1000") } @@ -117,5 +117,14 @@ data class AudioRecorderSettings( 256 * 1000, 320 * 1000, ) + val EXAMPLE_SAMPLING_RATE = listOf( + null, + 8000, + 16000, + 22050, + 44100, + 48000, + 96000, + ) } } diff --git a/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/SamplingRateTile.kt b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/SamplingRateTile.kt new file mode 100644 index 0000000..2c029a5 --- /dev/null +++ b/app/src/main/java/app/myzel394/locationtest/ui/components/SettingsScreen/atoms/SamplingRateTile.kt @@ -0,0 +1,122 @@ +package app.myzel394.locationtest.ui.components.SettingsScreen.atoms + +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.RadioButtonChecked +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 androidx.compose.ui.text.input.KeyboardType +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 SamplingRateTile() { + val scope = rememberCoroutineScope() + val showDialog = rememberUseCaseState() + val dataStore = LocalContext.current.dataStore + val settings = dataStore + .data + .collectAsState(initial = AppSettings.getDefaultInstance()) + .value + + fun updateValue(samplingRate: Int?) { + scope.launch { + dataStore.updateData { + it.setAudioRecorderSettings( + it.audioRecorderSettings.setSamplingRate(samplingRate) + ) + } + } + } + + InputDialog( + state = showDialog, + selection = InputSelection( + input = listOf( + InputTextField( + header = InputHeader( + title = "Set the sampling rate", + icon = IconSource(Icons.Default.RadioButtonChecked), + ), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Number, + ), + type = InputTextFieldType.OUTLINED, + text = (settings.audioRecorderSettings.bitRate / 1000).toString(), + validationListener = { text -> + val samplingRate = text?.toIntOrNull() + + if (samplingRate == null) { + ValidationResult.Invalid("Please enter a valid number") + } + + if (samplingRate!! <= 1000) { + ValidationResult.Invalid("Sampling rate must be greater than 1000") + } + + ValidationResult.Valid + }, + key = "samplingRate", + ) + ), + ) { result -> + val samplingRate = result.getString("samplingRate")?.toIntOrNull() ?: throw IllegalStateException("SamplingRate is null") + + updateValue(samplingRate) + } + ) + SettingsTile( + title = "Sampling rate", + description = "Define how many samples per second are taken from the audio signal", + leading = { + Icon( + Icons.Default.RadioButtonChecked, + contentDescription = null, + ) + }, + trailing = { + Button( + onClick = showDialog::show, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + shape = MaterialTheme.shapes.medium, + ) { + Text( + text = (settings.audioRecorderSettings.samplingRate ?: "Auto").toString() + ) + } + }, + extra = { + ExampleListRoulette( + items = AudioRecorderSettings.EXAMPLE_SAMPLING_RATE, + onItemSelected = ::updateValue, + ) {samplingRate -> + Text( + text = (samplingRate ?: "Auto").toString() + ) + } + } + ) +} \ 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 a8f8d39..e13daca 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 @@ -33,6 +33,7 @@ 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.SettingsScreen.atoms.SamplingRateTile import app.myzel394.locationtest.ui.components.atoms.GlobalSwitch import app.myzel394.locationtest.ui.components.atoms.SettingsTile import app.myzel394.locationtest.ui.utils.formatDuration @@ -93,6 +94,7 @@ fun SettingsScreen( Column { IntervalDurationTile() BitrateTile() + SamplingRateTile() } } }