Show the wallpaper gradient on bubbles in the theme preview

The wallpaper-picker preview already draws the SIMPLEX sunrise gradient
as its background, but the sample message bubbles stayed flat: bubbles
anchor their gradient to the chat viewport, which the preview never
provided. Give the preview its own viewport (with the same expanded
axis the preview background uses), so the sample bubbles show the same
gradient they do in a real chat, aligned with the background.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
another-simple-pixel
2026-07-07 17:18:35 -07:00
co-authored by Claude Opus 4.8
parent f40589743f
commit 2650f57e4f
2 changed files with 20 additions and 10 deletions
@@ -29,15 +29,16 @@ private const val SIMPLEX_TILT_DEG = 20f
class ChatViewportInfo(
val sizePx: State<IntSize>,
val originInWindow: State<Offset>,
val previewMode: Boolean = false,
)
val LocalChatViewportInfo = compositionLocalOf<ChatViewportInfo?> { null }
@Composable
fun rememberChatViewportInfo(): Pair<ChatViewportInfo, Modifier> {
fun rememberChatViewportInfo(previewMode: Boolean = false): Pair<ChatViewportInfo, Modifier> {
val sizePx = remember { mutableStateOf(IntSize.Zero) }
val originInWindow = remember { mutableStateOf(Offset.Zero) }
val info = remember { ChatViewportInfo(sizePx, originInWindow) }
val info = remember { ChatViewportInfo(sizePx, originInWindow, previewMode) }
val mod = Modifier
.onSizeChanged { sizePx.value = it }
.onGloballyPositioned { originInWindow.value = it.positionInWindow() }
@@ -97,7 +98,12 @@ fun Modifier.simplexBubbleBackground(slot: SimplexBubbleSlot): Modifier = compos
.drawBehind {
val sz = viewport.sizePx.value
if (sz.width == 0 || sz.height == 0) return@drawBehind
val (axisStartLocal, axisEndLocal) = axisEndpoints(sz.width.toFloat(), sz.height.toFloat())
val (bl, tr) = axisEndpoints(sz.width.toFloat(), sz.height.toFloat())
// The preview swatch stretches the axis (same as simplexGradient()'s previewMode in
// ChatWallpaper.kt) so bubbles show the same representative slice as the wallpaper background.
val span = tr - bl
val axisStartLocal = if (viewport.previewMode) bl - span else bl
val axisEndLocal = if (viewport.previewMode) tr + span * 2f else tr
val viewportOrigin = viewport.originInWindow.value
val offset = viewportOrigin - bubblePos.value
val brush = Brush.linearGradient(
@@ -279,6 +279,7 @@ object AppearanceScope {
val themeBackgroundColor = MaterialTheme.colors.background
val backgroundColor = backgroundColor ?: wallpaperType?.defaultBackgroundColor(theme, MaterialTheme.colors.background)
val tintColor = tintColor ?: wallpaperType?.defaultTintColor(theme)
val (previewViewport, previewViewportModifier) = rememberChatViewportInfo(previewMode = true)
Column(Modifier
.drawWithCache {
if (wallpaperImage != null && wallpaperType != null && backgroundColor != null && tintColor != null) {
@@ -289,19 +290,22 @@ object AppearanceScope {
}
}
}
.then(previewViewportModifier)
.padding(DEFAULT_PADDING_HALF)
) {
if (withMessages) {
val chatItemTail = remember { appPreferences.chatItemTail.state }
Column(verticalArrangement = Arrangement.spacedBy(4.dp), modifier = if (chatItemTail.value) Modifier else Modifier.padding(horizontal = msgTailWidthDp)) {
val alice = remember { ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), generalGetString(MR.strings.wallpaper_preview_hello_bob)) }
PreviewChatItemView(alice)
PreviewChatItemView(
ChatItem.getSampleData(2, CIDirection.DirectSnd(), Clock.System.now(), stringResource(MR.strings.wallpaper_preview_hello_alice),
quotedItem = CIQuote(alice.chatDir, alice.id, sentAt = alice.meta.itemTs, formattedText = alice.formattedText, content = MsgContent.MCText(alice.content.text))
CompositionLocalProvider(LocalChatViewportInfo provides previewViewport) {
Column(verticalArrangement = Arrangement.spacedBy(4.dp), modifier = if (chatItemTail.value) Modifier else Modifier.padding(horizontal = msgTailWidthDp)) {
val alice = remember { ChatItem.getSampleData(1, CIDirection.DirectRcv(), Clock.System.now(), generalGetString(MR.strings.wallpaper_preview_hello_bob)) }
PreviewChatItemView(alice)
PreviewChatItemView(
ChatItem.getSampleData(2, CIDirection.DirectSnd(), Clock.System.now(), stringResource(MR.strings.wallpaper_preview_hello_alice),
quotedItem = CIQuote(alice.chatDir, alice.id, sentAt = alice.meta.itemTs, formattedText = alice.formattedText, content = MsgContent.MCText(alice.content.text))
)
)
)
}
}
} else {
Box(Modifier.fillMaxSize())