mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Add VideoRecorderBitrateTile
This commit is contained in:
parent
4f265b23f8
commit
9598cd45fa
@ -40,6 +40,10 @@ data class AppSettings(
|
||||
return copy(audioRecorderSettings = audioRecorderSettings)
|
||||
}
|
||||
|
||||
fun setVideoRecorderSettings(videoRecorderSettings: VideoRecorderSettings): AppSettings {
|
||||
return copy(videoRecorderSettings = videoRecorderSettings)
|
||||
}
|
||||
|
||||
fun setNotificationSettings(notificationSettings: NotificationSettings?): AppSettings {
|
||||
return copy(notificationSettings = notificationSettings)
|
||||
}
|
||||
@ -401,6 +405,20 @@ data class VideoRecorderSettings(
|
||||
"FHD" to Quality.FHD,
|
||||
"UHD" to Quality.UHD,
|
||||
)
|
||||
|
||||
val EXAMPLE_BITRATE_VALUES = listOf(
|
||||
null,
|
||||
500 * 1000,
|
||||
// 1 Mbps
|
||||
1 * 1000 * 1000,
|
||||
2 * 1000 * 1000,
|
||||
4 * 1000 * 1000,
|
||||
8 * 1000 * 1000,
|
||||
16 * 1000 * 1000,
|
||||
32 * 1000 * 1000,
|
||||
50 * 1000 * 1000,
|
||||
100 * 1000 * 1000,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,145 @@
|
||||
package app.myzel394.alibi.ui.components.SettingsScreen.Tiles
|
||||
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
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.rememberCoroutineScope
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import app.myzel394.alibi.R
|
||||
import app.myzel394.alibi.dataStore
|
||||
import app.myzel394.alibi.db.AppSettings
|
||||
import app.myzel394.alibi.db.AudioRecorderSettings
|
||||
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.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 VideoRecorderBitrateTile(
|
||||
settings: AppSettings,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val showDialog = rememberUseCaseState()
|
||||
val dataStore = LocalContext.current.dataStore
|
||||
|
||||
fun updateValue(bitRate: Int?) {
|
||||
scope.launch {
|
||||
dataStore.updateData {
|
||||
it.setVideoRecorderSettings(
|
||||
it.videoRecorderSettings.setTargetedVideoBitRate(bitRate)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val notNumberLabel = stringResource(R.string.form_error_type_notNumber)
|
||||
InputDialog(
|
||||
state = showDialog,
|
||||
header = Header.Default(
|
||||
title = stringResource(R.string.ui_settings_option_videoTargetedBitrate_title),
|
||||
icon = IconSource(
|
||||
painter = IconResource.fromImageVector(Icons.Default.Tune).asPainterResource(),
|
||||
contentDescription = null,
|
||||
)
|
||||
),
|
||||
selection = InputSelection(
|
||||
input = listOf(
|
||||
InputTextField(
|
||||
header = InputHeader(
|
||||
title = stringResource(id = R.string.ui_settings_option_videoTargetedBitrate_explanation),
|
||||
),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Number,
|
||||
),
|
||||
type = InputTextFieldType.OUTLINED,
|
||||
text = if (settings.videoRecorderSettings.targetedVideoBitRate == null) "" else (settings.videoRecorderSettings.targetedVideoBitRate / 1000).toString(),
|
||||
validationListener = { text ->
|
||||
val bitRate = text?.toIntOrNull()
|
||||
|
||||
if (bitRate == null) {
|
||||
return@InputTextField ValidationResult.Invalid(notNumberLabel)
|
||||
}
|
||||
|
||||
ValidationResult.Valid
|
||||
},
|
||||
key = "bitrate",
|
||||
)
|
||||
),
|
||||
) { result ->
|
||||
val bitRate = result.getString("bitrate")?.toIntOrNull() ?: return@InputSelection
|
||||
|
||||
updateValue(bitRate * 1000)
|
||||
}
|
||||
)
|
||||
SettingsTile(
|
||||
title = stringResource(R.string.ui_settings_option_videoTargetedBitrate_title),
|
||||
description = stringResource(R.string.ui_settings_option_bitrate_description),
|
||||
leading = {
|
||||
Icon(
|
||||
Icons.Default.Tune,
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
trailing = {
|
||||
Button(
|
||||
onClick = showDialog::show,
|
||||
colors = ButtonDefaults.filledTonalButtonColors(
|
||||
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||
),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Text(formatBitrate(settings.videoRecorderSettings.targetedVideoBitRate))
|
||||
}
|
||||
},
|
||||
extra = {
|
||||
ExampleListRoulette(
|
||||
items = VideoRecorderSettings.EXAMPLE_BITRATE_VALUES,
|
||||
onItemSelected = ::updateValue,
|
||||
) { bitRate ->
|
||||
Text(formatBitrate(bitRate))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun formatBitrate(bitrate: Int?): String {
|
||||
return if (bitrate == null)
|
||||
stringResource(R.string.ui_settings_value_auto_label)
|
||||
else if (bitrate >= 1000 * 1000 && bitrate % (1000 * 1000) == 0)
|
||||
stringResource(
|
||||
R.string.format_mbps,
|
||||
bitrate / 1000 / 1000,
|
||||
)
|
||||
else if (bitrate >= 1000 && bitrate % 1000 == 0)
|
||||
stringResource(
|
||||
R.string.format_kbps,
|
||||
bitrate / 1000,
|
||||
)
|
||||
else
|
||||
stringResource(
|
||||
R.string.format_bps,
|
||||
bitrate,
|
||||
)
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
package app.myzel394.alibi.ui.screens
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
@ -40,7 +38,7 @@ 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.AudioRecorderBitrateTile
|
||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoRecorderBitrateTile
|
||||
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
|
||||
@ -164,15 +162,20 @@ fun SettingsScreen(
|
||||
title = stringResource(R.string.ui_settings_sections_audio_title),
|
||||
description = stringResource(R.string.ui_settings_sections_audio_description),
|
||||
)
|
||||
|
||||
AudioRecorderShowAllMicrophonesTile(settings = settings)
|
||||
AudioRecorderBitrateTile(settings = settings)
|
||||
VideoRecorderBitrateTile(settings = settings)
|
||||
AudioRecorderSamplingRateTile(settings = settings)
|
||||
AudioRecorderEncoderTile(
|
||||
snackbarHostState = snackbarHostState,
|
||||
settings = settings
|
||||
)
|
||||
AudioRecorderOutputFormatTile(settings = settings)
|
||||
|
||||
DividerTitle(
|
||||
title = stringResource(R.string.ui_settings_sections_video_title),
|
||||
description = stringResource(R.string.ui_settings_sections_video_description),
|
||||
)
|
||||
VideoRecorderBitrateTile(settings = settings)
|
||||
}
|
||||
Divider(
|
||||
modifier = Modifier
|
||||
|
@ -122,4 +122,10 @@
|
||||
<string name="ui_audioRecorder_action_save_openFolder">Open</string>
|
||||
<string name="ui_settings_sections_audio_title">Audio Recording</string>
|
||||
<string name="ui_settings_sections_audio_description">Only applies to audio recordings</string>
|
||||
<string name="ui_settings_sections_video_title">Video Recording</string>
|
||||
<string name="ui_settings_sections_video_description">Only applies to video recordings</string>
|
||||
<string name="ui_settings_option_videoTargetedBitrate_title">Targeted Bitrate</string>
|
||||
<string name="ui_settings_option_videoTargetedBitrate_explanation">Bitrate for the video recording. Only applies to the video itself, not the audio. The actual bitrate may be different depending on what you will be recording.</string>
|
||||
<string name="format_mbps">%s MB/s</string>
|
||||
<string name="format_bps">%s B/s</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user