From b74e33e73700bf04aa30c7a5ec58deaa2ebd84eb Mon Sep 17 00:00:00 2001 From: kareem esam Date: Mon, 23 Jun 2025 01:14:50 +0300 Subject: [PATCH 1/4] feat: add MainViewModel and MainState for managing app theme and onboarding state --- .../washingtondcsquad/tudee/MainActivity.kt | 15 ++---- .../com/washingtondcsquad/tudee/MainState.kt | 6 +++ .../washingtondcsquad/tudee/MainViewModel.kt | 54 +++++++++++++++++++ .../tudee/di/viewModelModule.kt | 10 ++-- 4 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/washingtondcsquad/tudee/MainState.kt create mode 100644 app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt index bdcd9002..c08abd29 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt @@ -33,8 +33,6 @@ import androidx.navigation.compose.rememberNavController import com.washingtondcsquad.tudee.data.localSource.TudeeDataBase import com.washingtondcsquad.tudee.data.localSource.mapper.toEntity import com.washingtondcsquad.tudee.domain.entity.Category -import com.washingtondcsquad.tudee.domain.services.AppPreferencesService -import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesScreen import com.washingtondcsquad.tudee.presentation.components.SnackBarCard import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.TudeeNavigationBar import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.bottomNavBarRoutes @@ -42,6 +40,7 @@ import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.navBar import com.washingtondcsquad.tudee.presentation.components.snack_bar.ObserveAsEvent import com.washingtondcsquad.tudee.presentation.components.snack_bar.SnackbarController import com.washingtondcsquad.tudee.presentation.design.AppTheme +import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesScreen import com.washingtondcsquad.tudee.presentation.features.home.HomeScreen import com.washingtondcsquad.tudee.presentation.features.onBoarding.OnBoardingScreen import com.washingtondcsquad.tudee.presentation.features.tasks_screen.TasksScreen @@ -52,23 +51,19 @@ import org.koin.android.ext.android.inject @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") class MainActivity : ComponentActivity() { - private val appPreferencesService: AppPreferencesService by inject() - + private val mainViewModel: MainViewModel by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { - val isDarkMode by appPreferencesService.isDarkModeEnabled() - .collectAsState(initial = false) - val isOnboardingShownFlow = appPreferencesService.hasOnboardingBeenShown() - val isOnboardingShownState by isOnboardingShownFlow.collectAsState(initial = null) + val mainState by mainViewModel.state.collectAsState() AppTheme( - useDarkTheme = isDarkMode + useDarkTheme = mainState.isDarkTheme ) { - when (val isOnboardingShown = isOnboardingShownState) { + when (val isOnboardingShown = mainState.hasOnBoardingShown) { null -> { Box( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt new file mode 100644 index 00000000..cf2c53a1 --- /dev/null +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt @@ -0,0 +1,6 @@ +package com.washingtondcsquad.tudee + +data class MainState( + val isDarkTheme: Boolean = false, + val hasOnBoardingShown: Boolean? = null, +) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt new file mode 100644 index 00000000..b1789569 --- /dev/null +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt @@ -0,0 +1,54 @@ +package com.washingtondcsquad.tudee + +import androidx.lifecycle.viewModelScope +import com.washingtondcsquad.tudee.domain.services.AppPreferencesService +import com.washingtondcsquad.tudee.presentation.base.BaseViewModel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +class MainViewModel( + private val appPreferencesService: AppPreferencesService +) : BaseViewModel(MainState()) { + + init { + getIsDarkTheme() + getOnBoardingState() + } + + private fun getIsDarkTheme() { + tryToExecute( + request = { + appPreferencesService.isDarkModeEnabled() + }, + onSuccess = ::onDarkThemeEnabled, + onError = {} + ) + } + + private fun onDarkThemeEnabled(isDarkThemeEnabled: Flow) = viewModelScope.launch { + isDarkThemeEnabled.collectLatest { + updateState { + copy(isDarkTheme = it) + } + } + } + + private fun getOnBoardingState() { + tryToExecute( + request = { + appPreferencesService.hasOnboardingBeenShown() + }, + onSuccess = ::onOnBoardingState, + onError = {} + ) + } + + private fun onOnBoardingState(hasOnboardingBeenShown: Flow) = viewModelScope.launch { + hasOnboardingBeenShown.collectLatest { + updateState { + copy(hasOnBoardingShown = it) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt b/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt index 72d8a5bb..68ba2db1 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt @@ -1,16 +1,17 @@ package com.washingtondcsquad.tudee.di +import com.washingtondcsquad.tudee.MainViewModel +import com.washingtondcsquad.tudee.presentation.features.add_task.AddTaskViewModel +import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesViewModel import com.washingtondcsquad.tudee.presentation.features.home.HomeViewModel -import com.washingtondcsquad.tudee.presentation.features.task_details.BottomSheetTaskViewModel import com.washingtondcsquad.tudee.presentation.features.onBoarding.OnboardingViewModel -import com.washingtondcsquad.tudee.presentation.features.add_task.AddTaskViewModel -import com.washingtondcsquad.tudee.presentation.screens.add_task.EditTaskViewModel +import com.washingtondcsquad.tudee.presentation.features.task_details.BottomSheetTaskViewModel import com.washingtondcsquad.tudee.presentation.features.tasks_screen.TasksViewModel +import com.washingtondcsquad.tudee.presentation.screens.add_task.EditTaskViewModel import org.koin.core.module.dsl.viewModel import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import java.time.LocalDate -import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesViewModel val viewModelModule = module { @@ -21,6 +22,7 @@ val viewModelModule = module { get(), get() ) } + viewModelOf(::MainViewModel) viewModel { BottomSheetTaskViewModel(get()) } viewModel { (taskDate: LocalDate, onCancel: () -> Unit, onActionResult: (success: Boolean, message: String) -> Unit) -> AddTaskViewModel( From 6c8e5fd4aef3382ea3f5bc673435427f7d9e7c87 Mon Sep 17 00:00:00 2001 From: kareem esam Date: Tue, 24 Jun 2025 01:36:34 +0300 Subject: [PATCH 2/4] feat: add locale management to AppPreferencesService and MainViewModel --- .../washingtondcsquad/tudee/MainActivity.kt | 72 ++++--------------- .../com/washingtondcsquad/tudee/MainState.kt | 3 + .../washingtondcsquad/tudee/MainViewModel.kt | 18 +++++ .../services/AppPreferencesServiceImpl.kt | 20 ++++++ .../domain/services/AppPreferencesService.kt | 2 + .../tudee/presentation/utils/SnackBar.kt | 61 ++++++++++++++++ 6 files changed, 116 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/com/washingtondcsquad/tudee/presentation/utils/SnackBar.kt diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt index 9130db59..50c3203b 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt @@ -6,6 +6,7 @@ import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatDelegate import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -14,38 +15,24 @@ import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.BottomAppBarDefaults.windowInsets import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarDuration -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp +import androidx.core.os.LocaleListCompat import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.washingtondcsquad.tudee.data.localSource.TudeeDataBase -import com.washingtondcsquad.tudee.domain.entity.Category -import com.washingtondcsquad.tudee.presentation.components.SnackBarCard import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.TudeeNavigationBar import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.bottomNavBarRoutes import com.washingtondcsquad.tudee.presentation.components.bottom_nav_bar.navBarItemsList -import com.washingtondcsquad.tudee.presentation.components.snack_bar.ObserveAsEvent -import com.washingtondcsquad.tudee.presentation.components.snack_bar.SnackbarController import com.washingtondcsquad.tudee.presentation.design.AppTheme import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesScreen import com.washingtondcsquad.tudee.presentation.features.home.HomeScreen import com.washingtondcsquad.tudee.presentation.features.onBoarding.OnBoardingScreen import com.washingtondcsquad.tudee.presentation.features.tasks_screen.TasksScreen -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch +import com.washingtondcsquad.tudee.presentation.utils.SnackBarHandler import org.koin.android.ext.android.inject @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @@ -59,6 +46,7 @@ class MainActivity : ComponentActivity() { setContent { val mainState by mainViewModel.state.collectAsState() + updateAppLocale(mainState) AppTheme( useDarkTheme = mainState.isDarkTheme ) { @@ -76,7 +64,7 @@ class MainActivity : ComponentActivity() { "home" } else { Log.d("sdasdsad", "onCreate: ") - /// createPreDefineCategories() + /// createPreDefineCategories() "onboarding" } val navController = rememberNavController() @@ -122,7 +110,7 @@ class MainActivity : ComponentActivity() { } } } - SnackbarHandler() + SnackBarHandler() } } // @@ -155,49 +143,13 @@ class MainActivity : ComponentActivity() { // } // } // } -} - - -@Composable -fun SnackbarHandler() { - val snackbarHostState = remember { SnackbarHostState() } - val coroutineScope = rememberCoroutineScope() - ObserveAsEvent( - flow = SnackbarController.event, - onEvent = { event -> - coroutineScope.launch { - snackbarHostState.currentSnackbarData?.dismiss() - snackbarHostState.showSnackbar( - message = event.message, - duration = SnackbarDuration.Short - ) - } - } - ) - - SnackbarHost( - hostState = snackbarHostState, - snackbar = { snackbarData -> - val (iconRes, iconTint) = when { - snackbarData.visuals.message.contains("success", ignoreCase = true) -> - Pair(R.drawable.checkmark, AppTheme.colors.greenAccent) - snackbarData.visuals.message.contains("error", ignoreCase = true) -> - Pair(R.drawable.checkmark, AppTheme.colors.error) - - else -> - Pair(R.drawable.information_diamond, AppTheme.colors.error) - } + private fun updateAppLocale(state: MainState) { + AppCompatDelegate.setApplicationLocales( + LocaleListCompat.forLanguageTags(state.currentAppLocale.toLanguageTag()) + ) + } +} - SnackBarCard( - message = snackbarData.visuals.message, - icon = painterResource(id = iconRes), - iconTint = iconTint, - iconBackgroundColor = AppTheme.colors.surface, - modifier = Modifier.padding(horizontal = 8.dp, vertical = 48.dp) - ) - } - ) -} diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt index cf2c53a1..9ffeba5a 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt @@ -1,6 +1,9 @@ package com.washingtondcsquad.tudee +import java.util.Locale + data class MainState( val isDarkTheme: Boolean = false, val hasOnBoardingShown: Boolean? = null, + val currentAppLocale: Locale = Locale.ENGLISH ) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt index b1789569..0165351c 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt @@ -6,6 +6,7 @@ import com.washingtondcsquad.tudee.presentation.base.BaseViewModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import java.util.Locale class MainViewModel( private val appPreferencesService: AppPreferencesService @@ -14,6 +15,7 @@ class MainViewModel( init { getIsDarkTheme() getOnBoardingState() + getAppLocale() } private fun getIsDarkTheme() { @@ -51,4 +53,20 @@ class MainViewModel( } } } + + private fun getAppLocale() { + tryToCollect( + request = { + appPreferencesService.getCurrentLocale() + }, + onChange = ::onAppLanguageChanged, + onError = {}, + ) + } + + private fun onAppLanguageChanged(newLocale: Locale) { + updateState { + copy(currentAppLocale = newLocale) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/washingtondcsquad/tudee/data/services/AppPreferencesServiceImpl.kt b/app/src/main/java/com/washingtondcsquad/tudee/data/services/AppPreferencesServiceImpl.kt index f73caf73..d7bf90bc 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/data/services/AppPreferencesServiceImpl.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/data/services/AppPreferencesServiceImpl.kt @@ -1,17 +1,37 @@ package com.washingtondcsquad.tudee.data.services +import androidx.appcompat.app.AppCompatDelegate import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import com.washingtondcsquad.tudee.domain.services.AppPreferencesService import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map +import java.util.Locale class AppPreferencesServiceImpl( private val dataStore: DataStore ) : AppPreferencesService { + private val _currentLocale = MutableStateFlow(getCurrentAppLocale()) + val currentLocale: Flow = _currentLocale.asStateFlow() + + override suspend fun getCurrentLocale(): Flow = currentLocale.distinctUntilChanged() + + + private fun getCurrentAppLocale(): Locale { + val androidLocale = AppCompatDelegate.getApplicationLocales()[0] + ?: Locale.getDefault() + return Locale.Builder() + .setLocale(androidLocale) + .setLanguage(androidLocale.language) + .build() + } + companion object PreferencesKeys { val HAS_ONBOARDING_BEEN_SHOWN = booleanPreferencesKey("has_onboarding_been_shown") val DARK_MODE_ENABLED = booleanPreferencesKey("dark_mode_enabled") diff --git a/app/src/main/java/com/washingtondcsquad/tudee/domain/services/AppPreferencesService.kt b/app/src/main/java/com/washingtondcsquad/tudee/domain/services/AppPreferencesService.kt index 41f74682..8fece7c7 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/domain/services/AppPreferencesService.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/domain/services/AppPreferencesService.kt @@ -1,8 +1,10 @@ package com.washingtondcsquad.tudee.domain.services import kotlinx.coroutines.flow.Flow +import java.util.Locale interface AppPreferencesService { + suspend fun getCurrentLocale(): Flow fun hasOnboardingBeenShown(): Flow suspend fun setOnboardingShown() fun isDarkModeEnabled(): Flow diff --git a/app/src/main/java/com/washingtondcsquad/tudee/presentation/utils/SnackBar.kt b/app/src/main/java/com/washingtondcsquad/tudee/presentation/utils/SnackBar.kt new file mode 100644 index 00000000..463817db --- /dev/null +++ b/app/src/main/java/com/washingtondcsquad/tudee/presentation/utils/SnackBar.kt @@ -0,0 +1,61 @@ +package com.washingtondcsquad.tudee.presentation.utils + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.washingtondcsquad.tudee.R +import com.washingtondcsquad.tudee.presentation.components.SnackBarCard +import com.washingtondcsquad.tudee.presentation.components.snack_bar.ObserveAsEvent +import com.washingtondcsquad.tudee.presentation.components.snack_bar.SnackbarController +import com.washingtondcsquad.tudee.presentation.design.AppTheme +import kotlinx.coroutines.launch + +@Composable +fun SnackBarHandler() { + val snackBarHostState = remember { SnackbarHostState() } + val coroutineScope = rememberCoroutineScope() + ObserveAsEvent( + flow = SnackbarController.event, + onEvent = { event -> + coroutineScope.launch { + snackBarHostState.currentSnackbarData?.dismiss() + snackBarHostState.showSnackbar( + message = event.message, + duration = SnackbarDuration.Short + ) + } + } + ) + + SnackbarHost( + hostState = snackBarHostState, + snackbar = { snackbarData -> + val (iconRes, iconTint) = when { + snackbarData.visuals.message.contains("success", ignoreCase = true) -> + Pair(R.drawable.checkmark, AppTheme.colors.greenAccent) + + snackbarData.visuals.message.contains("error", ignoreCase = true) -> + Pair(R.drawable.checkmark, AppTheme.colors.error) + + else -> + Pair(R.drawable.information_diamond, AppTheme.colors.error) + } + + SnackBarCard( + message = snackbarData.visuals.message, + icon = painterResource(id = iconRes), + iconTint = iconTint, + iconBackgroundColor = AppTheme.colors.surface, + modifier = Modifier.padding(horizontal = 8.dp, vertical = 48.dp) + ) + + } + ) +} From e32552a8cf2962f80ab7e1b60de3c442d5169c9f Mon Sep 17 00:00:00 2001 From: kareem esam Date: Tue, 24 Jun 2025 01:40:07 +0300 Subject: [PATCH 3/4] refactor: clean up viewModelModule.kt imports and formatting --- .../tudee/di/viewModelModule.kt | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt b/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt index ce613786..8f1300f8 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/di/viewModelModule.kt @@ -3,28 +3,27 @@ package com.washingtondcsquad.tudee.di import com.washingtondcsquad.tudee.MainViewModel import com.washingtondcsquad.tudee.presentation.features.add_task.AddTaskViewModel import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesViewModel +import com.washingtondcsquad.tudee.presentation.features.edit_task.EditTaskViewModel import com.washingtondcsquad.tudee.presentation.features.home.HomeViewModel -import com.washingtondcsquad.tudee.presentation.features.task_details.BottomSheetTaskViewModel import com.washingtondcsquad.tudee.presentation.features.onBoarding.OnboardingViewModel -import com.washingtondcsquad.tudee.presentation.features.add_task.AddTaskViewModel -import com.washingtondcsquad.tudee.presentation.features.edit_task.EditTaskViewModel +import com.washingtondcsquad.tudee.presentation.features.task_details.BottomSheetTaskViewModel import com.washingtondcsquad.tudee.presentation.features.tasks_screen.TasksViewModel -import com.washingtondcsquad.tudee.presentation.screens.add_task.EditTaskViewModel import org.koin.core.module.dsl.viewModel import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module import java.time.LocalDate -import com.washingtondcsquad.tudee.presentation.features.categories.CategoriesViewModel val viewModelModule = module { viewModelOf(::CategoriesViewModel) viewModelOf(::OnboardingViewModel) viewModelOf(::HomeViewModel) - viewModel{ TasksViewModel( - get(), - get() - ) } + viewModel { + TasksViewModel( + get(), + get() + ) + } viewModelOf(::MainViewModel) viewModel { BottomSheetTaskViewModel(get()) } viewModel { (taskDate: LocalDate, onCancel: () -> Unit, onActionResult: (success: Boolean, message: String) -> Unit) -> @@ -37,7 +36,7 @@ val viewModelModule = module { ) } - viewModel { (taskId:Int , onCancel: () -> Unit , onActionResult: (success: Boolean, message: String) -> Unit) -> + viewModel { (taskId: Int, onCancel: () -> Unit, onActionResult: (success: Boolean, message: String) -> Unit) -> EditTaskViewModel( tasksService = get(), categoryService = get(), From b7054c4d944011397e18851fbc0d94bf05640e83 Mon Sep 17 00:00:00 2001 From: kareem esam Date: Wed, 25 Jun 2025 01:48:18 +0300 Subject: [PATCH 4/4] refactor: rename MainState to MainActivityUiState and update onboarding logic and initial value --- .../washingtondcsquad/tudee/MainActivity.kt | 100 ++++++++---------- .../{MainState.kt => MainActivityUiState.kt} | 4 +- .../washingtondcsquad/tudee/MainViewModel.kt | 2 +- 3 files changed, 45 insertions(+), 61 deletions(-) rename app/src/main/java/com/washingtondcsquad/tudee/{MainState.kt => MainActivityUiState.kt} (66%) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt index 50c3203b..0cc29949 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainActivity.kt @@ -8,16 +8,12 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatDelegate import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.material3.BottomAppBarDefaults.windowInsets -import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Scaffold import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.core.os.LocaleListCompat import androidx.navigation.compose.NavHost @@ -50,62 +46,50 @@ class MainActivity : ComponentActivity() { AppTheme( useDarkTheme = mainState.isDarkTheme ) { - when (val isOnboardingShown = mainState.hasOnBoardingShown) { - null -> { - Box( - modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } - } + val isOnboardingShown = mainState.hasOnBoardingShown + val startDestination = if (isOnboardingShown) { + "home" + } else { + Log.d("sdasdsad", "onCreate: ") + "onboarding" + } + val navController = rememberNavController() + val navBackStackEntry = navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry.value?.destination?.route - else -> { - val startDestination = if (isOnboardingShown) { - "home" - } else { - Log.d("sdasdsad", "onCreate: ") - /// createPreDefineCategories() - "onboarding" + Scaffold( + bottomBar = { + AnimatedVisibility(currentDestination in bottomNavBarRoutes) { + TudeeNavigationBar( + navBarItemDataList = navBarItemsList, + navController = navController, + modifier = Modifier.windowInsetsPadding(windowInsets) + ) } - val navController = rememberNavController() - val navBackStackEntry = navController.currentBackStackEntryAsState() - val currentDestination = navBackStackEntry.value?.destination?.route - - Scaffold( - bottomBar = { - AnimatedVisibility(currentDestination in bottomNavBarRoutes) { - TudeeNavigationBar( - navBarItemDataList = navBarItemsList, - navController = navController, - modifier = Modifier.windowInsetsPadding(windowInsets) - ) - } - }) { innerPadding -> - NavHost( - navController = navController, - startDestination = startDestination, - modifier = Modifier.padding(innerPadding) - ) { - composable(route = "onboarding") { - OnBoardingScreen( - onFinish = { - navController.navigate("home") { - popUpTo("onboarding") { inclusive = true } - } - }, - ) - } - composable(route = "home") { - HomeScreen() - } - composable(route = "task") { - TasksScreen() - } - composable(route = "category") { - CategoriesScreen() - } - } + }) { innerPadding -> + NavHost( + navController = navController, + startDestination = startDestination, + modifier = Modifier.padding(innerPadding) + ) { + composable(route = "onboarding") { + OnBoardingScreen( + onFinish = { + navController.navigate("home") { + popUpTo("onboarding") { inclusive = true } + } + }, + ) + } + composable(route = "home") { + HomeScreen() + } + composable(route = "task") { + TasksScreen() + } + composable(route = "category") { + CategoriesScreen() } } } @@ -144,7 +128,7 @@ class MainActivity : ComponentActivity() { // } // } - private fun updateAppLocale(state: MainState) { + private fun updateAppLocale(state: MainActivityUiState) { AppCompatDelegate.setApplicationLocales( LocaleListCompat.forLanguageTags(state.currentAppLocale.toLanguageTag()) ) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainActivityUiState.kt similarity index 66% rename from app/src/main/java/com/washingtondcsquad/tudee/MainState.kt rename to app/src/main/java/com/washingtondcsquad/tudee/MainActivityUiState.kt index 9ffeba5a..2ef04699 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainState.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainActivityUiState.kt @@ -2,8 +2,8 @@ package com.washingtondcsquad.tudee import java.util.Locale -data class MainState( +data class MainActivityUiState( val isDarkTheme: Boolean = false, - val hasOnBoardingShown: Boolean? = null, + val hasOnBoardingShown: Boolean = false, val currentAppLocale: Locale = Locale.ENGLISH ) diff --git a/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt index 0165351c..9d83cd0a 100644 --- a/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt +++ b/app/src/main/java/com/washingtondcsquad/tudee/MainViewModel.kt @@ -10,7 +10,7 @@ import java.util.Locale class MainViewModel( private val appPreferencesService: AppPreferencesService -) : BaseViewModel(MainState()) { +) : BaseViewModel(MainActivityUiState()) { init { getIsDarkTheme()