feat: add EPG markers count setting in player preferences

This commit is contained in:
tunbmoon
2026-03-25 15:28:47 +08:00
parent 5d1957c0c0
commit 347b6bcdb2
7 changed files with 177 additions and 37 deletions
@@ -12,17 +12,23 @@ import androidx.compose.material.icons.outlined.Check
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.antoniegil.astronia.R
import com.antoniegil.astronia.ui.common.HapticFeedback.slightHapticFeedback
@Composable
@@ -201,6 +207,97 @@ fun PreferenceSwitch(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PreferenceNumberPicker(
title: String,
description: String? = null,
icon: ImageVector? = null,
value: Int,
valueRange: IntRange,
onValueChange: (Int) -> Unit
) {
var expanded by remember { mutableStateOf(false) }
Surface(
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 12.dp)
.padding(start = if (icon == null) 12.dp else 0.dp),
verticalAlignment = Alignment.CenterVertically
) {
if (icon != null) {
Icon(
imageVector = icon,
contentDescription = null,
modifier = Modifier.padding(start = 8.dp, end = 16.dp).size(24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
if (description != null) {
Text(
text = description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
}
ExposedDropdownMenuBox(
expanded = expanded,
onExpandedChange = { expanded = it },
modifier = Modifier.padding(start = 16.dp)
) {
TextField(
value = if (value == 0) stringResource(R.string.epg_markers_off) else value.toString(),
onValueChange = {},
readOnly = true,
modifier = Modifier
.menuAnchor()
.width(80.dp),
colors = TextFieldDefaults.colors(
focusedContainerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent
),
textStyle = MaterialTheme.typography.bodyLarge,
shape = MaterialTheme.shapes.medium
)
ExposedDropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
valueRange.forEach { num ->
DropdownMenuItem(
text = { Text(if (num == 0) stringResource(R.string.epg_markers_off) else num.toString()) },
onClick = {
onValueChange(num)
expanded = false
}
)
}
}
}
}
}
}
@Composable
fun PreferenceSingleChoiceItem(
text: String,
@@ -21,6 +21,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.antoniegil.astronia.R
import com.antoniegil.astronia.ui.component.BackButton
import com.antoniegil.astronia.ui.component.PreferenceNumberPicker
import com.antoniegil.astronia.ui.component.PreferenceSwitch
import com.antoniegil.astronia.ui.component.PreferenceSubtitle
import com.antoniegil.astronia.util.SettingsManager
@@ -48,6 +49,7 @@ fun PlayerSettingsPage(onNavigateBack: () -> Unit) {
var autoPlay by remember { mutableStateOf(SettingsManager.getAutoPlay(context)) }
var autoHideControls by remember { mutableStateOf(SettingsManager.getAutoHideControls(context)) }
var epgMarkersCount by remember { mutableIntStateOf(SettingsManager.getEpgMarkersCount(context)) }
var enablePictureInPicture by remember { mutableStateOf(SettingsManager.getEnablePip(context)) }
var backgroundPlay by remember { mutableStateOf(SettingsManager.getBackgroundPlay(context)) }
var keepScreenOn by remember { mutableStateOf(SettingsManager.getKeepScreenOn(context)) }
@@ -82,43 +84,7 @@ fun PlayerSettingsPage(onNavigateBack: () -> Unit) {
}
)
}
item {
PreferenceSubtitle(text = stringResource(R.string.interface_control))
}
item {
PreferenceSwitch(
title = stringResource(R.string.auto_hide_controls),
description = stringResource(R.string.auto_hide_controls_desc),
icon = Icons.Outlined.VisibilityOff,
isChecked = autoHideControls,
onCheckedChange = {
autoHideControls = it
SettingsManager.setAutoHideControls(context, it)
}
)
}
item {
val isPipSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
PreferenceSwitch(
title = stringResource(R.string.pip),
description = if (isPipSupported) {
stringResource(R.string.pip_desc)
} else {
stringResource(R.string.pip_unsupported)
},
icon = Icons.Outlined.PictureInPicture,
isChecked = enablePictureInPicture,
enabled = isPipSupported,
onCheckedChange = {
enablePictureInPicture = it
SettingsManager.setEnablePip(context, it)
}
)
}
item {
PreferenceSwitch(
title = stringResource(R.string.background_play),
@@ -139,6 +105,60 @@ fun PlayerSettingsPage(onNavigateBack: () -> Unit) {
}
)
}
item {
PreferenceSubtitle(text = stringResource(R.string.control_bar))
}
item {
PreferenceSwitch(
title = stringResource(R.string.auto_hide_controls),
description = stringResource(R.string.auto_hide_controls_desc),
icon = Icons.Outlined.VisibilityOff,
isChecked = autoHideControls,
onCheckedChange = {
autoHideControls = it
SettingsManager.setAutoHideControls(context, it)
}
)
}
item {
PreferenceNumberPicker(
title = stringResource(R.string.epg_markers),
description = stringResource(R.string.epg_markers_desc),
icon = Icons.Outlined.Timeline,
value = epgMarkersCount,
valueRange = 0..3,
onValueChange = {
epgMarkersCount = it
SettingsManager.setEpgMarkersCount(context, it)
}
)
}
item {
PreferenceSubtitle(text = stringResource(R.string.interface_control))
}
item {
val isPipSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
PreferenceSwitch(
title = stringResource(R.string.pip),
description = if (isPipSupported) {
stringResource(R.string.pip_desc)
} else {
stringResource(R.string.pip_unsupported)
},
icon = Icons.Outlined.PictureInPicture,
isChecked = enablePictureInPicture,
enabled = isPipSupported,
onCheckedChange = {
enablePictureInPicture = it
SettingsManager.setEnablePip(context, it)
}
)
}
item {
PreferenceSwitch(
@@ -40,6 +40,9 @@ object SettingsManager {
fun getAutoHideControls(context: Context): Boolean = getInstance(context).getAutoHideControls()
fun setAutoHideControls(context: Context, value: Boolean) = getInstance(context).setAutoHideControls(value)
fun getEpgMarkersCount(context: Context): Int = getInstance(context).getEpgMarkersCount()
fun setEpgMarkersCount(context: Context, value: Int) = getInstance(context).setEpgMarkersCount(value)
fun getEnablePip(context: Context): Boolean = getInstance(context).getEnablePip()
fun setEnablePip(context: Context, value: Boolean) = getInstance(context).setEnablePip(value)
@@ -177,6 +180,9 @@ internal class PreferenceManagerImpl(context: Context) {
fun getAutoHideControls(): Boolean = getBoolean(KEY_AUTO_HIDE_CONTROLS, true)
fun setAutoHideControls(value: Boolean) = putBoolean(KEY_AUTO_HIDE_CONTROLS, value)
fun getEpgMarkersCount(): Int = getInt(KEY_EPG_MARKERS_COUNT, 3)
fun setEpgMarkersCount(value: Int) = putInt(KEY_EPG_MARKERS_COUNT, value.coerceIn(0, 3))
fun getEnablePip(): Boolean = getBoolean(KEY_ENABLE_PIP, true)
fun setEnablePip(value: Boolean) = putBoolean(KEY_ENABLE_PIP, value)
@@ -330,6 +336,7 @@ internal class PreferenceManagerImpl(context: Context) {
private const val KEY_AUTO_PLAY = "auto_play"
private const val KEY_REMEMBER_POSITION = "remember_position"
private const val KEY_AUTO_HIDE_CONTROLS = "auto_hide_controls"
private const val KEY_EPG_MARKERS_COUNT = "epg_markers_count"
private const val KEY_ENABLE_PIP = "enable_pip"
private const val KEY_BACKGROUND_PLAY = "background_play"
private const val KEY_HARDWARE_ACCELERATION = "hardware_acceleration"
@@ -82,9 +82,13 @@
<string name="about_desc">应用信息和版本</string>
<string name="playback_behavior">播放行为</string>
<string name="control_bar">控制栏</string>
<string name="interface_control">界面控制</string>
<string name="auto_play">自动播放</string>
<string name="auto_play_desc">打开视频时自动开始播放</string>
<string name="epg_markers">EPG 标记</string>
<string name="epg_markers_desc">在进度条上显示 EPG 节目段的标记</string>
<string name="epg_markers_off">关闭</string>
<string name="auto_hide_controls">自动隐藏控制栏</string>
<string name="auto_hide_controls_desc">播放时自动隐藏控制栏</string>
<string name="pip">画中画</string>
@@ -82,9 +82,13 @@
<string name="about_desc">應用程式資訊同版本</string>
<string name="playback_behavior">播放行為</string>
<string name="control_bar">控制欄</string>
<string name="interface_control">介面控制</string>
<string name="auto_play">自動播放</string>
<string name="auto_play_desc">開片嗰陣自動開始播放</string>
<string name="epg_markers">EPG 標記</string>
<string name="epg_markers_desc">喺進度條上面顯示 EPG 節目段嘅標記</string>
<string name="epg_markers_off">關閉</string>
<string name="auto_hide_controls">自動隱藏控制欄</string>
<string name="auto_hide_controls_desc">播放時自動收埋控制欄</string>
<string name="pip">子母畫面</string>
@@ -82,9 +82,13 @@
<string name="about_desc">應用程式資訊與版本</string>
<string name="playback_behavior">播放行為</string>
<string name="control_bar">控制列</string>
<string name="interface_control">介面控制</string>
<string name="auto_play">自動播放</string>
<string name="auto_play_desc">開啟影片時自動開始播放</string>
<string name="epg_markers">EPG 標記</string>
<string name="epg_markers_desc">在進度條上顯示 EPG 節目段的標記</string>
<string name="epg_markers_off">關閉</string>
<string name="auto_hide_controls">自動隱藏控制列</string>
<string name="auto_hide_controls_desc">播放時自動隱藏控制列</string>
<string name="pip">子母畫面</string>
+4
View File
@@ -85,9 +85,13 @@
<string name="about_desc">App info and version</string>
<string name="playback_behavior">Playback Behavior</string>
<string name="control_bar">Control Bar</string>
<string name="interface_control">Interface Control</string>
<string name="auto_play">Auto Play</string>
<string name="auto_play_desc">Automatically start playing when opening video</string>
<string name="epg_markers">EPG Markers</string>
<string name="epg_markers_desc">Show EPG program segment markers on progress bar</string>
<string name="epg_markers_off">off</string>
<string name="auto_hide_controls">Auto Hide Controls</string>
<string name="auto_hide_controls_desc">Automatically hide controls during playback</string>
<string name="pip">Picture in Picture</string>