mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-23 08:40:14 +01:00
Add separate window breakpoints for windows with large widths vs large heights.
This commit is contained in:
@@ -16,7 +16,6 @@ import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.window.core.layout.WindowSizeClass
|
||||
import org.signal.core.ui.WindowBreakpoint
|
||||
import org.signal.core.ui.getWindowBreakpoint
|
||||
import org.signal.core.ui.rememberIsSplitPane
|
||||
|
||||
@@ -79,7 +78,7 @@ data class MainContentLayoutData(
|
||||
val isSplitPane = resources.rememberIsSplitPane()
|
||||
|
||||
return remember(windowSizeClass, mode, breakpoint, isSplitPane) {
|
||||
val isLargeWindowSize = breakpoint == WindowBreakpoint.LARGE
|
||||
val isLargeWindowSize = breakpoint.isLargeWindow
|
||||
|
||||
MainContentLayoutData(
|
||||
shape = when {
|
||||
|
||||
@@ -61,7 +61,6 @@ import org.signal.core.ui.WindowBreakpoint
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.getWindowBreakpoint
|
||||
import org.signal.core.ui.isWidthExpanded
|
||||
import org.signal.core.ui.rememberIsSplitPane
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.main.MainFloatingActionButtonsCallback
|
||||
@@ -82,16 +81,8 @@ enum class NavigationType {
|
||||
val windowBreakpoint = remember(config) { resources.getWindowBreakpoint() }
|
||||
|
||||
return when (windowBreakpoint) {
|
||||
WindowBreakpoint.SMALL -> BAR
|
||||
WindowBreakpoint.MEDIUM -> {
|
||||
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
|
||||
if (windowSizeClass.isWidthExpanded) {
|
||||
RAIL
|
||||
} else {
|
||||
BAR
|
||||
}
|
||||
}
|
||||
WindowBreakpoint.LARGE -> RAIL
|
||||
WindowBreakpoint.SMALL, WindowBreakpoint.MEDIUM -> BAR
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> RAIL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,14 @@ val WindowSizeClass.detailPaneMaxContentWidth: Dp get() = 624.dp
|
||||
val WindowSizeClass.isWidthCompact
|
||||
get() = !isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)
|
||||
|
||||
val WindowSizeClass.isWidthExpanded
|
||||
get() = isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)
|
||||
|
||||
val WindowSizeClass.isHeightCompact
|
||||
get() = !isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)
|
||||
|
||||
val WindowSizeClass.isWidthExpanded
|
||||
get() = isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)
|
||||
val WindowSizeClass.isHeightExpanded
|
||||
get() = isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_EXPANDED_LOWER_BOUND)
|
||||
|
||||
fun Resources.getWindowSizeClass(): WindowSizeClass {
|
||||
return WindowSizeClass.BREAKPOINTS_V1.computeWindowSizeClass(
|
||||
@@ -48,12 +51,11 @@ fun rememberWindowBreakpoint(): WindowBreakpoint {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the device's form factor (PHONE, FOLDABLE, or TABLET) based on the current
|
||||
* [Resources] and window size class.
|
||||
* Determines the device's form factor based on the current [Resources] and window size class.
|
||||
*
|
||||
* This function uses several heuristics:
|
||||
* - Returns [WindowBreakpoint.SMALL] if the width or height is compact
|
||||
* - Otherwise, falls back to aspect ratio heuristics: wider (≥ 1.5) is [WindowBreakpoint.LARGE], else [WindowBreakpoint.MEDIUM].
|
||||
* - Otherwise, falls back to aspect ratio heuristics: wide windows use [WindowBreakpoint.LARGE_WIDTH], tall windows use [WindowBreakpoint.LARGE_HEIGHT], else [WindowBreakpoint.MEDIUM].
|
||||
*
|
||||
* @return the inferred [WindowBreakpoint] for the current device.
|
||||
*/
|
||||
@@ -68,24 +70,31 @@ fun Resources.getWindowBreakpoint(): WindowBreakpoint {
|
||||
val denominator = minOf(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
val aspectRatio = numerator.toFloat() / denominator
|
||||
|
||||
return if (aspectRatio >= TABLET_ASPECT_RATIO) {
|
||||
WindowBreakpoint.LARGE
|
||||
} else {
|
||||
WindowBreakpoint.MEDIUM
|
||||
return when {
|
||||
aspectRatio < TABLET_ASPECT_RATIO -> WindowBreakpoint.MEDIUM
|
||||
else -> {
|
||||
if (displayMetrics.widthPixels >= displayMetrics.heightPixels) {
|
||||
WindowBreakpoint.LARGE_WIDTH
|
||||
} else {
|
||||
WindowBreakpoint.LARGE_HEIGHT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates the general form factor of the device for responsive UI purposes.
|
||||
*
|
||||
* - [SMALL]: A window similar to a phone-sized device, typically with a compact width or height.
|
||||
* - [MEDIUM]: A window similar to a foldable or medium-size device, or a device which doesn't obviously fit into phone or tablet by heuristics.
|
||||
* - [LARGE]: A window similar to a large-screen tablet device, typically with an expanded height or wide aspect ratio.
|
||||
* - [SMALL]: A window with a compact width or height, typical of phone-sized devices.
|
||||
* - [MEDIUM]: A window where neither width nor height is compact or expanded, typical of foldables.
|
||||
* - [LARGE_WIDTH]: A window with expanded width and medium height, typical of tablets in landscape orientation.
|
||||
* - [LARGE_HEIGHT]: A window with medium width and expanded height, typical of tablets in portrait orientation.
|
||||
*/
|
||||
enum class WindowBreakpoint {
|
||||
SMALL,
|
||||
MEDIUM,
|
||||
LARGE
|
||||
enum class WindowBreakpoint(val isLargeWindow: Boolean) {
|
||||
SMALL(isLargeWindow = false),
|
||||
MEDIUM(isLargeWindow = false),
|
||||
LARGE_WIDTH(isLargeWindow = true),
|
||||
LARGE_HEIGHT(isLargeWindow = true)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -108,14 +117,8 @@ fun Resources.isSplitPane(
|
||||
return true
|
||||
}
|
||||
|
||||
val breakpoint = getWindowBreakpoint()
|
||||
if (breakpoint == WindowBreakpoint.SMALL) {
|
||||
return false
|
||||
return when (getWindowBreakpoint()) {
|
||||
WindowBreakpoint.SMALL, WindowBreakpoint.LARGE_HEIGHT -> false
|
||||
WindowBreakpoint.MEDIUM, WindowBreakpoint.LARGE_WIDTH -> true
|
||||
}
|
||||
|
||||
if (breakpoint == WindowBreakpoint.LARGE && displayMetrics.widthPixels < displayMetrics.heightPixels) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ fun EnterAepScreen(
|
||||
MediumLayout(state, onEvent)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(state, onEvent)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ fun CountryCodePickerScreen(
|
||||
MediumLayout(state, onEvent)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(state, onEvent)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ fun PermissionsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
Surface(modifier = modifier.testTag(TestTags.PERMISSIONS_SCREEN)) {
|
||||
LargeLayout(
|
||||
permissionsState = permissionsState,
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ fun PhoneNumberScreen(
|
||||
MediumLayout(state, onEvent)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(state, onEvent)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ fun RemoteRestoreScreen(
|
||||
when (windowBreakpoint) {
|
||||
WindowBreakpoint.SMALL -> CompactLayout(state = state, onEvent = onEvent, modifier = modifier)
|
||||
WindowBreakpoint.MEDIUM -> MediumLayout(state = state, onEvent = onEvent, modifier = modifier)
|
||||
WindowBreakpoint.LARGE -> LargeLayout(state = state, onEvent = onEvent, modifier = modifier)
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> LargeLayout(state = state, onEvent = onEvent, modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ fun ArchiveRestoreSelectionScreen(
|
||||
MediumLayout(state, onEvent, modifier)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(state, onEvent, modifier)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ fun VerificationCodeScreen(
|
||||
)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(
|
||||
digits = digits,
|
||||
focusRequesters = focusRequesters,
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ fun WelcomeScreen(
|
||||
)
|
||||
}
|
||||
|
||||
WindowBreakpoint.LARGE -> {
|
||||
WindowBreakpoint.LARGE_WIDTH, WindowBreakpoint.LARGE_HEIGHT -> {
|
||||
LargeLayout(
|
||||
onEvent = onEvent,
|
||||
onTermsAndPrivacyClick = onTermsAndPrivacyClick,
|
||||
|
||||
Reference in New Issue
Block a user