Repo created
This commit is contained in:
parent
75dc487a7a
commit
39c29d175b
6317 changed files with 388324 additions and 2 deletions
15
core/ui/compose/preference/build.gradle.kts
Normal file
15
core/ui/compose/preference/build.gradle.kts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.androidCompose)
|
||||
alias(libs.plugins.kotlin.parcelize)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "net.thunderbird.core.ui.compose.preference"
|
||||
resourcePrefix = "core_ui_preference_"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.ui.compose.designsystem)
|
||||
|
||||
testImplementation(projects.core.ui.compose.testing)
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import app.k9mail.core.ui.compose.common.annotation.PreviewDevicesWithBackground
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@PreviewDevicesWithBackground
|
||||
fun PreferenceViewPreview() {
|
||||
PreviewWithTheme {
|
||||
PreferenceView(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
preferences = FakePreferenceData.preferences,
|
||||
onPreferenceChange = {},
|
||||
onBack = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceTopBarPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceTopBar(
|
||||
title = "Title",
|
||||
subtitle = null,
|
||||
onBack = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceTopBarWithSubtitlePreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceTopBar(
|
||||
title = "Title",
|
||||
subtitle = "Subtitle",
|
||||
onBack = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.common
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ColorViewPreview() {
|
||||
PreviewWithThemes {
|
||||
ColorView(
|
||||
color = 0xFFFF0000.toInt(),
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun ColorViewWithSelectionPreview() {
|
||||
PreviewWithThemes {
|
||||
ColorView(
|
||||
color = 0xFFFF0000.toInt(),
|
||||
onClick = null,
|
||||
isSelected = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceDialogColorViewPreview() {
|
||||
PreviewWithTheme {
|
||||
PreferenceDialogColorView(
|
||||
preference = FakePreferenceData.colorPreference,
|
||||
onConfirmClick = {},
|
||||
onDismissClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceDialogLayoutPreview() {
|
||||
PreviewWithTheme {
|
||||
PreferenceDialogLayout(
|
||||
title = "Dialog",
|
||||
icon = null,
|
||||
onConfirmClick = {},
|
||||
onDismissClick = {},
|
||||
onDismissRequest = {},
|
||||
) {
|
||||
TextBodyMedium("PreferenceDialogLayoutContent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceDialogSingleChoiceCompactViewPreview() {
|
||||
PreviewWithTheme {
|
||||
PreferenceDialogSingleChoiceCompactView(
|
||||
preference = FakePreferenceData.singleChoiceCompactPreference,
|
||||
onConfirmClick = {},
|
||||
onDismissClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceDialogTextViewPreview() {
|
||||
PreviewWithTheme {
|
||||
PreferenceDialogTextView(
|
||||
preference = FakePreferenceData.textPreference,
|
||||
onConfirmClick = {},
|
||||
onDismissClick = {},
|
||||
onDismissRequest = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemColorViewPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemColorView(
|
||||
preference = FakePreferenceData.colorPreference,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleLarge
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemLayoutPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemLayout(
|
||||
onClick = {},
|
||||
icon = null,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
TextTitleLarge(text = "PreferenceItemLayoutContent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemLayoutWithIconPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemLayout(
|
||||
onClick = {},
|
||||
icon = Icons.Outlined.Info,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
TextTitleLarge(text = "PreferenceItemLayoutContent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemSingleChoiceCompactViewPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSingleChoiceCompactView(
|
||||
preference = FakePreferenceData.singleChoiceCompactPreference,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemSingleChoiceViewPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSingleChoiceView(
|
||||
preference = FakePreferenceData.singleChoicePreference.copy(description = { null }),
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemSingleChoiceViewWithDescriptionPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSingleChoiceView(
|
||||
preference = FakePreferenceData.singleChoicePreference,
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun Preview_Switch_On_Enabled() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSwitchView(
|
||||
preference = FakePreferenceData.switchPreference,
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun Preview_Switch_Off_Enabled() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSwitchView(
|
||||
preference = FakePreferenceData.switchPreference.copy(value = false),
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun Preview_Switch_On_Disabled() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSwitchView(
|
||||
preference = FakePreferenceData.switchPreference.copy(enabled = false),
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun Preview_Switch_Off_Disabled() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemSwitchView(
|
||||
preference = FakePreferenceData.switchPreference.copy(value = false, enabled = false),
|
||||
onPreferenceChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.k9mail.core.ui.compose.designsystem.PreviewWithThemes
|
||||
import net.thunderbird.core.ui.compose.preference.ui.fake.FakePreferenceData
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true)
|
||||
internal fun PreferenceItemTextViewPreview() {
|
||||
PreviewWithThemes {
|
||||
PreferenceItemTextView(
|
||||
preference = FakePreferenceData.textPreference,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.fake
|
||||
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting.SingleChoice.Choice
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting.SingleChoiceCompact.CompactChoice
|
||||
|
||||
internal object FakePreferenceData {
|
||||
|
||||
val textPreference = PreferenceSetting.Text(
|
||||
id = "text",
|
||||
icon = { Icons.Outlined.Delete },
|
||||
title = { "Title" },
|
||||
description = { "Description" },
|
||||
value = "Value",
|
||||
)
|
||||
|
||||
val colorPreference = PreferenceSetting.Color(
|
||||
id = "color",
|
||||
icon = { Icons.Outlined.Delete },
|
||||
title = { "Title" },
|
||||
description = { "Description" },
|
||||
value = 0xFFFF0000.toInt(),
|
||||
colors = persistentListOf(
|
||||
0xFFFF0000.toInt(),
|
||||
0xFF00FF00.toInt(),
|
||||
0xFF0000FF.toInt(),
|
||||
),
|
||||
)
|
||||
|
||||
private val choices = persistentListOf<Choice>(
|
||||
Choice("1") { "Choice 1" },
|
||||
Choice("2") { "Choice 2" },
|
||||
Choice("3") { "Choice 3" },
|
||||
)
|
||||
|
||||
val singleChoicePreference = PreferenceSetting.SingleChoice(
|
||||
id = "single_choice",
|
||||
title = { "Title" },
|
||||
description = { "Description" },
|
||||
value = choices[1],
|
||||
options = choices,
|
||||
)
|
||||
|
||||
private val compactChoices = persistentListOf<CompactChoice>(
|
||||
CompactChoice("1") { "Compact Choice 1" },
|
||||
CompactChoice("2") { "Compact Choice 2" },
|
||||
CompactChoice("3") { "Compact Choice 3" },
|
||||
CompactChoice("1") { "Compact Choice 4" },
|
||||
CompactChoice("2") { "Compact Choice 5" },
|
||||
CompactChoice("3") { "Compact Choice 6" },
|
||||
)
|
||||
|
||||
val singleChoiceCompactPreference = PreferenceSetting.SingleChoiceCompact(
|
||||
id = "single_choice_compact",
|
||||
title = { "Title" },
|
||||
icon = { Icons.Outlined.Info },
|
||||
description = { "Description" },
|
||||
value = compactChoices[1],
|
||||
options = compactChoices,
|
||||
)
|
||||
|
||||
val switchPreference = PreferenceSetting.Switch(
|
||||
id = "switch",
|
||||
title = { "Title" },
|
||||
description = { "Description" },
|
||||
enabled = true,
|
||||
value = true,
|
||||
)
|
||||
|
||||
val preferences = persistentListOf(
|
||||
textPreference,
|
||||
colorPreference,
|
||||
switchPreference,
|
||||
singleChoicePreference,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
package net.thunderbird.core.ui.compose.preference.api
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.parcelize.IgnoredOnParcel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting.SingleChoice.Choice
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting.SingleChoiceCompact.CompactChoice
|
||||
|
||||
/**
|
||||
* A preference that can be displayed in a preference screen.
|
||||
*/
|
||||
sealed interface Preference : Parcelable {
|
||||
val id: String
|
||||
}
|
||||
|
||||
/**
|
||||
* A preference that holds a value of type [T].
|
||||
*/
|
||||
sealed interface PreferenceSetting<T> : Preference {
|
||||
val value: T
|
||||
val requiresEditView: Boolean
|
||||
|
||||
@Parcelize
|
||||
data class Text(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val description: () -> String? = { null },
|
||||
val icon: () -> ImageVector? = { null },
|
||||
override val value: String,
|
||||
) : PreferenceSetting<String> {
|
||||
@IgnoredOnParcel
|
||||
override val requiresEditView: Boolean = true
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Color(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val description: () -> String? = { null },
|
||||
val icon: () -> ImageVector? = { null },
|
||||
override val value: Int,
|
||||
val colors: ImmutableList<Int>,
|
||||
) : PreferenceSetting<Int> {
|
||||
@IgnoredOnParcel
|
||||
override val requiresEditView: Boolean = true
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class SingleChoice(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val description: () -> String? = { null },
|
||||
override val value: Choice,
|
||||
val options: ImmutableList<Choice>,
|
||||
) : PreferenceSetting<Choice> {
|
||||
@IgnoredOnParcel
|
||||
override val requiresEditView: Boolean = false
|
||||
|
||||
@Parcelize
|
||||
data class Choice(
|
||||
val id: String,
|
||||
val title: () -> String,
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class SingleChoiceCompact(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val description: () -> String? = { null },
|
||||
val icon: () -> ImageVector? = { null },
|
||||
override val value: CompactChoice,
|
||||
val options: ImmutableList<CompactChoice>,
|
||||
) : PreferenceSetting<CompactChoice> {
|
||||
@IgnoredOnParcel
|
||||
override val requiresEditView: Boolean = true
|
||||
|
||||
@Parcelize
|
||||
data class CompactChoice(
|
||||
val id: String,
|
||||
val title: () -> String,
|
||||
) : Parcelable
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
data class Switch(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val description: () -> String? = { null },
|
||||
val enabled: Boolean,
|
||||
override val value: Boolean,
|
||||
) : PreferenceSetting<Boolean> {
|
||||
@IgnoredOnParcel
|
||||
override val requiresEditView: Boolean = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A preference that does not hold a value. It is used to display a section, a divider or custom UI.
|
||||
*/
|
||||
sealed interface PreferenceDisplay : Preference {
|
||||
|
||||
@Parcelize
|
||||
data class Custom(
|
||||
override val id: String,
|
||||
val customUi: @Composable (Modifier) -> Unit,
|
||||
) : PreferenceDisplay
|
||||
|
||||
@Parcelize
|
||||
data class SectionHeader(
|
||||
override val id: String,
|
||||
val title: () -> String,
|
||||
val color: () -> Color = { Color.Unspecified },
|
||||
) : PreferenceDisplay
|
||||
|
||||
@Parcelize
|
||||
data class SectionDivider(
|
||||
override val id: String,
|
||||
) : PreferenceDisplay
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import net.thunderbird.core.ui.compose.preference.api.Preference
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
/**
|
||||
* A view that displays a list of preferences.
|
||||
*
|
||||
* @param title The title of the view.
|
||||
* @param subtitle The subtitle of the view (optional).
|
||||
* @param preferences The list of preferences to display.
|
||||
* @param onPreferenceChange The callback to be invoked when a preference is changed.
|
||||
* @param onBack The callback to be invoked when the back button is clicked.
|
||||
* @param modifier The modifier to be applied to the view.
|
||||
*/
|
||||
@Composable
|
||||
fun PreferenceView(
|
||||
title: String,
|
||||
preferences: ImmutableList<Preference>,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: String? = null,
|
||||
) {
|
||||
PreferenceViewWithDialog(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
preferences = preferences,
|
||||
onPreferenceChange = onPreferenceChange,
|
||||
onBack = onBack,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.template.ResponsiveWidthContainer
|
||||
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import net.thunderbird.core.ui.compose.preference.api.Preference
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
import net.thunderbird.core.ui.compose.preference.ui.components.PreferenceTopBar
|
||||
import net.thunderbird.core.ui.compose.preference.ui.components.dialog.PreferenceDialog
|
||||
import net.thunderbird.core.ui.compose.preference.ui.components.list.PreferenceList
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceViewWithDialog(
|
||||
title: String,
|
||||
preferences: ImmutableList<Preference>,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
onBack: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
subtitle: String? = null,
|
||||
) {
|
||||
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||
var selectedIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
PreferenceTopBar(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
onBack = onBack,
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
) { innerPadding ->
|
||||
ResponsiveWidthContainer { contentPadding ->
|
||||
PreferenceList(
|
||||
preferences = preferences,
|
||||
onItemClick = { index, _ ->
|
||||
selectedIndex = index
|
||||
showDialog = true
|
||||
},
|
||||
onPreferenceChange = onPreferenceChange,
|
||||
modifier = Modifier
|
||||
.padding(innerPadding)
|
||||
.padding(contentPadding),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showDialog) {
|
||||
val preference = preferences[selectedIndex]
|
||||
|
||||
PreferenceDialog(
|
||||
preference = preference,
|
||||
onConfirmClick = { preference ->
|
||||
onPreferenceChange(preference)
|
||||
showDialog = false
|
||||
},
|
||||
onDismissClick = { showDialog = false },
|
||||
onDismissRequest = { showDialog = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.SubtitleTopAppBarWithBackButton
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.TopAppBarWithBackButton
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceTopBar(
|
||||
title: String,
|
||||
subtitle: String?,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
if (subtitle != null) {
|
||||
SubtitleTopAppBarWithBackButton(
|
||||
title = title,
|
||||
subtitle = subtitle,
|
||||
onBackClick = onBack,
|
||||
)
|
||||
} else {
|
||||
TopAppBarWithBackButton(
|
||||
title = title,
|
||||
onBackClick = onBack,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.common
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Surface
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icons
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
internal fun ColorView(
|
||||
color: Int,
|
||||
onClick: ((Int) -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
isSelected: Boolean = false,
|
||||
size: Dp = MainTheme.sizes.icon,
|
||||
) {
|
||||
Surface(
|
||||
color = Color(color),
|
||||
modifier = modifier
|
||||
.size(size)
|
||||
.clip(CircleShape)
|
||||
.let {
|
||||
if (onClick != null) {
|
||||
it.clickable(onClick = { onClick(color) })
|
||||
} else {
|
||||
it
|
||||
}
|
||||
},
|
||||
) {
|
||||
if (isSelected) {
|
||||
Icon(
|
||||
tint = MainTheme.colors.onSecondary,
|
||||
imageVector = Icons.Outlined.Check,
|
||||
modifier = Modifier.padding(MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import net.thunderbird.core.ui.compose.preference.api.Preference
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceDialog(
|
||||
preference: Preference,
|
||||
onConfirmClick: (PreferenceSetting<*>) -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
require(preference is PreferenceSetting<*>) {
|
||||
"Unsupported preference type: ${preference::class.java.simpleName}"
|
||||
}
|
||||
|
||||
when (preference) {
|
||||
is PreferenceSetting.Text -> {
|
||||
PreferenceDialogTextView(
|
||||
preference = preference,
|
||||
onConfirmClick = onConfirmClick,
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.Color -> {
|
||||
PreferenceDialogColorView(
|
||||
preference = preference,
|
||||
onConfirmClick = onConfirmClick,
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.SingleChoiceCompact -> {
|
||||
PreferenceDialogSingleChoiceCompactView(
|
||||
preference = preference,
|
||||
onConfirmClick = onConfirmClick,
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
// No dialog needed
|
||||
is PreferenceSetting.SingleChoice, is PreferenceSetting.Switch -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
import net.thunderbird.core.ui.compose.preference.ui.components.common.ColorView
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceDialogColorView(
|
||||
preference: PreferenceSetting.Color,
|
||||
onConfirmClick: (PreferenceSetting<*>) -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val currentColor = rememberSaveable { mutableIntStateOf(preference.value) }
|
||||
val gridState = rememberLazyGridState()
|
||||
|
||||
PreferenceDialogLayout(
|
||||
title = preference.title(),
|
||||
icon = preference.icon(),
|
||||
onConfirmClick = { onConfirmClick(preference.copy(value = currentColor.intValue)) },
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
) {
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
|
||||
Spacer(modifier = Modifier.height(MainTheme.spacings.double))
|
||||
}
|
||||
LazyVerticalGrid(
|
||||
state = gridState,
|
||||
columns = GridCells.Adaptive(minSize = MainTheme.sizes.iconAvatar),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
horizontalArrangement = Arrangement.spacedBy(MainTheme.spacings.default),
|
||||
) {
|
||||
items(preference.colors) { color ->
|
||||
ColorView(
|
||||
color = color,
|
||||
onClick = { newColor ->
|
||||
currentColor.intValue = newColor
|
||||
},
|
||||
isSelected = color == currentColor.intValue,
|
||||
modifier = Modifier.size(MainTheme.sizes.iconAvatar),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.k9mail.core.ui.compose.designsystem.organism.AlertDialog
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.R
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceDialogLayout(
|
||||
title: String,
|
||||
icon: ImageVector?,
|
||||
onConfirmClick: () -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
AlertDialog(
|
||||
title = title,
|
||||
icon = icon,
|
||||
confirmText = stringResource(id = R.string.core_ui_preference_dialog_button_accept),
|
||||
onConfirmClick = onConfirmClick,
|
||||
dismissText = stringResource(id = R.string.core_ui_preference_dialog_button_cancel),
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.RadioGroup
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceDialogSingleChoiceCompactView(
|
||||
preference: PreferenceSetting.SingleChoiceCompact,
|
||||
onConfirmClick: (PreferenceSetting<*>) -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val options by remember { mutableStateOf(preference.options) }
|
||||
var selectedOption by remember { mutableStateOf(preference.value) }
|
||||
|
||||
PreferenceDialogLayout(
|
||||
title = preference.title(),
|
||||
icon = preference.icon(),
|
||||
onConfirmClick = {
|
||||
onConfirmClick(preference.copy(value = selectedOption))
|
||||
},
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
) {
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
|
||||
Spacer(modifier = Modifier.height(MainTheme.spacings.default))
|
||||
}
|
||||
|
||||
RadioGroup(
|
||||
onClick = { selectedOption = it },
|
||||
options = options,
|
||||
optionTitle = { it.title() },
|
||||
selectedOption = selectedOption,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.dialog
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.molecule.input.AdvancedTextInput
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import kotlinx.coroutines.delay
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
// This a workaround for a bug in Compose, preventing the keyboard been show when requesting focus on a dialog,
|
||||
// see: https://issuetracker.google.com/issues/204502668
|
||||
private const val EDIT_TEXT_FOCUS_DELAY = 200L
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceDialogTextView(
|
||||
preference: PreferenceSetting.Text,
|
||||
onConfirmClick: (PreferenceSetting<*>) -> Unit,
|
||||
onDismissClick: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
||||
mutableStateOf(
|
||||
TextFieldValue(
|
||||
text = preference.value,
|
||||
selection = TextRange(preference.value.length),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
delay(EDIT_TEXT_FOCUS_DELAY)
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
|
||||
PreferenceDialogLayout(
|
||||
title = preference.title(),
|
||||
icon = preference.icon(),
|
||||
onConfirmClick = {
|
||||
onConfirmClick(preference.copy(value = textFieldValue.text))
|
||||
},
|
||||
onDismissClick = onDismissClick,
|
||||
onDismissRequest = onDismissRequest,
|
||||
modifier = modifier,
|
||||
) {
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
|
||||
Spacer(modifier = Modifier.height(MainTheme.spacings.default))
|
||||
}
|
||||
|
||||
AdvancedTextInput(
|
||||
text = textFieldValue,
|
||||
contentPadding = PaddingValues(),
|
||||
onTextChange = { changedText ->
|
||||
textFieldValue = changedText
|
||||
},
|
||||
modifier = Modifier.focusRequester(focusRequester),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import net.thunderbird.core.ui.compose.preference.api.Preference
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceDisplay
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItem(
|
||||
preference: Preference,
|
||||
onClick: () -> Unit,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (preference) {
|
||||
// PreferenceSetting
|
||||
is PreferenceSetting.Text -> {
|
||||
PreferenceItemTextView(
|
||||
preference = preference,
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.Color -> {
|
||||
PreferenceItemColorView(
|
||||
preference = preference,
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.SingleChoice -> {
|
||||
PreferenceItemSingleChoiceView(
|
||||
preference = preference,
|
||||
onPreferenceChange = onPreferenceChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.Switch -> {
|
||||
PreferenceItemSwitchView(
|
||||
preference = preference,
|
||||
onPreferenceChange = onPreferenceChange,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceSetting.SingleChoiceCompact -> PreferenceItemSingleChoiceCompactView(
|
||||
preference = preference,
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
|
||||
// PreferenceDisplay
|
||||
is PreferenceDisplay.Custom -> {
|
||||
PreferenceItemCustomView(
|
||||
preference = preference,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceDisplay.SectionHeader -> {
|
||||
PreferenceItemSectionHeaderView(
|
||||
preference = preference,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
is PreferenceDisplay.SectionDivider -> {
|
||||
PreferenceItemSectionDividerView(
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
import net.thunderbird.core.ui.compose.preference.ui.components.common.ColorView
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemColorView(
|
||||
preference: PreferenceSetting.Color,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceItemLayout(
|
||||
onClick = onClick,
|
||||
icon = preference.icon(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
) {
|
||||
TextTitleMedium(text = preference.title())
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
}
|
||||
}
|
||||
ColorView(
|
||||
color = preference.value,
|
||||
onClick = null,
|
||||
modifier = Modifier.padding(start = MainTheme.spacings.default),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceDisplay
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemCustomView(
|
||||
preference: PreferenceDisplay.Custom,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
preference.customUi(modifier)
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.icon.Icon
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemLayout(
|
||||
onClick: () -> Unit,
|
||||
icon: ImageVector?,
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.clickable(onClick = onClick),
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
icon?.let {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.padding(MainTheme.spacings.double),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.padding(MainTheme.spacings.double),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.DividerHorizontal
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemSectionDividerView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
DividerHorizontal(
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceDisplay
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemSectionHeaderView(
|
||||
preference: PreferenceDisplay.SectionHeader,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier.padding(MainTheme.spacings.double)) {
|
||||
TextTitleMedium(
|
||||
text = preference.title(),
|
||||
color = preference.color(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemSingleChoiceCompactView(
|
||||
preference: PreferenceSetting.SingleChoiceCompact,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceItemLayout(
|
||||
onClick = onClick,
|
||||
icon = preference.icon(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
) {
|
||||
TextTitleMedium(text = preference.value.title())
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonSegmentedSingleChoice
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemSingleChoiceView(
|
||||
preference: PreferenceSetting.SingleChoice,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.padding(MainTheme.spacings.double),
|
||||
verticalArrangement = Arrangement.spacedBy(MainTheme.spacings.half),
|
||||
) {
|
||||
TextTitleMedium(text = preference.title())
|
||||
|
||||
ButtonSegmentedSingleChoice(
|
||||
onClick = {
|
||||
onPreferenceChange(preference.copy(value = it))
|
||||
},
|
||||
options = preference.options,
|
||||
optionTitle = { it.title() },
|
||||
selectedOption = preference.value,
|
||||
)
|
||||
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(
|
||||
modifier = Modifier.padding(start = MainTheme.spacings.oneHalf),
|
||||
color = MainTheme.colors.onSurfaceVariant,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.Switch
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import app.k9mail.core.ui.compose.theme2.MainTheme
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemSwitchView(
|
||||
preference: PreferenceSetting.Switch,
|
||||
modifier: Modifier = Modifier,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier.padding(MainTheme.spacings.double),
|
||||
) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
) {
|
||||
TextTitleMedium(text = preference.title())
|
||||
preference.description()?.let {
|
||||
TextBodyMedium(text = it)
|
||||
}
|
||||
}
|
||||
Switch(
|
||||
checked = preference.value,
|
||||
onCheckedChange = {
|
||||
onPreferenceChange(preference.copy(value = it))
|
||||
},
|
||||
enabled = preference.enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextBodyMedium
|
||||
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceItemTextView(
|
||||
preference: PreferenceSetting.Text,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PreferenceItemLayout(
|
||||
onClick = onClick,
|
||||
icon = preference.icon(),
|
||||
modifier = modifier,
|
||||
) {
|
||||
TextTitleMedium(text = preference.title())
|
||||
TextBodyMedium(text = preference.value)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package net.thunderbird.core.ui.compose.preference.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import net.thunderbird.core.ui.compose.preference.api.Preference
|
||||
import net.thunderbird.core.ui.compose.preference.api.PreferenceSetting
|
||||
|
||||
@Composable
|
||||
internal fun PreferenceList(
|
||||
preferences: ImmutableList<Preference>,
|
||||
onItemClick: (index: Int, item: Preference) -> Unit,
|
||||
onPreferenceChange: (PreferenceSetting<*>) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = modifier,
|
||||
) {
|
||||
itemsIndexed(preferences) { index, item ->
|
||||
PreferenceItem(
|
||||
preference = item,
|
||||
onClick = {
|
||||
onItemClick(index, item)
|
||||
},
|
||||
onPreferenceChange = onPreferenceChange,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="core_ui_preference_dialog_button_accept">Accept</string>
|
||||
<string name="core_ui_preference_dialog_button_cancel">Cancel</string>
|
||||
</resources>
|
||||
Loading…
Add table
Add a link
Reference in a new issue