From 390e0615d136d629b55f8d37305bd58925fe2b38 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 25 Apr 2025 11:10:04 -0400 Subject: [PATCH] Removing these disabled lock behavior code until we get it working --- .../compose/material3/adaptive/Posture.kt | 182 ------------------ .../material3/adaptive/WindowAdaptiveInfo.kt | 122 ------------ .../ui/components/ZoomableContentView.kt | 14 -- 3 files changed, 318 deletions(-) delete mode 100644 amethyst/src/main/java/androidx/compose/material3/adaptive/Posture.kt delete mode 100644 amethyst/src/main/java/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt diff --git a/amethyst/src/main/java/androidx/compose/material3/adaptive/Posture.kt b/amethyst/src/main/java/androidx/compose/material3/adaptive/Posture.kt deleted file mode 100644 index 8331338f9..000000000 --- a/amethyst/src/main/java/androidx/compose/material3/adaptive/Posture.kt +++ /dev/null @@ -1,182 +0,0 @@ -/** - * Copyright (c) 2024 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package androidx.compose.material3.adaptive - -import androidx.compose.runtime.Immutable -import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.toComposeRect -import androidx.window.layout.FoldingFeature - -/** - * Calculates the [Posture] for a given list of [FoldingFeature]s. This methods converts framework - * folding info into the Material-opinionated posture info. - */ -fun calculatePosture(foldingFeatures: List): Posture { - var isTableTop = false - val hingeList = mutableListOf() - @Suppress("ListIterator") - foldingFeatures.forEach { - if (it.orientation == FoldingFeature.Orientation.HORIZONTAL && - it.state == FoldingFeature.State.HALF_OPENED - ) { - isTableTop = true - } - hingeList.add( - HingeInfo( - bounds = it.bounds.toComposeRect(), - isFlat = it.state == FoldingFeature.State.FLAT, - isVertical = it.orientation == FoldingFeature.Orientation.VERTICAL, - isSeparating = it.isSeparating, - isOccluding = it.occlusionType == FoldingFeature.OcclusionType.FULL, - ), - ) - } - return Posture(isTableTop, hingeList) -} - -/** - * Posture info that can help make layout adaptation decisions. For example when - * [Posture.separatingVerticalHingeBounds] is not empty, the layout may want to avoid putting any - * content over those hinge area. We suggest to use [calculatePosture] to retrieve instances of this - * class in applications, unless you have a strong need of customization that cannot be fulfilled by - * the default implementation. - * - * Note that the hinge bounds will be represent as [Rect] with window coordinates, instead of layout - * coordinate. - * - * @constructor create an instance of [Posture] - * @property isTabletop `true` if the current window is considered as in the table top mode, i.e. - * there is one half-opened horizontal hinge in the middle of the current window. When - * this is `true` it usually means it's hard for users to interact with the window area - * around the hinge and developers may consider separating the layout along the hinge and - * show software keyboard or other controls in the bottom half of the window. - * @property hingeList a list of all hinges that are relevant to the posture. - */ -@Immutable -class Posture( - val isTabletop: Boolean = false, - val hingeList: List = emptyList(), -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Posture) return false - if (isTabletop != other.isTabletop) return false - if (hingeList != other.hingeList) return false - return true - } - - override fun hashCode(): Int { - var result = isTabletop.hashCode() - result = 31 * result + hingeList.hashCode() - return result - } - - override fun toString(): String { - @Suppress("ListIterator") - return "Posture(isTabletop=$isTabletop, " + - "hinges=[${hingeList.joinToString(", ")}])" - } -} - -/** - * Returns the list of vertical hinge bounds that are separating. - */ -val Posture.separatingVerticalHingeBounds get() = hingeList.getBounds { isVertical && isSeparating } - -/** - * Returns the list of vertical hinge bounds that are occluding. - */ -val Posture.occludingVerticalHingeBounds get() = hingeList.getBounds { isVertical && isOccluding } - -/** - * Returns the list of all vertical hinge bounds. - */ -val Posture.allVerticalHingeBounds get() = hingeList.getBounds { isVertical } - -/** - * Returns the list of horizontal hinge bounds that are separating. - */ -val Posture.separatingHorizontalHingeBounds - get() = hingeList.getBounds { !isVertical && isSeparating } - -/** - * Returns the list of horizontal hinge bounds that are occluding. - */ -val Posture.occludingHorizontalHingeBounds - get() = hingeList.getBounds { !isVertical && isOccluding } - -/** - * Returns the list of all horizontal hinge bounds. - */ -val Posture.allHorizontalHingeBounds - get() = hingeList.getBounds { !isVertical } - -/** - * A class that contains the info of a hinge relevant to a [Posture]. - * - * @param bounds the bounds of the hinge in the relevant viewport. - * @param isFlat `true` if the hinge is fully open and the relevant window space presented to the - * user is flat. - * @param isVertical `true` if the hinge is a vertical one, i.e., it separates the viewport into - * left and right; `false` if the hinge is horizontal, i.e., it separates the viewport - * into top and bottom. - * @param isSeparating `true` if the hinge creates two logical display areas. - * @param isOccluding `true` if the hinge conceals part of the display. - */ -@Immutable -class HingeInfo( - val bounds: Rect, - val isFlat: Boolean, - val isVertical: Boolean, - val isSeparating: Boolean, - val isOccluding: Boolean, -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is HingeInfo) return false - if (bounds != other.bounds) return false - if (isFlat != other.isFlat) return false - if (isVertical != other.isVertical) return false - if (isSeparating != other.isSeparating) return false - if (isOccluding != other.isOccluding) return false - return true - } - - override fun hashCode(): Int { - var result = bounds.hashCode() - result = 31 * result + isFlat.hashCode() - result = 31 * result + isVertical.hashCode() - result = 31 * result + isSeparating.hashCode() - result = 31 * result + isOccluding.hashCode() - return result - } - - override fun toString(): String = - "HingeInfo(bounds=$bounds, " + - "isFlat=$isFlat, " + - "isVertical=$isVertical, " + - "isSeparating=$isSeparating, " + - "isOccluding=$isOccluding)" -} - -private inline fun List.getBounds(predicate: HingeInfo.() -> Boolean): List = - @Suppress("ListIterator") - mapNotNull { if (it.predicate()) it.bounds else null } diff --git a/amethyst/src/main/java/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt b/amethyst/src/main/java/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt deleted file mode 100644 index 056c1e154..000000000 --- a/amethyst/src/main/java/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2024 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package androidx.compose.material3.adaptive - -import android.app.Activity -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.State -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.remember -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.IntSize -import androidx.compose.ui.unit.toSize -import androidx.window.core.layout.WindowSizeClass -import androidx.window.layout.FoldingFeature -import androidx.window.layout.WindowInfoTracker -import androidx.window.layout.WindowMetricsCalculator -import kotlinx.coroutines.flow.map - -@Composable -fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo { - val windowSize = - with(LocalDensity.current) { - currentWindowSize().toSize().toDpSize() - } - return WindowAdaptiveInfo( - WindowSizeClass.compute(windowSize.width.value, windowSize.height.value), - calculatePosture(collectFoldingFeaturesAsState().value), - ) -} - -/** - * Returns and automatically update the current window size from [WindowMetricsCalculator]. - * - * @return an [IntSize] that represents the current window size. - */ -@Composable -fun currentWindowSize(): IntSize { - // Observe view configuration changes and recalculate the size class on each change. We can't - // use Activity#onConfigurationChanged as this will sometimes fail to be called on different - // API levels, hence why this function needs to be @Composable so we can observe the - // ComposeView's configuration changes. - LocalConfiguration.current - val windowBounds = - WindowMetricsCalculator - .getOrCreate() - .computeCurrentWindowMetrics(LocalContext.current) - .bounds - return IntSize(windowBounds.width(), windowBounds.height()) -} - -/** - * Collects the current window folding features from [WindowInfoTracker] in to a [State]. - * - * @return a [State] of a [FoldingFeature] list. - */ -@Composable -fun collectFoldingFeaturesAsState(): State> { - val context = LocalContext.current - return remember(context) { - if (context is Activity) { - // TODO(b/284347941) remove the instance check after the test bug is fixed. - WindowInfoTracker - .getOrCreate(context) - .windowLayoutInfo(context) - } else { - WindowInfoTracker - .getOrCreate(context) - .windowLayoutInfo(context) - }.map { it.displayFeatures.filterIsInstance() } - }.collectAsState(emptyList()) -} - -/** - * This class collects window info that affects adaptation decisions. An adaptive layout is supposed - * to use the info from this class to decide how the layout is supposed to be adapted. - * - * @constructor create an instance of [WindowAdaptiveInfo] - * @param windowSizeClass [WindowSizeClass] of the current window. - * @param windowPosture [Posture] of the current window. - */ -@Immutable -class WindowAdaptiveInfo( - val windowSizeClass: WindowSizeClass, - val windowPosture: Posture, -) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is WindowAdaptiveInfo) return false - if (windowSizeClass != other.windowSizeClass) return false - if (windowPosture != other.windowPosture) return false - return true - } - - override fun hashCode(): Int { - var result = windowSizeClass.hashCode() - result = 31 * result + windowPosture.hashCode() - return result - } - - override fun toString(): String = "WindowAdaptiveInfo(windowSizeClass=$windowSizeClass, windowPosture=$windowPosture)" -} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt index 34fcb00d2..73975d3a4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt @@ -39,7 +39,6 @@ import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text -import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState @@ -56,7 +55,6 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.platform.LocalView import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString @@ -83,7 +81,6 @@ import com.vitorpamplona.amethyst.service.images.BlurhashWrapper import com.vitorpamplona.amethyst.service.playback.composable.VideoView import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.actions.InformationDialog -import com.vitorpamplona.amethyst.ui.components.util.DeviceUtils import com.vitorpamplona.amethyst.ui.note.BlankNote import com.vitorpamplona.amethyst.ui.note.DownloadForOfflineIcon import com.vitorpamplona.amethyst.ui.note.HashCheckFailedIcon @@ -120,13 +117,6 @@ fun ZoomableContentView( ) { var dialogOpen by remember(content) { mutableStateOf(false) } - val activity = LocalView.current.context.getActivity() - val currentWindowSize = currentWindowAdaptiveInfo().windowSizeClass - - val isLandscapeMode = DeviceUtils.isLandscapeMetric(LocalContext.current) - val isFoldableOrLarge = DeviceUtils.windowIsLarge(windowSize = currentWindowSize, isInLandscapeMode = isLandscapeMode) - val isOrientationLocked = DeviceUtils.screenOrientationIsLocked(LocalContext.current) - when (content) { is MediaUrlImage -> SensitivityWarning(content.contentWarning != null, accountViewModel) { @@ -155,9 +145,6 @@ fun ZoomableContentView( nostrUriCallback = content.uri, onDialog = { dialogOpen = true - // if (!isFoldableOrLarge && !isOrientationLocked) { - // DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) - // } }, accountViewModel = accountViewModel, ) @@ -198,7 +185,6 @@ fun ZoomableContentView( images, onDismiss = { dialogOpen = false - // if (!isFoldableOrLarge && !isOrientationLocked) DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) }, accountViewModel, )