diff --git a/data/models/src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt b/data/models/src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt index d0a931103..4ae74f90b 100644 --- a/data/models/src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt +++ b/data/models/src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt @@ -23,6 +23,9 @@ fun sampleProfile(): Profile { createdListCount = 0, createdFeedGeneratorCount = 0, createdStarterPackCount = 0, + chat = Profile.ChatInfo( + allowed = Profile.ChatInfo.Allowed.NoOne, + ), ), labels = emptyList(), isLabeler = false, diff --git a/feature/settings/src/androidMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.android.kt b/feature/settings/src/androidMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.android.kt index a5a469a58..1de6660fa 100644 --- a/feature/settings/src/androidMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.android.kt +++ b/feature/settings/src/androidMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.android.kt @@ -16,10 +16,10 @@ package com.tunjid.heron.settings.ui -actual fun isDynamicThemingSupported(): Boolean { - return true -} +import androidx.compose.runtime.Stable -actual fun isCompactNavigationSupported(): Boolean { - return true -} +@Stable +actual fun isDynamicThemingSupported(): Boolean = true + +@Stable +actual fun isCompactNavigationSupported(): Boolean = true diff --git a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.kt b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.kt index 349819352..4fd9af837 100644 --- a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.kt +++ b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.kt @@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Palette import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.ui.Modifier import com.tunjid.heron.data.core.models.Preferences import heron.feature.settings.generated.resources.Res @@ -28,8 +29,10 @@ import heron.feature.settings.generated.resources.use_compact_navigation import heron.feature.settings.generated.resources.use_dynamic_theming import org.jetbrains.compose.resources.stringResource +@Stable expect fun isDynamicThemingSupported(): Boolean +@Stable expect fun isCompactNavigationSupported(): Boolean @Composable @@ -49,12 +52,16 @@ fun AppearanceItem( icon = Icons.Rounded.Palette, ) { SettingsToggleItem( + modifier = Modifier + .fillMaxWidth(), text = stringResource(Res.string.use_dynamic_theming), enabled = isDynamicThemingSupported, checked = signedInProfilePreferences.useDynamicTheming, onCheckedChange = setDynamicThemingPreference, ) SettingsToggleItem( + modifier = Modifier + .fillMaxWidth(), text = stringResource(Res.string.use_compact_navigation), enabled = isCompactNavigationSupported, checked = signedInProfilePreferences.useCompactNavigation, diff --git a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/ContentAndMediaItem.kt b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/ContentAndMediaItem.kt index dd2bbaf65..58e7a5230 100644 --- a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/ContentAndMediaItem.kt +++ b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/ContentAndMediaItem.kt @@ -16,15 +16,10 @@ package com.tunjid.heron.settings.ui -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Newspaper -import androidx.compose.material3.Switch -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import com.tunjid.heron.data.core.models.Preferences import heron.feature.settings.generated.resources.Res @@ -44,18 +39,13 @@ fun ContentAndMediaItem( title = stringResource(Res.string.content_and_media), icon = Icons.Rounded.Newspaper, ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = stringResource(Res.string.refresh_timelines_on_launch), - ) - Switch( - checked = signedInProfilePreferences.refreshHomeTimelineOnLaunch, - onCheckedChange = setRefreshHomeTimelineOnLaunch, - ) - } + SettingsToggleItem( + modifier = Modifier + .fillMaxWidth(), + text = stringResource(Res.string.refresh_timelines_on_launch), + enabled = true, + checked = signedInProfilePreferences.refreshHomeTimelineOnLaunch, + onCheckedChange = setRefreshHomeTimelineOnLaunch, + ) } } diff --git a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/OpenSourceLibrariesItem.kt b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/OpenSourceLibrariesItem.kt index f0e450fd7..ac6eb528b 100644 --- a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/OpenSourceLibrariesItem.kt +++ b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/OpenSourceLibrariesItem.kt @@ -90,7 +90,7 @@ private fun LibrariesHorizontalGrid( LazyHorizontalGrid( modifier = modifier, rows = GridCells.Adaptive(56.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), ) { items( items = libs, diff --git a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/SettingsItemRow.kt b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/SettingsItemRow.kt index 53c314d56..d7de7b849 100644 --- a/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/SettingsItemRow.kt +++ b/feature/settings/src/commonMain/kotlin/com/tunjid/heron/settings/ui/SettingsItemRow.kt @@ -24,7 +24,7 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically -import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row @@ -33,6 +33,8 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.selection.toggleable +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandLess import androidx.compose.material3.Icon @@ -46,9 +48,11 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.IntSize @@ -68,14 +72,17 @@ fun SettingsItemRow( ) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = modifier - .semantics { - contentDescription = title - } - .fillMaxWidth() - .padding( - horizontal = 24.dp, - vertical = 8.dp, + modifier = SettingsItemClipModifier + .then( + modifier + .semantics { + contentDescription = title + } + .fillMaxWidth() + .padding( + horizontal = 24.dp, + vertical = 8.dp, + ), ), ) { Icon( @@ -108,9 +115,16 @@ fun ExpandableSettingsItemRow( var isExpanded by rememberSaveable { mutableStateOf(false) } Column( - modifier = modifier - .fillMaxWidth() - .clickable { isExpanded = !isExpanded }, + modifier = SettingsItemClipModifier + .then( + modifier + .fillMaxWidth() + .toggleable( + value = isExpanded, + onValueChange = { isExpanded = it }, + role = Role.Button, + ), + ), ) { SettingsItemRow( modifier = Modifier @@ -147,6 +161,9 @@ fun ExpandableSettingsItemRow( content = { Column( modifier = Modifier + // Inset expanded content from the start to disambiguate + // it from other items + .padding(start = 8.dp) .fillMaxWidth(), ) { content() @@ -158,24 +175,43 @@ fun ExpandableSettingsItemRow( @Composable fun SettingsToggleItem( + modifier: Modifier = Modifier, text: String, enabled: Boolean, checked: Boolean, onCheckedChange: (Boolean) -> Unit, ) { Row( - modifier = Modifier.fillMaxWidth(), + modifier = SettingsItemClipModifier + .then( + modifier + .toggleable( + value = checked, + onValueChange = onCheckedChange, + enabled = enabled, + role = Role.Switch, + ) + .padding( + horizontal = 8.dp, + vertical = 4.dp, + ), + ), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, ) { Text( + modifier = Modifier + .weight(1f), text = text, ) - Spacer(Modifier.weight(1f)) - Spacer(Modifier.width(16.dp)) + Spacer( + modifier = Modifier + .width(16.dp), + ) Switch( enabled = enabled, checked = checked, - onCheckedChange = onCheckedChange, + onCheckedChange = null, ) } } @@ -183,3 +219,7 @@ fun SettingsToggleItem( private val EnterTransition = fadeIn() + slideInVertically { -it } private val ExitTransition = shrinkOut { IntSize(it.width, 0) } + slideOutVertically { -it } + fadeOut() + +private val SettingsItemShape = RoundedCornerShape(8.dp) +private val SettingsItemClipModifier = Modifier + .clip(SettingsItemShape) diff --git a/feature/settings/src/desktopMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.jvm.kt b/feature/settings/src/desktopMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.jvm.kt index 2cac5853b..ef6ecfa70 100644 --- a/feature/settings/src/desktopMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.jvm.kt +++ b/feature/settings/src/desktopMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.jvm.kt @@ -16,10 +16,10 @@ package com.tunjid.heron.settings.ui -actual fun isDynamicThemingSupported(): Boolean { - return false -} +import androidx.compose.runtime.Stable -actual fun isCompactNavigationSupported(): Boolean { - return false -} +@Stable +actual fun isDynamicThemingSupported(): Boolean = false + +@Stable +actual fun isCompactNavigationSupported(): Boolean = false diff --git a/feature/settings/src/iosMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.ios.kt b/feature/settings/src/iosMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.ios.kt index 55f0be7c3..5047cbc71 100644 --- a/feature/settings/src/iosMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.ios.kt +++ b/feature/settings/src/iosMain/kotlin/com/tunjid/heron/settings/ui/AppearanceItem.ios.kt @@ -16,10 +16,10 @@ package com.tunjid.heron.settings.ui -actual fun isDynamicThemingSupported(): Boolean { - return false -} +import androidx.compose.runtime.Stable -actual fun isCompactNavigationSupported(): Boolean { - return true -} +@Stable +actual fun isDynamicThemingSupported(): Boolean = false + +@Stable +actual fun isCompactNavigationSupported(): Boolean = true diff --git a/ui/core/src/commonMain/kotlin/com/tunjid/heron/ui/Tokens.kt b/ui/core/src/commonMain/kotlin/com/tunjid/heron/ui/Tokens.kt index 18deb4bc1..c8ef16e20 100644 --- a/ui/core/src/commonMain/kotlin/com/tunjid/heron/ui/Tokens.kt +++ b/ui/core/src/commonMain/kotlin/com/tunjid/heron/ui/Tokens.kt @@ -61,7 +61,7 @@ object UiTokens { fun bottomNavHeight( isCompact: Boolean, - ): Dp = if (isCompact) 64.dp else 80.dp + ): Dp = if (isCompact) 48.dp else 80.dp @Composable fun bottomNavAndInsetPaddingValues(