From a1bef15076132af2bfd811bb127f75c46d98f6f2 Mon Sep 17 00:00:00 2001 From: Pauline Auvray Date: Wed, 7 Jun 2023 13:49:46 +0200 Subject: [PATCH 1/5] [#545] Replace demo item saver by OdsExposedDropdownMenuItemSaver class in the library --- .../components/menus/MenuExposedDropdown.kt | 23 ++++--------------- .../component/menu/OdsExposedDropdownMenu.kt | 17 +++++++++----- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt index 88157e331..050a90ee0 100644 --- a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt +++ b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt @@ -17,14 +17,8 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.rememberBottomSheetScaffoldState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.mapSaver +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource @@ -41,6 +35,7 @@ import com.orange.ods.compose.component.list.OdsListItem import com.orange.ods.compose.component.list.OdsSwitchTrailing import com.orange.ods.compose.component.menu.OdsExposedDropdownMenu import com.orange.ods.compose.component.menu.OdsExposedDropdownMenuItem +import com.orange.ods.compose.component.menu.OdsExposedDropdownMenuItemSaver @OptIn(ExperimentalMaterialApi::class) @Composable @@ -58,20 +53,10 @@ fun MenuExposedDropdown() { } var items by remember { mutableStateOf(dropdownItems) } - val itemSaver = run { - val itemKey = "item" - mapSaver( - save = { - mapOf(itemKey to it.label) - }, - restore = { - OdsExposedDropdownMenuItem(it[itemKey] as String) - } - ) - } with(customizationState) { - val selectedItem: MutableState = rememberSaveable(stateSaver = itemSaver) { mutableStateOf(dropdownItems.first()) } + val selectedItem: MutableState = + rememberSaveable(stateSaver = OdsExposedDropdownMenuItemSaver()) { mutableStateOf(dropdownItems.first()) } if (hasIcons) { items = dropdownItems selectedItem.value = dropdownItems.first { selectedItem.value.label == it.label } diff --git a/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt b/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt index ccd8170d2..909609ebd 100644 --- a/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt +++ b/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt @@ -13,12 +13,9 @@ package com.orange.ods.compose.component.menu import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExposedDropdownMenuBox -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.SaverScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource @@ -90,6 +87,14 @@ fun OdsExposedDropdownMenu( data class OdsExposedDropdownMenuItem(val label: String, val icon: Painter? = null) +/** + * This Saver implementation converts OdsExposedDropdownMenuItem object which we don't know how to save to String which we can save. + */ +class OdsExposedDropdownMenuItemSaver : Saver { + override fun restore(value: String) = OdsExposedDropdownMenuItem(label = value) + override fun SaverScope.save(value: OdsExposedDropdownMenuItem) = value.label +} + /** * Note: Please use Android Studio preview interactive mode to see the OdsExposedDropdownMenu preview cause expanded is a target state. */ From b30fde2a50912c18180a5030a013e631cf14900b Mon Sep 17 00:00:00 2001 From: Pauline Auvray Date: Wed, 7 Jun 2023 13:50:22 +0200 Subject: [PATCH 2/5] [#545] Update documentation to mention OdsExposedDropdownMenuItemSaver --- docs/components/Menus.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/components/Menus.md b/docs/components/Menus.md index ad2784cf6..640779a75 100644 --- a/docs/components/Menus.md +++ b/docs/components/Menus.md @@ -11,8 +11,8 @@ description: Menus appear from a button, action, or other control. It contains a * [Specifications references](#specifications-references) * [Accessibility](#accessibility) * [Variants](#variants) - * [Dropdown menu](#dropdown-menu) - * [Exposed dropdown menu](#exposed-dropdown-menu) + * [Dropdown menu](#dropdown-menu) + * [Exposed dropdown menu](#exposed-dropdown-menu) * [Component specific tokens](#component-specific-tokens) --- @@ -43,22 +43,22 @@ The library offers an `OdsDropdownMenu` container composable in which you can ad var menuExpanded by remember { mutableStateOf(false) } OdsDropdownMenu( - expanded = menuExpanded, - onDismissRequest = { menuExpanded = false }, + expanded = menuExpanded, + onDismissRequest = { menuExpanded = false }, offset = DpOffset(x = (-100).dp, y = (-10).dp) ) { OdsDropdownMenuItem( text = "Summer salad", icon = painterResource(id = R.drawable.ic_salad), - onClick = { + onClick = { // Do something - } + } ) OdsDivider() // Allow to add a divider between the 2 items OdsDropdownMenuItem( text = "Brocoli soup", icon = painterResource(id = R.drawable.ic_soup), - onClick = { + onClick = { // Do something } ) @@ -85,7 +85,8 @@ val items = listOf( OdsExposedDropdownMenuItem("Map", painterResource(id = android.R.drawable.ic_dialog_map)), OdsExposedDropdownMenuItem("Dialer", painterResource(id = android.R.drawable.ic_dialog_dialer)), ) -val selectedItem = remember { mutableStateOf(items.first()) } +val selectedItem = + rememberSaveable(stateSaver = OdsExposedDropdownMenuItemSaver()) { mutableStateOf(items.first()) } OdsExposedDropdownMenu( label = "Dropdown menu label", @@ -98,6 +99,8 @@ OdsExposedDropdownMenu( ) ``` +Note that ODS library provides an `OdsExposedDropdownMenuItemSaver` that allows you to store and restore an `OdsExposedDropdownMenuItem`. + > **XML implementation** *Not available yet* From 24be58aeace2ff813a23dc1d4152a6adc4606864 Mon Sep 17 00:00:00 2001 From: Pauline Auvray Date: Wed, 7 Jun 2023 13:52:17 +0200 Subject: [PATCH 3/5] [#545] Update changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 2bd84e65a..5e5a04dee 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - \[App\] Add component image item ([#473](https://github.com/Orange-OpenSource/ods-android/issues/473)) - \[Lib\] Add `OdsImageItem` component ([#473](https://github.com/Orange-OpenSource/ods-android/issues/473)) +- \[Lib\] Add `OdsExposedDropdownMenuItemSaver` class to allow to save and restore `OdsExposedDropdownMenuItem` ([#545](https://github.com/Orange-OpenSource/ods-android/issues/545)) ## [0.13.0](https://github.com/Orange-OpenSource/ods-android/compare/0.12.0...0.13.0) - 2023-06-01 From 8d99471d811885748f30e02e25b7fa9b4bff367a Mon Sep 17 00:00:00 2001 From: Pauline Auvray Date: Tue, 20 Jun 2023 17:03:59 +0200 Subject: [PATCH 4/5] [#545] Review: Use parcelize annotation on OdsExposedDropdownMenuItem instead of a custom saver --- .../app/ui/components/menus/MenuDropdown.kt | 6 +--- .../components/menus/MenuExposedDropdown.kt | 9 ++---- docs/components/Menus.md | 11 +++---- lib/build.gradle.kts | 1 + .../component/menu/OdsExposedDropdownMenu.kt | 29 +++++++------------ 5 files changed, 20 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuDropdown.kt b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuDropdown.kt index f00a9658d..936b83b5e 100644 --- a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuDropdown.kt +++ b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuDropdown.kt @@ -20,12 +20,8 @@ import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.rememberBottomSheetScaffoldState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.platform.LocalContext diff --git a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt index 050a90ee0..0692d4e33 100644 --- a/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt +++ b/app/src/main/java/com/orange/ods/app/ui/components/menus/MenuExposedDropdown.kt @@ -22,7 +22,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import com.orange.ods.app.R import com.orange.ods.app.domain.recipes.LocalRecipes @@ -35,7 +34,6 @@ import com.orange.ods.compose.component.list.OdsListItem import com.orange.ods.compose.component.list.OdsSwitchTrailing import com.orange.ods.compose.component.menu.OdsExposedDropdownMenu import com.orange.ods.compose.component.menu.OdsExposedDropdownMenuItem -import com.orange.ods.compose.component.menu.OdsExposedDropdownMenuItemSaver @OptIn(ExperimentalMaterialApi::class) @Composable @@ -46,7 +44,7 @@ fun MenuExposedDropdown() { val recipes = LocalRecipes.current.take(4) val dropdownItems = recipes.map { recipe -> - OdsExposedDropdownMenuItem(label = recipe.title, icon = recipe.iconResId?.let { painterResource(id = it) }) + OdsExposedDropdownMenuItem(label = recipe.title, iconResId = recipe.iconResId) } val textOnlyDropdownItems = recipes.map { recipe -> OdsExposedDropdownMenuItem(label = recipe.title) @@ -55,8 +53,7 @@ fun MenuExposedDropdown() { var items by remember { mutableStateOf(dropdownItems) } with(customizationState) { - val selectedItem: MutableState = - rememberSaveable(stateSaver = OdsExposedDropdownMenuItemSaver()) { mutableStateOf(dropdownItems.first()) } + val selectedItem: MutableState = rememberSaveable { mutableStateOf(dropdownItems.first()) } if (hasIcons) { items = dropdownItems selectedItem.value = dropdownItems.first { selectedItem.value.label == it.label } @@ -107,7 +104,7 @@ fun MenuExposedDropdown() { items.forEach { item -> classInstance(OdsExposedDropdownMenuItem::class.java) { string("label", item.label) - if (hasIcons) icon() + if (hasIcons) simple("iconResId", "") } } } diff --git a/docs/components/Menus.md b/docs/components/Menus.md index 640779a75..ec5c65dcd 100644 --- a/docs/components/Menus.md +++ b/docs/components/Menus.md @@ -81,12 +81,11 @@ To display an exposed dropdown menu, you can use the `OdsExposedDropdownMenu` co ```kotlin val items = listOf( - OdsExposedDropdownMenuItem("Email", painterResource(id = android.R.drawable.ic_dialog_email)), - OdsExposedDropdownMenuItem("Map", painterResource(id = android.R.drawable.ic_dialog_map)), - OdsExposedDropdownMenuItem("Dialer", painterResource(id = android.R.drawable.ic_dialog_dialer)), + OdsExposedDropdownMenuItem("Email", android.R.drawable.ic_dialog_email), + OdsExposedDropdownMenuItem("Map", android.R.drawable.ic_dialog_map), + OdsExposedDropdownMenuItem("Dialer", android.R.drawable.ic_dialog_dialer), ) -val selectedItem = - rememberSaveable(stateSaver = OdsExposedDropdownMenuItemSaver()) { mutableStateOf(items.first()) } +val selectedItem = rememberSaveable() { mutableStateOf(items.first()) } OdsExposedDropdownMenu( label = "Dropdown menu label", @@ -99,8 +98,6 @@ OdsExposedDropdownMenu( ) ``` -Note that ODS library provides an `OdsExposedDropdownMenuItemSaver` that allows you to store and restore an `OdsExposedDropdownMenuItem`. - > **XML implementation** *Not available yet* diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 035405a55..7df646b8d 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -17,6 +17,7 @@ plugins { id("kotlin-android") id("github") id("maven-central-publish") + id("kotlin-parcelize") } /** diff --git a/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt b/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt index 909609ebd..2fd1cb6a2 100644 --- a/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt +++ b/lib/src/main/java/com/orange/ods/compose/component/menu/OdsExposedDropdownMenu.kt @@ -10,14 +10,13 @@ package com.orange.ods.compose.component.menu +import android.os.Parcelable +import androidx.annotation.DrawableRes import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExposedDropdownMenuBox import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.Saver -import androidx.compose.runtime.saveable.SaverScope import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.PreviewParameter import com.orange.ods.compose.component.OdsComposable @@ -26,6 +25,7 @@ import com.orange.ods.compose.component.textfield.OdsTextField import com.orange.ods.compose.component.utilities.BasicPreviewParameterProvider import com.orange.ods.compose.component.utilities.Preview import com.orange.ods.compose.component.utilities.UiModePreviews +import kotlinx.parcelize.Parcelize /** * ODS menus. @@ -64,7 +64,7 @@ fun OdsExposedDropdownMenu( onValueChange = {}, readOnly = true, label = label, - leadingIcon = selectedItem.value.icon, + leadingIcon = selectedItem.value.iconResId?.let { painterResource(id = it) }, trailing = OdsExposedDropdownMenuTrailing(expanded = if (enabled) expanded else false, enabled = enabled), enabled = enabled ) @@ -74,7 +74,7 @@ fun OdsExposedDropdownMenu( onDismissRequest = { expanded = false }, content = { items.forEach { item -> - OdsDropdownMenuItem(text = item.label, icon = item.icon, onClick = { + OdsDropdownMenuItem(text = item.label, icon = item.iconResId?.let { painterResource(id = it) }, onClick = { selectedItem.value = item expanded = false onItemSelectionChange(item) @@ -85,15 +85,8 @@ fun OdsExposedDropdownMenu( } } -data class OdsExposedDropdownMenuItem(val label: String, val icon: Painter? = null) - -/** - * This Saver implementation converts OdsExposedDropdownMenuItem object which we don't know how to save to String which we can save. - */ -class OdsExposedDropdownMenuItemSaver : Saver { - override fun restore(value: String) = OdsExposedDropdownMenuItem(label = value) - override fun SaverScope.save(value: OdsExposedDropdownMenuItem) = value.label -} +@Parcelize +data class OdsExposedDropdownMenuItem(val label: String, @DrawableRes val iconResId: Int? = null) : Parcelable /** * Note: Please use Android Studio preview interactive mode to see the OdsExposedDropdownMenu preview cause expanded is a target state. @@ -102,10 +95,10 @@ class OdsExposedDropdownMenuItemSaver : Saver Date: Tue, 20 Jun 2023 17:05:50 +0200 Subject: [PATCH 5/5] [#545] Update changelog --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 5e5a04dee..4f0fa8fa1 100644 --- a/changelog.md +++ b/changelog.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - \[App\] Add component image item ([#473](https://github.com/Orange-OpenSource/ods-android/issues/473)) - \[Lib\] Add `OdsImageItem` component ([#473](https://github.com/Orange-OpenSource/ods-android/issues/473)) -- \[Lib\] Add `OdsExposedDropdownMenuItemSaver` class to allow to save and restore `OdsExposedDropdownMenuItem` ([#545](https://github.com/Orange-OpenSource/ods-android/issues/545)) +- \[Lib\] Add `@Parcelize` annotation on `OdsExposedDropdownMenuItem` to allow to save and restore it ([#545](https://github.com/Orange-OpenSource/ods-android/issues/545)) ## [0.13.0](https://github.com/Orange-OpenSource/ods-android/compare/0.12.0...0.13.0) - 2023-06-01