diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaDrawers.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaDrawers.kt index 3dac1f04..c3624a13 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaDrawers.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaDrawers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2024, Petr Laštovička as Lasta apps, All rights reserved + * Copyright 2025, Petr Laštovička as Lasta apps, All rights reserved * * This file is part of Menza. * @@ -21,8 +21,6 @@ package cz.lastaapps.menza.features.main.ui.layout import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.material3.DismissibleDrawerSheet import androidx.compose.material3.DismissibleNavigationDrawer import androidx.compose.material3.DrawerState @@ -33,7 +31,6 @@ import androidx.compose.material3.PermanentNavigationDrawer import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.zIndex -import cz.lastaapps.menza.ui.theme.Padding @Composable internal fun MenzaModalDrawer( @@ -50,12 +47,10 @@ internal fun MenzaModalDrawer( if (!alternativeNavigation) { // handles predictive back gesture ModalDrawerSheet(drawerState) { - Spacer(Modifier.height(Padding.MidSmall)) drawerContent() } } else { ModalDrawerSheet { - Spacer(Modifier.height(Padding.MidSmall)) drawerContent() } } diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaScaffold.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaScaffold.kt index 76a022ba..985f1143 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaScaffold.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/layout/MenzaScaffold.kt @@ -23,7 +23,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.material3.DrawerState import androidx.compose.material3.Scaffold import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass @@ -32,6 +31,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max import cz.lastaapps.menza.ui.locals.FoldingClass @@ -57,8 +57,6 @@ fun MenzaScaffold( foldingFeature: FoldingClass = LocalFoldProvider.current, content: @Composable () -> Unit, ) { - val modifier = modifier.safeDrawingPadding() - when (windowWidth) { WindowWidthSizeClass.Compact -> AppLayoutCompact( @@ -199,8 +197,10 @@ private fun AppLayoutMedium( MenzaDismissibleDrawerWithRailLayout( modifier = Modifier - .padding(insets) - .fillMaxSize(), + .padding( + top = insets.calculateTopPadding(), + bottom = insets.calculateBottomPadding(), + ).fillMaxSize(), rail = rail, ) { MenzaDismissibleDrawer( @@ -210,7 +210,11 @@ private fun AppLayoutMedium( drawerContent = drawerContent, ) { BoxWithConstraints( - Modifier.fillMaxSize(), + Modifier + .fillMaxSize() + .padding( + end = insets.calculateRightPadding(LocalLayoutDirection.current), + ), ) { val padding = Padding.More.Screen val totalWidthAvailable = maxWidth - padding @@ -292,7 +296,10 @@ private fun AppLayoutExpandedNoFold( MenzaDismissibleDrawerWithRailLayout( modifier = Modifier - .padding(insets) + .padding( + top = insets.calculateTopPadding(), + bottom = insets.calculateBottomPadding(), + ) .fillMaxSize(), rail = rail, ) { @@ -302,7 +309,11 @@ private fun AppLayoutExpandedNoFold( drawerContent = drawerContent, ) { BoxWithConstraints( - Modifier.fillMaxSize(), + Modifier + .fillMaxSize() + .padding( + end = insets.calculateRightPadding(LocalLayoutDirection.current), + ), ) { val padding = Padding.More.Screen val totalWidthAvailable = maxWidth - padding @@ -347,8 +358,11 @@ private fun AppLayoutExpandedFold( MenzaDismissibleDrawerWithRailLayout( modifier = Modifier - .padding(insets) - .fillMaxSize(), + .fillMaxSize() + .padding( + top = insets.calculateTopPadding(), + bottom = insets.calculateBottomPadding(), + ), rail = rail, ) { val density = LocalDensity.current @@ -370,7 +384,11 @@ private fun AppLayoutExpandedFold( drawerContent = drawerContent, ) { BoxWithConstraints( - Modifier.fillMaxSize(), + Modifier + .padding( + end = insets.calculateRightPadding(LocalLayoutDirection.current), + ) + .fillMaxSize(), ) { val totalWidthAvailable = maxWidth - spacesWidth + railWidth val startWidth = totalWidthAvailable * weightStart - railWidth diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/navigation/MainContent.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/navigation/MainContent.kt index 4ada6b2d..dc00fa68 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/navigation/MainContent.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/main/ui/navigation/MainContent.kt @@ -19,6 +19,7 @@ package cz.lastaapps.menza.features.main.ui.navigation +import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.DrawerValue.Closed import androidx.compose.material3.DrawerValue.Open @@ -34,6 +35,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import com.arkivanov.decompose.ExperimentalDecomposeApi import com.arkivanov.decompose.extensions.compose.experimental.stack.ChildStack @@ -104,6 +106,7 @@ internal fun MainContent( component = component.drawerComponent, drawerState = drawerState, snackbarHostState = hostState, + modifier = Modifier.background(Color.Red), ) }, content = { diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/navigation/TodayComponent.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/navigation/TodayComponent.kt index 43fbe4e9..0edc2385 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/navigation/TodayComponent.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/navigation/TodayComponent.kt @@ -41,7 +41,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -70,9 +69,11 @@ import com.arkivanov.essenty.backhandler.BackHandlerOwner import cz.lastaapps.api.core.domain.model.DishOriginDescriptor import cz.lastaapps.api.core.domain.model.dish.Dish import cz.lastaapps.api.core.domain.model.toOrigin +import cz.lastaapps.core.ui.vm.HandleDismiss import cz.lastaapps.menza.R import cz.lastaapps.menza.features.today.ui.navigation.DefaultTodayComponent.Config.DetailsConfig import cz.lastaapps.menza.features.today.ui.screen.ImagePreviewDialog +import cz.lastaapps.menza.features.today.ui.vm.TodayState import cz.lastaapps.menza.features.today.ui.vm.TodayViewModel import cz.lastaapps.menza.features.today.ui.widget.NoDishSelected import cz.lastaapps.menza.ui.theme.Padding @@ -183,11 +184,13 @@ internal fun TodayContent( modifier: Modifier = Modifier, ) { val state by component.viewModel.flowState - LaunchedEffect(state.selectedMenza) { - state.selectedMenza?.let { - component.dismissDetail() - } - } + + HandleDismiss( + component.viewModel, + TodayState::menzaChanged, + TodayViewModel::dismissMenzaChanged, + component::dismissDetail, + ) var videoFeedUrl by remember(state.selectedMenza) { mutableStateOf(null) @@ -221,6 +224,10 @@ internal fun TodayContent( SharedTransitionLayout( modifier = Modifier.padding(padding), ) { + // If this is enabled in split pane mode, the shared element overlay breaks and shows + // items over each other + val sharedElementEnabled = component.content.value.mode == ChildPanelsMode.SINGLE + ChildPanels( modifier = Modifier.fillMaxSize(), panels = component.content, @@ -230,14 +237,14 @@ internal fun TodayContent( it.instance, onOsturak = onOsturak, hostState = hostState, - scopes = AnimationScopes(), + scopes = AnimationScopes(sharedElementEnabled), modifier = panelModifier, ) }, detailsChild = { DishDetailContent( it.instance, - scopes = AnimationScopes(), + scopes = AnimationScopes(sharedElementEnabled), modifier = panelModifier, ) }, diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/vm/TodayViewModel.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/vm/TodayViewModel.kt index 31ad2795..ce1ffa72 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/vm/TodayViewModel.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/vm/TodayViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2024, Petr Laštovička as Lasta apps, All rights reserved + * Copyright 2025, Petr Laštovička as Lasta apps, All rights reserved * * This file is part of Menza. * @@ -43,6 +43,7 @@ internal class TodayViewModel( updateState { copy( selectedMenza = it.toOption(), + menzaChanged = true, ) } }.launchIn(scope) @@ -52,9 +53,12 @@ internal class TodayViewModel( updateState { copy(language = it) } }.launchIn(scope) } + + fun dismissMenzaChanged(): Unit = updateState { copy(menzaChanged = false) } } internal data class TodayState( val selectedMenza: Option? = null, val language: DataLanguage = DataLanguage.Czech, + val menzaChanged: Boolean = false, ) : VMState diff --git a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/widget/DishImage.kt b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/widget/DishImage.kt index d55961a2..b665099c 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/widget/DishImage.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/features/today/ui/widget/DishImage.kt @@ -54,6 +54,7 @@ import androidx.compose.ui.unit.dp import coil3.compose.SubcomposeAsyncImage import coil3.request.CachePolicy import coil3.request.ImageRequest.Builder +import coil3.size.SizeResolver import cz.lastaapps.api.core.domain.model.dish.Dish import cz.lastaapps.menza.R.string import cz.lastaapps.menza.ui.components.placeholders.PlaceholderHighlight @@ -131,6 +132,7 @@ internal fun DishImage( networkCachePolicy(CachePolicy.DISABLED) } + size(SizeResolver.ORIGINAL) data(photoLink) build() } diff --git a/app/src/main/kotlin/cz/lastaapps/menza/ui/util/AnimationScopes.kt b/app/src/main/kotlin/cz/lastaapps/menza/ui/util/AnimationScopes.kt index 1ba1fa4e..ea1bee7e 100644 --- a/app/src/main/kotlin/cz/lastaapps/menza/ui/util/AnimationScopes.kt +++ b/app/src/main/kotlin/cz/lastaapps/menza/ui/util/AnimationScopes.kt @@ -51,10 +51,12 @@ import androidx.compose.ui.unit.dp data class AnimationScopes( val sharedTransitionScope: SharedTransitionScope, val animatedVisibilityScope: AnimatedVisibilityScope, + val isEnabled: Boolean, ) context(AnimatedVisibilityScope) -fun SharedTransitionScope.AnimationScopes() = AnimationScopes(this, this@AnimatedVisibilityScope) +fun SharedTransitionScope.AnimationScopes(isEnabled: Boolean = true) = + AnimationScopes(this, this@AnimatedVisibilityScope, isEnabled = isEnabled) @Composable fun Modifier.sharedBounds( @@ -68,6 +70,10 @@ fun Modifier.sharedBounds( zIndexInOverlay: Float = 0f, ): Modifier = with(scopes.sharedTransitionScope) { + if (!scopes.isEnabled) { + return@with this@sharedBounds + } + this@sharedBounds .sharedBounds( sharedContentState = rememberSharedContentState(key), @@ -118,6 +124,10 @@ fun Modifier.sharedContainer( clipInOverlayDuringTransition: OverlayClip = OverlayParentClip(), ): Modifier = with(scopes.sharedTransitionScope) { + if (!scopes.isEnabled) { + return@with this@sharedContainer + } + this@sharedContainer .sharedBounds( sharedContentState = rememberSharedContentState(key), @@ -141,6 +151,10 @@ fun Modifier.sharedElement( zIndexInOverlay: Float = 0f, ): Modifier = with(scopes.sharedTransitionScope) { + if (!scopes.isEnabled) { + return@with this@sharedElement + } + this@sharedElement.sharedElement( sharedContentState = rememberSharedContentState(key), animatedVisibilityScope = scopes.animatedVisibilityScope, @@ -156,6 +170,10 @@ fun Modifier.renderInSharedTransitionScopeOverlay( zIndexInOverlay: Float = 0f, ): Modifier = with(scopes.sharedTransitionScope) { + if (!scopes.isEnabled) { + return@with this@renderInSharedTransitionScopeOverlay + } + this@renderInSharedTransitionScopeOverlay.renderInSharedTransitionScopeOverlay( renderInOverlay = renderInOverlay, zIndexInOverlay = zIndexInOverlay, @@ -164,6 +182,10 @@ fun Modifier.renderInSharedTransitionScopeOverlay( fun Modifier.skipToLookaheadSize(scopes: AnimationScopes): Modifier = with(scopes.sharedTransitionScope) { + if (!scopes.isEnabled) { + return@with this@skipToLookaheadSize + } + this@skipToLookaheadSize.skipToLookaheadSize() } diff --git a/core/src/androidMain/kotlin/cz/lastaapps/core/ui/vm/HandleDismiss.kt b/core/src/androidMain/kotlin/cz/lastaapps/core/ui/vm/HandleDismiss.kt index 2c30c28b..ed123040 100644 --- a/core/src/androidMain/kotlin/cz/lastaapps/core/ui/vm/HandleDismiss.kt +++ b/core/src/androidMain/kotlin/cz/lastaapps/core/ui/vm/HandleDismiss.kt @@ -1,5 +1,5 @@ /* - * Copyright 2024, Petr Laštovička as Lasta apps, All rights reserved + * Copyright 2025, Petr Laštovička as Lasta apps, All rights reserved * * This file is part of Menza. * @@ -32,7 +32,7 @@ inline fun > HandleDismiss( viewModel: VM, getVal: KProperty1, dismiss: KFunction1, - noinline launch: () -> Unit, + noinline launch: () -> Unit = {}, ) { val isSelected = getVal(viewModel.flowState.value) val launchLambda by rememberUpdatedState(newValue = launch)