mirror of
https://github.com/FluxaMedia/fluxa.git
synced 2026-08-04 07:56:01 +00:00
Add settings rows for notifications, auto-updates, subtitle shadow, and home hero trailer autoplay
These profile fields (notificationsEnabled, automaticUpdates, subtitleShadow, trailerOnHomeHeroEnabled/DelaySeconds) already drove real behavior but had no visible Settings UI on TV or mobile. Also gates the background update-check loop in MainActivity behind automaticUpdates, and wires a TV "Check for updates" action mirroring the existing mobile flow.
This commit is contained in:
parent
3bbbcb206c
commit
cffda2dad9
9 changed files with 111 additions and 5 deletions
|
|
@ -346,6 +346,10 @@ class MainActivity : FragmentActivity() {
|
|||
if (initialProfile == null) {
|
||||
homeViewModel.loadInitialData(null)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(activeProfile?.safeAutomaticUpdates) {
|
||||
if (activeProfile?.safeAutomaticUpdates == false) return@LaunchedEffect
|
||||
while (isActive) {
|
||||
val update = UpdateManager.checkUpdate()
|
||||
if (update != null) {
|
||||
|
|
|
|||
|
|
@ -214,7 +214,8 @@ fun SettingsScreen(
|
|||
onBack = onBack,
|
||||
onLogout = onLogout,
|
||||
onManageAddons = onManageAddons,
|
||||
onUpdateInfoChanged = onUpdateInfoChanged
|
||||
onUpdateInfoChanged = onUpdateInfoChanged,
|
||||
onUpdateProfile = onUpdateProfile
|
||||
)
|
||||
} else mobileCategory?.let { category ->
|
||||
MobileCategoryDetail(
|
||||
|
|
|
|||
|
|
@ -157,6 +157,21 @@ internal fun AppearanceSettings(profile: UserProfile, lang: String, previewMeta:
|
|||
checked = profile.safeHomeSeasonPostersOnHero,
|
||||
onToggle = { onUpdateProfile(profile.copy(homeSeasonPostersOnHero = it)) }
|
||||
)
|
||||
SettingsToggleTile(
|
||||
title = AppStrings.t(lang, "settings.trailer_on_home_hero"),
|
||||
subtitle = AppStrings.t(lang, "settings.trailer_on_home_hero_desc"),
|
||||
checked = profile.safeTrailerOnHomeHeroEnabled,
|
||||
onToggle = { onUpdateProfile(profile.copy(trailerOnHomeHeroEnabled = it)) }
|
||||
)
|
||||
if (profile.safeTrailerOnHomeHeroEnabled) {
|
||||
SettingsSecondsSliderTile(
|
||||
title = AppStrings.t(lang, "settings.trailer_on_home_hero_delay"),
|
||||
subtitle = AppStrings.t(lang, "settings.trailer_on_home_hero_delay_desc"),
|
||||
value = profile.safeTrailerOnHomeHeroDelaySeconds,
|
||||
valueRange = 0..15,
|
||||
onValueChange = { onUpdateProfile(profile.copy(trailerOnHomeHeroDelaySeconds = it)) }
|
||||
)
|
||||
}
|
||||
SettingsToggleTile(
|
||||
title = AppStrings.t(lang, "auto.continue_watching"),
|
||||
subtitle = "",
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ internal fun SettingsContent(
|
|||
}
|
||||
"downloads" -> DownloadSettings(profileValue, lang, onUpdateProfile)
|
||||
"addons" -> AddonSettings(profileValue, lang, onManageAddons, onUpdateProfile)
|
||||
"system" -> SystemSettings(profileValue, lang, onReboot, onLogout)
|
||||
"system" -> SystemSettings(profileValue, lang, onReboot, onLogout, onUpdateProfile)
|
||||
"developer" -> DeveloperSettings(lang)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun DownloadSettings(profile: UserProfile, lang: String, onUpdateProfile: (UserProfile) -> Unit) {
|
||||
|
|
@ -75,6 +76,12 @@ internal fun SubtitleSettings(profile: UserProfile, lang: String, onUpdateProfil
|
|||
checked = profile.safeAutoEnableSubtitles,
|
||||
onToggle = { onUpdateProfile(profile.copy(autoEnableSubtitles = it)) }
|
||||
)
|
||||
SettingsToggleTile(
|
||||
title = AppStrings.t(lang, "settings.subtitle_shadow"),
|
||||
subtitle = AppStrings.t(lang, "settings.subtitle_shadow_desc"),
|
||||
checked = profile.safeSubtitleShadow,
|
||||
onToggle = { onUpdateProfile(profile.copy(subtitleShadow = it)) }
|
||||
)
|
||||
SettingsChoiceTile(
|
||||
title = AppStrings.t(lang, "auto.preferred_subtitle_language"),
|
||||
subtitle = AppStrings.t(lang, "auto.default_subtitle_track_preference"),
|
||||
|
|
@ -161,9 +168,41 @@ internal fun AddonSettings(profile: UserProfile, lang: String, onManageAddons: (
|
|||
}
|
||||
|
||||
@Composable
|
||||
internal fun SystemSettings(profile: UserProfile, lang: String, onReboot: () -> Unit, onLogout: () -> Unit) {
|
||||
internal fun SystemSettings(profile: UserProfile, lang: String, onReboot: () -> Unit, onLogout: () -> Unit, onUpdateProfile: (UserProfile) -> Unit) {
|
||||
val scope = rememberCoroutineScope()
|
||||
var isCheckingUpdate by remember { mutableStateOf(false) }
|
||||
var updateStatus by remember { mutableStateOf<String?>(null) }
|
||||
SettingsSection(AppStrings.t(lang, "auto.system"), AppStrings.t(lang, "auto.app_and_device_actions")) {
|
||||
SettingsInfoTile(AppStrings.t(lang, "auto.version"), "1.2.5", FluxaIcons.Settings)
|
||||
SettingsInfoTile(
|
||||
AppStrings.t(lang, "auto.version"),
|
||||
"${com.fluxa.app.BuildConfig.VERSION_NAME} (${com.fluxa.app.BuildConfig.VERSION_CODE})",
|
||||
FluxaIcons.Settings
|
||||
)
|
||||
SettingsToggleTile(
|
||||
title = AppStrings.t(lang, "settings.automatic_updates"),
|
||||
subtitle = AppStrings.t(lang, "settings.automatic_updates_desc"),
|
||||
checked = profile.safeAutomaticUpdates,
|
||||
onToggle = { onUpdateProfile(profile.copy(automaticUpdates = it)) }
|
||||
)
|
||||
SettingsActionTile(
|
||||
title = AppStrings.t(lang, "settings.check_for_updates"),
|
||||
subtitle = updateStatus ?: AppStrings.t(lang, "settings.check_for_updates_desc"),
|
||||
icon = FluxaIcons.Settings,
|
||||
onClick = {
|
||||
if (!isCheckingUpdate) {
|
||||
isCheckingUpdate = true
|
||||
updateStatus = AppStrings.t(lang, "settings.checking_for_updates")
|
||||
scope.launch {
|
||||
val update = UpdateManager.checkUpdate()
|
||||
isCheckingUpdate = false
|
||||
updateStatus = if (update != null)
|
||||
AppStrings.format(lang, "settings.update_available", update.versionName)
|
||||
else
|
||||
AppStrings.t(lang, "settings.up_to_date")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
SettingsActionTile(
|
||||
title = AppStrings.t(lang, "auto.restart_app"),
|
||||
subtitle = AppStrings.t(lang, "auto.refresh_the_app_after_playback_or_network_ch"),
|
||||
|
|
|
|||
|
|
@ -294,6 +294,12 @@ internal fun MobileCategoryDetail(
|
|||
}
|
||||
item {
|
||||
MobileSettingsGroup(AppStrings.t(lang, "settings.notifications")) {
|
||||
MobileToggleRow(
|
||||
title = AppStrings.t(lang, "settings.enable_notifications"),
|
||||
subtitle = AppStrings.t(lang, "settings.enable_notifications_desc"),
|
||||
checked = profile.safeNotificationsEnabled,
|
||||
onToggle = { onUpdateProfile(profile.sanitizedUpdate(notificationsEnabled = !profile.safeNotificationsEnabled)) }
|
||||
)
|
||||
MobileToggleRow(
|
||||
title = AppStrings.t(lang, "settings.alert_new_episodes"),
|
||||
subtitle = AppStrings.t(lang, "settings.alert_new_episodes_desc"),
|
||||
|
|
@ -395,6 +401,21 @@ internal fun MobileCategoryDetail(
|
|||
checked = profile.safeHomeSeasonPostersOnHero,
|
||||
onToggle = { onUpdateProfile(profile.copy(homeSeasonPostersOnHero = !profile.safeHomeSeasonPostersOnHero)) }
|
||||
)
|
||||
MobileToggleRow(
|
||||
title = AppStrings.t(lang, "settings.trailer_on_home_hero"),
|
||||
subtitle = AppStrings.t(lang, "settings.trailer_on_home_hero_desc"),
|
||||
checked = profile.safeTrailerOnHomeHeroEnabled,
|
||||
onToggle = { onUpdateProfile(profile.copy(trailerOnHomeHeroEnabled = !profile.safeTrailerOnHomeHeroEnabled)) }
|
||||
)
|
||||
if (profile.safeTrailerOnHomeHeroEnabled) {
|
||||
MobileStepperRow(
|
||||
title = AppStrings.t(lang, "settings.trailer_on_home_hero_delay"),
|
||||
value = "${profile.safeTrailerOnHomeHeroDelaySeconds}s",
|
||||
subtitle = AppStrings.t(lang, "settings.trailer_on_home_hero_delay_desc"),
|
||||
onDecrease = { onUpdateProfile(profile.copy(trailerOnHomeHeroDelaySeconds = (profile.safeTrailerOnHomeHeroDelaySeconds - 1).coerceIn(0, 15))) },
|
||||
onIncrease = { onUpdateProfile(profile.copy(trailerOnHomeHeroDelaySeconds = (profile.safeTrailerOnHomeHeroDelaySeconds + 1).coerceIn(0, 15))) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
|
|
@ -688,6 +709,12 @@ internal fun MobileCategoryDetail(
|
|||
checked = profile.safeAutoEnableSubtitles,
|
||||
onToggle = { onUpdateProfile(profile.copy(autoEnableSubtitles = !profile.safeAutoEnableSubtitles)) }
|
||||
)
|
||||
MobileToggleRow(
|
||||
title = AppStrings.t(lang, "settings.subtitle_shadow"),
|
||||
subtitle = AppStrings.t(lang, "settings.subtitle_shadow_desc"),
|
||||
checked = profile.safeSubtitleShadow,
|
||||
onToggle = { onUpdateProfile(profile.copy(subtitleShadow = !profile.safeSubtitleShadow)) }
|
||||
)
|
||||
MobileSubtitlePreview(profile = profile, lang = lang)
|
||||
MobileStepperRow(
|
||||
title = AppStrings.t(lang, "auto.subtitle_size_7fc78c82"),
|
||||
|
|
|
|||
|
|
@ -132,7 +132,8 @@ internal fun MobileSettingsHub(
|
|||
onBack: () -> Unit,
|
||||
onLogout: () -> Unit,
|
||||
onManageAddons: () -> Unit,
|
||||
onUpdateInfoChanged: (UpdateManager.UpdateInfo?) -> Unit = {}
|
||||
onUpdateInfoChanged: (UpdateManager.UpdateInfo?) -> Unit = {},
|
||||
onUpdateProfile: (UserProfile) -> Unit
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var updateDialogMessage by remember { mutableStateOf<String?>(null) }
|
||||
|
|
@ -275,6 +276,13 @@ internal fun MobileSettingsHub(
|
|||
}
|
||||
}
|
||||
if (isSystemSection) {
|
||||
MobileToggleRow(
|
||||
title = AppStrings.t(lang, "settings.automatic_updates"),
|
||||
subtitle = AppStrings.t(lang, "settings.automatic_updates_desc"),
|
||||
checked = profile.safeAutomaticUpdates,
|
||||
onToggle = { onUpdateProfile(profile.sanitizedUpdate(automaticUpdates = !profile.safeAutomaticUpdates)) }
|
||||
)
|
||||
MobileSettingsRowDivider()
|
||||
MobileSettingsRow(
|
||||
title = AppStrings.t(lang, "settings.check_for_updates"),
|
||||
subtitle = if (availableUpdate != null)
|
||||
|
|
|
|||
|
|
@ -575,6 +575,12 @@
|
|||
"settings.picture_in_picture_desc": "Shows the player in a floating window when supported.",
|
||||
"settings.notifications_desc": "Allows app status and playback notifications.",
|
||||
"settings.notifications": "NOTIFICATIONS",
|
||||
"settings.enable_notifications": "Enable Notifications",
|
||||
"settings.enable_notifications_desc": "Master switch for all app notifications.",
|
||||
"settings.automatic_updates": "Automatic Updates",
|
||||
"settings.automatic_updates_desc": "Check for new app versions in the background.",
|
||||
"settings.subtitle_shadow": "Subtitle Shadow",
|
||||
"settings.subtitle_shadow_desc": "Adds a drop shadow behind subtitle text for readability.",
|
||||
"settings.alert_new_episodes": "Alert me on new episodes",
|
||||
"settings.alert_new_episodes_desc": "Notifies when upcoming episodes are released in your device timezone.",
|
||||
"settings.default_player_desc": "Chooses which player opens streams by default.",
|
||||
|
|
|
|||
|
|
@ -575,6 +575,12 @@
|
|||
"settings.picture_in_picture_desc": "Destekleyen cihazlarda oynatıcıyı küçük pencerede gösterir.",
|
||||
"settings.notifications_desc": "Uygulama durumu ve oynatma bildirimlerine izin verir.",
|
||||
"settings.notifications": "BİLDİRİMLER",
|
||||
"settings.enable_notifications": "Bildirimleri Etkinleştir",
|
||||
"settings.enable_notifications_desc": "Tüm uygulama bildirimleri için ana anahtar.",
|
||||
"settings.automatic_updates": "Otomatik Güncellemeler",
|
||||
"settings.automatic_updates_desc": "Arka planda yeni uygulama sürümlerini kontrol eder.",
|
||||
"settings.subtitle_shadow": "Altyazı Gölgesi",
|
||||
"settings.subtitle_shadow_desc": "Okunabilirlik için altyazı metninin arkasına gölge ekler.",
|
||||
"settings.alert_new_episodes": "Yeni bölümlerde uyar",
|
||||
"settings.alert_new_episodes_desc": "Yaklaşan bölümler cihaz saat diliminde yayınlandığında bildirir.",
|
||||
"settings.default_player_desc": "Yayınların varsayılan olarak hangi oynatıcıda açılacağını seçer.",
|
||||
|
|
|
|||
Loading…
Reference in a new issue