Skip to content

Commit a2a9004

Browse files
committed
Fix: App crash due in full space mode.
1 parent 27b696d commit a2a9004

File tree

15 files changed

+315
-120
lines changed

15 files changed

+315
-120
lines changed

AdaptiveJetStream/gradle/libs.versions.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ android-test-plugin = "8.13.0"
55
androidx-baselineprofile = "1.4.1"
66
benchmark-macro-junit4 = "1.4.1"
77
coil-compose = "2.7.0"
8-
compose-bom = "2025.09.00"
8+
compose-bom = "2025.09.01"
99
tv-material = "1.0.1"
1010
core-ktx = "1.17.0"
1111
core-splashscreen = "1.0.1"
1212
hilt-navigation-compose = "1.3.0"
13-
hilt-android = "2.57.1"
13+
hilt-android = "2.57.2"
1414
junit = "1.3.0"
1515
kotlin-android = "2.2.20"
1616
kotlinx-serialization = "1.9.0"
1717
ksp = "2.2.20-2.0.3"
1818
lifecycle-runtime-ktx = "2.9.4"
1919
material3-adaptive = "1.1.0"
20-
material3-adaptive-navigation = "1.4.0-rc01"
20+
material3-adaptive-navigation = "1.4.0"
2121
media3 = "1.8.0"
22-
navigation-compose = "2.9.4"
22+
navigation-compose = "2.9.5"
2323
profileinstaller = "1.4.1"
2424
uiautomator = "2.3.0"
2525
rules = "1.7.0"
26-
window = "1.4.0"
27-
xr = "1.0.0-alpha06"
26+
window = "1.5.0"
27+
xr = "1.0.0-alpha07"
2828
xr-material3 = "1.0.0-alpha11"
2929

3030
[libraries]

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/MainActivity.kt

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,10 @@ import androidx.compose.foundation.layout.safeDrawingPadding
3333
import androidx.compose.material3.LocalAbsoluteTonalElevation
3434
import androidx.compose.material3.LocalContentColor
3535
import androidx.compose.material3.MaterialTheme
36-
import androidx.compose.material3.Surface
3736
import androidx.compose.material3.surfaceColorAtElevation
3837
import androidx.compose.runtime.CompositionLocalProvider
3938
import androidx.compose.ui.Modifier
4039
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
41-
import androidx.xr.compose.material3.EnableXrComponentOverrides
4240
import androidx.xr.compose.material3.ExperimentalMaterial3XrApi
4341
import com.google.jetstream.presentation.App
4442
import com.google.jetstream.presentation.theme.JetStreamTheme
@@ -59,21 +57,17 @@ class MainActivity : ComponentActivity() {
5957
CompositionLocalProvider(
6058
LocalContentColor provides MaterialTheme.colorScheme.onSurface
6159
) {
62-
EnableXrComponentOverrides {
63-
Surface {
64-
App(
65-
onActivityBackPressed = onBackPressedDispatcher::onBackPressed,
66-
modifier = Modifier
67-
.safeDrawingPadding()
68-
.fillMaxSize()
69-
.background(
70-
MaterialTheme.colorScheme.surfaceColorAtElevation(
71-
LocalAbsoluteTonalElevation.current
72-
)
73-
)
60+
App(
61+
onActivityBackPressed = onBackPressedDispatcher::onBackPressed,
62+
modifier = Modifier
63+
.safeDrawingPadding()
64+
.fillMaxSize()
65+
.background(
66+
MaterialTheme.colorScheme.surfaceColorAtElevation(
67+
LocalAbsoluteTonalElevation.current
68+
)
7469
)
75-
}
76-
}
70+
)
7771
}
7872
}
7973
}

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/presentation/App.kt

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.google.jetstream.presentation
1818

19+
import androidx.compose.material3.Surface
1920
import androidx.compose.runtime.Composable
2021
import androidx.compose.runtime.LaunchedEffect
2122
import androidx.compose.runtime.remember
@@ -28,6 +29,7 @@ import com.google.jetstream.presentation.app.rememberAppState
2829
import com.google.jetstream.presentation.app.rememberNavigationComponentType
2930
import com.google.jetstream.presentation.app.withNavigationSuiteScaffold.AppWithNavigationSuiteScaffold
3031
import com.google.jetstream.presentation.app.withNavigationSuiteScaffold.EnableProminentMovieListOverride
32+
import com.google.jetstream.presentation.app.withSpatialNavigation.AppWithSpatialNavigation
3133
import com.google.jetstream.presentation.app.withTopBarNavigation.AppWithTopBarNavigation
3234
import com.google.jetstream.presentation.components.KeyboardShortcut
3335
import com.google.jetstream.presentation.components.ModifierKey
@@ -141,21 +143,35 @@ fun App(
141143
when (navigationComponentType) {
142144
NavigationComponentType.NavigationSuiteScaffold -> {
143145
EnableProminentMovieListOverride {
144-
AppWithNavigationSuiteScaffold(
146+
Surface {
147+
AppWithNavigationSuiteScaffold(
148+
appState = appState,
149+
navController = navController,
150+
modifier = modifier.handleKeyboardShortcuts(keyboardShortcuts),
151+
)
152+
}
153+
}
154+
}
155+
156+
NavigationComponentType.TopBar -> {
157+
Surface {
158+
AppWithTopBarNavigation(
145159
appState = appState,
160+
onActivityBackPressed = onActivityBackPressed,
146161
navController = navController,
147162
modifier = modifier.handleKeyboardShortcuts(keyboardShortcuts),
148163
)
149164
}
150165
}
151166

152-
NavigationComponentType.TopBar -> {
153-
AppWithTopBarNavigation(
154-
appState = appState,
155-
onActivityBackPressed = onActivityBackPressed,
156-
navController = navController,
157-
modifier = modifier.handleKeyboardShortcuts(keyboardShortcuts),
158-
)
167+
NavigationComponentType.Spatial -> {
168+
EnableProminentMovieListOverride {
169+
AppWithSpatialNavigation(
170+
appState = appState,
171+
navController = navController,
172+
modifier = modifier.handleKeyboardShortcuts(keyboardShortcuts),
173+
)
174+
}
159175
}
160176
}
161177
}

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/presentation/app/AppState.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,11 @@ class AppState internal constructor(
7070

7171
private fun updateNavigationVisibility() {
7272
isNavigationVisible = when (navigationComponentType) {
73-
NavigationComponentType.NavigationSuiteScaffold -> {
74-
selectedScreen.navigationVisibility.isVisibleInNavigationSuite
75-
}
76-
7773
NavigationComponentType.TopBar -> {
78-
selectedScreen.navigationVisibility.isVisibleInCustomNavigation
74+
selectedScreen.navigationVisibility.isVisibleInTopBar
75+
}
76+
else -> {
77+
selectedScreen.navigationVisibility.isVisibleInNavigationSuite
7978
}
8079
}
8180
}

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/presentation/app/NavigationComponentType.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,31 @@ package com.google.jetstream.presentation.app
1919
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
2020
import androidx.compose.runtime.Composable
2121
import androidx.compose.runtime.remember
22+
import com.google.jetstream.presentation.components.feature.SpatialMode
23+
import com.google.jetstream.presentation.components.feature.currentSpatialMode
2224
import com.google.jetstream.presentation.components.feature.isAutomotiveEnabled
2325
import com.google.jetstream.presentation.components.feature.isLeanbackEnabled
2426
import com.google.jetstream.presentation.components.feature.isWidthAtLeastLarge
2527

2628
enum class NavigationComponentType {
2729
NavigationSuiteScaffold,
28-
TopBar
30+
TopBar,
31+
Spatial
2932
}
3033

3134
@Composable
3235
fun rememberNavigationComponentType(): NavigationComponentType {
3336
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
3437
val isLeanbackEnabled = isLeanbackEnabled()
3538
val isAutomotiveEnabled = isAutomotiveEnabled()
39+
val spatialMode = currentSpatialMode()
3640

37-
return remember(isLeanbackEnabled, isAutomotiveEnabled, windowSizeClass) {
41+
return remember(isLeanbackEnabled, isAutomotiveEnabled, windowSizeClass, spatialMode) {
3842
selectNavigationComponentType(
3943
isLeanbackEnabled = isLeanbackEnabled,
4044
isAutomotiveEnabled = isAutomotiveEnabled,
41-
isLargeWindow = windowSizeClass.isWidthAtLeastLarge()
45+
isLargeWindow = windowSizeClass.isWidthAtLeastLarge(),
46+
spatialMode = spatialMode
4247
)
4348
}
4449
}
@@ -48,8 +53,10 @@ private fun selectNavigationComponentType(
4853
isLeanbackEnabled: Boolean,
4954
isAutomotiveEnabled: Boolean,
5055
isLargeWindow: Boolean,
56+
spatialMode: SpatialMode,
5157
): NavigationComponentType {
5258
return when {
59+
spatialMode == SpatialMode.Full -> NavigationComponentType.Spatial
5360
isLeanbackEnabled -> NavigationComponentType.TopBar
5461
isAutomotiveEnabled -> NavigationComponentType.TopBar
5562
isLargeWindow -> NavigationComponentType.TopBar

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/presentation/app/withNavigationSuiteScaffold/AppWithNavigationSuiteScaffold.kt

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,18 @@ import androidx.compose.foundation.layout.Arrangement
2323
import androidx.compose.foundation.layout.fillMaxSize
2424
import androidx.compose.foundation.layout.padding
2525
import androidx.compose.material3.Scaffold
26-
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
2726
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
28-
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults
29-
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldValue
30-
import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType
3127
import androidx.compose.material3.adaptive.navigationsuite.rememberNavigationSuiteScaffoldState
3228
import androidx.compose.runtime.Composable
3329
import androidx.compose.runtime.LaunchedEffect
3430
import androidx.compose.runtime.remember
3531
import androidx.compose.ui.Modifier
3632
import androidx.compose.ui.unit.dp
3733
import androidx.navigation.NavHostController
38-
import androidx.xr.compose.platform.LocalSession
39-
import androidx.xr.compose.platform.LocalSpatialCapabilities
40-
import androidx.xr.compose.platform.LocalSpatialConfiguration
4134
import com.google.jetstream.presentation.app.AppState
4235
import com.google.jetstream.presentation.app.NavigationTree
4336
import com.google.jetstream.presentation.app.updateTopBarVisibility
37+
import com.google.jetstream.presentation.components.feature.hasXrSpatialFeature
4438
import com.google.jetstream.presentation.screens.Screens
4539

4640
@Composable
@@ -49,17 +43,12 @@ fun AppWithNavigationSuiteScaffold(
4943
navController: NavHostController,
5044
modifier: Modifier = Modifier,
5145
) {
52-
5346
val navigationSuiteScaffoldState = rememberNavigationSuiteScaffoldState()
5447
val screensInGlobalNavigation = remember {
5548
Screens.entries.filter { it.isMainNavigation }
5649
}
5750

58-
val xrSession = LocalSession.current
59-
val isSpatialUiEnabled = LocalSpatialCapabilities.current.isSpatialUiEnabled
60-
val spatialConfiguration = LocalSpatialConfiguration.current
61-
val navigationType =
62-
NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(currentWindowAdaptiveInfo())
51+
val hasXrSpatialFeature = hasXrSpatialFeature()
6352

6453
LaunchedEffect(appState.isNavigationVisible) {
6554
if (appState.isNavigationVisible) {
@@ -69,57 +58,45 @@ fun AppWithNavigationSuiteScaffold(
6958
}
7059
}
7160

72-
val paddingTop = remember(xrSession) {
73-
if (xrSession != null) {
61+
val topBarPaddingTop = remember(hasXrSpatialFeature) {
62+
if (hasXrSpatialFeature) {
7463
32.dp
7564
} else {
7665
0.dp
7766
}
7867
}
7968

80-
val shouldShowTopBar =
81-
navigationSuiteScaffoldState.currentValue == NavigationSuiteScaffoldValue.Visible
82-
8369
NavigationSuiteScaffold(
84-
modifier = modifier.fillMaxSize(),
70+
modifier = modifier,
8571
state = navigationSuiteScaffoldState,
72+
navigationItemVerticalArrangement = Arrangement.Center,
8673
navigationItems = {
87-
AdaptiveAppNavigationItems(appState.selectedScreen, screensInGlobalNavigation) {
74+
AdaptiveAppNavigationItems(
75+
currentScreen = appState.selectedScreen,
76+
screens = screensInGlobalNavigation
77+
) {
8878
if (it != appState.selectedScreen) {
8979
navController.navigate(it())
9080
}
9181
}
92-
if (xrSession != null) {
93-
ToggleFullSpaceModeItem(
94-
xrSession = xrSession,
95-
isSpatialUiEnabled = isSpatialUiEnabled,
96-
spatialConfiguration = spatialConfiguration
97-
)
98-
}
99-
},
100-
navigationItemVerticalArrangement = Arrangement.Center
82+
RequestFullSpaceModeItem(hasXrSpatialFeature = hasXrSpatialFeature)
83+
}
10184
) {
10285
Scaffold(
10386
modifier = Modifier.fillMaxSize(),
10487
topBar = {
10588
AnimatedVisibility(
106-
visible = shouldShowTopBar,
89+
visible = appState.isNavigationVisible,
10790
enter = slideInVertically(),
10891
exit = slideOutVertically()
10992
) {
110-
val horizontalPadding = remember(navigationType) {
111-
when (navigationType) {
112-
NavigationSuiteType.NavigationRail -> 32.dp
113-
else -> 8.dp
114-
}
115-
}
11693
TopBar(
11794
appState = appState,
11895
navController = navController,
11996
modifier = Modifier.padding(
120-
start = horizontalPadding,
121-
end = horizontalPadding,
122-
top = paddingTop
97+
start = 24.dp,
98+
end = 24.dp,
99+
top = topBarPaddingTop
123100
)
124101
)
125102
}

AdaptiveJetStream/jetstream/src/main/java/com/google/jetstream/presentation/app/withNavigationSuiteScaffold/navigationSuiteItems.kt

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ import androidx.compose.ui.graphics.vector.ImageVector
2727
import androidx.compose.ui.res.stringResource
2828
import androidx.compose.ui.res.vectorResource
2929
import androidx.compose.ui.unit.dp
30+
import androidx.xr.compose.platform.LocalSpatialConfiguration
3031
import androidx.xr.compose.platform.SpatialConfiguration
31-
import androidx.xr.runtime.Session
3232
import com.google.jetstream.R
33+
import com.google.jetstream.presentation.components.feature.hasXrSpatialFeature
3334
import com.google.jetstream.presentation.screens.Screens
3435

3536
@Composable
@@ -58,43 +59,28 @@ fun AdaptiveAppNavigationItems(
5859
}
5960

6061
@Composable
61-
fun ToggleFullSpaceModeItem(
62-
xrSession: Session?,
63-
spatialConfiguration: SpatialConfiguration,
64-
isSpatialUiEnabled: Boolean,
62+
fun RequestFullSpaceModeItem(
63+
hasXrSpatialFeature: Boolean = hasXrSpatialFeature(),
64+
spatialConfiguration: SpatialConfiguration = LocalSpatialConfiguration.current
6565
) {
6666

67-
if (xrSession != null) {
68-
val icon = if (isSpatialUiEnabled) {
69-
R.drawable.ic_collapse_content
70-
} else {
71-
R.drawable.ic_expand_content
72-
}
73-
val description = if (isSpatialUiEnabled) {
74-
R.string.home_space_mode
75-
} else {
76-
R.string.full_space_mode
77-
}
78-
67+
if (hasXrSpatialFeature) {
7968
NavigationSuiteItem(
8069
selected = false,
81-
onClick = {
82-
if (isSpatialUiEnabled) {
83-
spatialConfiguration.requestHomeSpaceMode()
84-
} else {
85-
spatialConfiguration.requestFullSpaceMode()
86-
}
87-
},
70+
onClick = spatialConfiguration::requestFullSpaceMode,
8871
icon = {
8972
Icon(
90-
imageVector = ImageVector.vectorResource(icon),
73+
imageVector = ImageVector.vectorResource(R.drawable.ic_expand_content),
9174
modifier = Modifier.size(24.dp),
92-
contentDescription = stringResource(description),
75+
contentDescription = stringResource(R.string.full_space_mode),
9376
tint = MaterialTheme.colorScheme.primary
9477
)
9578
},
9679
label = {
97-
Text(stringResource(description), color = MaterialTheme.colorScheme.primary)
80+
Text(
81+
stringResource(R.string.full_space_mode),
82+
color = MaterialTheme.colorScheme.primary
83+
)
9884
}
9985
)
10086
}

0 commit comments

Comments
 (0)