compose: details: Adjust adaptive screens based on latest alpha changes

* WindowWidthSizeClass is deprecated, switch to WindowSizeClass and breakpoints instead with flipped logic
* Specify a dragHandle and adaptStratergy for supporting pane to levitate on single pane screens

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2025-08-20 11:26:02 +08:00
parent d4179319f4
commit 94c5f90fbb
10 changed files with 99 additions and 37 deletions

View File

@@ -9,7 +9,7 @@ import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.painterResource
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import com.aurora.store.R
/**
@@ -17,7 +17,10 @@ import com.aurora.store.R
*/
val WindowAdaptiveInfo.adaptiveNavigationIcon: Painter
@Composable
get() = when (windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> painterResource(R.drawable.ic_arrow_back)
else -> painterResource(R.drawable.ic_cancel)
get() = when {
windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
painterResource(R.drawable.ic_cancel)
}
else -> painterResource(R.drawable.ic_arrow_back)
}

View File

@@ -6,6 +6,7 @@
package com.aurora.store.compose.ui.details
import android.content.ActivityNotFoundException
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -16,16 +17,24 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalMinimumInteractiveComponentSize
import androidx.compose.material3.Scaffold
import androidx.compose.material3.VerticalDragHandle
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.material3.adaptive.layout.AdaptStrategy
import androidx.compose.material3.adaptive.layout.AnimatedPane
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective
import androidx.compose.material3.adaptive.navigation.NavigableSupportingPaneScaffold
import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -194,10 +203,19 @@ private fun ScreenContentApp(
onCancelDownload: () -> Unit = {},
onUninstall: () -> Unit = {},
onOpen: () -> Unit = {},
onTestingSubscriptionChange: (subscribe: Boolean) -> Unit = {}
onTestingSubscriptionChange: (subscribe: Boolean) -> Unit = {},
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
) {
val context = LocalContext.current
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator<Screen>()
val scaffoldDirective = calculatePaneScaffoldDirective(windowAdaptiveInfo)
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator<Screen>(
scaffoldDirective = scaffoldDirective,
adaptStrategies = SupportingPaneScaffoldDefaults.adaptStrategies(
supportingPaneAdaptStrategy = AdaptStrategy
.Levitate()
.onlyIfSinglePane(scaffoldDirective)
)
)
val coroutineScope = rememberCoroutineScope()
val shouldShowMenuOnMainPane = scaffoldNavigator
.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden
@@ -423,8 +441,12 @@ private fun ScreenContentApp(
scaffoldNavigator.currentDestination?.contentKey?.let { screen ->
AnimatedPane {
when (screen) {
is Screen.DetailsReview -> DetailsReviewScreen(onNavigateUp = ::showMainPane)
is Screen.DetailsExodus -> DetailsExodusScreen(onNavigateUp = ::showMainPane)
is Screen.DetailsReview -> DetailsReviewScreen(
onNavigateUp = ::showMainPane
)
is Screen.DetailsExodus -> DetailsExodusScreen(
onNavigateUp = ::showMainPane
)
is Screen.DetailsMore -> DetailsMoreScreen(
onNavigateUp = ::showMainPane,
onNavigateToAppDetails = onNavigateToAppDetails
@@ -449,6 +471,16 @@ private fun ScreenContentApp(
}
}
}
},
paneExpansionDragHandle = { state ->
VerticalDragHandle(
modifier = Modifier.paneExpansionDraggable(
state = state,
minTouchTargetSize = LocalMinimumInteractiveComponentSize.current,
interactionSource = remember { MutableInteractionSource() }
),
interactionSource = remember { MutableInteractionSource() }
)
}
)
}

View File

@@ -22,7 +22,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import com.aurora.Constants.EXODUS_REPORT_URL
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.extensions.browse
@@ -49,9 +49,12 @@ fun DetailsExodusScreen(
val exodusReport by appDetailsViewModel.exodusReport.collectAsStateWithLifecycle()
val trackers by detailsExodusViewModel.trackers.collectAsStateWithLifecycle()
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app!!.displayName
else -> stringResource(R.string.details_privacy)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.details_privacy)
}
else -> app!!.displayName
}
ScreenContent(

View File

@@ -43,6 +43,7 @@ import androidx.compose.ui.unit.dp
import androidx.core.text.isDigitsOnly
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.extensions.toast
@@ -63,9 +64,12 @@ fun DetailsManualDownloadScreen(
val context = LocalContext.current
val app by viewModel.app.collectAsStateWithLifecycle()
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app!!.displayName
else -> stringResource(R.string.title_manual_download)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.title_manual_download)
}
else -> app!!.displayName
}
LaunchedEffect(key1 = Unit) {

View File

@@ -31,7 +31,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import coil3.compose.LocalAsyncImagePreviewHandler
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.gplayapi.data.models.App
@@ -74,9 +74,12 @@ private fun ScreenContent(
onNavigateToAppDetails: (packageName: String) -> Unit = {},
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
) {
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app.displayName
else -> stringResource(R.string.details_more_about_app)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.details_more_about_app)
}
else -> app.displayName
}
Scaffold(

View File

@@ -25,7 +25,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.gplayapi.data.models.App
import com.aurora.store.R
@@ -48,9 +48,12 @@ fun DetailsPermissionScreen(
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val permissionsInfo by detailsPermissionViewModel.permissionsInfo.collectAsStateWithLifecycle()
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app!!.displayName
else -> stringResource(R.string.details_permission)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.details_permission)
}
else -> app!!.displayName
}
ScreenContent(

View File

@@ -37,7 +37,7 @@ import androidx.paging.PagingData
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemKey
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import coil3.compose.LocalAsyncImagePreviewHandler
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.gplayapi.data.models.Review
@@ -63,9 +63,12 @@ fun DetailsReviewScreen(
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val reviews = detailsReviewViewModel.reviews.collectAsLazyPagingItems()
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app!!.displayName
else -> stringResource(R.string.details_ratings)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.details_ratings)
}
else -> app!!.displayName
}
ScreenContent(

View File

@@ -21,7 +21,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.WindowSizeClass
import com.aurora.extensions.adaptiveNavigationIcon
import com.aurora.gplayapi.data.models.Artwork
import com.aurora.store.R
@@ -38,9 +38,12 @@ fun DetailsScreenshotScreen(
) {
val app by viewModel.app.collectAsStateWithLifecycle()
val topAppBarTitle = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> app!!.displayName
else -> stringResource(R.string.details_more_about_app)
val topAppBarTitle = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
stringResource(R.string.details_more_about_app)
}
else -> app!!.displayName
}
ScreenContent(

View File

@@ -21,6 +21,7 @@ import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import com.aurora.store.R
@@ -49,9 +50,12 @@ fun AppActions(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_medium))
) {
val buttonWidthModifier = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> Modifier.weight(1F)
else -> Modifier.widthIn(min = dimensionResource(R.dimen.width_button))
val buttonWidthModifier = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
Modifier.widthIn(min = dimensionResource(R.dimen.width_button))
}
else -> Modifier.weight(1F)
}
FilledTonalButton(

View File

@@ -30,6 +30,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.util.fastForEach
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.Rating
@@ -64,9 +65,12 @@ fun AppRatingAndReviews(
if (it.sum() == 0F) return
}
val avgRating = when (windowAdaptiveInfo.windowSizeClass.windowWidthSizeClass) {
WindowWidthSizeClass.COMPACT -> String.format(Locale.getDefault(), "%.1f", rating.average)
else -> String.format(Locale.getDefault(), "%.1f / 5.0", rating.average)
val avgRating = when {
windowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) -> {
String.format(Locale.getDefault(), "%.1f / 5.0", rating.average)
}
else -> String.format(Locale.getDefault(), "%.1f", rating.average)
}
HeaderComposable(