From 962e1d513a4c86e7f130725330ee3f72e20481d2 Mon Sep 17 00:00:00 2001 From: bootoshi <127834715+kingbootoshi@users.noreply.github.com> Date: Thu, 20 Aug 2026 17:21:22 -0400 Subject: [PATCH] feat(ios): detached thumbnail cards for attached images in user messages Attached images previously stacked vertically inside the message bubble at up to 200pt each, ballooning the bubble far beyond its text. Images now render as 100pt rounded thumbnail cards in rows of three sitting on the chat background above the bubble, and the tinted bubble wraps only the text - attachments and speech read as separate layers, matching how major chat clients present image turns. Drag-out of full images still works from each thumbnail. Co-Authored-By: Claude Fable 5 --- apps/ios/Sources/Litter/Extensions.swift | 9 +++ .../Litter/Views/MessageBubbleView.swift | 59 ++++++++++--------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/apps/ios/Sources/Litter/Extensions.swift b/apps/ios/Sources/Litter/Extensions.swift index aaa6e458b..0e922204e 100644 --- a/apps/ios/Sources/Litter/Extensions.swift +++ b/apps/ios/Sources/Litter/Extensions.swift @@ -595,3 +595,12 @@ extension View { } } } + +extension Array { + func chunked(into size: Int) -> [[Element]] { + guard size > 0 else { return [self] } + return stride(from: 0, to: count, by: size).map { + Array(self[$0.. some View { + if let request = UserBubble.imageRequest(for: img) { + LazyImage(request: request) { state in + if let image = state.image { + let thumb = image + .resizable() + .scaledToFill() + .frame(width: 100, height: 100) + .clipShape(RoundedRectangle(cornerRadius: 12)) + if let ui = state.imageContainer?.image { + thumb.draggable(Image(uiImage: ui)) { + Image(uiImage: ui) + .resizable() + .scaledToFit() + .frame(width: 120) + } + } else { + thumb + } + } + } + } + } + private var visibleText: String { guard shouldLimitText, !expandedLongText else { return text