Skip to content

Commit 202ed08

Browse files
committed
fix: disable dynamic accents and clear keyboard insets
1 parent dd3c15d commit 202ed08

5 files changed

Lines changed: 96 additions & 11 deletions

File tree

‎app/src/androidTest/java/dev/typetype/android/feature/settings/appearance/AppearanceScreenTest.kt‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package dev.typetype.android.feature.settings.appearance
22

3+
import android.os.Build
34
import androidx.compose.ui.test.assertHasClickAction
45
import androidx.compose.ui.test.assertIsDisplayed
6+
import androidx.compose.ui.test.assertIsEnabled
7+
import androidx.compose.ui.test.assertIsNotEnabled
58
import androidx.compose.ui.test.assertIsNotSelected
69
import androidx.compose.ui.test.assertIsSelected
710
import androidx.compose.ui.test.hasText
@@ -14,9 +17,11 @@ import androidx.compose.ui.test.performScrollToIndex
1417
import dev.typetype.android.core.ui.theme.TypeTypeTheme
1518
import dev.typetype.android.domain.preferences.AccentColor
1619
import dev.typetype.android.domain.preferences.AppPreferences
20+
import dev.typetype.android.domain.preferences.AppearancePersonality
1721
import dev.typetype.android.domain.preferences.AppearanceTheme
1822
import java.util.concurrent.atomic.AtomicReference
1923
import org.junit.Assert.assertEquals
24+
import org.junit.Assume.assumeTrue
2025
import org.junit.Rule
2126
import org.junit.Test
2227

@@ -69,4 +74,43 @@ class AppearanceScreenTest {
6974

7075
assertEquals(AppearanceAction.SelectTheme(AppearanceTheme.Forest), selected.get())
7176
}
77+
78+
@Test
79+
fun accentCellsAreDisabledWhenDynamicColorsAreActive() {
80+
assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
81+
82+
composeRule.setContent {
83+
TypeTypeTheme {
84+
AppearanceScreen(
85+
state = AppPreferences(appearanceTheme = AppearanceTheme.Dynamic),
86+
onAction = {},
87+
onNavigateBack = {},
88+
)
89+
}
90+
}
91+
92+
composeRule.onAllNodes(hasScrollAction())[0].performScrollToIndex(11)
93+
composeRule.onNode(isSelectable() and hasText("Red"))
94+
.assertIsNotEnabled()
95+
}
96+
97+
@Test
98+
fun accentCellsRemainEnabledForMangaDynamicTheme() {
99+
composeRule.setContent {
100+
TypeTypeTheme {
101+
AppearanceScreen(
102+
state = AppPreferences(
103+
appearancePersonality = AppearancePersonality.Manga,
104+
appearanceTheme = AppearanceTheme.Dynamic,
105+
),
106+
onAction = {},
107+
onNavigateBack = {},
108+
)
109+
}
110+
}
111+
112+
composeRule.onAllNodes(hasScrollAction())[0].performScrollToIndex(11)
113+
composeRule.onNode(isSelectable() and hasText("Red"))
114+
.assertIsEnabled()
115+
}
72116
}

‎app/src/main/java/dev/typetype/android/AppShell.kt‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.consumeWindowInsets
1212
import androidx.compose.foundation.layout.Row
1313
import androidx.compose.foundation.layout.WindowInsets
1414
import androidx.compose.foundation.layout.fillMaxSize
15+
import androidx.compose.foundation.layout.ime
1516
import androidx.compose.foundation.layout.padding
1617
import androidx.compose.foundation.layout.systemBars
1718
import androidx.compose.material3.Scaffold
@@ -101,6 +102,12 @@ fun AppShell(
101102
var isPlayerFullscreen by remember { mutableStateOf(false) }
102103
var bottomNavigationHeight by remember { mutableStateOf(0.dp) }
103104
val density = LocalDensity.current
105+
val imeVisible = WindowInsets.ime.getBottom(density) > 0
106+
val appNavigationVisible = shouldShowAppNavigation(
107+
showsNavigation = showsNavigation,
108+
isPlayerFullscreen = isPlayerFullscreen,
109+
imeVisible = imeVisible,
110+
)
104111
var playerTransitionProgress by remember { mutableFloatStateOf(0f) }
105112
val playerHostState by playerHostController.state.collectAsStateWithLifecycle()
106113
val appChromeVisible = isAppChromeVisible(playerHostState.target, isPlayerFullscreen)
@@ -164,7 +171,7 @@ fun AppShell(
164171
}
165172
},
166173
bottomBar = {
167-
if (showsNavigation && !isPlayerFullscreen) {
174+
if (appNavigationVisible) {
168175
AppBottomBar(
169176
expanded = tabletLayout,
170177
selectedTabRouteQualifiedName = selectedTabRouteQualifiedName,
@@ -199,14 +206,15 @@ fun AppShell(
199206
}
200207
PlayerHost(
201208
controller = playerHostController,
202-
reserveNavigationBarInset = !tabletLayout || !showsNavigation || isPlayerFullscreen,
209+
reserveNavigationBarInset = (!tabletLayout && !imeVisible) ||
210+
!showsNavigation || isPlayerFullscreen,
203211
modifier = Modifier.padding(
204-
bottom = if (tabletLayout && showsNavigation && !isPlayerFullscreen) bottomNavigationHeight else 0.dp,
212+
bottom = if (tabletLayout && appNavigationVisible) bottomNavigationHeight else 0.dp,
205213
).consumeWindowInsets(PaddingValues(
206-
bottom = if (tabletLayout && showsNavigation && !isPlayerFullscreen) bottomNavigationHeight else 0.dp,
214+
bottom = if (tabletLayout && appNavigationVisible) bottomNavigationHeight else 0.dp,
207215
)),
208216
bottomBarHeightDp = if (
209-
!tabletLayout && showsNavigation && !isPlayerFullscreen
217+
!tabletLayout && appNavigationVisible
210218
) {
211219
NAV_BAR_HEIGHT_DP
212220
} else {
@@ -241,6 +249,12 @@ internal fun isAppChromeVisible(
241249
isPlayerFullscreen: Boolean,
242250
): Boolean = playerTarget != PlayerHostTarget.Expanded && !isPlayerFullscreen
243251

252+
internal fun shouldShowAppNavigation(
253+
showsNavigation: Boolean,
254+
isPlayerFullscreen: Boolean,
255+
imeVisible: Boolean,
256+
): Boolean = showsNavigation && !isPlayerFullscreen && !imeVisible
257+
244258
internal fun playerPhoneChromeAlpha(
245259
hasVideo: Boolean,
246260
playerTarget: PlayerHostTarget,

‎app/src/main/java/dev/typetype/android/feature/settings/appearance/AppearanceScreen.kt‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.typetype.android.feature.settings.appearance
22

3+
import android.os.Build
34
import androidx.compose.foundation.layout.Arrangement
45
import androidx.compose.foundation.layout.PaddingValues
56
import androidx.compose.foundation.layout.fillMaxSize
@@ -19,6 +20,7 @@ import dev.typetype.android.core.ui.components.SectionHeader
1920
import dev.typetype.android.core.ui.components.KomiStoreAttribution
2021
import dev.typetype.android.domain.preferences.AppearanceMode
2122
import dev.typetype.android.domain.preferences.AppearancePersonality
23+
import dev.typetype.android.domain.preferences.AppearanceTheme
2224
import dev.typetype.android.domain.preferences.AppPreferences
2325
import dev.typetype.android.feature.settings.SettingsDetailTopBar
2426

@@ -68,7 +70,16 @@ fun AppearanceScreen(
6870
appearanceModeItems(state, onAction)
6971
if (state.appearanceMode != AppearanceMode.Light) appearanceAmoledItem(state, onAction)
7072
appearanceSection(R.string.settings_appearance_accent_color)
71-
item { AccentChooser(state.accentColor, onAction) }
73+
item {
74+
val accentDisabled = state.appearanceTheme == AppearanceTheme.Dynamic &&
75+
state.appearancePersonality == AppearancePersonality.Classic &&
76+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
77+
AccentChooser(
78+
current = state.accentColor,
79+
accentDisabled = accentDisabled,
80+
onAction = onAction,
81+
)
82+
}
7283
appearanceSection(R.string.appearance_typography)
7384
appearanceFontItems(state, onAction)
7485
appearanceSection(R.string.appearance_motion)

‎app/src/main/java/dev/typetype/android/feature/settings/appearance/AppearanceSettingsSections.kt‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import androidx.compose.material3.Text
2525
import androidx.compose.runtime.Composable
2626
import androidx.compose.ui.Alignment
2727
import androidx.compose.ui.Modifier
28+
import androidx.compose.ui.draw.alpha
2829
import androidx.compose.ui.draw.rotate
2930
import androidx.compose.ui.geometry.Offset
3031
import androidx.compose.ui.graphics.Color
@@ -216,18 +217,25 @@ private fun AppearanceToggleRow(
216217
}
217218

218219
@Composable
219-
fun AccentChooser(current: AccentColor, onAction: (AppearanceAction) -> Unit) {
220+
fun AccentChooser(
221+
current: AccentColor,
222+
accentDisabled: Boolean = false,
223+
onAction: (AppearanceAction) -> Unit,
224+
) {
220225
Row(
221226
Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()).padding(horizontal = 20.dp, vertical = 8.dp),
222227
horizontalArrangement = Arrangement.spacedBy(16.dp),
223228
) {
224229
accents.forEach { swatch ->
225230
val label = stringResource(swatch.label)
226231
Column(
227-
modifier = Modifier.selectable(
228-
selected = swatch.accent == current,
229-
role = Role.RadioButton,
230-
) { onAction(AppearanceAction.SelectAccent(swatch.accent)) },
232+
modifier = Modifier
233+
.alpha(if (accentDisabled) 0.38f else 1f)
234+
.selectable(
235+
selected = swatch.accent == current,
236+
enabled = !accentDisabled,
237+
role = Role.RadioButton,
238+
) { onAction(AppearanceAction.SelectAccent(swatch.accent)) },
231239
horizontalAlignment = Alignment.CenterHorizontally,
232240
) {
233241
Box(

‎app/src/test/java/dev/typetype/android/AppChromeVisibilityTest.kt‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ class AppChromeVisibilityTest {
2121
assertFalse(isAppChromeVisible(PlayerHostTarget.Mini, true))
2222
}
2323

24+
@Test
25+
fun keyboardHidesAppNavigationWithoutChangingOtherVisibilityRules() {
26+
assertTrue(shouldShowAppNavigation(true, false, false))
27+
assertFalse(shouldShowAppNavigation(true, false, true))
28+
assertFalse(shouldShowAppNavigation(false, false, false))
29+
assertFalse(shouldShowAppNavigation(true, true, false))
30+
}
31+
2432
@Test
2533
fun phoneChromeFollowsPlayerMotionInBothDirections() {
2634
assertEquals(

0 commit comments

Comments
 (0)