diff --git a/app/src/main/java/com/fluxa/app/ui/MainActivity.kt b/app/src/main/java/com/fluxa/app/ui/MainActivity.kt index 7fc466d..14059ab 100644 --- a/app/src/main/java/com/fluxa/app/ui/MainActivity.kt +++ b/app/src/main/java/com/fluxa/app/ui/MainActivity.kt @@ -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) { diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/SettingsScreen.kt b/app/src/main/java/com/fluxa/app/ui/catalog/SettingsScreen.kt index d893c2f..73d0eb4 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/SettingsScreen.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/SettingsScreen.kt @@ -214,7 +214,8 @@ fun SettingsScreen( onBack = onBack, onLogout = onLogout, onManageAddons = onManageAddons, - onUpdateInfoChanged = onUpdateInfoChanged + onUpdateInfoChanged = onUpdateInfoChanged, + onUpdateProfile = onUpdateProfile ) } else mobileCategory?.let { category -> MobileCategoryDetail( diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsAppearanceSection.kt b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsAppearanceSection.kt index c338654..e380107 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsAppearanceSection.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsAppearanceSection.kt @@ -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 = "", diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsComponents.kt b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsComponents.kt index 830a894..ef51650 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsComponents.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsComponents.kt @@ -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) } } diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsSystemSection.kt b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsSystemSection.kt index 2d9693a..98874e1 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsSystemSection.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/TvSettingsSystemSection.kt @@ -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(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"), diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsCategoryDetail.kt b/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsCategoryDetail.kt index 84c1a93..6f538ae 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsCategoryDetail.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsCategoryDetail.kt @@ -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"), diff --git a/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsComponents.kt b/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsComponents.kt index 99f7c0a..7c78a67 100644 --- a/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsComponents.kt +++ b/app/src/main/java/com/fluxa/app/ui/catalog/mobile/settings/MobileSettingsComponents.kt @@ -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(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) diff --git a/core/src/main/assets/i18n/en-US.json b/core/src/main/assets/i18n/en-US.json index 10781e6..90c87c0 100644 --- a/core/src/main/assets/i18n/en-US.json +++ b/core/src/main/assets/i18n/en-US.json @@ -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.", diff --git a/core/src/main/assets/i18n/tr-TR.json b/core/src/main/assets/i18n/tr-TR.json index 1d4ca10..f50e038 100644 --- a/core/src/main/assets/i18n/tr-TR.json +++ b/core/src/main/assets/i18n/tr-TR.json @@ -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.",