mac: re-pin the feed on a text-size change — a shrink could blank the pane (#429)
Changing the Text Size relayouts every row at once; when the content got shorter the scroll offset stayed clamped past the new end, showing an empty feed until the next message arrival's wedge check rescued it. Run the same verified pin on chatFontSize changes: immediately when the reader was at the bottom, and after a layout beat (only if the viewport actually came up empty) when scrolled back, so history readers aren't yanked to the newest message.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+19
−0
ios/LChatMac/NativeFeedView.swift+19 −0
diff --git a/ios/LChatMac/NativeFeedView.swift b/ios/LChatMac/NativeFeedView.swift| index a320116..0b214cf 100644 |
| --- a/ios/LChatMac/NativeFeedView.swift |
| +++ b/ios/LChatMac/NativeFeedView.swift |
| @@ -310,6 +310,25 @@ struct NativeFeedView: View { |
| // Search hits land on their message: page history until the |
| // target is loaded, then jump-and-wave. |
| .onChange(of: app.nativeJump) { _, _ in consumeJump(proxy) } |
| + // A Text Size change (⌘+/⌘−, Settings slider) relayouts every row |
| + // at once; a shrink can leave the scroll offset clamped past the |
| + // new content end — a fully blank feed, the same wedge the |
| + // message-arrival handler guards against (and which un-wedged |
| + // itself only on the next arrival). Re-pin immediately when the |
| + // reader was at the bottom; from deep in history, give layout a |
| + // beat and rescue only if the viewport actually came up empty, so |
| + // a scrolled-back reader isn't yanked to the newest message. |
| + .onChange(of: chatFontSize) { _, _ in |
| + let nearBottom = model.messages.last.flatMap { frames.rows[$0.id]?.minY } |
| + .map { $0 < frames.viewport.height + 150 } ?? false |
| + if nearBottom { |
| + pinUntilSettled(proxy) |
| + return |
| + } |
| + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { |
| + if frames.rows.isEmpty && !model.messages.isEmpty { pinUntilSettled(proxy) } |
| + } |
| + } |
| .onAppear { |
| pinUntilSettled(proxy) |
| consumeJump(proxy) |