diff --git a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt index 1bc97bf..44fe949 100644 --- a/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt +++ b/app/src/main/java/app/myzel394/alibi/db/AppSettings.kt @@ -379,14 +379,21 @@ data class VideoRecorderSettings( return copy(targetedVideoBitRate = bitRate) } - fun setQuality(quality: String): VideoRecorderSettings { - return copy(quality = quality) + fun setQuality(quality: Quality?): VideoRecorderSettings { + val invertedMap = QUALITY_NAME_QUALITY_MAP.entries.associateBy({ it.value }, { it.key }) + + return copy(quality = quality?.let { invertedMap[it] }) } fun setTargetFrameRate(frameRate: Int?): VideoRecorderSettings { return copy(targetFrameRate = frameRate) } + fun getQuality(): Quality? = + quality?.let { + QUALITY_NAME_QUALITY_MAP[it]!! + } + fun getQualitySelector(): QualitySelector? = quality?.let { QualitySelector.from( @@ -428,6 +435,19 @@ data class VideoRecorderSettings( 120, 240, ) + + val AVAILABLE_QUALITIES = listOf( + Quality.HIGHEST, + Quality.UHD, + Quality.FHD, + Quality.HD, + Quality.SD, + Quality.LOWEST, + ) + + val EXAMPLE_QUALITY_VALUES = listOf( + null, + ) + AVAILABLE_QUALITIES } } diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/VideoRecorderQualityTile.kt b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/VideoRecorderQualityTile.kt new file mode 100644 index 0000000..f872d05 --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/SettingsScreen/Tiles/VideoRecorderQualityTile.kt @@ -0,0 +1,118 @@ +package app.myzel394.alibi.ui.components.SettingsScreen.Tiles + +import android.media.MediaRecorder +import androidx.camera.video.Quality +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.HighQuality +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.rememberCoroutineScope +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import app.myzel394.alibi.R +import app.myzel394.alibi.dataStore +import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.db.VideoRecorderSettings +import app.myzel394.alibi.ui.components.atoms.ExampleListRoulette +import app.myzel394.alibi.ui.components.atoms.SettingsTile +import app.myzel394.alibi.ui.utils.IconResource +import com.maxkeppeker.sheets.core.models.base.Header +import com.maxkeppeker.sheets.core.models.base.IconSource +import com.maxkeppeker.sheets.core.models.base.rememberUseCaseState +import com.maxkeppeler.sheets.input.models.InputHeader +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 VideoRecorderQualityTile( + settings: AppSettings, +) { + val QUALITY_NAME_TEXT_MAP = mapOf( + Quality.HIGHEST to stringResource(R.string.ui_settings_value_videoQuality_values_highest), + Quality.UHD to stringResource(R.string.ui_settings_value_videoQuality_values_uhd), + Quality.FHD to stringResource(R.string.ui_settings_value_videoQuality_values_fhd), + Quality.HD to stringResource(R.string.ui_settings_value_videoQuality_values_hd), + Quality.SD to stringResource(R.string.ui_settings_value_videoQuality_values_sd), + Quality.LOWEST to stringResource(R.string.ui_settings_value_videoQuality_values_lowest), + ) + + val scope = rememberCoroutineScope() + val showDialog = rememberUseCaseState() + val dataStore = LocalContext.current.dataStore + + fun updateValue(quality: Quality?) { + scope.launch { + dataStore.updateData { + it.setVideoRecorderSettings( + it.videoRecorderSettings.setQuality(quality) + ) + } + } + } + + ListDialog( + state = showDialog, + header = Header.Default( + title = stringResource(R.string.ui_settings_option_videoQualityTile_title), + icon = IconSource( + painter = IconResource.fromImageVector(Icons.Default.HighQuality) + .asPainterResource(), + contentDescription = null, + ), + ), + selection = ListSelection.Single( + showRadioButtons = true, + options = VideoRecorderSettings.AVAILABLE_QUALITIES.map { quality -> + ListOption( + titleText = QUALITY_NAME_TEXT_MAP[quality]!!, + selected = settings.videoRecorderSettings.quality == quality.toString(), + ) + }.toList() + ) { index, _ -> + val quality = VideoRecorderSettings.AVAILABLE_QUALITIES[index] + + updateValue(quality) + }, + ) + SettingsTile( + title = stringResource(R.string.ui_settings_option_videoQualityTile_title), + leading = { + Icon( + Icons.Default.HighQuality, + contentDescription = null, + ) + }, + trailing = { + Button( + onClick = showDialog::show, + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + shape = MaterialTheme.shapes.medium, + ) { + Text( + QUALITY_NAME_TEXT_MAP[settings.videoRecorderSettings.getQuality()] + ?: stringResource( + R.string.ui_settings_value_auto_label + ) + ) + } + }, + extra = { + ExampleListRoulette( + items = listOf(null), + onItemSelected = ::updateValue, + ) { + Text(stringResource(R.string.ui_settings_value_auto_label)) + } + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt index 7772a65..61afec2 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/screens/SettingsScreen.kt @@ -38,11 +38,12 @@ import app.myzel394.alibi.R import app.myzel394.alibi.dataStore import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AboutTile +import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderEncoderTile import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoRecorderFrameRateTile import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.CustomNotificationTile import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.DeleteRecordingsImmediatelyTile import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.DividerTitle -import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderEncoderTile +import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoRecorderQualityTile import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.ImportExport import app.myzel394.alibi.ui.components.SettingsScreen.atoms.InAppLanguagePicker import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.IntervalDurationTile @@ -158,13 +159,11 @@ fun SettingsScreen( DividerTitle( modifier = Modifier - .fillMaxWidth() - .padding(16.dp), + .fillMaxWidth(), title = stringResource(R.string.ui_settings_sections_audio_title), description = stringResource(R.string.ui_settings_sections_audio_description), ) AudioRecorderShowAllMicrophonesTile(settings = settings) - VideoRecorderFrameRateTile(settings = settings) AudioRecorderSamplingRateTile(settings = settings) AudioRecorderEncoderTile( snackbarHostState = snackbarHostState, @@ -176,6 +175,7 @@ fun SettingsScreen( title = stringResource(R.string.ui_settings_sections_video_title), description = stringResource(R.string.ui_settings_sections_video_description), ) + VideoRecorderQualityTile(settings = settings) VideoRecorderBitrateTile(settings = settings) VideoRecorderFrameRateTile(settings = settings) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bc51404..3b1280a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,4 +131,11 @@ Targeted Frame Rate How many frames per second should be recorded. The actual frame rate may be different. This can for example happen if the device is not able to record with the specified frame rate. + Quality + Highest + Ultra HD + Full HD + HD + Standard + Lowest \ No newline at end of file