From f934ac6bfbaa19029441f82eabe31af04633ee9d Mon Sep 17 00:00:00 2001 From: Vincent TE Date: Mon, 26 Aug 2024 17:11:27 +0200 Subject: [PATCH] Add base realm use for app settings theme --- app/build.gradle.kts | 5 ++ .../swisstransfer/di/ApplicationModule.kt | 17 +++-- .../swisstransfer/ui/MainActivity.kt | 8 +++ .../ui/screen/main/settings/SettingsScreen.kt | 63 ++++++++++++++++--- .../main/settings/SettingsThemeScreen.kt | 13 ++-- .../screen/main/settings/SettingsViewModel.kt | 44 +++++++++++++ gradle/libs.versions.toml | 2 + settings.gradle.kts | 2 + 8 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9b2abe0702..21dc3836ae 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,11 @@ dependencies { implementation(libs.androidx.adaptive.layout) implementation(libs.androidx.adaptive.navigation) + //SwissTransfer Libraries + implementation("com.github.infomaniak.multiplatform_swisstransfer:STCore:0.0.4-vte") + implementation("com.github.infomaniak.multiplatform_swisstransfer:STCommon:0.0.4-vte") + implementation("com.github.infomaniak.multiplatform_swisstransfer:STDatabase:0.0.4-vte") + // Compose preview tools implementation(libs.compose.ui.tooling.preview) debugImplementation(libs.compose.ui.tooling) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/di/ApplicationModule.kt b/app/src/main/java/com/infomaniak/swisstransfer/di/ApplicationModule.kt index 046c0eb13d..3b4ff9f233 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/di/ApplicationModule.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/di/ApplicationModule.kt @@ -18,11 +18,18 @@ package com.infomaniak.swisstransfer.di +import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) object ApplicationModule { -// @Provides -// @Singleton -// fun providesSwissTransferInjection() { -// // TODO: Implement this method -// } + @Provides + @Singleton + fun providesSwissTransferInjection() = SwissTransferInjection() } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/MainActivity.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/MainActivity.kt index f15d3f41ee..1197f65439 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/MainActivity.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/MainActivity.kt @@ -22,15 +22,23 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.lifecycle.lifecycleScope +import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection import com.infomaniak.swisstransfer.ui.screen.main.MainScreen import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch +import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { + @Inject + lateinit var swissTransferInjection: SwissTransferInjection + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + lifecycleScope.launch { swissTransferInjection.loadDefaultAccount() } enableEdgeToEdge() setContent { SwissTransferTheme { diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreen.kt index 04e8dda81d..12451fd436 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreen.kt @@ -24,6 +24,7 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.provider.Settings +import android.util.Log import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize @@ -46,8 +47,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.stringResource +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavHostController +import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection +import com.infomaniak.multiplatform_swisstransfer.common.models.Theme +import com.infomaniak.multiplatform_swisstransfer.database.models.setting.Language import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.components.BrandTobAppBar import com.infomaniak.swisstransfer.ui.components.TwoPaneScaffold @@ -69,8 +76,10 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewTablet fun SettingsScreenWrapper( navController: NavHostController? = null, windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), - isBarNavigation: Boolean = false + isBarNavigation: Boolean = false, + settingsViewModel: SettingsViewModel = hiltViewModel() ) { + val appSettings by settingsViewModel.appSettingsFlow.collectAsStateWithLifecycle(null) val context = LocalContext.current val aboutURL = stringResource(R.string.urlAbout) val userReportURL = stringResource(R.string.urlUserReportAndroid) @@ -91,6 +100,7 @@ fun SettingsScreenWrapper( } }, getSelectedSetting = { currentDestination?.content }, + appSettings?.theme ) }, detailPane = { @@ -108,7 +118,10 @@ fun SettingsScreenWrapper( } when (destination) { - THEME -> SettingsThemeScreen(navigateBack) + THEME -> SettingsThemeScreen(appSettings?.theme ?: Theme.SYSTEM, navigateBack) { + Log.i("vincent", "click with $appSettings") + settingsViewModel.setTheme(it) + } VALIDITY_PERIOD -> SettingsValidityPeriodScreen(navigateBack) DOWNLOAD_LIMIT -> SettingsDownloadsLimitScreen(navigateBack) EMAIL_LANGUAGE -> SettingsEmailLanguageScreen(navigateBack) @@ -160,7 +173,36 @@ fun openAppNotificationSettings(context: Context) { } @Composable -private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedSetting: () -> SettingsOptionScreens?) { +private fun Theme.getString(): String { + return when (this) { + Theme.SYSTEM -> stringResource(R.string.settingsOptionThemeSystem) + Theme.DARK -> stringResource(R.string.settingsOptionThemeDark) + Theme.LIGHT -> stringResource(R.string.settingsOptionThemeLight) + } +} + +@Composable +private fun getValidityPeriodString(validityPeriod: Int): String { + return pluralStringResource(R.plurals.settingsValidityPeriodValue, validityPeriod, validityPeriod) +} + +@Composable +private fun Language.getEmailLanguageString(): String { + return when (this) { + Language.ENGLISH -> stringResource(R.string.settingsEmailLanguageValueEnglish) + Language.FRENCH -> stringResource(R.string.settingsEmailLanguageValueFrench) + Language.GERMAN -> stringResource(R.string.settingsEmailLanguageValueGerman) + Language.ITALIAN -> stringResource(R.string.settingsEmailLanguageValueItalian) + Language.SPANISH -> stringResource(R.string.settingsEmailLanguageValueSpanish) + } +} + +@Composable +private fun SettingsScreen( + onItemClick: (SettingsOptionScreens) -> Unit, + getSelectedSetting: () -> SettingsOptionScreens?, + theme: Theme? +) { val selectedSetting = getSelectedSetting() Column( @@ -168,7 +210,6 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele .verticalScroll(rememberScrollState()) .selectableGroup(), ) { - BrandTobAppBar() Text( @@ -182,7 +223,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele titleRes = R.string.settingsOptionTheme, isSelected = { selectedSetting == THEME }, icon = AppIcons.PaintbrushPalette, - description = "TODO", + description = theme?.getString(), CHEVRON ) { onItemClick(THEME) @@ -204,7 +245,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele titleRes = R.string.settingsOptionValidityPeriod, isSelected = { selectedSetting == VALIDITY_PERIOD }, icon = AppIcons.FileBadgeArrowDown, - description = "TODO", + description = /*getValidityPeriodString(validityPeriod)*/"", endIcon = CHEVRON, ) { onItemClick(VALIDITY_PERIOD) @@ -213,7 +254,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele titleRes = R.string.settingsOptionDownloadLimit, isSelected = { selectedSetting == DOWNLOAD_LIMIT }, icon = AppIcons.Clock, - description = "TODO", + description = /*downloadLimit.toString()*/"", endIcon = CHEVRON, ) { onItemClick(DOWNLOAD_LIMIT) @@ -222,7 +263,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele titleRes = R.string.settingsOptionEmailLanguage, isSelected = { selectedSetting == EMAIL_LANGUAGE }, icon = AppIcons.SpeechBubble, - description = "TODO", + description = /*emailLanguage.getEmailLanguageString()*/"", endIcon = CHEVRON, ) { onItemClick(EMAIL_LANGUAGE) @@ -231,7 +272,11 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingDivider() SettingTitle(R.string.settingsCategoryAbout) - SettingItem(R.string.settingsOptionDiscoverInfomaniak, { selectedSetting == DISCOVER_INFOMANIAK }, endIcon = OPEN_OUTSIDE) { + SettingItem( + R.string.settingsOptionDiscoverInfomaniak, + { selectedSetting == DISCOVER_INFOMANIAK }, + endIcon = OPEN_OUTSIDE + ) { onItemClick(DISCOVER_INFOMANIAK) } SettingItem(R.string.settingsOptionShareIdeas, { selectedSetting == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt index cb82b77349..294028b63c 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource +import com.infomaniak.multiplatform_swisstransfer.common.models.Theme import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar import com.infomaniak.swisstransfer.ui.components.TopAppBarButton @@ -45,14 +46,18 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewMobile import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable -fun SettingsThemeScreen(navigateBack: () -> Unit) { +fun SettingsThemeScreen(theme: Theme, navigateBack: () -> Unit, onThemeUpdate: (Theme) -> Unit) { Column(modifier = Modifier.verticalScroll(rememberScrollState())) { SwissTransferTobAppBar(R.string.settingsOptionTheme, navigationMenu = TopAppBarButton.backButton(navigateBack)) SettingTitle(titleRes = R.string.settingsThemeTitle) - var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - SingleSelectOptions(ThemeOption.entries, { selectedItem }, { selectedItem = it }) + var selectedItem by rememberSaveable { mutableIntStateOf(theme.indexOf()) } + SingleSelectOptions(ThemeOption.entries, { selectedItem }, { + selectedItem = it + val selectedTheme = Theme.entries[it] + onThemeUpdate(selectedTheme) + }) } } @@ -72,7 +77,7 @@ enum class ThemeOption( private fun SettingsThemeScreenPreview() { SwissTransferTheme { Surface { - SettingsThemeScreen {} + SettingsThemeScreen(Theme.SYSTEM, {}, {}) } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt new file mode 100644 index 0000000000..83e24615e3 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsViewModel.kt @@ -0,0 +1,44 @@ +/* + * Infomaniak SwissTransfer - Android + * Copyright (C) 2024 Infomaniak Network SA + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.infomaniak.swisstransfer.ui.screen.main.settings + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.infomaniak.multiplatform_swisstransfer.SwissTransferInjection +import com.infomaniak.multiplatform_swisstransfer.common.models.Theme +import com.infomaniak.swisstransfer.di.IoDispatcher +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SettingsViewModel @Inject constructor( + private val swissTransferInjection: SwissTransferInjection, + @IoDispatcher private val ioDispatcher: CoroutineDispatcher, +) : ViewModel() { + private val appSettingsManager + inline get() = swissTransferInjection.appSettingsManager + + val appSettingsFlow = appSettingsManager.appSettings + + fun setTheme(theme: Theme) = viewModelScope.launch(ioDispatcher) { + appSettingsManager.setTheme(theme) + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 545482f800..81e5e775f5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,7 @@ lifecycleRuntimeKtx = "2.8.4" material3Beta = "1.3.0-rc01" navigation = "2.8.0-rc01" serialization = "1.7.1" +database = "a5b5f3e8e6" [libraries] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } @@ -21,6 +22,7 @@ androidx-adaptive = { module = "androidx.compose.material3.adaptive:adaptive", v androidx-adaptive-layout = { module = "androidx.compose.material3.adaptive:adaptive-layout", version.ref = "adaptiveLayout" } androidx-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "adaptiveLayout" } androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "constraintlayoutCompose" } +swisstransfer-database = { module = "com.github.Infomaniak.multiplatform-SwissTransfer:STDatabase", version.ref = "database" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 90211f2156..34d89f9e73 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,7 +17,9 @@ dependencyResolutionManagement { @Suppress("UnstableApiUsage") repositories { google() + mavenLocal() mavenCentral() + maven { url = uri("https://jitpack.io") } } }