Let Preference composables use ListItem.
Let PreferenceCheckbox use ListItem and add missing previews. Let PreferenceCategory use ListSectionHeader Let PreferenceSlide use ListItem Let PreferenceRow use ListItem Let PreferenceText use ListItem
This commit is contained in:
@@ -43,7 +43,7 @@ fun LockScreenSettingsView(
|
||||
onBackPressed = onBackPressed,
|
||||
modifier = modifier
|
||||
) {
|
||||
PreferenceCategory(showDivider = false) {
|
||||
PreferenceCategory(showTopDivider = false) {
|
||||
PreferenceText(
|
||||
title = stringResource(id = R.string.screen_app_lock_settings_change_pin),
|
||||
onClick = onChangePinClicked
|
||||
|
||||
@@ -48,7 +48,10 @@ fun DeveloperSettingsView(
|
||||
title = stringResource(id = CommonStrings.common_developer_options)
|
||||
) {
|
||||
// Note: this is OK to hardcode strings in this debug screen.
|
||||
PreferenceCategory(title = "Feature flags") {
|
||||
PreferenceCategory(
|
||||
title = "Feature flags",
|
||||
showTopDivider = false,
|
||||
) {
|
||||
FeatureListContent(state)
|
||||
}
|
||||
ElementCallCategory(state = state)
|
||||
@@ -67,14 +70,14 @@ fun DeveloperSettingsView(
|
||||
RageshakePreferencesView(
|
||||
state = state.rageshakeState,
|
||||
)
|
||||
PreferenceCategory(title = "Crash", showDivider = false) {
|
||||
PreferenceCategory(title = "Crash", showTopDivider = false) {
|
||||
PreferenceText(
|
||||
title = "Crash the app 💥",
|
||||
onClick = { error("This crash is a test.") }
|
||||
)
|
||||
}
|
||||
val cache = state.cacheSize
|
||||
PreferenceCategory(title = "Cache", showDivider = false) {
|
||||
PreferenceCategory(title = "Cache", showTopDivider = false) {
|
||||
PreferenceText(
|
||||
title = "Clear cache",
|
||||
currentValue = cache.dataOrNull(),
|
||||
@@ -93,11 +96,12 @@ fun DeveloperSettingsView(
|
||||
private fun ElementCallCategory(
|
||||
state: DeveloperSettingsState,
|
||||
) {
|
||||
PreferenceCategory(title = "Element Call", showDivider = true) {
|
||||
PreferenceCategory(title = "Element Call", showTopDivider = true) {
|
||||
val callUrlState = state.customElementCallBaseUrlState
|
||||
fun isUsingDefaultUrl(value: String?): Boolean {
|
||||
return value.isNullOrEmpty() || value == callUrlState.defaultUrl
|
||||
}
|
||||
|
||||
val supportingText = if (isUsingDefaultUrl(callUrlState.baseUrl)) {
|
||||
stringResource(R.string.screen_advanced_settings_element_call_base_url_description)
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package io.element.android.features.preferences.impl.notifications
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -121,7 +120,6 @@ private fun NotificationSettingsContentView(
|
||||
PreferenceSwitch(
|
||||
title = stringResource(id = R.string.screen_notification_settings_enable_notifications),
|
||||
isChecked = systemSettings.appNotificationsEnabled,
|
||||
switchAlignment = Alignment.Top,
|
||||
onCheckedChange = onNotificationsEnabledChanged
|
||||
)
|
||||
|
||||
@@ -145,7 +143,6 @@ private fun NotificationSettingsContentView(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.screen_notification_settings_room_mention_label),
|
||||
isChecked = matrixSettings.atRoomNotificationsEnabled,
|
||||
switchAlignment = Alignment.Top,
|
||||
onCheckedChange = onMentionNotificationsChanged
|
||||
)
|
||||
}
|
||||
@@ -162,7 +159,6 @@ private fun NotificationSettingsContentView(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.screen_notification_settings_invite_for_me_label),
|
||||
isChecked = matrixSettings.inviteForMeNotificationsEnabled,
|
||||
switchAlignment = Alignment.Top,
|
||||
onCheckedChange = onInviteForMeNotificationsChanged
|
||||
)
|
||||
}
|
||||
|
||||
@@ -68,7 +68,10 @@ fun EditDefaultNotificationSettingView(
|
||||
} else {
|
||||
R.string.screen_notification_settings_edit_screen_group_section_header
|
||||
}
|
||||
PreferenceCategory(title = stringResource(id = categoryTitle)) {
|
||||
PreferenceCategory(
|
||||
title = stringResource(id = categoryTitle),
|
||||
showTopDivider = false,
|
||||
) {
|
||||
if (state.mode != null) {
|
||||
Column(modifier = Modifier.selectableGroup()) {
|
||||
validModes.forEach { item ->
|
||||
@@ -83,7 +86,7 @@ fun EditDefaultNotificationSettingView(
|
||||
}
|
||||
}
|
||||
if (state.roomsWithUserDefinedMode.isNotEmpty()) {
|
||||
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_edit_custom_settings_section_title)) {
|
||||
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_edit_custom_settings_section_title),) {
|
||||
state.roomsWithUserDefinedMode.forEach { summary ->
|
||||
val subtitle = when (summary.details.userDefinedNotificationMode) {
|
||||
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages)
|
||||
|
||||
@@ -399,7 +399,10 @@ private fun TopicSection(
|
||||
roomTopic: RoomTopicState,
|
||||
onActionClicked: (RoomDetailsAction) -> Unit,
|
||||
) {
|
||||
PreferenceCategory(title = stringResource(CommonStrings.common_topic)) {
|
||||
PreferenceCategory(
|
||||
title = stringResource(CommonStrings.common_topic),
|
||||
showTopDivider = false,
|
||||
) {
|
||||
if (roomTopic is RoomTopicState.CanAddTopic) {
|
||||
PreferenceText(
|
||||
title = stringResource(R.string.screen_room_details_add_topic_title),
|
||||
@@ -489,7 +492,7 @@ private fun SecuritySection() {
|
||||
|
||||
@Composable
|
||||
private fun OtherActionsSection(isDm: Boolean, onLeaveRoom: () -> Unit) {
|
||||
PreferenceCategory(showDivider = false) {
|
||||
PreferenceCategory(showTopDivider = true) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
val leaveText = stringResource(
|
||||
|
||||
@@ -45,7 +45,7 @@ fun BlockUserSection(
|
||||
) {
|
||||
PreferenceCategory(
|
||||
modifier = modifier,
|
||||
showDivider = false,
|
||||
showTopDivider = false,
|
||||
) {
|
||||
when (state.isBlocked) {
|
||||
is AsyncData.Failure -> PreferenceBlockUser(isBlocked = state.isBlocked.prevData, isLoading = false, eventSink = state.eventSink)
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components.preferences
|
||||
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
internal val preferenceMinHeightOnlyTitle = 56.dp
|
||||
internal val preferenceMinHeight = 56.dp
|
||||
internal val preferencePaddingHorizontal = 16.dp
|
||||
@@ -19,22 +19,20 @@ package io.element.android.libraries.designsystem.components.preferences
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.ListSectionHeader
|
||||
|
||||
@Composable
|
||||
fun PreferenceCategory(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String? = null,
|
||||
showDivider: Boolean = true,
|
||||
showTopDivider: Boolean = true,
|
||||
showBottomDivider: Boolean = false,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
Column(
|
||||
@@ -42,30 +40,20 @@ fun PreferenceCategory(
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
if (title != null) {
|
||||
PreferenceCategoryTitle(title = title)
|
||||
ListSectionHeader(
|
||||
title = title,
|
||||
hasDivider = showTopDivider,
|
||||
)
|
||||
} else if (showTopDivider) {
|
||||
PreferenceDivider()
|
||||
}
|
||||
content()
|
||||
if (showDivider) {
|
||||
if (showBottomDivider) {
|
||||
PreferenceDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PreferenceCategoryTitle(title: String) {
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
top = 20.dp,
|
||||
bottom = 8.dp,
|
||||
start = preferencePaddingHorizontal,
|
||||
end = preferencePaddingHorizontal,
|
||||
),
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.materialColors.primary,
|
||||
text = title,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
@Composable
|
||||
internal fun PreferenceCategoryPreview() = ElementThemedPreview {
|
||||
|
||||
@@ -17,25 +17,18 @@
|
||||
package io.element.android.libraries.designsystem.components.preferences
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
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 androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.preferenceIcon
|
||||
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
import io.element.android.libraries.designsystem.toSecondaryEnabledColor
|
||||
@@ -52,29 +45,22 @@ fun PreferenceCheckbox(
|
||||
@DrawableRes iconResourceId: Int? = null,
|
||||
showIconAreaIfNoIcon: Boolean = false,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = preferenceMinHeight)
|
||||
.clickable { onCheckedChange(!isChecked) }
|
||||
.padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
PreferenceIcon(
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
leadingContent = preferenceIcon(
|
||||
icon = icon,
|
||||
iconResourceId = iconResourceId,
|
||||
enabled = enabled,
|
||||
isVisible = showIconAreaIfNoIcon
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
showIconAreaIfNoIcon = showIconAreaIfNoIcon,
|
||||
),
|
||||
headlineContent = {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
text = title,
|
||||
color = enabled.toEnabledColor(),
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
if (supportingText != null) {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
@@ -82,15 +68,13 @@ fun PreferenceCheckbox(
|
||||
color = enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Checkbox(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically),
|
||||
},
|
||||
trailingContent = ListItemContent.Checkbox(
|
||||
checked = isChecked,
|
||||
onChange = onCheckedChange,
|
||||
enabled = enabled,
|
||||
onCheckedChange = onCheckedChange
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
@@ -112,5 +96,31 @@ internal fun PreferenceCheckboxPreview() = ElementThemedPreview {
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
PreferenceCheckbox(
|
||||
title = "Checkbox with supporting text",
|
||||
supportingText = "Supporting text",
|
||||
iconResourceId = CompoundDrawables.ic_compound_threads,
|
||||
enabled = false,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
PreferenceCheckbox(
|
||||
title = "Checkbox with supporting text",
|
||||
supportingText = "Supporting text",
|
||||
iconResourceId = null,
|
||||
showIconAreaIfNoIcon = true,
|
||||
enabled = true,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
PreferenceCheckbox(
|
||||
title = "Checkbox with supporting text",
|
||||
supportingText = "Supporting text",
|
||||
iconResourceId = null,
|
||||
showIconAreaIfNoIcon = false,
|
||||
enabled = true,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package io.element.android.libraries.designsystem.components.preferences
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
@@ -28,10 +27,7 @@ import io.element.android.libraries.designsystem.theme.components.HorizontalDivi
|
||||
fun PreferenceDivider(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
HorizontalDivider(
|
||||
modifier = modifier,
|
||||
color = ElementTheme.colors.borderDisabled,
|
||||
)
|
||||
HorizontalDivider(modifier = modifier)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
|
||||
@@ -19,14 +19,13 @@ package io.element.android.libraries.designsystem.components.preferences
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
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.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
/**
|
||||
@@ -37,15 +36,17 @@ fun PreferenceRow(
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.padding(horizontal = preferencePaddingHorizontal)
|
||||
.heightIn(min = preferenceMinHeight)
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
headlineContent = {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
|
||||
@@ -19,23 +19,18 @@ package io.element.android.libraries.designsystem.components.preferences
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.preferenceIcon
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Slider
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
|
||||
@Composable
|
||||
fun PreferenceSlide(
|
||||
@@ -51,51 +46,57 @@ fun PreferenceSlide(
|
||||
summary: String? = null,
|
||||
steps: Int = 0,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = preferenceMinHeight)
|
||||
.padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal),
|
||||
) {
|
||||
PreferenceIcon(
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
leadingContent = preferenceIcon(
|
||||
icon = icon,
|
||||
iconResourceId = iconResourceId,
|
||||
isVisible = showIconAreaIfNoIcon,
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f),
|
||||
) {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
text = title,
|
||||
color = enabled.toEnabledColor(),
|
||||
)
|
||||
summary?.let {
|
||||
enabled = enabled,
|
||||
showIconAreaIfNoIcon = showIconAreaIfNoIcon,
|
||||
),
|
||||
headlineContent = {
|
||||
Column {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
text = summary,
|
||||
color = enabled.toEnabledColor(),
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
text = title,
|
||||
)
|
||||
summary?.let {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
text = summary,
|
||||
)
|
||||
}
|
||||
Slider(
|
||||
value = value,
|
||||
steps = steps,
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
Slider(
|
||||
value = value,
|
||||
steps = steps,
|
||||
onValueChange = onValueChange,
|
||||
enabled = enabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
@Composable
|
||||
internal fun PreferenceSlidePreview() = ElementThemedPreview {
|
||||
PreferenceSlide(
|
||||
icon = CompoundIcons.UserProfile(),
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
value = 0.75F,
|
||||
onValueChange = {},
|
||||
)
|
||||
Column {
|
||||
PreferenceSlide(
|
||||
icon = CompoundIcons.UserProfile(),
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
enabled = true,
|
||||
value = 0.75F,
|
||||
onValueChange = {},
|
||||
)
|
||||
PreferenceSlide(
|
||||
icon = CompoundIcons.UserProfile(),
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
enabled = false,
|
||||
value = 0.75F,
|
||||
onValueChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,30 +17,19 @@
|
||||
package io.element.android.libraries.designsystem.components.preferences
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.preferenceIcon
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.Switch
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
import io.element.android.libraries.designsystem.toSecondaryEnabledColor
|
||||
|
||||
@Composable
|
||||
fun PreferenceSwitch(
|
||||
@@ -53,62 +42,57 @@ fun PreferenceSwitch(
|
||||
icon: ImageVector? = null,
|
||||
@DrawableRes iconResourceId: Int? = null,
|
||||
showIconAreaIfNoIcon: Boolean = false,
|
||||
switchAlignment: Alignment.Vertical = Alignment.CenterVertically
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = preferenceMinHeight)
|
||||
.clickable { onCheckedChange(!isChecked) }
|
||||
.padding(vertical = 4.dp, horizontal = preferencePaddingHorizontal),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
PreferenceIcon(
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
leadingContent = preferenceIcon(
|
||||
icon = icon,
|
||||
iconResourceId = iconResourceId,
|
||||
enabled = enabled,
|
||||
isVisible = showIconAreaIfNoIcon
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
showIconAreaIfNoIcon = showIconAreaIfNoIcon,
|
||||
),
|
||||
headlineContent = {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
text = title,
|
||||
color = enabled.toEnabledColor(),
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
if (subtitle != null) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
text = subtitle,
|
||||
color = enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.width(16.dp))
|
||||
// TODO Create a wrapper for Switch
|
||||
Switch(
|
||||
modifier = Modifier
|
||||
.align(switchAlignment),
|
||||
},
|
||||
trailingContent = ListItemContent.Switch(
|
||||
checked = isChecked,
|
||||
onChange = onCheckedChange,
|
||||
enabled = enabled,
|
||||
onCheckedChange = onCheckedChange
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
@Composable
|
||||
internal fun PreferenceSwitchPreview() = ElementThemedPreview {
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
subtitle = "Subtitle Switch",
|
||||
icon = CompoundIcons.Threads(),
|
||||
enabled = true,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
Column {
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
subtitle = "Subtitle Switch",
|
||||
icon = CompoundIcons.Threads(),
|
||||
enabled = true,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
subtitle = "Subtitle Switch",
|
||||
icon = CompoundIcons.Threads(),
|
||||
enabled = false,
|
||||
isChecked = true,
|
||||
onCheckedChange = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,9 @@
|
||||
package io.element.android.libraries.designsystem.components.preferences
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.progressSemantics
|
||||
@@ -38,18 +35,17 @@ import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.components.preferences.components.preferenceIcon
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
import io.element.android.libraries.designsystem.toSecondaryEnabledColor
|
||||
|
||||
/**
|
||||
* Tried to use ListItem, but it cannot really match the design. Keep custom Layout for now.
|
||||
*/
|
||||
@Composable
|
||||
fun PreferenceText(
|
||||
title: String,
|
||||
@@ -67,34 +63,26 @@ fun PreferenceText(
|
||||
tintColor: Color? = null,
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
val minHeight = if (subtitle == null && subtitleAnnotated == null) preferenceMinHeightOnlyTitle else preferenceMinHeight
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = minHeight)
|
||||
.clickable { onClick() }
|
||||
.padding(horizontal = preferencePaddingHorizontal, vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
PreferenceIcon(
|
||||
ListItem(
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
leadingContent = preferenceIcon(
|
||||
icon = icon,
|
||||
iconResourceId = iconResourceId,
|
||||
showIconBadge = showIconBadge,
|
||||
enabled = enabled,
|
||||
isVisible = showIconAreaIfNoIcon,
|
||||
tintColor = tintColor ?: enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
showIconAreaIfNoIcon = showIconAreaIfNoIcon,
|
||||
tintColor = tintColor,
|
||||
),
|
||||
headlineContent = {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
text = title,
|
||||
color = tintColor ?: enabled.toEnabledColor(),
|
||||
)
|
||||
},
|
||||
supportingContent = {
|
||||
if (subtitle != null) {
|
||||
Text(
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
@@ -108,35 +96,35 @@ fun PreferenceText(
|
||||
color = tintColor ?: enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (currentValue != null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.padding(start = 16.dp, end = 8.dp),
|
||||
text = currentValue,
|
||||
style = ElementTheme.typography.fontBodyXsMedium,
|
||||
color = enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
} else if (loadingCurrentValue) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.progressSemantics()
|
||||
.padding(start = 16.dp, end = 8.dp)
|
||||
.size(20.dp)
|
||||
.align(Alignment.CenterVertically),
|
||||
strokeWidth = 2.dp
|
||||
)
|
||||
}
|
||||
if (showEndBadge) {
|
||||
val endBadgeStartPadding = if (currentValue != null || loadingCurrentValue) 8.dp else 16.dp
|
||||
RedIndicatorAtom(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterVertically)
|
||||
.padding(start = endBadgeStartPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
trailingContent = ListItemContent.Custom {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
if (currentValue != null) {
|
||||
Text(
|
||||
text = currentValue,
|
||||
style = ElementTheme.typography.fontBodyXsMedium,
|
||||
color = enabled.toSecondaryEnabledColor(),
|
||||
)
|
||||
} else if (loadingCurrentValue) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.progressSemantics()
|
||||
.size(20.dp),
|
||||
strokeWidth = 2.dp
|
||||
)
|
||||
}
|
||||
if (showEndBadge) {
|
||||
val endBadgeStartPadding = if (currentValue != null || loadingCurrentValue) 16.dp else 0.dp
|
||||
RedIndicatorAtom(
|
||||
modifier = Modifier
|
||||
.padding(start = endBadgeStartPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.Preferences)
|
||||
|
||||
@@ -19,7 +19,6 @@ package io.element.android.libraries.designsystem.components.preferences.compone
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -31,13 +30,37 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RedIndicatorAtom
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.toSecondaryEnabledColor
|
||||
|
||||
@Composable
|
||||
fun PreferenceIcon(
|
||||
fun preferenceIcon(
|
||||
icon: ImageVector? = null,
|
||||
@DrawableRes iconResourceId: Int? = null,
|
||||
showIconBadge: Boolean = false,
|
||||
tintColor: Color? = null,
|
||||
enabled: Boolean = true,
|
||||
showIconAreaIfNoIcon: Boolean = false,
|
||||
): ListItemContent.Custom? {
|
||||
return if (icon != null || iconResourceId != null || showIconAreaIfNoIcon) {
|
||||
ListItemContent.Custom {
|
||||
PreferenceIcon(
|
||||
icon = icon,
|
||||
iconResourceId = iconResourceId,
|
||||
showIconBadge = showIconBadge,
|
||||
enabled = enabled,
|
||||
isVisible = showIconAreaIfNoIcon,
|
||||
tintColor = tintColor,
|
||||
)
|
||||
}
|
||||
} else null
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PreferenceIcon(
|
||||
modifier: Modifier = Modifier,
|
||||
icon: ImageVector? = null,
|
||||
@DrawableRes iconResourceId: Int? = null,
|
||||
@@ -54,19 +77,17 @@ fun PreferenceIcon(
|
||||
contentDescription = null,
|
||||
tint = tintColor ?: enabled.toSecondaryEnabledColor(),
|
||||
modifier = Modifier
|
||||
.padding(end = 16.dp)
|
||||
.size(24.dp),
|
||||
)
|
||||
if (showIconBadge) {
|
||||
RedIndicatorAtom(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.padding(end = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (isVisible) {
|
||||
Spacer(modifier = modifier.width(40.dp))
|
||||
Spacer(modifier = modifier.width(24.dp))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user