eleven / messenger Public

mac,ios: cancelling a reply no longer blanks the feed (#318)

The delete-implosion put a scale(0.05) REMOVAL transition on every
row. When the composer inset shrinks (a reply cancelled, a banner
dismissed), SwiftUI runs an animated layout pass and the LazyVStack
destroys off-screen rows inside it — firing the scale removal on the
whole feed, which imploded to nothing until you left and returned.
Removal is a plain fade now; a delete still fades out gracefully. A
safer targeted implosion can come back later.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 81cb6b3841f37b7773ef9d21a2caf3900628cf15 parent 426a09f
2 files changed, +7 −4
  • ios/LChat/Views/NativeChatScreen.swift +6 −1
  • ios/LChatMac/NativeFeedView.swift +1 −3
diff --git a/ios/LChat/Views/NativeChatScreen.swift b/ios/LChat/Views/NativeChatScreen.swift
index 0ab3776..970c703 100644
--- a/ios/LChat/Views/NativeChatScreen.swift
+++ b/ios/LChat/Views/NativeChatScreen.swift
@@ -295,9 +295,14 @@ struct NativeChatScreen: View {
ForEach(Array(model.messages.enumerated()), id: \.element.id) { i, m in
row(m, previous: i > 0 ? model.messages[i - 1] : nil, proxy: proxy)
.id(m.id)
+ // Removal is a plain fade, NOT a scale-implosion:
+ // the LazyVStack destroys off-screen rows during
+ // animated layout passes (cancelling a reply shrinks
+ // the composer inset), and a scale removal imploded
+ // the WHOLE feed to nothing until you left + returned.
.transition(.asymmetric(
insertion: .move(edge: .bottom).combined(with: .opacity),
- removal: .scale(scale: 0.05).combined(with: .opacity)))
+ removal: .opacity))
.onAppear {
// `settled` gate: the opening pin-jump
// transiently materialises top rows, and each
diff --git a/ios/LChatMac/NativeFeedView.swift b/ios/LChatMac/NativeFeedView.swift
index 55e3446..262ac6c 100644
--- a/ios/LChatMac/NativeFeedView.swift
+++ b/ios/LChatMac/NativeFeedView.swift
@@ -152,9 +152,7 @@ struct NativeFeedView: View {
.id(m.id)
// Deleted messages implode — a quick shrink-and-
// fade where the bubble stood.
- .transition(.asymmetric(
- insertion: .identity,
- removal: .scale(scale: 0.05).combined(with: .opacity)))
+ .transition(.opacity) // plain fade — a scale-implosion removal blanked the whole feed on inset changes
// Geometry probe for "is this row already in view?"
// (jump-without-scroll). Writes to the frame store,
// never to state.