Replace categorical window size classes with breakpoint-based checks.

This commit is contained in:
jeffrey-signal
2026-01-22 13:57:09 -05:00
committed by Alex Hart
parent 585bd5f24c
commit 4c43bf2228
7 changed files with 40 additions and 39 deletions

View File

@@ -12,8 +12,7 @@ import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowWidthSizeClass
import org.thoughtcrime.securesms.window.isAtLeast
import androidx.window.core.layout.WindowSizeClass
/**
* Displays the screen title for split-pane UIs on tablets and foldable devices.
@@ -31,7 +30,7 @@ fun ScreenTitlePane(
color = MaterialTheme.colorScheme.onSurface,
modifier = modifier
.padding(
start = if (windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED)) 80.dp else 20.dp,
start = if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)) 80.dp else 20.dp,
end = 20.dp,
bottom = 12.dp
)

View File

@@ -44,7 +44,6 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowWidthSizeClass
import org.signal.core.ui.compose.AllNightPreviews
import org.signal.core.ui.compose.NightPreview
import org.signal.core.ui.compose.Previews
@@ -55,6 +54,7 @@ import org.thoughtcrime.securesms.events.CallParticipant
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.rememberRecipientField
import org.thoughtcrime.securesms.service.webrtc.links.CallLinkRoomId
import org.thoughtcrime.securesms.window.isWidthCompact
import kotlin.math.max
/**
@@ -85,7 +85,7 @@ fun CallScreenPreJoinOverlay(
.background(color = Color(0f, 0f, 0f, 0.4f))
.then(modifier)
) {
val isCompactWidth = currentWindowAdaptiveInfo().windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.COMPACT
val isCompactWidth = currentWindowAdaptiveInfo().windowSizeClass.isWidthCompact
if (!isLocalVideoEnabled) {
TopWithCenteredContentLayout(

View File

@@ -6,7 +6,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.signal.core.util.DimensionUnit
@@ -17,6 +16,7 @@ import org.thoughtcrime.securesms.components.ComposeText
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerFragmentV2
import org.thoughtcrime.securesms.util.adapter.mapping.AnyMappingModel
import org.thoughtcrime.securesms.util.doOnEachLayout
import org.thoughtcrime.securesms.window.isHeightCompact
/**
* Controller for inline search results.
@@ -73,7 +73,7 @@ class InlineQueryResultsControllerV2(
}
fun onWindowSizeClassChanged(windowSizeClass: WindowSizeClass) {
this.shouldHideForWindowSizeClass = windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT
this.shouldHideForWindowSizeClass = windowSizeClass.isHeightCompact
if (shouldHideForWindowSizeClass) {
dismiss()

View File

@@ -53,7 +53,6 @@ import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSmoothScroller;
import androidx.recyclerview.widget.RecyclerView;
import androidx.window.core.layout.WindowHeightSizeClass;
import com.airbnb.lottie.SimpleColorFilter;
import com.annimon.stream.Stream;
@@ -162,6 +161,7 @@ import org.thoughtcrime.securesms.util.adapter.mapping.PagingMappingAdapter;
import org.thoughtcrime.securesms.components.SignalProgressDialog;
import org.thoughtcrime.securesms.util.views.Stub;
import org.thoughtcrime.securesms.wallpaper.ChatWallpaper;
import org.thoughtcrime.securesms.window.WindowSizeClassExtensionsKt;
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
import java.lang.ref.WeakReference;
@@ -317,7 +317,7 @@ public class ConversationListFragment extends MainFragment implements Conversati
searchAdapter = contactSearchMediator.getAdapter();
if (getWindowSizeClass(getResources()).getWindowHeightSizeClass() == WindowHeightSizeClass.COMPACT) {
if (WindowSizeClassExtensionsKt.isHeightCompact(getWindowSizeClass(getResources()))) {
ViewUtil.setBottomMargin(bottomActionBar, ViewUtil.getNavigationBarHeight(bottomActionBar));
}

View File

@@ -14,8 +14,7 @@ import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.window.core.layout.WindowWidthSizeClass
import org.thoughtcrime.securesms.window.isAtLeast
import androidx.window.core.layout.WindowSizeClass
import org.thoughtcrime.securesms.window.isSplitPane
private val MEDIUM_CONTENT_CORNERS = 18.dp
@@ -58,7 +57,7 @@ data class MainContentLayoutData(
return remember(maxWidth, windowSizeClass) {
when {
!windowSizeClass.isSplitPane() -> maxWidth
windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) -> 416.dp
windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND) -> 416.dp
else -> (maxWidth - extraPadding) / 2f
}
}
@@ -73,24 +72,27 @@ data class MainContentLayoutData(
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
return remember(windowSizeClass, mode) {
val isSplitPane = windowSizeClass.isSplitPane()
val isWidthExpanded = windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)
MainContentLayoutData(
shape = when {
!windowSizeClass.isSplitPane() -> RectangleShape
windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) -> RoundedCornerShape(EXTENDED_CONTENT_CORNERS)
!isSplitPane -> RectangleShape
isWidthExpanded -> RoundedCornerShape(EXTENDED_CONTENT_CORNERS)
else -> RoundedCornerShape(MEDIUM_CONTENT_CORNERS)
},
navigationBarShape = when {
!windowSizeClass.isSplitPane() -> RectangleShape
windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) -> RoundedCornerShape(0.dp, 0.dp, EXTENDED_CONTENT_CORNERS, EXTENDED_CONTENT_CORNERS)
!isSplitPane -> RectangleShape
isWidthExpanded -> RoundedCornerShape(0.dp, 0.dp, EXTENDED_CONTENT_CORNERS, EXTENDED_CONTENT_CORNERS)
else -> RoundedCornerShape(0.dp, 0.dp, MEDIUM_CONTENT_CORNERS, MEDIUM_CONTENT_CORNERS)
},
partitionWidth = when {
!windowSizeClass.isSplitPane() -> 0.dp
windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) -> 24.dp
!isSplitPane -> 0.dp
isWidthExpanded -> 24.dp
else -> 13.dp
},
listPaddingStart = when {
!windowSizeClass.isSplitPane() -> 0.dp
!isSplitPane -> 0.dp
else -> {
when (mode) {
MainToolbarMode.SEARCH -> 24.dp
@@ -99,8 +101,8 @@ data class MainContentLayoutData(
}
},
detailPaddingEnd = when {
!windowSizeClass.isSplitPane() -> 0.dp
windowSizeClass.windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) -> 24.dp
!isSplitPane -> 0.dp
isWidthExpanded -> 24.dp
else -> 12.dp
}
)

View File

@@ -13,13 +13,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.fragment.app.DialogFragment
import androidx.window.core.layout.WindowHeightSizeClass
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.Previews
import org.thoughtcrime.securesms.megaphone.Megaphone
import org.thoughtcrime.securesms.megaphone.MegaphoneActionController
import org.thoughtcrime.securesms.megaphone.MegaphoneComponent
import org.thoughtcrime.securesms.megaphone.Megaphones
import org.thoughtcrime.securesms.window.isHeightCompact
data class MainMegaphoneState(
val megaphone: Megaphone = Megaphone.NONE,
@@ -47,7 +47,7 @@ fun MainMegaphoneContainer(
) {
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
val visible = remember(windowSizeClass, state) {
!(state.megaphone == Megaphone.NONE || state.mainToolbarMode != MainToolbarMode.FULL || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT)
!(state.megaphone == Megaphone.NONE || state.mainToolbarMode != MainToolbarMode.FULL || windowSizeClass.isHeightCompact)
}
AnimatedVisibility(visible = visible) {
@@ -58,7 +58,7 @@ fun MainMegaphoneContainer(
}
LaunchedEffect(state, windowSizeClass) {
if (state.megaphone == Megaphone.NONE || state.mainToolbarMode == MainToolbarMode.BASIC || windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT) {
if (state.megaphone == Megaphone.NONE || state.mainToolbarMode == MainToolbarMode.BASIC || windowSizeClass.isHeightCompact) {
return@LaunchedEffect
}

View File

@@ -8,27 +8,25 @@ package org.thoughtcrime.securesms.window
import android.content.res.Resources
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.window.core.ExperimentalWindowCoreApi
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
import androidx.window.core.layout.WindowWidthSizeClass
import androidx.window.core.layout.computeWindowSizeClass
import org.thoughtcrime.securesms.keyvalue.SignalStore
val WindowSizeClass.listPaneDefaultPreferredWidth: Dp get() = if (windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED)) 416.dp else 316.dp
val WindowSizeClass.listPaneDefaultPreferredWidth: Dp get() = if (isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND)) 416.dp else 316.dp
val WindowSizeClass.horizontalPartitionDefaultSpacerSize: Dp get() = 12.dp
val WindowSizeClass.detailPaneMaxContentWidth: Dp get() = 624.dp
fun WindowHeightSizeClass.isAtLeast(other: WindowHeightSizeClass): Boolean {
return hashCode() >= other.hashCode()
}
val WindowSizeClass.isWidthCompact
get() = !isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)
fun WindowWidthSizeClass.isAtLeast(other: WindowWidthSizeClass): Boolean {
return hashCode() >= other.hashCode()
}
val WindowSizeClass.isHeightCompact
get() = !isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)
@OptIn(ExperimentalWindowCoreApi::class)
fun Resources.getWindowSizeClass(): WindowSizeClass {
return WindowSizeClass.compute(displayMetrics.widthPixels / displayMetrics.density, displayMetrics.heightPixels / displayMetrics.density)
return WindowSizeClass.BREAKPOINTS_V1.computeWindowSizeClass(
widthDp = displayMetrics.widthPixels / displayMetrics.density,
heightDp = displayMetrics.heightPixels / displayMetrics.density
)
}
/**
@@ -42,6 +40,8 @@ fun WindowSizeClass.isSplitPane(
return true
}
return windowWidthSizeClass.isAtLeast(WindowWidthSizeClass.EXPANDED) &&
windowHeightSizeClass.isAtLeast(WindowHeightSizeClass.MEDIUM)
return isAtLeastBreakpoint(
widthDpBreakpoint = WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND,
heightDpBreakpoint = WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND
)
}