From 3bca94874fe4ed0c35f526967675e7ae8df3eb31 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Mon, 19 Aug 2024 15:28:01 +0200 Subject: [PATCH 01/17] Create a MutuallyExclusiveOptions component for setting screens --- .../swisstransfer/ui/icons/app/Checkmark.kt | 61 +++++++++ .../main/settings/SettingsThemeScreen.kt | 122 ++++++++++++++++++ 2 files changed, 183 insertions(+) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Checkmark.kt create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Checkmark.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Checkmark.kt new file mode 100644 index 000000000..182d7eca8 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Checkmark.kt @@ -0,0 +1,61 @@ +package com.infomaniak.swisstransfer.ui.icons.app + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.Checkmark: ImageVector + get() { + if (_checkmark != null) { + return _checkmark!! + } + _checkmark = Builder( + name = "Checkmark", + defaultWidth = 16.0.dp, + defaultHeight = 16.0.dp, + viewportWidth = 16.0f, + viewportHeight = 16.0f + ).apply { + path( + fill = null, + stroke = SolidColor(Color(0xFF9F9F9F)), + strokeLineWidth = 2.0f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(15.0f, 3.0f) + lineTo(5.593f, 13.419f) + lineTo(1.0f, 9.085f) + } + }.build() + return _checkmark!! + } + +private var _checkmark: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.Checkmark, + contentDescription = null, + modifier = Modifier.size(AppIcons.previewSize) + ) + } +} 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 new file mode 100644 index 000000000..4216e23f9 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/SettingsThemeScreen.kt @@ -0,0 +1,122 @@ +/* + * 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.annotation.StringRes +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SharpRippleButton +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import com.infomaniak.swisstransfer.ui.icons.app.Add +import com.infomaniak.swisstransfer.ui.icons.app.Checkmark +import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle +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 + +@Composable +fun SettingsThemeScreen() { + Column { + SettingTitle(titleRes = R.string.appName) + MutuallyExclusiveOptions(ThemeOption.entries) + } +} + +enum class ThemeOption(override val title: Int, override val icon: ImageVector) : SettingOption { + SYSTEM(R.string.appName, AppIcons.Add), + LIGHT(R.string.appName, AppIcons.Add), + DARK(R.string.appName, AppIcons.Add), +} + +interface SettingOption { + @get:StringRes + val title: Int + val icon: ImageVector? +} + +@Composable +fun MutuallyExclusiveOptions(items: List) { + var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore + + Column(Modifier.selectableGroup()) { + items.forEachIndexed { index, item -> + if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) + SettingOptionItem(item, isSelected = selectedItem == index) { selectedItem = index } + } + } +} + +@Composable +private fun SettingOptionItem(item: SettingOption, isSelected: Boolean, onClick: () -> Unit) { + SharpRippleButton( + modifier = Modifier.selectable(selected = isSelected, onClick = {}), // onClick left empty because handled by button + onClick = onClick + ) { + Row( + Modifier + .fillMaxWidth() + .padding(horizontal = Margin.Medium, vertical = Margin.Medium), + verticalAlignment = Alignment.CenterVertically, + ) { + item.icon?.let { + Icon(imageVector = it, contentDescription = null) + Spacer(modifier = Modifier.width(Margin.Medium)) + } + + Text(text = stringResource(id = item.title), Modifier.weight(1f)) + + if (isSelected) { + Spacer(modifier = Modifier.width(Margin.Medium)) + Icon( + imageVector = AppIcons.Checkmark, + contentDescription = null, + tint = SwissTransferTheme.materialColors.primary, + ) + } + } + } +} + + +@PreviewMobile +@PreviewTablet +@Composable +private fun SettingsThemeScreenPreview() { + SwissTransferTheme { + Surface { + SettingsThemeScreen() + } + } +} From 1a3bb4fd3b5166aed807af9d281eb60a72b4c54b Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Mon, 19 Aug 2024 17:11:48 +0200 Subject: [PATCH 02/17] Extract the mutually exclusive component to its own file --- .../ui/components/SettingOption.kt | 89 +++++++++++++++++++ .../main/settings/SettingsThemeScreen.kt | 70 +-------------- 2 files changed, 92 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt new file mode 100644 index 000000000..83fe9e45a --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt @@ -0,0 +1,89 @@ +/* + * 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.components + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.selection.selectable +import androidx.compose.foundation.selection.selectableGroup +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +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.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import com.infomaniak.swisstransfer.ui.icons.app.Checkmark +import com.infomaniak.swisstransfer.ui.theme.Margin +import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme + +@Composable +fun MutuallyExclusiveOptions(items: List) { + var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + + Column(Modifier.selectableGroup()) { + items.forEachIndexed { index, item -> + if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) + SettingOptionItem(item, isSelected = selectedItem == index) { selectedItem = index } + } + } +} + +@Composable +private fun SettingOptionItem(item: SettingOption, isSelected: Boolean, onClick: () -> Unit) { + SharpRippleButton( + modifier = Modifier.selectable(selected = isSelected, onClick = {}), // onClick left empty because handled by button + onClick = onClick + ) { + Row( + Modifier + .fillMaxWidth() + .padding(horizontal = Margin.Medium, vertical = Margin.Medium), + verticalAlignment = Alignment.CenterVertically, + ) { + item.icon?.let { + Icon(imageVector = it, contentDescription = null) + Spacer(modifier = Modifier.width(Margin.Medium)) + } + + Text(text = stringResource(id = item.title), Modifier.weight(1f)) + + if (isSelected) { + Spacer(modifier = Modifier.width(Margin.Medium)) + Icon( + imageVector = AppIcons.Checkmark, + contentDescription = null, + tint = SwissTransferTheme.materialColors.primary, + ) + } + } + } +} + +interface SettingOption { + @get:StringRes + val title: Int + val icon: ImageVector? +} 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 4216e23f9..4ceac582e 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 @@ -18,30 +18,16 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.selection.selectable -import androidx.compose.foundation.selection.selectableGroup -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon +import androidx.compose.foundation.layout.Column import androidx.compose.material3.Surface -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -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.graphics.vector.ImageVector -import androidx.compose.ui.res.stringResource import com.infomaniak.swisstransfer.R -import com.infomaniak.swisstransfer.ui.components.SharpRippleButton +import com.infomaniak.swisstransfer.ui.components.MutuallyExclusiveOptions +import com.infomaniak.swisstransfer.ui.components.SettingOption import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add -import com.infomaniak.swisstransfer.ui.icons.app.Checkmark import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle -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 @@ -60,56 +46,6 @@ enum class ThemeOption(override val title: Int, override val icon: ImageVector) DARK(R.string.appName, AppIcons.Add), } -interface SettingOption { - @get:StringRes - val title: Int - val icon: ImageVector? -} - -@Composable -fun MutuallyExclusiveOptions(items: List) { - var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore - - Column(Modifier.selectableGroup()) { - items.forEachIndexed { index, item -> - if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) - SettingOptionItem(item, isSelected = selectedItem == index) { selectedItem = index } - } - } -} - -@Composable -private fun SettingOptionItem(item: SettingOption, isSelected: Boolean, onClick: () -> Unit) { - SharpRippleButton( - modifier = Modifier.selectable(selected = isSelected, onClick = {}), // onClick left empty because handled by button - onClick = onClick - ) { - Row( - Modifier - .fillMaxWidth() - .padding(horizontal = Margin.Medium, vertical = Margin.Medium), - verticalAlignment = Alignment.CenterVertically, - ) { - item.icon?.let { - Icon(imageVector = it, contentDescription = null) - Spacer(modifier = Modifier.width(Margin.Medium)) - } - - Text(text = stringResource(id = item.title), Modifier.weight(1f)) - - if (isSelected) { - Spacer(modifier = Modifier.width(Margin.Medium)) - Icon( - imageVector = AppIcons.Checkmark, - contentDescription = null, - tint = SwissTransferTheme.materialColors.primary, - ) - } - } - } -} - - @PreviewMobile @PreviewTablet @Composable From e8517de68b9685c392c148d3ea418e8395e92d74 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 08:38:39 +0200 Subject: [PATCH 03/17] Extract mutually exclusive state outside of its component --- .../swisstransfer/ui/components/SettingOption.kt | 10 ++-------- .../ui/screen/main/settings/SettingsThemeScreen.kt | 5 ++++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt index 83fe9e45a..4ba127064 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt @@ -26,10 +26,6 @@ import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -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.graphics.vector.ImageVector @@ -40,13 +36,11 @@ import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @Composable -fun MutuallyExclusiveOptions(items: List) { - var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - +fun MutuallyExclusiveOptions(items: List, selectedItem: Int, setSelectedItem: (Int) -> Unit) { Column(Modifier.selectableGroup()) { items.forEachIndexed { index, item -> if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) - SettingOptionItem(item, isSelected = selectedItem == index) { selectedItem = index } + SettingOptionItem(item, isSelected = selectedItem == index) { setSelectedItem(index) } } } } 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 4ceac582e..6e1b0dac6 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 @@ -21,6 +21,8 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.components.MutuallyExclusiveOptions @@ -36,7 +38,8 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewTablet fun SettingsThemeScreen() { Column { SettingTitle(titleRes = R.string.appName) - MutuallyExclusiveOptions(ThemeOption.entries) + val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + MutuallyExclusiveOptions(ThemeOption.entries, selectedItem, setSelectedItem) } } From a6fef60a9457a7ff04d851e79872616a89d5cdc7 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 08:43:55 +0200 Subject: [PATCH 04/17] Add SettingOptionItemPreview --- .../ui/components/SettingOption.kt | 23 +++++++++++++++++++ .../main/settings/SettingsThemeScreen.kt | 1 + 2 files changed, 24 insertions(+) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt index 4ba127064..24be130bb 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt @@ -18,19 +18,24 @@ package com.infomaniak.swisstransfer.ui.components +import android.content.res.Configuration import androidx.annotation.StringRes import androidx.compose.foundation.layout.* import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.icons.AppIcons +import com.infomaniak.swisstransfer.ui.icons.app.Add import com.infomaniak.swisstransfer.ui.icons.app.Checkmark import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @@ -81,3 +86,21 @@ interface SettingOption { val title: Int val icon: ImageVector? } + +@Preview(name = "Light") +@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Composable +private fun SettingOptionItemPreview() { + SwissTransferTheme { + Surface { + Column { + val item = object : SettingOption { + override val title: Int = R.string.appName + override val icon: ImageVector = AppIcons.Add + } + SettingOptionItem(item, true) {} + SettingOptionItem(item, false) {} + } + } + } +} 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 6e1b0dac6..2f49f087d 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 @@ -38,6 +38,7 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewTablet fun SettingsThemeScreen() { Column { SettingTitle(titleRes = R.string.appName) + val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm MutuallyExclusiveOptions(ThemeOption.entries, selectedItem, setSelectedItem) } From aada3d9570794503a9217dc713527ece4c79cfa5 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 08:57:03 +0200 Subject: [PATCH 05/17] Add checkmark animation --- .../swisstransfer/ui/components/SettingOption.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt index 24be130bb..6561e27bf 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt @@ -20,6 +20,9 @@ package com.infomaniak.swisstransfer.ui.components import android.content.res.Configuration import androidx.annotation.StringRes +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut import androidx.compose.foundation.layout.* import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup @@ -69,8 +72,12 @@ private fun SettingOptionItem(item: SettingOption, isSelected: Boolean, onClick: Text(text = stringResource(id = item.title), Modifier.weight(1f)) - if (isSelected) { - Spacer(modifier = Modifier.width(Margin.Medium)) + if (isSelected) Spacer(modifier = Modifier.width(Margin.Medium)) + AnimatedVisibility( + visible = isSelected, + enter = scaleIn(), + exit = scaleOut(), + ) { Icon( imageVector = AppIcons.Checkmark, contentDescription = null, From baf3219e83f631dfc974e61804f01b87e024243a Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 09:05:40 +0200 Subject: [PATCH 06/17] Add navigation between settings option screens --- .../ui/screen/main/settings/SettingsScreen.kt | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) 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 1833ca783..57effe6df 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 @@ -36,12 +36,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.infomaniak.swisstransfer.R -import com.infomaniak.swisstransfer.ui.components.* +import com.infomaniak.swisstransfer.ui.components.TwoPaneScaffold import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add import com.infomaniak.swisstransfer.ui.icons.app.Bell import com.infomaniak.swisstransfer.ui.icons.app.SpeechBubble -import com.infomaniak.swisstransfer.ui.screen.main.settings.components.EndIconType +import com.infomaniak.swisstransfer.ui.screen.main.settings.SettingsOptionScreens.* +import com.infomaniak.swisstransfer.ui.screen.main.settings.components.EndIconType.CHEVRON +import com.infomaniak.swisstransfer.ui.screen.main.settings.components.EndIconType.OPEN_OUTSIDE import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingDivider import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingItem import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle @@ -55,7 +57,7 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewTablet fun SettingsScreenWrapper( windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo(), ) { - TwoPaneScaffold( // TODO: Replace Any with item type + TwoPaneScaffold( windowAdaptiveInfo, listPane = { SettingsScreen( @@ -67,19 +69,29 @@ fun SettingsScreenWrapper( }, detailPane = { // Show the detail pane content if selected item is available - if (currentDestination?.content == null) { + val destination = currentDestination?.content + if (destination == null) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Text("Select a setting item", color = SwissTransferTheme.colors.secondaryTextColor) } } else { - Text("Show selected item") + when (destination) { + THEME -> SettingsThemeScreen() + NOTIFICATIONS -> {} + VALIDITY_PERIOD -> {} + DOWNLOAD_LIMIT -> {} + EMAIL_LANGUAGE -> {} + DISCOVER_INFOMANIAK -> {} + SHARE_IDEAS -> {} + GIVE_FEEDBACK -> {} + } } } ) } @Composable -private fun SettingsScreen(onItemClick: (Any) -> Unit) { +private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit) { Column(modifier = Modifier.verticalScroll(rememberScrollState())) { Text( modifier = Modifier.padding(horizontal = Margin.Medium, vertical = Margin.Large), @@ -89,28 +101,42 @@ private fun SettingsScreen(onItemClick: (Any) -> Unit) { SettingTitle(R.string.settingsCategoryGeneral) // TODO: Use correct icon - SettingItem(R.string.settingsOptionTheme, AppIcons.Add, "TODO", EndIconType.CHEVRON) {} - SettingItem(R.string.settingsOptionNotifications, AppIcons.Bell, "TODO", endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.settingsOptionTheme, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } + SettingItem(R.string.settingsOptionNotifications, AppIcons.Bell, "TODO", endIcon = OPEN_OUTSIDE) { + onItemClick(NOTIFICATIONS) + } SettingDivider() SettingTitle(R.string.settingsCategoryDefaultSettings) // TODO: Use correct icon - SettingItem(R.string.settingsOptionValidityPeriod, AppIcons.Add, "TODO", endIcon = EndIconType.CHEVRON) {} + SettingItem(R.string.settingsOptionValidityPeriod, AppIcons.Add, "TODO", endIcon = CHEVRON) { + onItemClick(VALIDITY_PERIOD) + } // TODO: Use correct icon - SettingItem(R.string.settingsOptionDownloadLimit, AppIcons.Add, "TODO", endIcon = EndIconType.CHEVRON) {} - SettingItem(R.string.settingsOptionEmailLanguage, AppIcons.SpeechBubble, "TODO", endIcon = EndIconType.CHEVRON) {} + SettingItem(R.string.settingsOptionDownloadLimit, AppIcons.Add, "TODO", endIcon = CHEVRON) { + onItemClick(DOWNLOAD_LIMIT) + } + SettingItem(R.string.settingsOptionEmailLanguage, AppIcons.SpeechBubble, "TODO", endIcon = CHEVRON) { + onItemClick(EMAIL_LANGUAGE) + } SettingDivider() SettingTitle(R.string.settingsCategoryAbout) - SettingItem(R.string.settingsOptionDiscoverInfomaniak, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.settingsOptionShareIdeas, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.settingsOptionGiveFeedback, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.settingsOptionDiscoverInfomaniak, endIcon = OPEN_OUTSIDE) { onItemClick(DISCOVER_INFOMANIAK) } + SettingItem(R.string.settingsOptionShareIdeas, endIcon = OPEN_OUTSIDE) { onItemClick(SHARE_IDEAS) } + SettingItem(R.string.settingsOptionGiveFeedback, endIcon = OPEN_OUTSIDE) { onItemClick(GIVE_FEEDBACK) } SettingItem(R.string.version, description = "0.0.1", onClick = null) } } +enum class SettingsOptionScreens { + THEME, NOTIFICATIONS, + VALIDITY_PERIOD, DOWNLOAD_LIMIT, EMAIL_LANGUAGE, + DISCOVER_INFOMANIAK, SHARE_IDEAS, GIVE_FEEDBACK, +} + @PreviewMobile @PreviewTablet @Composable From 000a6d6f2c81af633403979ac007a3e8621bb066 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 11:07:46 +0200 Subject: [PATCH 07/17] Rename MutuallyExclusiveOptions file correctly --- .../components/{SettingOption.kt => MutuallyExclusiveOptions.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/components/{SettingOption.kt => MutuallyExclusiveOptions.kt} (100%) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/MutuallyExclusiveOptions.kt similarity index 100% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/components/SettingOption.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/components/MutuallyExclusiveOptions.kt From 9aa1e6c9cbaf0328b9b3e94fbd72c6542449e553 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 13:16:51 +0200 Subject: [PATCH 08/17] Make theme settings vertically scrollable --- .../ui/screen/main/settings/SettingsThemeScreen.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 2f49f087d..737ca4ce4 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,10 +19,13 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableIntStateOf 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.MutuallyExclusiveOptions @@ -36,7 +39,7 @@ import com.infomaniak.swisstransfer.ui.utils.PreviewTablet @Composable fun SettingsThemeScreen() { - Column { + Column(modifier = Modifier.verticalScroll(rememberScrollState())) { SettingTitle(titleRes = R.string.appName) val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm From 7ee0e00f2a6e68930231e43cd04cb9ab45f53f67 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 13:30:23 +0200 Subject: [PATCH 09/17] Fix wrong detailPane when navigating back from a list of options for a setting --- .../ui/screen/main/settings/SettingsScreen.kt | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) 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 57effe6df..1498cc72a 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 @@ -32,6 +32,10 @@ import androidx.compose.material3.adaptive.WindowAdaptiveInfo import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole 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.res.stringResource @@ -68,23 +72,21 @@ fun SettingsScreenWrapper( ) }, detailPane = { - // Show the detail pane content if selected item is available - val destination = currentDestination?.content - if (destination == null) { - Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { - Text("Select a setting item", color = SwissTransferTheme.colors.secondaryTextColor) - } - } else { - when (destination) { - THEME -> SettingsThemeScreen() - NOTIFICATIONS -> {} - VALIDITY_PERIOD -> {} - DOWNLOAD_LIMIT -> {} - EMAIL_LANGUAGE -> {} - DISCOVER_INFOMANIAK -> {} - SHARE_IDEAS -> {} - GIVE_FEEDBACK -> {} - } + var lastSelectedScreen by rememberSaveable { mutableStateOf(null) } + + val destination = currentDestination?.content ?: lastSelectedScreen + currentDestination?.content?.let { lastSelectedScreen = it } + + when (destination) { + THEME -> SettingsThemeScreen() + NOTIFICATIONS -> {} + VALIDITY_PERIOD -> {} + DOWNLOAD_LIMIT -> {} + EMAIL_LANGUAGE -> {} + DISCOVER_INFOMANIAK -> {} + SHARE_IDEAS -> {} + GIVE_FEEDBACK -> {} + null -> NoSelectionEmptyState() } } ) @@ -131,6 +133,14 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit) { } } +// 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) + } +} + enum class SettingsOptionScreens { THEME, NOTIFICATIONS, VALIDITY_PERIOD, DOWNLOAD_LIMIT, EMAIL_LANGUAGE, From e5961d8e6d6df8dfc30803bbdc31b45edcc96a4e Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 15:33:40 +0200 Subject: [PATCH 10/17] Move MutuallyExclusiveOptions to the settings package --- .../main/settings}/MutuallyExclusiveOptions.kt | 3 ++- .../ui/screen/main/settings/SettingsThemeScreen.kt | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/{components => screen/main/settings}/MutuallyExclusiveOptions.kt (97%) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/MutuallyExclusiveOptions.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt similarity index 97% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/components/MutuallyExclusiveOptions.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt index 6561e27bf..d263ad432 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/MutuallyExclusiveOptions.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.infomaniak.swisstransfer.ui.components +package com.infomaniak.swisstransfer.ui.screen.main.settings import android.content.res.Configuration import androidx.annotation.StringRes @@ -37,6 +37,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.infomaniak.swisstransfer.R +import com.infomaniak.swisstransfer.ui.components.SharpRippleButton import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add import com.infomaniak.swisstransfer.ui.icons.app.Checkmark 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 737ca4ce4..42cffdceb 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 @@ -28,8 +28,6 @@ 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.MutuallyExclusiveOptions -import com.infomaniak.swisstransfer.ui.components.SettingOption import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SettingTitle From 8e183dda2fe524bc5348a99181fb8f2334c2c235 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Tue, 20 Aug 2024 15:37:35 +0200 Subject: [PATCH 11/17] Move MutuallyExclusiveOptions to the components package --- .../ui/screen/main/settings/SettingsThemeScreen.kt | 2 ++ .../main/settings/{ => components}/MutuallyExclusiveOptions.kt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/{ => components}/MutuallyExclusiveOptions.kt (98%) 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 42cffdceb..727b49a74 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,8 @@ import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add +import com.infomaniak.swisstransfer.ui.screen.main.settings.components.MutuallyExclusiveOptions +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.theme.SwissTransferTheme import com.infomaniak.swisstransfer.ui.utils.PreviewMobile diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt similarity index 98% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt index d263ad432..741c60d99 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MutuallyExclusiveOptions.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.infomaniak.swisstransfer.ui.screen.main.settings +package com.infomaniak.swisstransfer.ui.screen.main.settings.components import android.content.res.Configuration import androidx.annotation.StringRes From 2c39e3765631732abb1b33d20a5de1115f7d238c Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 12:44:03 +0200 Subject: [PATCH 12/17] Rename MutuallyExclusiveOptions into SingleSelectionOptions --- .../ui/screen/main/settings/SettingsThemeScreen.kt | 4 ++-- .../{MutuallyExclusiveOptions.kt => SingleSelectOptions.kt} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/{MutuallyExclusiveOptions.kt => SingleSelectOptions.kt} (97%) 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 727b49a74..6534f1951 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,7 +30,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add -import com.infomaniak.swisstransfer.ui.screen.main.settings.components.MutuallyExclusiveOptions +import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions 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.theme.SwissTransferTheme @@ -43,7 +43,7 @@ fun SettingsThemeScreen() { SettingTitle(titleRes = R.string.appName) val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - MutuallyExclusiveOptions(ThemeOption.entries, selectedItem, setSelectedItem) + SingleSelectOptions(ThemeOption.entries, selectedItem, setSelectedItem) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt similarity index 97% rename from app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt rename to app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt index 741c60d99..d6d8605d4 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/MutuallyExclusiveOptions.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt @@ -45,7 +45,7 @@ import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @Composable -fun MutuallyExclusiveOptions(items: List, selectedItem: Int, setSelectedItem: (Int) -> Unit) { +fun SingleSelectOptions(items: List, selectedItem: Int, setSelectedItem: (Int) -> Unit) { Column(Modifier.selectableGroup()) { items.forEachIndexed { index, item -> if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) From 228fbe0a09fa086b0fb3d7d009718def90ec8daa Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 13:05:01 +0200 Subject: [PATCH 13/17] Use two callbacks for good practice Here it's fine but as a good practice, so people don't take inspiration from the wrong way of writing things --- .../ui/screen/main/settings/SettingsThemeScreen.kt | 8 +++++--- .../main/settings/components/SingleSelectOptions.kt | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) 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 6534f1951..c994f2082 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 @@ -23,16 +23,18 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.icons.AppIcons import com.infomaniak.swisstransfer.ui.icons.app.Add -import com.infomaniak.swisstransfer.ui.screen.main.settings.components.SingleSelectOptions 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 @@ -42,8 +44,8 @@ fun SettingsThemeScreen() { Column(modifier = Modifier.verticalScroll(rememberScrollState())) { SettingTitle(titleRes = R.string.appName) - val (selectedItem, setSelectedItem) = rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm - SingleSelectOptions(ThemeOption.entries, selectedItem, setSelectedItem) + var selectedItem by rememberSaveable { mutableIntStateOf(0) } // TODO: Use DataStore or Realm + SingleSelectOptions(ThemeOption.entries, { selectedItem }, { selectedItem = it }) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt index d6d8605d4..5e2479f7a 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt @@ -45,11 +45,11 @@ import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @Composable -fun SingleSelectOptions(items: List, selectedItem: Int, setSelectedItem: (Int) -> Unit) { +fun SingleSelectOptions(items: List, selectedItem: () -> Int, setSelectedItem: (Int) -> Unit) { Column(Modifier.selectableGroup()) { items.forEachIndexed { index, item -> if (index > 0) HorizontalDivider(Modifier.padding(horizontal = Margin.Medium)) - SettingOptionItem(item, isSelected = selectedItem == index) { setSelectedItem(index) } + SettingOptionItem(item, isSelected = selectedItem() == index) { setSelectedItem(index) } } } } From 510abee5629df1c40f178ada78336842f266c4dd Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 14:37:45 +0200 Subject: [PATCH 14/17] Add selected color to setting items --- .../ui/components/SharpRippleButton.kt | 23 ++++++- .../ui/screen/main/settings/SettingsScreen.kt | 60 +++++++++++++++---- .../main/settings/components/SettingItem.kt | 23 ++++--- .../components/SingleSelectOptions.kt | 2 +- .../swisstransfer/ui/theme/ColorDark.kt | 1 + .../swisstransfer/ui/theme/ColorLight.kt | 1 + .../swisstransfer/ui/theme/Theme.kt | 1 + 7 files changed, 87 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt index 9e15dd863..ce639be8a 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt @@ -20,6 +20,7 @@ package com.infomaniak.swisstransfer.ui.components import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.selection.selectable import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.runtime.Composable @@ -29,10 +30,26 @@ import com.infomaniak.swisstransfer.ui.theme.CustomShapes import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @Composable -fun SharpRippleButton(modifier: Modifier = Modifier, onClick: () -> Unit, content: @Composable RowScope.() -> Unit) { +fun SharpRippleButton( + modifier: Modifier = Modifier, + isSelected: Boolean = false, + onClick: () -> Unit, + content: @Composable RowScope.() -> Unit, +) { + val colors = if (isSelected) { + ButtonDefaults.textButtonColors( + contentColor = SwissTransferTheme.colors.primaryTextColor, + containerColor = SwissTransferTheme.colors.selectedSettingItem, + ) + } else { + ButtonDefaults.textButtonColors(contentColor = SwissTransferTheme.colors.primaryTextColor) + } Button( - modifier = modifier, - colors = ButtonDefaults.textButtonColors(contentColor = SwissTransferTheme.colors.primaryTextColor), + modifier = modifier.selectable( + selected = isSelected, + onClick = onClick, + ), + colors = colors, shape = CustomShapes.None, onClick = onClick, content = content, 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 1498cc72a..3730998b4 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 @@ -23,6 +23,7 @@ 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.Surface @@ -69,6 +70,7 @@ fun SettingsScreenWrapper( // Navigate to the detail pane with the passed item navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, + getSelectedMenu = { currentDestination?.content }, ) }, detailPane = { @@ -93,8 +95,14 @@ fun SettingsScreenWrapper( } @Composable -private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit) { - Column(modifier = Modifier.verticalScroll(rememberScrollState())) { +private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedMenu: () -> SettingsOptionScreens?) { + val selectedMenu = getSelectedMenu() + + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .selectableGroup(), + ) { Text( modifier = Modifier.padding(horizontal = Margin.Medium, vertical = Margin.Large), text = stringResource(R.string.settingsTitle), @@ -103,8 +111,14 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit) { SettingTitle(R.string.settingsCategoryGeneral) // TODO: Use correct icon - SettingItem(R.string.settingsOptionTheme, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } - SettingItem(R.string.settingsOptionNotifications, AppIcons.Bell, "TODO", endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionTheme, selectedMenu == THEME, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } + SettingItem( + R.string.settingsOptionNotifications, + selectedMenu == NOTIFICATIONS, + AppIcons.Bell, + "TODO", + endIcon = OPEN_OUTSIDE, + ) { onItemClick(NOTIFICATIONS) } @@ -112,24 +126,48 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit) { SettingTitle(R.string.settingsCategoryDefaultSettings) // TODO: Use correct icon - SettingItem(R.string.settingsOptionValidityPeriod, AppIcons.Add, "TODO", endIcon = CHEVRON) { + SettingItem( + R.string.settingsOptionValidityPeriod, + selectedMenu == VALIDITY_PERIOD, + AppIcons.Add, + "TODO", + endIcon = CHEVRON, + ) { onItemClick(VALIDITY_PERIOD) } // TODO: Use correct icon - SettingItem(R.string.settingsOptionDownloadLimit, AppIcons.Add, "TODO", endIcon = CHEVRON) { + SettingItem( + R.string.settingsOptionDownloadLimit, + selectedMenu == DOWNLOAD_LIMIT, + AppIcons.Add, + "TODO", + endIcon = CHEVRON, + ) { onItemClick(DOWNLOAD_LIMIT) } - SettingItem(R.string.settingsOptionEmailLanguage, AppIcons.SpeechBubble, "TODO", endIcon = CHEVRON) { + SettingItem( + R.string.settingsOptionEmailLanguage, + selectedMenu == EMAIL_LANGUAGE, + AppIcons.SpeechBubble, + "TODO", + endIcon = CHEVRON, + ) { onItemClick(EMAIL_LANGUAGE) } SettingDivider() SettingTitle(R.string.settingsCategoryAbout) - SettingItem(R.string.settingsOptionDiscoverInfomaniak, endIcon = OPEN_OUTSIDE) { onItemClick(DISCOVER_INFOMANIAK) } - SettingItem(R.string.settingsOptionShareIdeas, endIcon = OPEN_OUTSIDE) { onItemClick(SHARE_IDEAS) } - SettingItem(R.string.settingsOptionGiveFeedback, endIcon = OPEN_OUTSIDE) { onItemClick(GIVE_FEEDBACK) } - SettingItem(R.string.version, description = "0.0.1", onClick = null) + SettingItem(R.string.settingsOptionDiscoverInfomaniak, selectedMenu == DISCOVER_INFOMANIAK, endIcon = OPEN_OUTSIDE) { + onItemClick(DISCOVER_INFOMANIAK) + } + SettingItem(R.string.settingsOptionShareIdeas, selectedMenu == SHARE_IDEAS, endIcon = OPEN_OUTSIDE) { + onItemClick(SHARE_IDEAS) + } + SettingItem(R.string.settingsOptionGiveFeedback, selectedMenu == GIVE_FEEDBACK, endIcon = OPEN_OUTSIDE) { + onItemClick(GIVE_FEEDBACK) + } + SettingItem(R.string.version, isSelected = false, description = "0.0.1", onClick = null) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt index 3865cffec..68328f57f 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt @@ -18,8 +18,10 @@ package com.infomaniak.swisstransfer.ui.screen.main.settings.components +import android.content.res.Configuration import androidx.annotation.StringRes import androidx.compose.foundation.layout.* +import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material3.Icon import androidx.compose.material3.Surface import androidx.compose.material3.Text @@ -46,6 +48,7 @@ private val ITEM_MIN_HEIGHT = 56.dp @Composable fun SettingItem( @StringRes titleRes: Int, + isSelected: Boolean, icon: ImageVector? = null, description: String? = null, endIcon: EndIconType? = null, @@ -58,6 +61,7 @@ fun SettingItem( onClick?.let { SharpRippleButton( modifier = modifier, + isSelected = isSelected, onClick = it, ) { SettingItemContent(icon, titleRes, description, endIcon) @@ -107,22 +111,23 @@ private fun SettingItemContent( } } -@Preview +@Preview(name = "Light") +@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) @Composable private fun SettingItemPreview() { SwissTransferTheme { Surface { - Column { + Column(modifier = Modifier.selectableGroup()) { SettingTitle(R.string.appName) - SettingItem(R.string.appName, AppIcons.Add, "Clair", EndIconType.CHEVRON) {} - SettingItem(R.string.appName, AppIcons.Folder, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, description = "1.1.2") {} - SettingItem(R.string.appName) {} + SettingItem(R.string.appName, true, AppIcons.Add, "Clair", EndIconType.CHEVRON) {} + SettingItem(R.string.appName, false, AppIcons.Folder, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, false, description = "1.1.2") {} + SettingItem(R.string.appName, false) {} SettingDivider() SettingTitle(R.string.appName) - SettingItem(R.string.appName, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, description = "0.0.1", onClick = null) + SettingItem(R.string.appName, false, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, false, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, false, description = "0.0.1", onClick = null) } } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt index 5e2479f7a..0b6f0005e 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SingleSelectOptions.kt @@ -57,7 +57,7 @@ fun SingleSelectOptions(items: List, selectedItem: () -> Int, set @Composable private fun SettingOptionItem(item: SettingOption, isSelected: Boolean, onClick: () -> Unit) { SharpRippleButton( - modifier = Modifier.selectable(selected = isSelected, onClick = {}), // onClick left empty because handled by button + modifier = Modifier.selectable(selected = isSelected, onClick = onClick), onClick = onClick ) { Row( diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt index 685d1e85a..342a7c3e4 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorDark.kt @@ -69,4 +69,5 @@ val CustomDarkColorScheme = CustomColorScheme( iconColor = Color(shark), navigationItemBackground = Color(dark2), tertiaryButtonBackground = Color(dark2), + selectedSettingItem = Color(dark2), ) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt index 51f77945f..80c2bef8c 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/ColorLight.kt @@ -73,4 +73,5 @@ val CustomLightColorScheme = CustomColorScheme( iconColor = Color(elephant), navigationItemBackground = LightColorScheme.background, tertiaryButtonBackground = Color(rabbit), + selectedSettingItem = Color(rabbit), ) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt index 832c5ec04..def44f51c 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/theme/Theme.kt @@ -67,4 +67,5 @@ data class CustomColorScheme( val iconColor: Color = Color.Unspecified, val navigationItemBackground: Color = Color.Unspecified, val tertiaryButtonBackground: Color = Color.Unspecified, + val selectedSettingItem: Color = Color.Unspecified, ) From e5d87f6bf29c96325dcd51a890b8d45634b2fae7 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 14:43:23 +0200 Subject: [PATCH 15/17] Make isSelected a lambda --- .../ui/components/SharpRippleButton.kt | 6 +-- .../ui/screen/main/settings/SettingsScreen.kt | 42 +++++++++---------- .../main/settings/components/SettingItem.kt | 16 +++---- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt index ce639be8a..37cd66c8f 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/SharpRippleButton.kt @@ -32,11 +32,11 @@ import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme @Composable fun SharpRippleButton( modifier: Modifier = Modifier, - isSelected: Boolean = false, + isSelected: () -> Boolean = { false }, onClick: () -> Unit, content: @Composable RowScope.() -> Unit, ) { - val colors = if (isSelected) { + val colors = if (isSelected()) { ButtonDefaults.textButtonColors( contentColor = SwissTransferTheme.colors.primaryTextColor, containerColor = SwissTransferTheme.colors.selectedSettingItem, @@ -46,7 +46,7 @@ fun SharpRippleButton( } Button( modifier = modifier.selectable( - selected = isSelected, + selected = isSelected(), onClick = onClick, ), colors = colors, 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 3730998b4..28d9d7c2a 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 @@ -111,12 +111,12 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingTitle(R.string.settingsCategoryGeneral) // TODO: Use correct icon - SettingItem(R.string.settingsOptionTheme, selectedMenu == THEME, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } + SettingItem(R.string.settingsOptionTheme, { selectedMenu == THEME }, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } SettingItem( - R.string.settingsOptionNotifications, - selectedMenu == NOTIFICATIONS, - AppIcons.Bell, - "TODO", + titleRes = R.string.settingsOptionNotifications, + isSelected = { selectedMenu == NOTIFICATIONS }, + icon = AppIcons.Bell, + description = "TODO", endIcon = OPEN_OUTSIDE, ) { onItemClick(NOTIFICATIONS) @@ -127,29 +127,29 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingTitle(R.string.settingsCategoryDefaultSettings) // TODO: Use correct icon SettingItem( - R.string.settingsOptionValidityPeriod, - selectedMenu == VALIDITY_PERIOD, - AppIcons.Add, - "TODO", + titleRes = R.string.settingsOptionValidityPeriod, + isSelected = { selectedMenu == VALIDITY_PERIOD }, + icon = AppIcons.Add, + description = "TODO", endIcon = CHEVRON, ) { onItemClick(VALIDITY_PERIOD) } // TODO: Use correct icon SettingItem( - R.string.settingsOptionDownloadLimit, - selectedMenu == DOWNLOAD_LIMIT, - AppIcons.Add, - "TODO", + titleRes = R.string.settingsOptionDownloadLimit, + isSelected = { selectedMenu == DOWNLOAD_LIMIT }, + icon = AppIcons.Add, + description = "TODO", endIcon = CHEVRON, ) { onItemClick(DOWNLOAD_LIMIT) } SettingItem( - R.string.settingsOptionEmailLanguage, - selectedMenu == EMAIL_LANGUAGE, - AppIcons.SpeechBubble, - "TODO", + titleRes = R.string.settingsOptionEmailLanguage, + isSelected = { selectedMenu == EMAIL_LANGUAGE }, + icon = AppIcons.SpeechBubble, + description = "TODO", endIcon = CHEVRON, ) { onItemClick(EMAIL_LANGUAGE) @@ -158,16 +158,16 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingDivider() SettingTitle(R.string.settingsCategoryAbout) - SettingItem(R.string.settingsOptionDiscoverInfomaniak, selectedMenu == DISCOVER_INFOMANIAK, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionDiscoverInfomaniak, { selectedMenu == DISCOVER_INFOMANIAK }, endIcon = OPEN_OUTSIDE) { onItemClick(DISCOVER_INFOMANIAK) } - SettingItem(R.string.settingsOptionShareIdeas, selectedMenu == SHARE_IDEAS, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionShareIdeas, { selectedMenu == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { onItemClick(SHARE_IDEAS) } - SettingItem(R.string.settingsOptionGiveFeedback, selectedMenu == GIVE_FEEDBACK, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionGiveFeedback, { selectedMenu == GIVE_FEEDBACK }, endIcon = OPEN_OUTSIDE) { onItemClick(GIVE_FEEDBACK) } - SettingItem(R.string.version, isSelected = false, description = "0.0.1", onClick = null) + SettingItem(R.string.version, isSelected = { false }, description = "0.0.1", onClick = null) } } diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt index 68328f57f..80ecb6bb1 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/components/SettingItem.kt @@ -48,7 +48,7 @@ private val ITEM_MIN_HEIGHT = 56.dp @Composable fun SettingItem( @StringRes titleRes: Int, - isSelected: Boolean, + isSelected: () -> Boolean, icon: ImageVector? = null, description: String? = null, endIcon: EndIconType? = null, @@ -119,15 +119,15 @@ private fun SettingItemPreview() { Surface { Column(modifier = Modifier.selectableGroup()) { SettingTitle(R.string.appName) - SettingItem(R.string.appName, true, AppIcons.Add, "Clair", EndIconType.CHEVRON) {} - SettingItem(R.string.appName, false, AppIcons.Folder, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, false, description = "1.1.2") {} - SettingItem(R.string.appName, false) {} + SettingItem(R.string.appName, { true }, AppIcons.Add, "Clair", EndIconType.CHEVRON) {} + SettingItem(R.string.appName, { false }, AppIcons.Folder, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, { false }, description = "1.1.2") {} + SettingItem(R.string.appName, { false }) {} SettingDivider() SettingTitle(R.string.appName) - SettingItem(R.string.appName, false, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, false, endIcon = EndIconType.OPEN_OUTSIDE) {} - SettingItem(R.string.appName, false, description = "0.0.1", onClick = null) + SettingItem(R.string.appName, { false }, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, { false }, endIcon = EndIconType.OPEN_OUTSIDE) {} + SettingItem(R.string.appName, { false }, description = "0.0.1", onClick = null) } } } From 90af63e06221ed5816fc92204c030941ea4bd6ca Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 14:51:23 +0200 Subject: [PATCH 16/17] Add missing icons to general setting page --- .../swisstransfer/ui/icons/app/Clock.kt | 64 ++++++++++++ .../ui/icons/app/FileBadgeArrowDown.kt | 91 +++++++++++++++++ .../ui/icons/app/PaintbrushPalette.kt | 97 +++++++++++++++++++ .../ui/screen/main/settings/SettingsScreen.kt | 21 ++-- 4 files changed, 264 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Clock.kt create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/FileBadgeArrowDown.kt create mode 100644 app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/PaintbrushPalette.kt diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Clock.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Clock.kt new file mode 100644 index 000000000..c0243b6cb --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/Clock.kt @@ -0,0 +1,64 @@ +package com.infomaniak.swisstransfer.ui.icons.app + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.Clock: ImageVector + get() { + if (_clock != null) { + return _clock!! + } + _clock = Builder( + name = "Clock", defaultWidth = 24.0.dp, defaultHeight = 24.0.dp, viewportWidth = 24.0f, viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(1.5f, 12.0f) + arcToRelative(10.5f, 10.5f, 0.0f, true, false, 21.0f, 0.0f) + arcToRelative(10.5f, 10.5f, 0.0f, false, false, -21.0f, 0.0f) + moveTo(12.0f, 12.0f) + verticalLineTo(8.25f) + moveTo(12.0f, 12.0f) + lineToRelative(4.687f, 4.688f) + } + } + }.build() + return _clock!! + } + +private var _clock: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.Clock, + contentDescription = null, + modifier = Modifier.size(AppIcons.previewSize) + ) + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/FileBadgeArrowDown.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/FileBadgeArrowDown.kt new file mode 100644 index 000000000..085b43d47 --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/FileBadgeArrowDown.kt @@ -0,0 +1,91 @@ +package com.infomaniak.swisstransfer.ui.icons.app + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.FileBadgeArrowDown: ImageVector + get() { + if (_fileBadgeArrowDown != null) { + return _fileBadgeArrowDown!! + } + _fileBadgeArrowDown = Builder( + name = "FileBadgeArrowDown", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(11.25f, 17.25f) + arcToRelative(6.0f, 6.0f, 0.0f, true, false, 12.0f, 0.0f) + arcToRelative(6.0f, 6.0f, 0.0f, false, false, -12.0f, 0.0f) + moveToRelative(6.0f, -3.0f) + verticalLineToRelative(6.0f) + moveToRelative(0.0f, 0.0f) + lineTo(15.0f, 18.0f) + moveToRelative(2.25f, 2.25f) + lineTo(19.5f, 18.0f) + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(8.25f, 20.25f) + horizontalLineToRelative(-6.0f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, -1.5f, -1.5f) + verticalLineTo(2.25f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.5f, -1.5f) + horizontalLineToRelative(10.629f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 1.06f, 0.439f) + lineToRelative(2.872f, 2.872f) + arcToRelative(1.5f, 1.5f, 0.0f, false, true, 0.439f, 1.06f) + verticalLineTo(8.25f) + } + } + }.build() + return _fileBadgeArrowDown!! + } + +private var _fileBadgeArrowDown: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.FileBadgeArrowDown, + contentDescription = null, + modifier = Modifier.size(AppIcons.previewSize) + ) + } +} diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/PaintbrushPalette.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/PaintbrushPalette.kt new file mode 100644 index 000000000..bade550ec --- /dev/null +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/icons/app/PaintbrushPalette.kt @@ -0,0 +1,97 @@ +package com.infomaniak.swisstransfer.ui.icons.app + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.PathFillType.Companion.NonZero +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.ImageVector.Builder +import androidx.compose.ui.graphics.vector.group +import androidx.compose.ui.graphics.vector.path +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.infomaniak.swisstransfer.ui.icons.AppIcons +import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound +import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + +val AppIcons.PaintbrushPalette: ImageVector + get() { + if (_paintbrushPalette != null) { + return _paintbrushPalette!! + } + _paintbrushPalette = Builder( + name = "PaintbrushPalette", + defaultWidth = 24.0.dp, + defaultHeight = 24.0.dp, + viewportWidth = 24.0f, + viewportHeight = 24.0f + ).apply { + group { + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(10.644f, 17.865f) + curveToRelative(1.589f, -1.9f, 0.1f, -4.338f, 1.513f, -5.981f) + arcToRelative(2.759f, 2.759f, 0.0f, true, true, 4.18f, 3.6f) + arcToRelative(6.5f, 6.5f, 0.0f, false, true, -5.693f, 2.38f) + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(16.62f, 12.277f) + lineToRelative(6.232f, -8.253f) + arcTo(2.037f, 2.037f, 0.0f, true, false, 19.4f, 1.88f) + lineTo(14.871f, 11.0f) + } + path( + fill = null, + stroke = SolidColor(Color(0xFF9f9f9f)), + strokeLineWidth = 1.5f, + strokeLineCap = strokeCapRound, + strokeLineJoin = strokeJoinRound, + strokeLineMiter = 4.0f, + pathFillType = NonZero + ) { + moveTo(13.5f, 5.225f) + horizontalLineTo(3.75f) + arcToRelative(3.0f, 3.0f, 0.0f, false, false, -3.0f, 3.0f) + verticalLineToRelative(12.0f) + arcToRelative(3.0f, 3.0f, 0.0f, false, false, 3.0f, 3.0f) + horizontalLineToRelative(12.0f) + arcToRelative(3.0f, 3.0f, 0.0f, false, false, 3.0f, -3.0f) + verticalLineToRelative(-1.5f) + } + } + }.build() + return _paintbrushPalette!! + } + +private var _paintbrushPalette: ImageVector? = null + +@Preview +@Composable +private fun Preview() { + Box { + Image( + imageVector = AppIcons.PaintbrushPalette, + contentDescription = null, + modifier = Modifier.size(AppIcons.previewSize) + ) + } +} 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 28d9d7c2a..5502b8ec2 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 @@ -43,9 +43,7 @@ import androidx.compose.ui.res.stringResource import com.infomaniak.swisstransfer.R import com.infomaniak.swisstransfer.ui.components.TwoPaneScaffold import com.infomaniak.swisstransfer.ui.icons.AppIcons -import com.infomaniak.swisstransfer.ui.icons.app.Add -import com.infomaniak.swisstransfer.ui.icons.app.Bell -import com.infomaniak.swisstransfer.ui.icons.app.SpeechBubble +import com.infomaniak.swisstransfer.ui.icons.app.* import com.infomaniak.swisstransfer.ui.screen.main.settings.SettingsOptionScreens.* import com.infomaniak.swisstransfer.ui.screen.main.settings.components.EndIconType.CHEVRON import com.infomaniak.swisstransfer.ui.screen.main.settings.components.EndIconType.OPEN_OUTSIDE @@ -110,8 +108,15 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele ) SettingTitle(R.string.settingsCategoryGeneral) - // TODO: Use correct icon - SettingItem(R.string.settingsOptionTheme, { selectedMenu == THEME }, AppIcons.Add, "TODO", CHEVRON) { onItemClick(THEME) } + SettingItem( + titleRes = R.string.settingsOptionTheme, + isSelected = { selectedMenu == THEME }, + icon = AppIcons.PaintbrushPalette, + description = "TODO", + CHEVRON + ) { + onItemClick(THEME) + } SettingItem( titleRes = R.string.settingsOptionNotifications, isSelected = { selectedMenu == NOTIFICATIONS }, @@ -125,21 +130,19 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingDivider() SettingTitle(R.string.settingsCategoryDefaultSettings) - // TODO: Use correct icon SettingItem( titleRes = R.string.settingsOptionValidityPeriod, isSelected = { selectedMenu == VALIDITY_PERIOD }, - icon = AppIcons.Add, + icon = AppIcons.FileBadgeArrowDown, description = "TODO", endIcon = CHEVRON, ) { onItemClick(VALIDITY_PERIOD) } - // TODO: Use correct icon SettingItem( titleRes = R.string.settingsOptionDownloadLimit, isSelected = { selectedMenu == DOWNLOAD_LIMIT }, - icon = AppIcons.Add, + icon = AppIcons.Clock, description = "TODO", endIcon = CHEVRON, ) { From bfb358dccce3a9d87f3718f763a17edaf55f207d Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Wed, 21 Aug 2024 16:06:28 +0200 Subject: [PATCH 17/17] Correctly name getSelectedSetting --- .../ui/screen/main/settings/SettingsScreen.kt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 5502b8ec2..f8fefb3be 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 @@ -68,7 +68,7 @@ fun SettingsScreenWrapper( // Navigate to the detail pane with the passed item navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, - getSelectedMenu = { currentDestination?.content }, + getSelectedSetting = { currentDestination?.content }, ) }, detailPane = { @@ -93,8 +93,8 @@ fun SettingsScreenWrapper( } @Composable -private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedMenu: () -> SettingsOptionScreens?) { - val selectedMenu = getSelectedMenu() +private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSelectedSetting: () -> SettingsOptionScreens?) { + val selectedSetting = getSelectedSetting() Column( modifier = Modifier @@ -110,7 +110,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingTitle(R.string.settingsCategoryGeneral) SettingItem( titleRes = R.string.settingsOptionTheme, - isSelected = { selectedMenu == THEME }, + isSelected = { selectedSetting == THEME }, icon = AppIcons.PaintbrushPalette, description = "TODO", CHEVRON @@ -119,7 +119,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele } SettingItem( titleRes = R.string.settingsOptionNotifications, - isSelected = { selectedMenu == NOTIFICATIONS }, + isSelected = { selectedSetting == NOTIFICATIONS }, icon = AppIcons.Bell, description = "TODO", endIcon = OPEN_OUTSIDE, @@ -132,7 +132,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingTitle(R.string.settingsCategoryDefaultSettings) SettingItem( titleRes = R.string.settingsOptionValidityPeriod, - isSelected = { selectedMenu == VALIDITY_PERIOD }, + isSelected = { selectedSetting == VALIDITY_PERIOD }, icon = AppIcons.FileBadgeArrowDown, description = "TODO", endIcon = CHEVRON, @@ -141,7 +141,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele } SettingItem( titleRes = R.string.settingsOptionDownloadLimit, - isSelected = { selectedMenu == DOWNLOAD_LIMIT }, + isSelected = { selectedSetting == DOWNLOAD_LIMIT }, icon = AppIcons.Clock, description = "TODO", endIcon = CHEVRON, @@ -150,7 +150,7 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele } SettingItem( titleRes = R.string.settingsOptionEmailLanguage, - isSelected = { selectedMenu == EMAIL_LANGUAGE }, + isSelected = { selectedSetting == EMAIL_LANGUAGE }, icon = AppIcons.SpeechBubble, description = "TODO", endIcon = CHEVRON, @@ -161,13 +161,13 @@ private fun SettingsScreen(onItemClick: (SettingsOptionScreens) -> Unit, getSele SettingDivider() SettingTitle(R.string.settingsCategoryAbout) - SettingItem(R.string.settingsOptionDiscoverInfomaniak, { selectedMenu == DISCOVER_INFOMANIAK }, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionDiscoverInfomaniak, { selectedSetting == DISCOVER_INFOMANIAK }, endIcon = OPEN_OUTSIDE) { onItemClick(DISCOVER_INFOMANIAK) } - SettingItem(R.string.settingsOptionShareIdeas, { selectedMenu == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionShareIdeas, { selectedSetting == SHARE_IDEAS }, endIcon = OPEN_OUTSIDE) { onItemClick(SHARE_IDEAS) } - SettingItem(R.string.settingsOptionGiveFeedback, { selectedMenu == GIVE_FEEDBACK }, endIcon = OPEN_OUTSIDE) { + SettingItem(R.string.settingsOptionGiveFeedback, { selectedSetting == GIVE_FEEDBACK }, endIcon = OPEN_OUTSIDE) { onItemClick(GIVE_FEEDBACK) } SettingItem(R.string.version, isSelected = { false }, description = "0.0.1", onClick = null)