mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-18 23:05:26 +02:00
feat: Add VideoFrameRate
This commit is contained in:
parent
9598cd45fa
commit
e8d7b2b6f8
@ -419,6 +419,15 @@ data class VideoRecorderSettings(
|
|||||||
50 * 1000 * 1000,
|
50 * 1000 * 1000,
|
||||||
100 * 1000 * 1000,
|
100 * 1000 * 1000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val EXAMPLE_FRAME_RATE_VALUES = listOf(
|
||||||
|
null,
|
||||||
|
24,
|
||||||
|
30,
|
||||||
|
60,
|
||||||
|
120,
|
||||||
|
240,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,127 @@
|
|||||||
|
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.BrokenImage
|
||||||
|
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.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 VideoFrameRate(
|
||||||
|
settings: AppSettings,
|
||||||
|
) {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val showDialog = rememberUseCaseState()
|
||||||
|
val dataStore = LocalContext.current.dataStore
|
||||||
|
|
||||||
|
fun updateValue(frameRate: Int?) {
|
||||||
|
scope.launch {
|
||||||
|
dataStore.updateData {
|
||||||
|
it.setVideoRecorderSettings(
|
||||||
|
it.videoRecorderSettings.setTargetFrameRate(frameRate)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val notNumberLabel = stringResource(R.string.form_error_type_notNumber)
|
||||||
|
InputDialog(
|
||||||
|
state = showDialog,
|
||||||
|
header = Header.Default(
|
||||||
|
title = stringResource(R.string.ui_settings_option_videoTargetedFrameRate_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_videoTargetedFrameRate_explanation),
|
||||||
|
),
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = KeyboardType.Number,
|
||||||
|
),
|
||||||
|
type = InputTextFieldType.OUTLINED,
|
||||||
|
text = if (settings.videoRecorderSettings.targetFrameRate == null) "" else settings.videoRecorderSettings.targetFrameRate.toString(),
|
||||||
|
validationListener = { text ->
|
||||||
|
val frameRate = text?.toIntOrNull()
|
||||||
|
|
||||||
|
if (frameRate == null) {
|
||||||
|
return@InputTextField ValidationResult.Invalid(notNumberLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidationResult.Valid
|
||||||
|
},
|
||||||
|
key = "framerate",
|
||||||
|
)
|
||||||
|
),
|
||||||
|
) { result ->
|
||||||
|
val frameRate = result.getString("framerate")?.toIntOrNull() ?: return@InputSelection
|
||||||
|
|
||||||
|
updateValue(frameRate)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingsTile(
|
||||||
|
title = stringResource(R.string.ui_settings_option_videoTargetedFrameRate_title),
|
||||||
|
leading = {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.BrokenImage,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
trailing = {
|
||||||
|
Button(
|
||||||
|
onClick = showDialog::show,
|
||||||
|
colors = ButtonDefaults.filledTonalButtonColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
),
|
||||||
|
shape = MaterialTheme.shapes.medium,
|
||||||
|
) {
|
||||||
|
if (settings.videoRecorderSettings.targetFrameRate == null)
|
||||||
|
Text(stringResource(R.string.ui_settings_value_auto_label))
|
||||||
|
else
|
||||||
|
Text(settings.videoRecorderSettings.targetFrameRate.toString())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
extra = {
|
||||||
|
ExampleListRoulette(
|
||||||
|
items = VideoRecorderSettings.EXAMPLE_FRAME_RATE_VALUES,
|
||||||
|
onItemSelected = ::updateValue,
|
||||||
|
) { frameRate ->
|
||||||
|
Text(
|
||||||
|
frameRate?.toString() ?: stringResource(R.string.ui_settings_value_auto_label)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -38,7 +38,7 @@ import app.myzel394.alibi.R
|
|||||||
import app.myzel394.alibi.dataStore
|
import app.myzel394.alibi.dataStore
|
||||||
import app.myzel394.alibi.ui.SUPPORTS_DARK_MODE_NATIVELY
|
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.AboutTile
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoRecorderBitrateTile
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoFrameRate
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.CustomNotificationTile
|
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.DeleteRecordingsImmediatelyTile
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.DividerTitle
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.DividerTitle
|
||||||
@ -51,6 +51,7 @@ import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderOutput
|
|||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderSamplingRateTile
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderSamplingRateTile
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.SaveFolderTile
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.SaveFolderTile
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderShowAllMicrophonesTile
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.AudioRecorderShowAllMicrophonesTile
|
||||||
|
import app.myzel394.alibi.ui.components.SettingsScreen.Tiles.VideoRecorderBitrateTile
|
||||||
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ThemeSelector
|
import app.myzel394.alibi.ui.components.SettingsScreen.atoms.ThemeSelector
|
||||||
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
|
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
|
||||||
import app.myzel394.alibi.ui.components.atoms.MessageBox
|
import app.myzel394.alibi.ui.components.atoms.MessageBox
|
||||||
@ -163,7 +164,7 @@ fun SettingsScreen(
|
|||||||
description = stringResource(R.string.ui_settings_sections_audio_description),
|
description = stringResource(R.string.ui_settings_sections_audio_description),
|
||||||
)
|
)
|
||||||
AudioRecorderShowAllMicrophonesTile(settings = settings)
|
AudioRecorderShowAllMicrophonesTile(settings = settings)
|
||||||
VideoRecorderBitrateTile(settings = settings)
|
VideoFrameRate(settings = settings)
|
||||||
AudioRecorderSamplingRateTile(settings = settings)
|
AudioRecorderSamplingRateTile(settings = settings)
|
||||||
AudioRecorderEncoderTile(
|
AudioRecorderEncoderTile(
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
@ -176,6 +177,7 @@ fun SettingsScreen(
|
|||||||
description = stringResource(R.string.ui_settings_sections_video_description),
|
description = stringResource(R.string.ui_settings_sections_video_description),
|
||||||
)
|
)
|
||||||
VideoRecorderBitrateTile(settings = settings)
|
VideoRecorderBitrateTile(settings = settings)
|
||||||
|
VideoFrameRate(settings = settings)
|
||||||
}
|
}
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -128,4 +128,7 @@
|
|||||||
<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="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_mbps">%s MB/s</string>
|
||||||
<string name="format_bps">%s B/s</string>
|
<string name="format_bps">%s B/s</string>
|
||||||
|
<string name="ui_settings_option_videoTargetedFrameRate_title">Targeted Frame Rate</string>
|
||||||
|
<string name="ui_settings_option_videoTargetedFrameRate_description">How many frames per second should be recorded.</string>
|
||||||
|
<string name="ui_settings_option_videoTargetedFrameRate_explanation">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.</string>
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user