diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt index 7c8634a078..b53618df11 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsView.kt @@ -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 diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 5a40534b87..dceeb795f1 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -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 { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index d62f972d71..7dda9b684b 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -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 ) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index 1938a4b4f0..dc7efc1f5d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -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) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 76807c07e6..34bb3a7a65 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -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( diff --git a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt index 6ad1bf8484..424219158a 100644 --- a/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt +++ b/features/userprofile/shared/src/main/kotlin/io/element/android/features/userprofile/shared/blockuser/BlockUserSection.kt @@ -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) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt deleted file mode 100644 index be8c86448e..0000000000 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/Config.kt +++ /dev/null @@ -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 diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt index f86177d98e..f11e39d62f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt @@ -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 { diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt index cebe0ddbe2..f2fddd21a3 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCheckbox.kt @@ -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 = {}, + ) } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDivider.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDivider.kt index 27a846aa10..57bd88b637 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDivider.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceDivider.kt @@ -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) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt index 80813a2d1a..e217f5150a 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceRow.kt @@ -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) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt index 392343f48e..9173c1e193 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSlide.kt @@ -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 = {}, + ) + } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt index e79e915484..d7edfd730f 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceSwitch.kt @@ -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 = {}, + ) + } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt index e8a859b54a..2e0a6ed48b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceText.kt @@ -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) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt index 61e8aabdd7..b298d2a1e9 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/components/PreferenceIcon.kt @@ -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)) } }