diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9b2abe070..d336e429b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -34,6 +34,11 @@ android { proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } + + buildFeatures { + buildConfig = true + } + compileOptions { sourceCompatibility = javaVersion targetCompatibility = javaVersion diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/TwoPaneScaffold.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/TwoPaneScaffold.kt index a7ec7dd95..c69719e60 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/TwoPaneScaffold.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/TwoPaneScaffold.kt @@ -28,6 +28,7 @@ import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import androidx.window.core.layout.WindowHeightSizeClass /** @@ -58,7 +59,10 @@ fun TwoPaneScaffold( else -> paneScaffoldDirective.maxHorizontalPartitions } val navigator = rememberListDetailPaneScaffoldNavigator( - scaffoldDirective = paneScaffoldDirective.copy(maxHorizontalPartitions) + scaffoldDirective = paneScaffoldDirective.copy( + maxHorizontalPartitions = maxHorizontalPartitions, + horizontalPartitionSpacerSize = 0.dp + ) ) BackHandler(navigator.canNavigateBack()) { diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainNavHost.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainNavHost.kt index 1313e6d2f..c8f4c4a86 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainNavHost.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/MainNavHost.kt @@ -22,10 +22,8 @@ import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.material3.adaptive.WindowAdaptiveInfo import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -46,7 +44,6 @@ fun MainNavHost( NavHost( navController = navController, startDestination = MainNavigation.startDestination, - modifier = Modifier.safeDrawingPadding(), enterTransition = { if (currentDestination.enableTransition) fadeIn() else EnterTransition.None }, exitTransition = { if (currentDestination.enableTransition) fadeOut() else ExitTransition.None }, ) { diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDownloadsLimitScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDownloadsLimitScreen.kt index a6ae36a71..931a60579 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDownloadsLimitScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDownloadsLimitScreen.kt @@ -19,8 +19,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableIntStateOf @@ -28,20 +30,30 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar +import com.infomaniak.swisstransfer.ui.components.TopAppBarButton import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingOption import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile -import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable -fun SettingsDownloadsLimitScreen() { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - SettingTitle(titleRes = R.string.settingsDownloadsLimitTitle) +fun SettingsDownloadsLimitScreen(navigateBack: (() -> Unit)?) { + Scaffold(topBar = { + val canDisplayBackButton = navigateBack?.let { TopAppBarButton.backButton(navigateBack) } + SwissTransferTobAppBar(R.string.settingsOptionDownloadLimit, navigationMenu = canDisplayBackButton) + }) { paddingsValue -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(paddingsValue) + ) { + SettingTitle(titleRes = R.string.settingsDownloadsLimitTitle) - val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - SingleSelectOptions(DownloadsLimit.entries, { selectedItem }, setSelectedItem) + val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + SingleSelectOptions(DownloadsLimit.entries, { selectedItem }, setSelectedItem) + } } } @@ -57,12 +69,11 @@ enum class DownloadsLimit( } @PreviewMobile -@PreviewTablet @Composable private fun SettingsThemeScreenPreview() { SwissTransferTheme { Surface { - SettingsDownloadsLimitScreen() + SettingsDownloadsLimitScreen {} } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDurationValidityScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDurationValidityScreen.kt index f2cedc951..6566ce6f8 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDurationValidityScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsDurationValidityScreen.kt @@ -19,8 +19,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableIntStateOf @@ -29,20 +31,30 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.pluralStringResource import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar +import com.infomaniak.swisstransfer.ui.components.TopAppBarButton import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingOption import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile -import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable -fun SettingsValidityPeriodScreen() { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - SettingTitle(titleRes = R.string.settingsValidityPeriodTitle) +fun SettingsValidityPeriodScreen(navigateBack: (() -> Unit)?) { + Scaffold(topBar = { + val canDisplayBackButton = navigateBack?.let { TopAppBarButton.backButton(navigateBack) } + SwissTransferTobAppBar(R.string.settingsOptionValidityPeriod, navigationMenu = canDisplayBackButton) + }) { paddingsValue -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(paddingsValue) + ) { + SettingTitle(titleRes = R.string.settingsValidityPeriodTitle) - val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - SingleSelectOptions(ValidityPeriod.entries, { selectedItem }, setSelectedItem) + val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + SingleSelectOptions(ValidityPeriod.entries, { selectedItem }, setSelectedItem) + } } } @@ -58,12 +70,11 @@ enum class ValidityPeriod( } @PreviewMobile -@PreviewTablet @Composable private fun SettingsThemeScreenPreview() { SwissTransferTheme { Surface { - SettingsValidityPeriodScreen() + SettingsValidityPeriodScreen {} } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsEmailLanguageScreen.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsEmailLanguageScreen.kt index ce6d7ffdc..26fdd768d 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsEmailLanguageScreen.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsEmailLanguageScreen.kt @@ -19,8 +19,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableIntStateOf @@ -29,20 +31,30 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar +import com.infomaniak.swisstransfer.ui.components.TopAppBarButton import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingOption import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile -import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable -fun SettingsEmailLanguageScreen() { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - SettingTitle(titleRes = R.string.settingsEmailLanguageTitle) +fun SettingsEmailLanguageScreen(navigateBack: (() -> Unit)?) { + Scaffold(topBar = { + val canDisplayBackButton = navigateBack?.let { TopAppBarButton.backButton(navigateBack) } + SwissTransferTobAppBar(R.string.settingsOptionEmailLanguage, navigationMenu = canDisplayBackButton) + }) { paddingsValue -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(paddingsValue) + ) { + SettingTitle(titleRes = R.string.settingsEmailLanguageTitle) - val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - SingleSelectOptions(EmailLanguage.entries, { selectedItem }, setSelectedItem) + val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + SingleSelectOptions(EmailLanguage.entries, { selectedItem }, setSelectedItem) + } } } @@ -59,12 +71,11 @@ enum class EmailLanguage( } @PreviewMobile -@PreviewTablet @Composable private fun SettingsThemeScreenPreview() { SwissTransferTheme { Surface { - SettingsEmailLanguageScreen() + SettingsEmailLanguageScreen {} } } } 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 d2ac70cd7..cf2956028 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 @@ -18,35 +18,21 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi -import androidx.compose.material3.adaptive.WindowAdaptiveInfo -import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo -import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole -import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -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.stringResource +import com.infomaniak.swisstransfer.BuildConfig import com.infomaniak.swisstransfer.R -import com.infomaniak.swisstransfer.extensions.goToPlayStore -import com.infomaniak.swisstransfer.extensions.openAppNotificationSettings -import com.infomaniak.swisstransfer.extensions.openUrl -import com.infomaniak.swisstransfer.ui.components.TwoPaneScaffold +import com.infomaniak.swisstransfer.ui.components.BrandTobAppBar import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.* import com.infomaniak.swisstransfer.ui.screen.main.settings.SettingsOptionScreens.* @@ -58,156 +44,93 @@ import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTi import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile -import com.infomaniak.swisstransfer.ui.utils.PreviewTablet -@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable -fun SettingsScreenWrapper( - windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), -) { - TwoPaneScaffold( - windowAdaptiveInfo, - listPane = { ListPane(this) }, - detailPane = { DetailPane(this) } - ) -} - -@OptIn(ExperimentalMaterial3AdaptiveApi::class) -@Composable -private fun ListPane(navigator: ThreePaneScaffoldNavigator) { - val context = LocalContext.current - val aboutURL = stringResource(R.string.urlAbout) - val userReportURL = stringResource(R.string.urlUserReportAndroid) - - SettingsScreen( - onItemClick = { item -> - when (item) { - NOTIFICATIONS -> context.openAppNotificationSettings() - DISCOVER_INFOMANIAK -> context.openUrl(aboutURL) - SHARE_IDEAS -> context.openUrl(userReportURL) - GIVE_FEEDBACK -> context.goToPlayStore() - else -> { - // Navigate to the detail pane with the passed item - navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) - } - } - }, - getSelectedSetting = { navigator.currentDestination?.content }, - ) -} - -@OptIn(ExperimentalMaterial3AdaptiveApi::class) -@Composable -private fun DetailPane(navigator: ThreePaneScaffoldNavigator) { - var lastSelectedScreen by rememberSaveable { mutableStateOf(null) } - - val destination = navigator.currentDestination?.content ?: lastSelectedScreen - navigator.currentDestination?.content?.let { lastSelectedScreen = it } - - when (destination) { - THEME -> SettingsThemeScreen() - VALIDITY_PERIOD -> SettingsValidityPeriodScreen() - DOWNLOAD_LIMIT -> SettingsDownloadsLimitScreen() - EMAIL_LANGUAGE -> SettingsEmailLanguageScreen() - NOTIFICATIONS, - DISCOVER_INFOMANIAK, - SHARE_IDEAS, - GIVE_FEEDBACK -> Unit - null -> NoSelectionEmptyState() - } -} - -@Composable -private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedSetting: () -> SettingsOptionScreens?) { +fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedSetting: () -> SettingsOptionScreens?) { val selectedSetting = getSelectedSetting() - Column( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .selectableGroup(), - ) { - Text( - modifier = Modifier.padding(horizontal = Margin.Medium, vertical = Margin.Large), - text = stringResource(R.string.settingsTitle), - style = SwissTransferTheme.typography.h1, - ) - - SettingTitle(R.string.settingsCategoryGeneral) - SettingItem( - titleRes = R.string.settingsOptionTheme, - isSelected = { selectedSetting == THEME }, - icon = AppIcons.PaintbrushPalette, - description = "TODO", - CHEVRON + Scaffold(topBar = { BrandTobAppBar() }) { paddingsValue -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .selectableGroup() + .padding(paddingsValue), ) { - onItemClick(THEME) - } - SettingItem( - titleRes = R.string.settingsOptionNotifications, - isSelected = { selectedSetting == NOTIFICATIONS }, - icon = AppIcons.Bell, - description = "TODO", - endIcon = OPEN_OUTSIDE, - ) { - onItemClick(NOTIFICATIONS) - } - - SettingDivider() + Text( + modifier = Modifier.padding(horizontal = Margin.Medium, vertical = Margin.Large), + text = stringResource(R.string.settingsTitle), + style = SwissTransferTheme.typography.h1, + ) + + SettingTitle(R.string.settingsCategoryGeneral) + SettingItem( + titleRes = R.string.settingsOptionTheme, + isSelected = { selectedSetting == THEME }, + icon = AppIcons.PaintbrushPalette, + description = "TODO", + CHEVRON + ) { + onItemClick(THEME) + } + SettingItem( + titleRes = R.string.settingsOptionNotifications, + isSelected = { selectedSetting == NOTIFICATIONS }, + icon = AppIcons.Bell, + description = "TODO", + endIcon = OPEN_OUTSIDE, + ) { + onItemClick(NOTIFICATIONS) + } - SettingTitle(R.string.settingsCategoryDefaultSettings) - SettingItem( - titleRes = R.string.settingsOptionValidityPeriod, - isSelected = { selectedSetting == VALIDITY_PERIOD }, - icon = AppIcons.FileBadgeArrowDown, - description = "TODO", - endIcon = CHEVRON, - ) { - onItemClick(VALIDITY_PERIOD) - } - SettingItem( - titleRes = R.string.settingsOptionDownloadLimit, - isSelected = { selectedSetting == DOWNLOAD_LIMIT }, - icon = AppIcons.Clock, - description = "TODO", - endIcon = CHEVRON, - ) { - onItemClick(DOWNLOAD_LIMIT) - } - SettingItem( - titleRes = R.string.settingsOptionEmailLanguage, - isSelected = { selectedSetting == EMAIL_LANGUAGE }, - icon = AppIcons.SpeechBubble, - description = "TODO", - endIcon = CHEVRON, - ) { - onItemClick(EMAIL_LANGUAGE) - } + SettingDivider() + + SettingTitle(R.string.settingsCategoryDefaultSettings) + SettingItem( + titleRes = R.string.settingsOptionValidityPeriod, + isSelected = { selectedSetting == VALIDITY_PERIOD }, + icon = AppIcons.FileBadgeArrowDown, + description = "TODO", + endIcon = CHEVRON, + ) { + onItemClick(VALIDITY_PERIOD) + } + SettingItem( + titleRes = R.string.settingsOptionDownloadLimit, + isSelected = { selectedSetting == DOWNLOAD_LIMIT }, + icon = AppIcons.Clock, + description = "TODO", + endIcon = CHEVRON, + ) { + onItemClick(DOWNLOAD_LIMIT) + } + SettingItem( + titleRes = R.string.settingsOptionEmailLanguage, + isSelected = { selectedSetting == EMAIL_LANGUAGE }, + icon = AppIcons.SpeechBubble, + description = "TODO", + endIcon = CHEVRON, + ) { + onItemClick(EMAIL_LANGUAGE) + } - SettingDivider() + SettingDivider() - SettingTitle(R.string.settingsCategoryAbout) - SettingItem( - R.string.settingsOptionDiscoverInfomaniak, - { selectedSetting == DISCOVER_INFOMANIAK }, - endIcon = OPEN_OUTSIDE - ) { - onItemClick(DISCOVER_INFOMANIAK) - } - SettingItem(R.string.settingsOptionShareIdeas, { selectedSetting == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { - onItemClick(SHARE_IDEAS) - } - SettingItem(R.string.settingsOptionGiveFeedback, { selectedSetting == GIVE_FEEDBACK }, endIcon = OPEN_OUTSIDE) { - onItemClick(GIVE_FEEDBACK) + SettingTitle(R.string.settingsCategoryAbout) + SettingItem( + R.string.settingsOptionDiscoverInfomaniak, + { selectedSetting == DISCOVER_INFOMANIAK }, + endIcon = OPEN_OUTSIDE + ) { + onItemClick(DISCOVER_INFOMANIAK) + } + SettingItem(R.string.settingsOptionShareIdeas, { selectedSetting == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { + onItemClick(SHARE_IDEAS) + } + SettingItem(R.string.settingsOptionGiveFeedback, { selectedSetting == GIVE_FEEDBACK }, endIcon = OPEN_OUTSIDE) { + onItemClick(GIVE_FEEDBACK) + } + SettingItem(R.string.version, isSelected = { false }, description = BuildConfig.VERSION_NAME, onClick = null) } - SettingItem(R.string.version, isSelected = { false }, description = "0.0.1", onClick = null) - } -} - -// Show the detail pane content if selected item is available -@Composable -private fun NoSelectionEmptyState() { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Text("Select a setting item", color = SwissTransferTheme.colors.secondaryTextColor) } } @@ -218,12 +141,11 @@ enum class SettingsOptionScreens { } @PreviewMobile -@PreviewTablet @Composable private fun SettingsScreenPreview() { SwissTransferTheme { Surface(color = MaterialTheme.colorScheme.background) { - SettingsScreenWrapper() + SettingsScreen(onItemClick = {}, getSelectedSetting = { null }) } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreenWrapper.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreenWrapper.kt new file mode 100644 index 000000000..6c27c6aef --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsScreenWrapper.kt @@ -0,0 +1,125 @@ +/* + * 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.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.WindowAdaptiveInfo +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole +import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +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.stringResource +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.extensions.goToPlayStore +import com.infomaniak.swisstransfer.extensions.openAppNotificationSettings +import com.infomaniak.swisstransfer.extensions.openUrl +import com.infomaniak.swisstransfer.ui.components.TwoPaneScaffold +import com.infomaniak.swisstransfer.ui.screen.main.settings.SettingsOptionScreens.* +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme +import com.infomaniak.swisstransfer.ui.utils.PreviewMobile +import com.infomaniak.swisstransfer.ui.utils.PreviewTablet + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +fun SettingsScreenWrapper(windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()) { + TwoPaneScaffold( + windowAdaptiveInfo, + listPane = { ListPane(this) }, + detailPane = { DetailPane(this) } + ) +} + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +private fun ListPane(navigator: ThreePaneScaffoldNavigator) { + val context = LocalContext.current + val aboutURL = stringResource(R.string.urlAbout) + val userReportURL = stringResource(R.string.urlUserReportAndroid) + + SettingsScreen( + onItemClick = { item -> + when (item) { + NOTIFICATIONS -> context.openAppNotificationSettings() + DISCOVER_INFOMANIAK -> context.openUrl(aboutURL) + SHARE_IDEAS -> context.openUrl(userReportURL) + GIVE_FEEDBACK -> context.goToPlayStore() + else -> { + // Navigate to the detail pane with the passed item + navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) + } + } + }, + getSelectedSetting = { navigator.currentDestination?.content }, + ) +} + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +private fun DetailPane(navigator: ThreePaneScaffoldNavigator) { + var lastSelectedScreen by rememberSaveable { mutableStateOf(null) } + + val destination = navigator.currentDestination?.content ?: lastSelectedScreen + navigator.currentDestination?.content?.let { lastSelectedScreen = it } + + val navigateBackCallback: () -> Unit = { navigator.navigateBack() } + val navigateBack: (() -> Unit)? = if (navigator.canNavigateBack()) navigateBackCallback else null + + when (destination) { + THEME -> SettingsThemeScreen(navigateBack) + VALIDITY_PERIOD -> SettingsValidityPeriodScreen(navigateBack) + DOWNLOAD_LIMIT -> SettingsDownloadsLimitScreen(navigateBack) + EMAIL_LANGUAGE -> SettingsEmailLanguageScreen(navigateBack) + NOTIFICATIONS, + DISCOVER_INFOMANIAK, + SHARE_IDEAS, + GIVE_FEEDBACK -> Unit + null -> NoSelectionEmptyState() + } +} + +// Show the detail pane content if selected item is available +@Composable +private fun NoSelectionEmptyState() { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Select a setting item", color = SwissTransferTheme.colors.secondaryTextColor) + } +} + +@PreviewMobile +@PreviewTablet +@Composable +private fun SettingsScreenWrapperPreview() { + SwissTransferTheme { + Surface(color = MaterialTheme.colorScheme.background) { + SettingsScreenWrapper() + } + } +} 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 66759eb8b..6760d87cc 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 @@ -19,8 +19,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -31,6 +33,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SwissTransferTobAppBar +import com.infomaniak.swisstransfer.ui.components.TopAppBarButton import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.BlackAndWhiteCircle import com.infomaniak.swisstransfer.ui.icons.app.BlackCircle @@ -40,15 +44,23 @@ import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTi import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile -import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable -fun SettingsThemeScreen() { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { - SettingTitle(titleRes = R.string.settingsThemeTitle) +fun SettingsThemeScreen(navigateBack: (() -> Unit)?) { + Scaffold(topBar = { + val canDisplayBackButton = navigateBack?.let { TopAppBarButton.backButton(navigateBack) } + SwissTransferTobAppBar(R.string.settingsOptionTheme, navigationMenu = canDisplayBackButton) + }) { paddingsValue -> + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .padding(paddingsValue) + ) { + 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(0) } // TODO: Use DataStore or Realm + SingleSelectOptions(ThemeOption.entries, { selectedItem }, { selectedItem = it }) + } } } @@ -63,12 +75,11 @@ enum class ThemeOption( } @PreviewMobile -@PreviewTablet @Composable private fun SettingsThemeScreenPreview() { SwissTransferTheme { Surface { - SettingsThemeScreen() + SettingsThemeScreen {} } } }