From f1471e280b3c56e6ba231d6c714f6aeafc4951db Mon Sep 17 00:00:00 2001 From: Owen LeJeune Date: Sun, 9 Jul 2023 15:37:26 -0400 Subject: [PATCH] flatten settigns navigation + move next mcu card behind preference --- .../tvtime/preferences/AppPreferences.kt | 7 + .../tvtime/ui/navigation/AppNavigation.kt | 18 +- .../ui/navigation/SettingsNavigation.kt | 84 ++ .../tvtime/ui/screens/MediaDetailScreen.kt | 12 +- .../tvtime/ui/screens/SettingsScreen.kt | 969 +++++++++--------- .../tvtime/ui/viewmodel/SettingsViewModel.kt | 12 + app/src/main/res/values/strings.xml | 4 + 7 files changed, 605 insertions(+), 501 deletions(-) create mode 100644 app/src/main/java/com/owenlejeune/tvtime/ui/navigation/SettingsNavigation.kt diff --git a/app/src/main/java/com/owenlejeune/tvtime/preferences/AppPreferences.kt b/app/src/main/java/com/owenlejeune/tvtime/preferences/AppPreferences.kt index f8e2a16..6c58825 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/preferences/AppPreferences.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/preferences/AppPreferences.kt @@ -34,6 +34,7 @@ class AppPreferences(context: Context) { private val ACCOUNT_TAB_POSITION = "account_tab_position" private val SHOW_BTAB_LABELS = "show_btab_labels" private val SHOW_POSTER_TITLE = "show_poster_titles" + private val SHOW_NEXT_MCU = "show_next_mcu" } private val preferences: SharedPreferences = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE) @@ -128,6 +129,12 @@ class AppPreferences(context: Context) { get() = preferences.getBoolean(SHOW_BACKDROP_GALLERY, showBackdropGalleryDefault) set(value) { preferences.put(SHOW_BACKDROP_GALLERY, value) } + /******** Special Features Preferences ********/ + val showNextMcuProductionDefault: Boolean = false + var showNextMcuProduction: Boolean + get() = preferences.getBoolean(SHOW_NEXT_MCU, showNextMcuProductionDefault) + set(value) { preferences.put(SHOW_NEXT_MCU, value) } + /********* Helpers ********/ private fun SharedPreferences.put(key: String, value: Any?) { edit().apply { diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AppNavigation.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AppNavigation.kt index 5b9e7ce..7cd9417 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/AppNavigation.kt @@ -1,7 +1,5 @@ package com.owenlejeune.tvtime.ui.navigation -import android.os.Build -import android.util.Log import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn @@ -93,18 +91,6 @@ fun AppNavigationHost( } } } - composable( - AppNavItem.SettingsView.route.plus("/{${NavConstants.SETTINGS_KEY}}"), - arguments = listOf( - navArgument(NavConstants.SETTINGS_KEY) { type = NavType.StringType } - ) - ) { - val route = it.arguments?.getString(NavConstants.SETTINGS_KEY) - SettingsScreen( - appNavController = appNavController, - route = route - ) - } composable(AppNavItem.SettingsView.route) { SettingsScreen(appNavController = appNavController) } @@ -237,9 +223,7 @@ sealed class AppNavItem(val route: String) { object DetailView: AppNavItem("detail_route") { fun withArgs(type: MediaViewType, id: Int) = route.plus("/${type}/${id}") } - object SettingsView: AppNavItem("settings_route") { - fun withArgs(page: String) = route.plus("/$page") - } + object SettingsView: AppNavItem("settings_route") object SearchView: AppNavItem("search_route") { fun withArgs(searchType: MediaViewType, pageTitle: String) = route.plus("?searchType=$searchType&pageTitle=$pageTitle") } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/SettingsNavigation.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/SettingsNavigation.kt new file mode 100644 index 0000000..9f17b33 --- /dev/null +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/navigation/SettingsNavigation.kt @@ -0,0 +1,84 @@ +package com.owenlejeune.tvtime.ui.navigation + +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.res.stringResource +import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.owenlejeune.tvtime.R +import com.owenlejeune.tvtime.ui.screens.DarkModePreferences +import com.owenlejeune.tvtime.ui.screens.DesignPreferences +import com.owenlejeune.tvtime.ui.screens.DevPreferences +import com.owenlejeune.tvtime.ui.screens.HomeScreenPreferences +import com.owenlejeune.tvtime.ui.screens.SearchPreferences +import com.owenlejeune.tvtime.ui.screens.SettingsHome +import com.owenlejeune.tvtime.ui.screens.SpecialFeaturePreferences + +@Composable +fun SettingsNavigationHost( + appNavController: NavController, + appBarTitle: MutableState, + popBackAction: MutableState<() -> Unit> +) { + val settingsNavController = rememberNavController() + NavHost( + navController = settingsNavController, + startDestination = SettingsNavItem.Home.route, + enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, tween(500)) }, + popEnterTransition = { fadeIn(tween(500)) }, + exitTransition = { fadeOut(tween(500)) }, + popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, tween(500)) } + ) { + composable(SettingsNavItem.Home.route) { + appBarTitle.value = stringResource(id = R.string.nav_settings_title) + popBackAction.value = { appNavController.popBackStack() } + SettingsHome(settingsNavController = settingsNavController) + } + composable(SettingsNavItem.Search.route) { + appBarTitle.value = stringResource(id = R.string.preference_heading_search) + popBackAction.value = { settingsNavController.popBackStack() } + SearchPreferences() + } + composable(SettingsNavItem.Design.route) { + appBarTitle.value = stringResource(id = R.string.preference_heading_design) + popBackAction.value = { settingsNavController.popBackStack() } + DesignPreferences(settingsNavController = settingsNavController) + } + composable(SettingsNavItem.DarkMode.route) { + appBarTitle.value = stringResource(id = R.string.preference_heading_dark_mode) + popBackAction.value = { settingsNavController.popBackStack() } + DarkModePreferences() + } + composable(SettingsNavItem.HomeScreen.route) { + appBarTitle.value = stringResource(id = R.string.preference_heading_home_screen) + popBackAction.value = { settingsNavController.popBackStack() } + HomeScreenPreferences() + } + composable(SettingsNavItem.SpecialFeatures.route) { + appBarTitle.value = stringResource(id = R.string.preference_heading_special_features) + popBackAction.value = { settingsNavController.popBackStack() } + SpecialFeaturePreferences() + } + composable(SettingsNavItem.Developer.route) { + appBarTitle.value = stringResource(id = R.string.preferences_debug_title) + popBackAction.value = { settingsNavController.popBackStack() } + DevPreferences() + } + } +} + +sealed class SettingsNavItem(val route: String) { + object Home: SettingsNavItem("settings_home") + object Search: SettingsNavItem("settings_search") + object Design: SettingsNavItem("settings_design") + object DarkMode: SettingsNavItem("settings_dark_mode") + object HomeScreen: SettingsNavItem("settings_home_screen") + object SpecialFeatures: SettingsNavItem("settings_special_feature") + object Developer: SettingsNavItem("settings_developer") +} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt index b99c049..e4f9f26 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/MediaDetailScreen.kt @@ -46,6 +46,7 @@ import com.owenlejeune.tvtime.extensions.format import com.owenlejeune.tvtime.extensions.getCalendarYear import com.owenlejeune.tvtime.extensions.lazyPagingItems import com.owenlejeune.tvtime.extensions.listItems +import com.owenlejeune.tvtime.preferences.AppPreferences import com.owenlejeune.tvtime.ui.components.* import com.owenlejeune.tvtime.ui.navigation.AppNavItem import com.owenlejeune.tvtime.ui.viewmodel.MainViewModel @@ -54,6 +55,7 @@ import com.owenlejeune.tvtime.utils.SessionManager import com.owenlejeune.tvtime.utils.TmdbUtils import com.owenlejeune.tvtime.utils.types.MediaViewType import kotlinx.coroutines.* +import org.koin.java.KoinJavaComponent.get @OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class) @Composable @@ -152,7 +154,8 @@ private fun MediaViewContent( type: MediaViewType, windowSize: WindowSizeClass, showImageGallery: MutableState, - pagerState: PagerState + pagerState: PagerState, + preferences: AppPreferences = get(AppPreferences::class.java) ) { LaunchedEffect(Unit) { mainViewModel.getExternalIds(itemId, type) @@ -249,7 +252,10 @@ private fun MediaViewContent( WatchProvidersCard(itemId = itemId, type = type, mainViewModel = mainViewModel) - if (mediaItem?.productionCompanies?.firstOrNull { it.name == "Marvel Studios" } != null) { + if ( + mediaItem?.productionCompanies?.firstOrNull { it.name == "Marvel Studios" } != null + && preferences.showNextMcuProduction + ) { NextMcuProjectCard(appNavController = appNavController) } @@ -1078,7 +1084,7 @@ private fun NextMcuProjectCard( Text( text = nextMcuProject.value?.title ?: "", style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.W700 + fontWeight = FontWeight.W600 ) val releaseDate = diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt index 87114cf..70a62d9 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/SettingsScreen.kt @@ -1,20 +1,50 @@ package com.owenlejeune.tvtime.ui.screens +import android.app.Activity import android.os.Build import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +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.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.IconButton import androidx.compose.material.TextButton import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Brightness6 +import androidx.compose.material.icons.filled.Check +import androidx.compose.material.icons.filled.DeveloperBoard +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Palette +import androidx.compose.material.icons.filled.RestartAlt +import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.outlined.DarkMode +import androidx.compose.material.icons.outlined.Flare import androidx.compose.material.icons.outlined.LightMode -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -36,25 +66,24 @@ import com.owenlejeune.tvtime.BuildConfig import com.owenlejeune.tvtime.OnboardingActivity import com.owenlejeune.tvtime.R import com.owenlejeune.tvtime.preferences.AppPreferences -import com.owenlejeune.tvtime.ui.components.* -import com.owenlejeune.tvtime.ui.navigation.AppNavItem +import com.owenlejeune.tvtime.ui.components.CenteredIconCircle +import com.owenlejeune.tvtime.ui.components.PaletteView +import com.owenlejeune.tvtime.ui.components.PreferenceHeading +import com.owenlejeune.tvtime.ui.components.RadioButtonPreference +import com.owenlejeune.tvtime.ui.components.SliderPreference +import com.owenlejeune.tvtime.ui.components.SwitchPreference +import com.owenlejeune.tvtime.ui.navigation.SettingsNavItem +import com.owenlejeune.tvtime.ui.navigation.SettingsNavigationHost import com.owenlejeune.tvtime.ui.viewmodel.SettingsViewModel import com.owenlejeune.tvtime.ui.views.HomeTabRecyclerAdapter import com.owenlejeune.tvtime.ui.views.ItemMoveCallback -import com.owenlejeune.tvtime.utils.ResourceUtils import com.owenlejeune.tvtime.utils.SessionManager import kotlinx.coroutines.launch -import org.koin.androidx.compose.koinViewModel -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject -import org.koin.java.KoinJavaComponent.get @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreen( - appNavController: NavController, - route: String? = null, - preferences: AppPreferences = get(AppPreferences::class.java) + appNavController: NavController ) { val systemUiController = rememberSystemUiController() systemUiController.setStatusBarColor(color = MaterialTheme.colorScheme.background) @@ -64,12 +93,7 @@ fun SettingsScreen( val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(topAppBarScrollState) val appBarTitle = remember { mutableStateOf("") } - val defaultRestoreAction = ::resetAllPreferences - val restoreAction = remember { mutableStateOf(defaultRestoreAction) } - - val settingsViewModel = viewModel() - - val activity = LocalContext.current as AppCompatActivity + val popBackAction = remember { mutableStateOf({}) } Scaffold( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), @@ -83,7 +107,7 @@ fun SettingsScreen( title = { Text(text = appBarTitle.value) }, navigationIcon = { IconButton( - onClick = { appNavController.popBackStack() } + onClick = popBackAction.value ) { Icon( imageVector = Icons.Filled.ArrowBack, @@ -91,53 +115,35 @@ fun SettingsScreen( ) } }, - actions = { - IconButton( - onClick = { - restoreAction.value(preferences, settingsViewModel, activity) - } - ) { - Icon( - imageVector = Icons.Filled.SettingsBackupRestore, - contentDescription = stringResource(R.string.preferences_restore_content_description) - ) - } - } +// actions = { +// IconButton( +// onClick = { +// restoreAction.value(preferences, settingsViewModel, activity) +// } +// ) { +// Icon( +// imageVector = Icons.Filled.SettingsBackupRestore, +// contentDescription = stringResource(R.string.preferences_restore_content_description) +// ) +// } +// } ) } ) { innerPadding -> Box(modifier = Modifier.padding(innerPadding)) { - if (route != null) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(all = 24.dp), - verticalArrangement = Arrangement.spacedBy(18.dp) - ) { - SettingsPage.getByRoute(route).apply { - appBarTitle.value = name - restoreAction.value = resetPreferencesHandler - settingsPageRenderer(appNavController, activity) - } - } - } else { - restoreAction.value = ::resetAllPreferences - SettingsTabView( - appNavController = appNavController, - appBarTitle = appBarTitle - ) - } + SettingsNavigationHost( + appNavController = appNavController, + appBarTitle = appBarTitle, + popBackAction = popBackAction + ) } } } @Composable -private fun SettingsTabView( - appNavController: NavController, - appBarTitle: MutableState +fun SettingsHome( + settingsNavController: NavController ) { - appBarTitle.value = stringResource(id = R.string.nav_settings_title) - Column( modifier = Modifier .fillMaxSize() @@ -148,182 +154,163 @@ private fun SettingsTabView( title = stringResource(id = R.string.preference_heading_search), subtitle = stringResource(R.string.preference_subtitle_search), icon = Icons.Filled.Search, - settingsView = SettingsPage.SearchSettings, - appNavController = appNavController + route = SettingsNavItem.Search.route, + settingsNavController = settingsNavController ) TopLevelSettingsCard( title = stringResource(id = R.string.preference_heading_design), subtitle = stringResource(R.string.preference_subtitle_design), icon = Icons.Filled.Palette, - settingsView = SettingsPage.DesignSettings, - appNavController = appNavController + route = SettingsNavItem.Design.route, + settingsNavController = settingsNavController ) TopLevelSettingsCard( title = stringResource(id = R.string.preference_heading_home_screen), subtitle = stringResource(R.string.preference_subtitle_home_screen), icon = Icons.Filled.Home, - settingsView = SettingsPage.HomeScreenSettings, - appNavController = appNavController + route = SettingsNavItem.HomeScreen.route, + settingsNavController = settingsNavController + ) + + TopLevelSettingsCard( + title = stringResource(id = R.string.preference_heading_special_features), + subtitle = stringResource(id = R.string.preference_subtitle_special_features), + icon = Icons.Outlined.Flare, + route = SettingsNavItem.SpecialFeatures.route, + settingsNavController = settingsNavController ) TopLevelSettingsCard( title = stringResource(id = R.string.preferences_debug_title), subtitle = stringResource(R.string.preference_subtitle_debug), icon = Icons.Filled.DeveloperBoard, - settingsView = SettingsPage.DeveloperSettings, - appNavController = appNavController + route = SettingsNavItem.Developer.route, + settingsNavController = settingsNavController ) } } @Composable -private fun TopLevelSettingsCard( - title: String, - subtitle: String? = null, - icon: ImageVector, - settingsView: SettingsPage, - appNavController: NavController -) { - Row( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - .clickable( - onClick = { - appNavController.navigate(AppNavItem.SettingsView.withArgs(settingsView.route)) - } - ) - ) { - Icon( - imageVector = icon, - contentDescription = subtitle, - modifier = Modifier - .align(Alignment.CenterVertically) - .padding(end = 16.dp), - tint = MaterialTheme.colorScheme.primary - ) - Column( - modifier = Modifier - .align(Alignment.CenterVertically) - .weight(1f) - ) { - val titleColor = MaterialTheme.colorScheme.onBackground - val subtitleColor = MaterialTheme.colorScheme.onSurfaceVariant - Text(text = title, style = MaterialTheme.typography.titleLarge, color = titleColor, fontSize = 20.sp) - subtitle?.let { - Text(text = subtitle, style = MaterialTheme.typography.bodyMedium, color = subtitleColor) - } - } - } -} - -@Composable -private fun SearchPreferences() { - val settingsViewModel = koinViewModel() - - SwitchPreference( - titleText = stringResource(R.string.preferences_persistent_search_title), - subtitleText = stringResource(R.string.preferences_persistent_search_subtitle), - checkState = settingsViewModel.showSearchBar.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleShowSearchBar() - } - ) - - SwitchPreference( - titleText = stringResource(R.string.preference_multi_search_title), - subtitleText = stringResource(R.string.preference_multi_search_subtitle), - checkState = settingsViewModel.useMultiSearch.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleMultiSearch() - } - ) -} - -@Composable -private fun DesignPreferences( - appNavController: NavController, - activity: AppCompatActivity -) { +fun SearchPreferences() { val settingsViewModel = viewModel() - TopLevelSettingsCard( - title = stringResource(id = R.string.preference_heading_dark_mode), - subtitle = stringResource(R.string.preference_subtitle_dark_mode), - icon = Icons.Outlined.DarkMode, - settingsView = SettingsPage.DarkModeSettings, - appNavController = appNavController - ) - - SwitchPreference( - titleText = stringResource(R.string.preferences_use_wallpaper_colors_title), - subtitleText = stringResource(R.string.preferences_use_wallpaper_colors_subtitle), - checkState = settingsViewModel.useWallpaperColors.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleUseWallpaperColors() - activity.recreate() - } - ) - - val isSystemColorsSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - if (isSystemColorsSupported) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { SwitchPreference( - titleText = stringResource(id = R.string.preference_system_colors_heading), - subtitleText = stringResource(R.string.preference_system_colors_subtitle), - checkState = settingsViewModel.useSystemColors.collectAsState(), - onCheckedChange = { isChecked -> - settingsViewModel.toggleUseSystemColors() - MonetCompat.useSystemColorsOnAndroid12 = isChecked - MonetCompat.getInstance().updateMonetColors() - }, - enabled = settingsViewModel.useSystemColors.collectAsState().value - ) - } - - SliderPreference( - titleText = stringResource(id = R.string.preference_chroma_factor_heading), - value = settingsViewModel.chromaMultiplier.collectAsState(), - onValueChangeFinished = { value -> - with((value / 50f)) { - settingsViewModel.setChromaMultiplier(value) - MonetCompat.chromaMultiplier = this + titleText = stringResource(R.string.preferences_persistent_search_title), + subtitleText = stringResource(R.string.preferences_persistent_search_subtitle), + checkState = settingsViewModel.showSearchBar.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleShowSearchBar() } - MonetCompat.getInstance().updateMonetColors() - }, - enabled = (if (isSystemColorsSupported) !settingsViewModel.useSystemColors.collectAsState().value else true) - .and(settingsViewModel.useWallpaperColors.collectAsState().value) - ) + ) - val showWallpaperPicker = remember { mutableStateOf(false) } - val wallpaperPickerModifier = - if (isSystemColorsSupported && settingsViewModel.useSystemColors.collectAsState().value && settingsViewModel.useWallpaperColors.collectAsState().value) { - Modifier - } else { - Modifier.clickable { showWallpaperPicker.value = true } - } - Text( - text = stringResource(id = R.string.preference_wallpaper_color_heading), - style = MaterialTheme.typography.titleLarge, - fontSize = 20.sp, - color = if (isSystemColorsSupported && settingsViewModel.useSystemColors.collectAsState().value) {//preferences.useSystemColors) { - MaterialTheme.colorScheme.outline - } else { - MaterialTheme.colorScheme.onBackground - }, - modifier = wallpaperPickerModifier - .padding(start = 8.dp) - ) - if (showWallpaperPicker.value) { - WallpaperPicker(showPopup = showWallpaperPicker) + SwitchPreference( + titleText = stringResource(R.string.preference_multi_search_title), + subtitleText = stringResource(R.string.preference_multi_search_subtitle), + checkState = settingsViewModel.useMultiSearch.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleMultiSearch() + } + ) } } @Composable -private fun DarkModePreferences( - activity: AppCompatActivity +fun DesignPreferences( + settingsNavController: NavController, ) { + val settingsViewModel = viewModel() + val activity = LocalContext.current as Activity + + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + TopLevelSettingsCard( + title = stringResource(id = R.string.preference_heading_dark_mode), + subtitle = stringResource(R.string.preference_subtitle_dark_mode), + icon = Icons.Outlined.DarkMode, + route = SettingsNavItem.DarkMode.route, + settingsNavController = settingsNavController + ) + + SwitchPreference( + titleText = stringResource(R.string.preferences_use_wallpaper_colors_title), + subtitleText = stringResource(R.string.preferences_use_wallpaper_colors_subtitle), + checkState = settingsViewModel.useWallpaperColors.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleUseWallpaperColors() + activity.recreate() + } + ) + + val isSystemColorsSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + if (isSystemColorsSupported) { + SwitchPreference( + titleText = stringResource(id = R.string.preference_system_colors_heading), + subtitleText = stringResource(R.string.preference_system_colors_subtitle), + checkState = settingsViewModel.useSystemColors.collectAsState(), + onCheckedChange = { isChecked -> + settingsViewModel.toggleUseSystemColors() + MonetCompat.useSystemColorsOnAndroid12 = isChecked + MonetCompat.getInstance().updateMonetColors() + }, + enabled = settingsViewModel.useSystemColors.collectAsState().value + ) + } + + SliderPreference( + titleText = stringResource(id = R.string.preference_chroma_factor_heading), + value = settingsViewModel.chromaMultiplier.collectAsState(), + onValueChangeFinished = { value -> + with((value / 50f)) { + settingsViewModel.setChromaMultiplier(value) + MonetCompat.chromaMultiplier = this + } + MonetCompat.getInstance().updateMonetColors() + }, + enabled = (if (isSystemColorsSupported) !settingsViewModel.useSystemColors.collectAsState().value else true) + .and(settingsViewModel.useWallpaperColors.collectAsState().value) + ) + + val showWallpaperPicker = remember { mutableStateOf(false) } + val wallpaperPickerModifier = + if (isSystemColorsSupported && settingsViewModel.useSystemColors.collectAsState().value && settingsViewModel.useWallpaperColors.collectAsState().value) { + Modifier + } else { + Modifier.clickable { showWallpaperPicker.value = true } + } + Text( + text = stringResource(id = R.string.preference_wallpaper_color_heading), + style = MaterialTheme.typography.titleLarge, + fontSize = 20.sp, + color = if (isSystemColorsSupported && settingsViewModel.useSystemColors.collectAsState().value) {//preferences.useSystemColors) { + MaterialTheme.colorScheme.outline + } else { + MaterialTheme.colorScheme.onBackground + }, + modifier = wallpaperPickerModifier + .padding(start = 8.dp) + ) + if (showWallpaperPicker.value) { + WallpaperPicker(showPopup = showWallpaperPicker) + } + } +} + +@Composable +fun DarkModePreferences() { + val activity = LocalContext.current as Activity + val settingsViewModel = viewModel() val isSelected: (Int) -> Boolean = { settingsViewModel.darkTheme.value == it } @@ -332,161 +319,204 @@ private fun DarkModePreferences( activity.recreate() } - PreferenceHeading(text = stringResource(R.string.preference_dark_mode_automatic_heading)) - RadioButtonPreference( - selected = isSelected(AppPreferences.DarkMode.Automatic.ordinal), - title = stringResource(R.string.preference_dark_mode_follow_system_label), - icon = Icons.Filled.Brightness6, - onClick = { - onChangeState(AppPreferences.DarkMode.Automatic.ordinal) - } - ) - - PreferenceHeading(text = stringResource(R.string.preference_dark_mode_maual_heading)) - RadioButtonPreference( - selected = isSelected(AppPreferences.DarkMode.Light.ordinal), - title = stringResource(R.string.preference_dark_mode_light_mode_label), - icon = Icons.Outlined.LightMode, - onClick = { - onChangeState(AppPreferences.DarkMode.Light.ordinal) - } - ) - RadioButtonPreference( - selected = isSelected(AppPreferences.DarkMode.Dark.ordinal), - title = stringResource(R.string.preference_dark_mode_dark_mode_label), - icon = Icons.Outlined.DarkMode, - onClick = { - onChangeState(AppPreferences.DarkMode.Dark.ordinal) - } - ) -} - -@Composable -private fun HomeScreenPreferences() { - val settingsViewModel = viewModel() - - PreferenceHeading(text = stringResource(R.string.preference_look_and_feel_heading)) - - SwitchPreference( - titleText = stringResource(R.string.preference_show_text_labels_title), - subtitleText = stringResource(R.string.preference_show_text_labels_subtitle), - checkState = settingsViewModel.showBottomTabLabels.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleShowBottomTabLabels() - } - ) - - SwitchPreference( - titleText = stringResource(R.string.preference_show_poster_titles_title), - subtitleText = stringResource(R.string.preference_show_poster_titles_subtitle), - checkState = settingsViewModel.showPosterTitles.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleShowPosterTitles() - } - ) - - PreferenceHeading(text = stringResource(R.string.preference_home_tab_order_heading)) - - Box(modifier = Modifier - .border( - width = 1.dp, - color = MaterialTheme.colorScheme.primary, - shape = RoundedCornerShape(10.dp) - ) - .padding(horizontal = 12.dp) + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) ) { - AndroidView( - modifier = Modifier.fillMaxWidth(), - factory = { context -> - RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - val mAdapter = HomeTabRecyclerAdapter() - val touchCallback = ItemMoveCallback(mAdapter) - val touchHelper = ItemTouchHelper(touchCallback) - touchHelper.attachToRecyclerView(this) - adapter = mAdapter - } - }, - update = { } + PreferenceHeading(text = stringResource(R.string.preference_dark_mode_automatic_heading)) + RadioButtonPreference( + selected = isSelected(AppPreferences.DarkMode.Automatic.ordinal), + title = stringResource(R.string.preference_dark_mode_follow_system_label), + icon = Icons.Filled.Brightness6, + onClick = { + onChangeState(AppPreferences.DarkMode.Automatic.ordinal) + } + ) + + PreferenceHeading(text = stringResource(R.string.preference_dark_mode_maual_heading)) + RadioButtonPreference( + selected = isSelected(AppPreferences.DarkMode.Light.ordinal), + title = stringResource(R.string.preference_dark_mode_light_mode_label), + icon = Icons.Outlined.LightMode, + onClick = { + onChangeState(AppPreferences.DarkMode.Light.ordinal) + } + ) + RadioButtonPreference( + selected = isSelected(AppPreferences.DarkMode.Dark.ordinal), + title = stringResource(R.string.preference_dark_mode_dark_mode_label), + icon = Icons.Outlined.DarkMode, + onClick = { + onChangeState(AppPreferences.DarkMode.Dark.ordinal) + } ) } } @Composable -private fun DevPreferences() { +fun HomeScreenPreferences() { + val settingsViewModel = viewModel() + + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + PreferenceHeading(text = stringResource(R.string.preference_look_and_feel_heading)) + + SwitchPreference( + titleText = stringResource(R.string.preference_show_text_labels_title), + subtitleText = stringResource(R.string.preference_show_text_labels_subtitle), + checkState = settingsViewModel.showBottomTabLabels.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleShowBottomTabLabels() + } + ) + + SwitchPreference( + titleText = stringResource(R.string.preference_show_poster_titles_title), + subtitleText = stringResource(R.string.preference_show_poster_titles_subtitle), + checkState = settingsViewModel.showPosterTitles.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleShowPosterTitles() + } + ) + + PreferenceHeading(text = stringResource(R.string.preference_home_tab_order_heading)) + + Box( + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colorScheme.primary, + shape = RoundedCornerShape(10.dp) + ) + .padding(horizontal = 12.dp) + ) { + AndroidView( + modifier = Modifier.fillMaxWidth(), + factory = { context -> + RecyclerView(context).apply { + layoutManager = LinearLayoutManager(context) + val mAdapter = HomeTabRecyclerAdapter() + val touchCallback = ItemMoveCallback(mAdapter) + val touchHelper = ItemTouchHelper(touchCallback) + touchHelper.attachToRecyclerView(this) + adapter = mAdapter + } + }, + update = { } + ) + } + } +} + +@Composable +fun SpecialFeaturePreferences() { + val settingsViewModel = viewModel() + + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + SwitchPreference( + titleText = stringResource(R.string.preferences_show_next_mcu_title), + subtitleText = stringResource(R.string.preferences_show_next_mcu_subtitle), + checkState = settingsViewModel.showNextMcuProduction.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleShowNextMcuProduction() + } + ) + } +} + +@Composable +fun DevPreferences() { if (BuildConfig.DEBUG) { val settingsViewModel = viewModel() val context = LocalContext.current val coroutineScope = rememberCoroutineScope() - SwitchPreference( - titleText = "Show backdrop gallery", - subtitleText = "Show galleries for movies/tv backdrops", - checkState = settingsViewModel.showBackdropGallery.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleShowBackdropGallery() - } - ) - - SwitchPreference( - titleText = "Always show onboarding flow", - subtitleText = "Show onboarding flow on each launch", - checkState = settingsViewModel.firstLaunchTesting.collectAsState(), - onCheckedChange = { - settingsViewModel.toggleFirstLaunchTesting() - } - ) - Text( - text = "Show onboarding UI", - color = MaterialTheme.colorScheme.onBackground, + Column( modifier = Modifier - .padding(horizontal = 8.dp, vertical = 12.dp) - .clickable { - OnboardingActivity.showActivity(context) + .fillMaxSize() + .padding(all = 24.dp), + verticalArrangement = Arrangement.spacedBy(24.dp) + ) { + SwitchPreference( + titleText = "Show backdrop gallery", + subtitleText = "Show galleries for movies/tv backdrops", + checkState = settingsViewModel.showBackdropGallery.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleShowBackdropGallery() } - ) + ) - val shouldShowPalette = remember { mutableStateOf(false) } - Text( - text = "Show material palette", - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier - .padding(horizontal = 8.dp, vertical = 12.dp) - .clickable( - onClick = { - shouldShowPalette.value = true + SwitchPreference( + titleText = "Always show onboarding flow", + subtitleText = "Show onboarding flow on each launch", + checkState = settingsViewModel.firstLaunchTesting.collectAsState(), + onCheckedChange = { + settingsViewModel.toggleFirstLaunchTesting() + } + ) + Text( + text = "Show onboarding UI", + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier + .padding(horizontal = 8.dp, vertical = 12.dp) + .clickable { + OnboardingActivity.showActivity(context) } + ) + + val shouldShowPalette = remember { mutableStateOf(false) } + Text( + text = "Show material palette", + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier + .padding(horizontal = 8.dp, vertical = 12.dp) + .clickable( + onClick = { + shouldShowPalette.value = true + } + ) + ) + if (shouldShowPalette.value) { + AlertDialog( + modifier = Modifier.padding(12.dp), + title = { Text(text = "Palette") }, + text = { PaletteView() }, + dismissButton = { + TextButton(onClick = { shouldShowPalette.value = false }) { + Text("Dismiss") + } + }, + confirmButton = {}, + onDismissRequest = { shouldShowPalette.value = false } ) - ) - if (shouldShowPalette.value) { - AlertDialog( - modifier = Modifier.padding(12.dp), - title = { Text(text = "Palette") }, - text = { PaletteView() }, - dismissButton = { - TextButton(onClick = { shouldShowPalette.value = false }) { - Text("Dismiss") - } - }, - confirmButton = {}, - onDismissRequest = { shouldShowPalette.value = false } + } + + Text( + text = "Clear session", + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier + .padding(horizontal = 8.dp, vertical = 12.dp) + .clickable( + onClick = { + coroutineScope.launch { + SessionManager.clearSession() + } + } + ) ) } - - Text( - text = "Clear session", - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier - .padding(horizontal = 8.dp, vertical = 12.dp) - .clickable( - onClick = { - coroutineScope.launch { - SessionManager.clearSession() - } - } - ) - ) } } @@ -570,151 +600,128 @@ private fun WallpaperPicker( } } -private fun resetAllPreferences( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity +@Composable +private fun TopLevelSettingsCard( + title: String, + subtitle: String? = null, + icon: ImageVector, + route: String, + settingsNavController: NavController ) { - resetSearchPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) - resetDesignPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) - resetHomeScreenPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) - resetDevModePreference(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) - activity.recreate() - Toast.makeText(activity, "All settings reset successfully", Toast.LENGTH_SHORT).show() -} - -private fun resetSearchPreferences( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity, - skipRecreate: Boolean = false -) { - settingsViewModel.setShowSearchBar(preferences.showSearchBarDefault) - settingsViewModel.setMultiSearch(preferences.multiSearchDefault) - if (!skipRecreate) { - activity.recreate() - } -} - -private fun resetDesignPreferences( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity, - skipRecreate: Boolean = false -) { - settingsViewModel.setUseSystemColors(preferences.useSystemColorsDefault) - settingsViewModel.setUseWallpaperColors(preferences.useWallpaperColorsDefault) - settingsViewModel.setChromaMultiplier(preferences.chromaMultiplierDefault) - settingsViewModel.setSelectedColor(preferences.selectedColorDefault) - resetDarkModePreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) - if (!skipRecreate) { - activity.recreate() - } -} - -private fun resetDarkModePreferences( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity, - skipRecreate: Boolean = false -) { - settingsViewModel.setDarkMode(preferences.darkThemeDefault) - if (!skipRecreate) { - activity.recreate() - } -} - -private fun resetDevModePreference( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity, - skipRecreate: Boolean = false -) { - settingsViewModel.setFirstLaunchTesting(preferences.firstLaunchTestingDefault) - settingsViewModel.setShowBackdropGallery(preferences.showBackdropGalleryDefault) - if (!skipRecreate) { - activity.recreate() - } -} - -private fun resetHomeScreenPreferences( - preferences: AppPreferences, - settingsViewModel: SettingsViewModel, - activity: AppCompatActivity, - skipRecreate: Boolean = false -) { - settingsViewModel.setShowBottomTabLabels(preferences.showBottomTabLabelsDefault) - settingsViewModel.setShowPosterTitles(preferences.showPosterTitlesDefault) - preferences.moviesTabPosition = preferences.moviesTabPositionDefault - preferences.tvTabPosition = preferences.tvTabPositionDefault - preferences.peopleTabPosition = preferences.peopleTabPositionDefault - preferences.accountTabPosition = preferences.accountTabPositionDefault - preferences.showBottomTabLabels = preferences.showBottomTabLabelsDefault - if (!skipRecreate) { - activity.recreate() - } -} - -private typealias SettingsResetHandler = (AppPreferences, SettingsViewModel, AppCompatActivity) -> Unit -private typealias SettingsPageRenderer = @Composable (NavController, AppCompatActivity) -> Unit - -private sealed class SettingsPage( - stringRes: Int, - val route: String, - val settingsPageRenderer: SettingsPageRenderer, - val resetPreferencesHandler: SettingsResetHandler -): KoinComponent { - private val resources: ResourceUtils by inject() - - val name = resources.getString(stringRes) - - companion object { - val Pages by lazy { - listOf( - SearchSettings, - DesignSettings, - DeveloperSettings, - DarkModeSettings, - HomeScreenSettings + Row( + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight() + .clickable( + onClick = { + settingsNavController.navigate(route) + } ) - } - - fun getByRoute(route: String): SettingsPage { - return Pages.map { it.route to it } - .find { it.first == route } - ?.second - ?: throw IllegalArgumentException("Invalid settings page route: $route") + ) { + Icon( + imageVector = icon, + contentDescription = subtitle, + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(end = 16.dp), + tint = MaterialTheme.colorScheme.primary + ) + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .weight(1f) + ) { + val titleColor = MaterialTheme.colorScheme.onBackground + val subtitleColor = MaterialTheme.colorScheme.onSurfaceVariant + Text(text = title, style = MaterialTheme.typography.titleLarge, color = titleColor, fontSize = 20.sp) + subtitle?.let { + Text(text = subtitle, style = MaterialTheme.typography.bodyMedium, color = subtitleColor) + } } } - - object SearchSettings: SettingsPage( - R.string.preference_heading_search, - "search", - @Composable { _, _ -> SearchPreferences() }, - ::resetSearchPreferences - ) - object DesignSettings: SettingsPage( - R.string.preference_heading_design, - "design", - @Composable { n, a -> DesignPreferences(n, a) }, - ::resetDesignPreferences - ) - object HomeScreenSettings: SettingsPage( - R.string.preference_heading_home_screen, - "home", - @Composable { _, _ -> HomeScreenPreferences() }, - ::resetHomeScreenPreferences - ) - object DeveloperSettings: SettingsPage( - R.string.preferences_debug_title, - "dev", - @Composable { _, _ -> DevPreferences() }, - ::resetDevModePreference - ) - object DarkModeSettings: SettingsPage( - R.string.preference_heading_dark_mode, - "darkmode", - @Composable { _, a -> DarkModePreferences(a) }, - ::resetDarkModePreferences - ) } + +//private fun resetAllPreferences( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity +//) { +// resetSearchPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) +// resetDesignPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) +// resetHomeScreenPreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) +// resetDevModePreference(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) +// activity.recreate() +// Toast.makeText(activity, "All settings reset successfully", Toast.LENGTH_SHORT).show() +//} +// +//private fun resetSearchPreferences( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity, +// skipRecreate: Boolean = false +//) { +// settingsViewModel.setShowSearchBar(preferences.showSearchBarDefault) +// settingsViewModel.setMultiSearch(preferences.multiSearchDefault) +// if (!skipRecreate) { +// activity.recreate() +// } +//} +// +//private fun resetDesignPreferences( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity, +// skipRecreate: Boolean = false +//) { +// settingsViewModel.setUseSystemColors(preferences.useSystemColorsDefault) +// settingsViewModel.setUseWallpaperColors(preferences.useWallpaperColorsDefault) +// settingsViewModel.setChromaMultiplier(preferences.chromaMultiplierDefault) +// settingsViewModel.setSelectedColor(preferences.selectedColorDefault) +// resetDarkModePreferences(preferences = preferences, settingsViewModel = settingsViewModel, activity = activity, skipRecreate = true) +// if (!skipRecreate) { +// activity.recreate() +// } +//} +// +//private fun resetDarkModePreferences( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity, +// skipRecreate: Boolean = false +//) { +// settingsViewModel.setDarkMode(preferences.darkThemeDefault) +// if (!skipRecreate) { +// activity.recreate() +// } +//} +// +//private fun resetDevModePreference( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity, +// skipRecreate: Boolean = false +//) { +// settingsViewModel.setFirstLaunchTesting(preferences.firstLaunchTestingDefault) +// settingsViewModel.setShowBackdropGallery(preferences.showBackdropGalleryDefault) +// if (!skipRecreate) { +// activity.recreate() +// } +//} +// +//private fun resetHomeScreenPreferences( +// preferences: AppPreferences, +// settingsViewModel: SettingsViewModel, +// activity: AppCompatActivity, +// skipRecreate: Boolean = false +//) { +// settingsViewModel.setShowBottomTabLabels(preferences.showBottomTabLabelsDefault) +// settingsViewModel.setShowPosterTitles(preferences.showPosterTitlesDefault) +// preferences.moviesTabPosition = preferences.moviesTabPositionDefault +// preferences.tvTabPosition = preferences.tvTabPositionDefault +// preferences.peopleTabPosition = preferences.peopleTabPositionDefault +// preferences.accountTabPosition = preferences.accountTabPositionDefault +// preferences.showBottomTabLabels = preferences.showBottomTabLabelsDefault +// if (!skipRecreate) { +// activity.recreate() +// } +//} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SettingsViewModel.kt index 19a1a73..72070c3 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/viewmodel/SettingsViewModel.kt @@ -23,6 +23,7 @@ class SettingsViewModel: ViewModel() { private val _showPosterTitles = MutableStateFlow(preferences.showPosterTitles) private val _firstLaunchTesting = MutableStateFlow(preferences.firstLaunchTesting) private val _showBackdropGallery = MutableStateFlow(preferences.showBackdropGallery) + private val _showNextMcuProduction = MutableStateFlow(preferences.showNextMcuProduction) } val showSearchBar = _showSearchBar.asStateFlow() @@ -36,6 +37,7 @@ class SettingsViewModel: ViewModel() { val showPosterTitles = _showPosterTitles.asStateFlow() val firstLaunchTesting = _firstLaunchTesting.asStateFlow() val showBackdropGallery = _showBackdropGallery.asStateFlow() + val showNextMcuProduction = _showNextMcuProduction.asStateFlow() fun toggleShowSearchBar() { _showSearchBar.value = _showSearchBar.value.not() @@ -132,4 +134,14 @@ class SettingsViewModel: ViewModel() { preferences.showBackdropGallery = value } + fun toggleShowNextMcuProduction() { + _showNextMcuProduction.value = _showNextMcuProduction.value.not() + preferences.showNextMcuProduction = _showNextMcuProduction.value + } + + fun setShowNextMcuProduction(value: Boolean) { + _showNextMcuProduction.value = value + preferences.showNextMcuProduction = value + } + } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e085299..b41c5c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,6 +84,10 @@ Show tab text labels Show text labels for tab items in the bottom tab bar or navigation rail Home Tab Order + Special Features + Extra features and hidden goodies + Show Next MCU Production + Show a card with information on the next scheduled MCU production when viewing details for an MCU release Clips