From 306f669b8af4f87e9d794690dc9011e73754d587 Mon Sep 17 00:00:00 2001 From: lm41 Date: Wed, 27 Mar 2024 15:46:19 +0100 Subject: [PATCH 1/3] Add ImageVector support to the preference datastore ui --- .../jetpref/datastore/ui/Common.kt | 19 ++++++ .../datastore/ui/DialogSliderPreference.kt | 59 +++++++++---------- .../jetpref/datastore/ui/JetIcon.kt | 41 +++++++++++++ .../jetpref/datastore/ui/ListPreference.kt | 5 +- .../jetpref/datastore/ui/Preference.kt | 5 +- .../jetpref/datastore/ui/PreferenceUi.kt | 11 ++-- .../jetpref/datastore/ui/SwitchPreference.kt | 11 ++-- example/build.gradle.kts | 1 + .../jetpref/example/ui/settings/HomeScreen.kt | 8 ++- gradle/libs.versions.toml | 2 + 10 files changed, 112 insertions(+), 50 deletions(-) create mode 100644 datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Common.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Common.kt index 8a6125f..69ccf43 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Common.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Common.kt @@ -19,6 +19,7 @@ package dev.patrickgold.jetpref.datastore.ui import androidx.annotation.DrawableRes import androidx.compose.material.Icon import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.painterResource @Composable @@ -38,3 +39,21 @@ internal fun maybeJetIcon( else -> null } } + +@Composable +internal fun maybeJetIcon( + imageVector: ImageVector?, + iconSpaceReserved: Boolean, + contentDescription: String? = null, +): @Composable (() -> Unit)? { + return when { + imageVector != null -> ({ + Icon( + imageVector = imageVector, + contentDescription = contentDescription, + ) + }) + iconSpaceReserved -> ({ }) + else -> null + } +} diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt index e66d7be..d8dc699 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt @@ -16,7 +16,6 @@ package dev.patrickgold.jetpref.datastore.ui -import androidx.annotation.DrawableRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -50,7 +49,7 @@ import kotlin.math.roundToLong internal fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier, - @DrawableRes iconId: Int?, + icon: JetIcon?, iconSpaceReserved: Boolean, title: String, valueLabel: @Composable (V) -> String, @@ -84,7 +83,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc isDialogOpen.value = true } ), - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved), text = title, secondaryText = summary(prefValue), enabled = isEnabled, @@ -139,7 +138,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier, - @DrawableRes iconId: Int?, + icon: JetIcon?, iconSpaceReserved: Boolean, title: String, primaryLabel: String, @@ -179,7 +178,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc isDialogOpen.value = true } ), - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved = iconSpaceReserved), text = title, secondaryText = summary(primaryPrefValue, secondaryPrefValue), enabled = isEnabled, @@ -262,7 +261,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc * * @param pref The integer preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry icon. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -289,7 +288,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Int) -> String = { it.toString() }, @@ -303,7 +302,7 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - pref, modifier, iconId, iconSpaceReserved, title, valueLabel, summary, min, max, + pref, modifier, icon, iconSpaceReserved, title, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedValue, dialogStrings, enabledIf, visibleIf, ) { try { @@ -353,7 +352,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -370,9 +369,9 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - primaryPref, secondaryPref, modifier, iconId, iconSpaceReserved, title, - primaryLabel, secondaryLabel, valueLabel, summary, min, max, stepIncrement, - onPreviewSelectedPrimaryValue, onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, + primaryPref, secondaryPref, modifier, icon, iconSpaceReserved, title, primaryLabel, + secondaryLabel, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedPrimaryValue, + onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, ) { try { it.roundToInt() @@ -414,7 +413,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Long) -> String = { it.toString() }, @@ -428,7 +427,7 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - pref, modifier, iconId, iconSpaceReserved, title, valueLabel, summary, min, max, + pref, modifier, icon, iconSpaceReserved, title, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedValue, dialogStrings, enabledIf, visibleIf, ) { try { @@ -478,7 +477,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -495,9 +494,9 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - primaryPref, secondaryPref, modifier, iconId, iconSpaceReserved, title, - primaryLabel, secondaryLabel, valueLabel, summary, min, max, stepIncrement, - onPreviewSelectedPrimaryValue, onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, + primaryPref, secondaryPref, modifier, icon, iconSpaceReserved, title, primaryLabel, + secondaryLabel, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedPrimaryValue, + onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, ) { try { it.roundToLong() @@ -539,7 +538,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Double) -> String = { it.toString() }, @@ -553,7 +552,7 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - pref, modifier, iconId, iconSpaceReserved, title, valueLabel, summary, min, max, + pref, modifier, icon, iconSpaceReserved, title, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedValue, dialogStrings, enabledIf, visibleIf, ) { it.toDouble() } } @@ -597,7 +596,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -614,9 +613,9 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - primaryPref, secondaryPref, modifier, iconId, iconSpaceReserved, title, - primaryLabel, secondaryLabel, valueLabel, summary, min, max, stepIncrement, - onPreviewSelectedPrimaryValue, onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, + primaryPref, secondaryPref, modifier, icon, iconSpaceReserved, title, primaryLabel, + secondaryLabel, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedPrimaryValue, + onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, ) { it.toDouble() } } @@ -652,7 +651,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Float) -> String = { it.toString() }, @@ -666,7 +665,7 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - pref, modifier, iconId, iconSpaceReserved, title, valueLabel, summary, min, max, + pref, modifier, icon, iconSpaceReserved, title, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedValue, dialogStrings, enabledIf, visibleIf, ) { it } } @@ -710,7 +709,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -727,8 +726,8 @@ fun PreferenceUiScope.DialogSliderPreference( visibleIf: PreferenceDataEvaluator = { true }, ) { DialogSliderPreference( - primaryPref, secondaryPref, modifier, iconId, iconSpaceReserved, title, - primaryLabel, secondaryLabel, valueLabel, summary, min, max, stepIncrement, - onPreviewSelectedPrimaryValue, onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, + primaryPref, secondaryPref, modifier, icon, iconSpaceReserved, title, primaryLabel, + secondaryLabel, valueLabel, summary, min, max, stepIncrement, onPreviewSelectedPrimaryValue, + onPreviewSelectedSecondaryValue, dialogStrings, enabledIf, visibleIf, ) { it } } diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt new file mode 100644 index 0000000..31ee041 --- /dev/null +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt @@ -0,0 +1,41 @@ +package dev.patrickgold.jetpref.datastore.ui + +import androidx.annotation.DrawableRes +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.vector.ImageVector + +interface JetIcon { + @Composable + fun getIcon(iconSpaceReserved: Boolean): @Composable (() -> Unit)? +} + +class ImageVectorIcon(private val imageVector: ImageVector?) : JetIcon { + @Composable + override fun getIcon(iconSpaceReserved: Boolean): @Composable (() -> Unit)? { + return maybeJetIcon(imageVector = imageVector, iconSpaceReserved = iconSpaceReserved) + } +} + +object EmptyIcon : JetIcon { + @Composable + override fun getIcon(iconSpaceReserved: Boolean): @Composable() (() -> Unit)? { + return if (iconSpaceReserved) { + ({ }) + } else { + null + } + } +} + +class DrawableResIcon(@DrawableRes private val iconId: Int?) : JetIcon { + @Composable + override fun getIcon(iconSpaceReserved: Boolean): @Composable (() -> Unit)? { + return maybeJetIcon(id = iconId, iconSpaceReserved = iconSpaceReserved) + } +} + +val ImageVector?.jetIcon: ImageVectorIcon + get() = ImageVectorIcon(this) + +val @receiver:DrawableRes Int?.jetIcon: DrawableResIcon + get() = DrawableResIcon(this) diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt index 3261e4c..28ae243 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt @@ -17,7 +17,6 @@ package dev.patrickgold.jetpref.datastore.ui import android.annotation.SuppressLint -import androidx.annotation.DrawableRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -198,7 +197,7 @@ fun PreferenceUiScope.ListPreference( listPref: PreferenceData, switchPref: PreferenceData? = null, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summarySwitchDisabled: String? = null, @@ -229,7 +228,7 @@ fun PreferenceUiScope.ListPreference( isDialogOpen.value = true } ), - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved), text = title, secondaryText = if (switchPrefValue?.value == true || switchPrefValue == null) { entries.find { diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt index 8eadca9..694d83b 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt @@ -16,7 +16,6 @@ package dev.patrickgold.jetpref.datastore.ui -import androidx.annotation.DrawableRes import androidx.compose.foundation.clickable import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -52,7 +51,7 @@ import dev.patrickgold.jetpref.material.ui.JetPrefListItem @Composable fun PreferenceUiScope.Preference( modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summary: String? = null, @@ -74,7 +73,7 @@ fun PreferenceUiScope.Preference( } else { modifier }, - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved = iconSpaceReserved), text = title, secondaryText = summary, trailing = trailing, diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt index f2a65fc..45638c2 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt @@ -16,7 +16,6 @@ package dev.patrickgold.jetpref.datastore.ui -import androidx.annotation.DrawableRes import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.rememberScrollState @@ -137,10 +136,10 @@ fun ScrollablePreferenceLayout( * Material preference group which automatically provides a title UI. * * @param modifier Modifier to be applied to this group. - * @param iconId The icon ID of the group title icon. + * @param icon The [JetIcon] of the group title. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank - * space) if no icon ID is provided. Also acts as a local setting if all sub-preference composables - * should reserve an additional space if no icon is specified. Can be overridden for each individual + * space) if no `icon` is provided. Also acts as a local setting if all sub-preference composables + * should reserve an additional space if no icon is specified. It Can be overridden for each * preference composable. * @param title The title of this preference group. * @param enabledIf Evaluator scope which allows to dynamically decide if this preference layout @@ -155,7 +154,7 @@ fun ScrollablePreferenceLayout( @Composable fun PreferenceUiScope.PreferenceGroup( modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, enabledIf: PreferenceDataEvaluator = { true }, @@ -174,7 +173,7 @@ fun PreferenceUiScope.PreferenceGroup( ) ListItem( - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved), text = { Text( text = title, color = MaterialTheme.colors.secondary, diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt index 46cef15..8a77ea2 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt @@ -16,7 +16,6 @@ package dev.patrickgold.jetpref.datastore.ui -import androidx.annotation.DrawableRes import androidx.compose.foundation.layout.size import androidx.compose.foundation.selection.toggleable import androidx.compose.material.Switch @@ -37,9 +36,7 @@ import dev.patrickgold.jetpref.material.ui.JetPrefListItem * * @param pref The boolean preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. - * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank - * space) if no icon ID is provided. + * @param icon The [JetIcon] of the list entry. * @param title The title of this preference, shown as the list item primary text (max 1 line). * @param summary The summary of this preference, shown as the list item secondary text (max 2 lines). * @param summaryOn The summary of this preference if the state is `true`. If this is specified it @@ -51,13 +48,15 @@ import dev.patrickgold.jetpref.material.ui.JetPrefListItem * @param visibleIf Evaluator scope which allows to dynamically decide if this preference should be * visible (true) or hidden (false). * + * @see maybeJetIcon + * * @since 0.1.0 */ @Composable fun PreferenceUiScope.SwitchPreference( pref: PreferenceData, modifier: Modifier = Modifier, - @DrawableRes iconId: Int? = null, + icon: JetIcon? = null, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summary: String? = null, @@ -79,7 +78,7 @@ fun PreferenceUiScope.SwitchPreference( role = Role.Switch, onValueChange = { pref.set(it) } ), - icon = maybeJetIcon(iconId, iconSpaceReserved), + icon = icon?.getIcon(iconSpaceReserved), text = title, secondaryText = when { prefValue && summaryOn != null -> summaryOn diff --git a/example/build.gradle.kts b/example/build.gradle.kts index 8597b52..9af17bf 100644 --- a/example/build.gradle.kts +++ b/example/build.gradle.kts @@ -81,6 +81,7 @@ dependencies { implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.material.icons) implementation(libs.androidx.navigation.compose) implementation(project(":datastore-model")) implementation(project(":datastore-ui")) diff --git a/example/src/main/kotlin/dev/patrickgold/jetpref/example/ui/settings/HomeScreen.kt b/example/src/main/kotlin/dev/patrickgold/jetpref/example/ui/settings/HomeScreen.kt index 6dec88a..3586447 100644 --- a/example/src/main/kotlin/dev/patrickgold/jetpref/example/ui/settings/HomeScreen.kt +++ b/example/src/main/kotlin/dev/patrickgold/jetpref/example/ui/settings/HomeScreen.kt @@ -17,6 +17,8 @@ package dev.patrickgold.jetpref.example.ui.settings import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Palette import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import dev.patrickgold.jetpref.datastore.model.observeAsState @@ -27,6 +29,7 @@ import dev.patrickgold.jetpref.datastore.ui.Preference import dev.patrickgold.jetpref.datastore.ui.PreferenceGroup import dev.patrickgold.jetpref.datastore.ui.ScrollablePreferenceLayout import dev.patrickgold.jetpref.datastore.ui.SwitchPreference +import dev.patrickgold.jetpref.datastore.ui.jetIcon import dev.patrickgold.jetpref.datastore.ui.listPrefEntries import dev.patrickgold.jetpref.example.LocalNavController import dev.patrickgold.jetpref.example.R @@ -47,6 +50,7 @@ fun HomeScreen() = ScrollablePreferenceLayout(examplePreferenceModel()) { ) ListPreference( prefs.theme, + icon = Icons.Default.Palette.jetIcon, title = "Theme", entries = Theme.listEntries(), ) @@ -67,7 +71,7 @@ fun HomeScreen() = ScrollablePreferenceLayout(examplePreferenceModel()) { ) SwitchPreference( prefs.showExampleGroup, - iconId = R.drawable.ic_question_answer_black_24dp, + icon = R.drawable.ic_question_answer_black_24dp.jetIcon, title = "Show example group", summary = "Show/hide the example group", ) @@ -78,7 +82,7 @@ fun HomeScreen() = ScrollablePreferenceLayout(examplePreferenceModel()) { ) SwitchPreference( prefs.example.isButtonShowing2, - iconId = R.drawable.ic_question_answer_black_24dp, + icon = R.drawable.ic_question_answer_black_24dp.jetIcon, title = "isBtnShow2", summaryOn = "Hello", summaryOff = "Bye", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 27df7b5..8cd199e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,6 +6,7 @@ androidx-compose = "1.6.1" androidx-compose-compiler = "1.5.9" androidx-core = "1.12.0" androidx-lifecycle = "2.7.0" +androidx-material-icons = "1.6.4" androidx-navigation = "2.7.7" kotlin = "1.9.22" kotlinx-coroutines = "1.7.3" @@ -25,6 +26,7 @@ androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", versi androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "androidx-compose" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" } androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } +androidx-material-icons = { module = "androidx.compose.material:material-icons-extended", version.ref = "androidx-material-icons" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } From d23e7181d8e425b535a7608e0aa30a481e640894 Mon Sep 17 00:00:00 2001 From: lm41 Date: Wed, 27 Mar 2024 22:30:17 +0100 Subject: [PATCH 2/3] fix: the iconSpaceReserved flag is no longer ignored --- .../datastore/ui/DialogSliderPreference.kt | 24 +++++++++---------- .../jetpref/datastore/ui/JetIcon.kt | 8 +++---- .../jetpref/datastore/ui/ListPreference.kt | 4 ++-- .../jetpref/datastore/ui/Preference.kt | 4 ++-- .../jetpref/datastore/ui/PreferenceUi.kt | 4 ++-- .../jetpref/datastore/ui/SwitchPreference.kt | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt index d8dc699..b358454 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt @@ -49,7 +49,7 @@ import kotlin.math.roundToLong internal fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier, - icon: JetIcon?, + icon: JetIcon, iconSpaceReserved: Boolean, title: String, valueLabel: @Composable (V) -> String, @@ -83,7 +83,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc isDialogOpen.value = true } ), - icon = icon?.getIcon(iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved), text = title, secondaryText = summary(prefValue), enabled = isEnabled, @@ -138,7 +138,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier, - icon: JetIcon?, + icon: JetIcon, iconSpaceReserved: Boolean, title: String, primaryLabel: String, @@ -178,7 +178,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc isDialogOpen.value = true } ), - icon = icon?.getIcon(iconSpaceReserved = iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved = iconSpaceReserved), text = title, secondaryText = summary(primaryPrefValue, secondaryPrefValue), enabled = isEnabled, @@ -288,7 +288,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Int) -> String = { it.toString() }, @@ -352,7 +352,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -413,7 +413,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Long) -> String = { it.toString() }, @@ -477,7 +477,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -538,7 +538,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Double) -> String = { it.toString() }, @@ -596,7 +596,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, @@ -651,7 +651,7 @@ fun PreferenceUiScope.DialogSliderPreference( fun PreferenceUiScope.DialogSliderPreference( pref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, valueLabel: @Composable (Float) -> String = { it.toString() }, @@ -709,7 +709,7 @@ fun PreferenceUiScope.DialogSliderPreference( primaryPref: PreferenceData, secondaryPref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, primaryLabel: String, diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt index 31ee041..b9dcc64 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt @@ -34,8 +34,8 @@ class DrawableResIcon(@DrawableRes private val iconId: Int?) : JetIcon { } } -val ImageVector?.jetIcon: ImageVectorIcon - get() = ImageVectorIcon(this) +val ImageVector?.jetIcon: JetIcon + get() = if (this == null) { EmptyIcon } else { ImageVectorIcon(this) } -val @receiver:DrawableRes Int?.jetIcon: DrawableResIcon - get() = DrawableResIcon(this) +val @receiver:DrawableRes Int?.jetIcon: JetIcon + get() = if(this == null) { EmptyIcon } else { DrawableResIcon(this) } diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt index 28ae243..45e54a2 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/ListPreference.kt @@ -197,7 +197,7 @@ fun PreferenceUiScope.ListPreference( listPref: PreferenceData, switchPref: PreferenceData? = null, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summarySwitchDisabled: String? = null, @@ -228,7 +228,7 @@ fun PreferenceUiScope.ListPreference( isDialogOpen.value = true } ), - icon = icon?.getIcon(iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved), text = title, secondaryText = if (switchPrefValue?.value == true || switchPrefValue == null) { entries.find { diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt index 694d83b..d1326c8 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/Preference.kt @@ -51,7 +51,7 @@ import dev.patrickgold.jetpref.material.ui.JetPrefListItem @Composable fun PreferenceUiScope.Preference( modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summary: String? = null, @@ -73,7 +73,7 @@ fun PreferenceUiScope.Preference( } else { modifier }, - icon = icon?.getIcon(iconSpaceReserved = iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved = iconSpaceReserved), text = title, secondaryText = summary, trailing = trailing, diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt index 45638c2..efbc7aa 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/PreferenceUi.kt @@ -154,7 +154,7 @@ fun ScrollablePreferenceLayout( @Composable fun PreferenceUiScope.PreferenceGroup( modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, enabledIf: PreferenceDataEvaluator = { true }, @@ -173,7 +173,7 @@ fun PreferenceUiScope.PreferenceGroup( ) ListItem( - icon = icon?.getIcon(iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved), text = { Text( text = title, color = MaterialTheme.colors.secondary, diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt index 8a77ea2..df10dc1 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/SwitchPreference.kt @@ -56,7 +56,7 @@ import dev.patrickgold.jetpref.material.ui.JetPrefListItem fun PreferenceUiScope.SwitchPreference( pref: PreferenceData, modifier: Modifier = Modifier, - icon: JetIcon? = null, + icon: JetIcon = EmptyIcon, iconSpaceReserved: Boolean = this.iconSpaceReserved, title: String, summary: String? = null, @@ -78,7 +78,7 @@ fun PreferenceUiScope.SwitchPreference( role = Role.Switch, onValueChange = { pref.set(it) } ), - icon = icon?.getIcon(iconSpaceReserved), + icon = icon.getIcon(iconSpaceReserved), text = title, secondaryText = when { prefValue && summaryOn != null -> summaryOn From a63dacc97853d8c10a37fbcfe361cbeda0583a88 Mon Sep 17 00:00:00 2001 From: lm41 Date: Thu, 28 Mar 2024 09:39:46 +0100 Subject: [PATCH 3/3] apply suggestions and write basic documentation --- .../datastore/ui/DialogSliderPreference.kt | 16 +++++------ .../jetpref/datastore/ui/JetIcon.kt | 28 +++++++++++++++++-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt index b358454..ce906a5 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/DialogSliderPreference.kt @@ -261,7 +261,7 @@ internal fun PreferenceUiScope.DialogSliderPreferenc * * @param pref The integer preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param icon The [JetIcon] of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -319,7 +319,7 @@ fun PreferenceUiScope.DialogSliderPreference( * @param primaryPref The primary integer preference data entry from the datastore. * @param secondaryPref The secondary integer preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -386,7 +386,7 @@ fun PreferenceUiScope.DialogSliderPreference( * * @param pref The long preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -444,7 +444,7 @@ fun PreferenceUiScope.DialogSliderPreference( * @param primaryPref The primary long preference data entry from the datastore. * @param secondaryPref The secondary long preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -511,7 +511,7 @@ fun PreferenceUiScope.DialogSliderPreference( * * @param pref The double preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -563,7 +563,7 @@ fun PreferenceUiScope.DialogSliderPreference( * @param primaryPref The primary double preference data entry from the datastore. * @param secondaryPref The secondary double preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -624,7 +624,7 @@ fun PreferenceUiScope.DialogSliderPreference( * * @param pref The float preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). @@ -676,7 +676,7 @@ fun PreferenceUiScope.DialogSliderPreference( * @param primaryPref The primary float preference data entry from the datastore. * @param secondaryPref The secondary float preference data entry from the datastore. * @param modifier Modifier to be applied to the underlying list item. - * @param iconId The icon ID of the list entry icon. + * @param icon The [JetIcon] of the list entry. * @param iconSpaceReserved If the space at the start of the list item should be reserved (blank * space) if no icon ID is provided. * @param title The title of this preference, shown as the list item primary text (max 1 line). diff --git a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt index b9dcc64..5d74421 100644 --- a/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt +++ b/datastore-ui/src/main/kotlin/dev/patrickgold/jetpref/datastore/ui/JetIcon.kt @@ -4,7 +4,20 @@ import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.vector.ImageVector +/** + * Interface which provides the Icon for the JetPref library + * + * @since 0.1.0 + */ interface JetIcon { + /** + * Provie the Icon. + * + * @param iconSpaceReserved If the space at the start of the preference should be reserved, + * if no icon is provided. + * + * @since 0.1.0 + */ @Composable fun getIcon(iconSpaceReserved: Boolean): @Composable (() -> Unit)? } @@ -18,7 +31,7 @@ class ImageVectorIcon(private val imageVector: ImageVector?) : JetIcon { object EmptyIcon : JetIcon { @Composable - override fun getIcon(iconSpaceReserved: Boolean): @Composable() (() -> Unit)? { + override fun getIcon(iconSpaceReserved: Boolean): @Composable (() -> Unit)? { return if (iconSpaceReserved) { ({ }) } else { @@ -34,8 +47,19 @@ class DrawableResIcon(@DrawableRes private val iconId: Int?) : JetIcon { } } + +/** + * Get the JetIcon from the [ImageVector] or the [EmptyIcon] if null + * + * @since 0.1.0 + */ val ImageVector?.jetIcon: JetIcon get() = if (this == null) { EmptyIcon } else { ImageVectorIcon(this) } +/** + * Get the JetIcon from the [DrawableRes] ID or the [EmptyIcon] if null + * + * @since 0.1.0 + */ val @receiver:DrawableRes Int?.jetIcon: JetIcon - get() = if(this == null) { EmptyIcon } else { DrawableResIcon(this) } + get() = if (this == null) { EmptyIcon } else { DrawableResIcon(this) }