From 7ad5955e5fcfb225e6713ea80bcae9427fc4b3d8 Mon Sep 17 00:00:00 2001 From: Kainoa Kanter Date: Sun, 4 Jan 2026 10:26:13 -0800 Subject: [PATCH 1/6] fix: actual compact navbar height --- ui/core/src/commonMain/kotlin/com/tunjid/heron/ui/Tokens.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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( From 608e07aa6bfe773e9ccbc641d786f4472e69529f Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sun, 4 Jan 2026 16:20:23 -0500 Subject: [PATCH 2/6] Improve UX of settings items --- .../settings/ui/AppearanceItem.android.kt | 12 ++-- .../heron/settings/ui/AppearanceItem.kt | 7 +++ .../heron/settings/ui/ContentAndMediaItem.kt | 26 +++------ .../settings/ui/OpenSourceLibrariesItem.kt | 2 +- .../heron/settings/ui/SettingsItemRow.kt | 58 ++++++++++++++----- .../heron/settings/ui/AppearanceItem.jvm.kt | 12 ++-- .../heron/settings/ui/AppearanceItem.ios.kt | 12 ++-- 7 files changed, 78 insertions(+), 51 deletions(-) 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..d974b4887 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 @@ -25,6 +25,7 @@ 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 +34,7 @@ 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.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandLess import androidx.compose.material3.Icon @@ -46,6 +48,7 @@ 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 @@ -68,14 +71,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 +114,12 @@ fun ExpandableSettingsItemRow( var isExpanded by rememberSaveable { mutableStateOf(false) } Column( - modifier = modifier - .fillMaxWidth() - .clickable { isExpanded = !isExpanded }, + modifier = SettingsItemClipModifier + .then( + modifier + .fillMaxWidth() + .clickable { isExpanded = !isExpanded }, + ), ) { SettingsItemRow( modifier = Modifier @@ -147,6 +156,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,20 +170,34 @@ 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 + .clickable { onCheckedChange(!checked) } + .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, @@ -183,3 +209,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 From 768acfb395207bd36ea66ad7f0c7b8c38dafd3e2 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sun, 4 Jan 2026 16:27:09 -0500 Subject: [PATCH 3/6] PR feedback --- .../com/tunjid/heron/settings/ui/SettingsItemRow.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 d974b4887..29a12bd73 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 @@ -34,6 +34,7 @@ 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 @@ -52,6 +53,7 @@ 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 @@ -180,7 +182,12 @@ fun SettingsToggleItem( modifier = SettingsItemClipModifier .then( modifier - .clickable { onCheckedChange(!checked) } + .toggleable( + value = checked, + onValueChange = onCheckedChange, + enabled = enabled, + role = Role.Switch, + ) .padding( horizontal = 8.dp, vertical = 4.dp, @@ -201,7 +208,7 @@ fun SettingsToggleItem( Switch( enabled = enabled, checked = checked, - onCheckedChange = onCheckedChange, + onCheckedChange = null, ) } } From 2e4ad966fe42568cb51a023a495c76826bf890e5 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sun, 4 Jan 2026 16:32:10 -0500 Subject: [PATCH 4/6] PR feedback --- .../kotlin/com/tunjid/heron/settings/ui/SettingsItemRow.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 29a12bd73..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,6 @@ 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 @@ -120,7 +119,11 @@ fun ExpandableSettingsItemRow( .then( modifier .fillMaxWidth() - .clickable { isExpanded = !isExpanded }, + .toggleable( + value = isExpanded, + onValueChange = { isExpanded = it }, + role = Role.Button, + ), ), ) { SettingsItemRow( From 0e4d7857c8a504c66317d645444f979ed69a6219 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sun, 4 Jan 2026 16:45:46 -0500 Subject: [PATCH 5/6] Fix missing arguments for Profile fake --- .../src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt | 4 ++++ 1 file changed, 4 insertions(+) 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..929ed6317 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 @@ -1,6 +1,7 @@ package com.tunjid.heron.fakes import com.tunjid.heron.data.core.models.Profile +import com.tunjid.heron.data.core.models.Profile.ChatInfo import com.tunjid.heron.data.core.types.ProfileHandle import com.tunjid.heron.data.core.types.ProfileId import kotlin.time.Instant @@ -23,6 +24,9 @@ fun sampleProfile(): Profile { createdListCount = 0, createdFeedGeneratorCount = 0, createdStarterPackCount = 0, + chat = ChatInfo( + allowed = ChatInfo.Allowed.NoOne, + ), ), labels = emptyList(), isLabeler = false, From c4b68f06d1fda0db1e396d587ec8eae99d7dd080 Mon Sep 17 00:00:00 2001 From: Adetunji Dahunsi Date: Sun, 4 Jan 2026 16:49:16 -0500 Subject: [PATCH 6/6] PR feedback --- .../src/commonTest/kotlin/com/tunjid/heron/fakes/Profile.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 929ed6317..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 @@ -1,7 +1,6 @@ package com.tunjid.heron.fakes import com.tunjid.heron.data.core.models.Profile -import com.tunjid.heron.data.core.models.Profile.ChatInfo import com.tunjid.heron.data.core.types.ProfileHandle import com.tunjid.heron.data.core.types.ProfileId import kotlin.time.Instant @@ -24,8 +23,8 @@ fun sampleProfile(): Profile { createdListCount = 0, createdFeedGeneratorCount = 0, createdStarterPackCount = 0, - chat = ChatInfo( - allowed = ChatInfo.Allowed.NoOne, + chat = Profile.ChatInfo( + allowed = Profile.ChatInfo.Allowed.NoOne, ), ), labels = emptyList(),