Skip to content

Iterate on preference design #2922

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 27, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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(),
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)

Expand All @@ -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
)
}
Expand All @@ -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
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class DeveloperSettingsViewTest {
}
}

@Config(qualifiers = "h1024dp")
@Test
fun `clicking on configure tracing invokes the expected callback`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>(expectEvents = false)
Expand All @@ -96,7 +97,7 @@ class DeveloperSettingsViewTest {
}
}

@Config(qualifiers = "h1024dp")
@Config(qualifiers = "h1500dp")
@Test
fun `clicking on clear cache emits the expected event`() {
val eventsRecorder = EventsRecorder<DeveloperSettingsEvents>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,53 +19,37 @@ 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,
content: @Composable ColumnScope.() -> Unit,
) {
Column(
modifier = modifier
.fillMaxWidth()
) {
if (title != null) {
PreferenceCategoryTitle(title = title)
}
content()
if (showDivider) {
ListSectionHeader(
title = title,
hasDivider = showTopDivider,
)
} else if (showTopDivider) {
PreferenceDivider()
}
content()
}
}

@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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -52,45 +45,36 @@ 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,
onClick = onCheckedChange.takeIf { enabled }?.let { { onCheckedChange(!isChecked) } },
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(),
)
if (supportingText != null) {
},
supportingContent = supportingText?.let {
{
Text(
style = ElementTheme.typography.fontBodyMdRegular,
text = supportingText,
text = it,
color = enabled.toSecondaryEnabledColor(),
)
}
}
Checkbox(
modifier = Modifier
.align(Alignment.CenterVertically),
},
trailingContent = ListItemContent.Checkbox(
checked = isChecked,
enabled = enabled,
onCheckedChange = onCheckedChange
)
}
),
)
}

@Preview(group = PreviewGroup.Preferences)
Expand All @@ -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 = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading
Loading