fix(chat): scope composer state to active session id (#62)

`RichChatInputBar`'s `@State` `text` and `attachments` survived
session switches because the surrounding view tree is structurally
identical across sessions — SwiftUI happily reused the same
instance and leaked the previous session's unsent draft into the
new one.

Bind the composer's identity to `richChat.sessionId` so SwiftUI
rebuilds the view (and its `@State`) on session change. A stable
fallback string covers the brief "no session selected" window;
using `UUID()` here would mint a fresh id on every render and
trash the composer per body re-eval.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alan Wizemann
2026-05-01 15:28:59 +02:00
parent fcfe1c89d6
commit 31e6c31acf
@@ -44,12 +44,23 @@ struct ChatTranscriptPane: View {
if let hint = richChat.transientHint {
steeringToast(hint)
}
// Issue #62: bind composer identity to the active session
// ID so SwiftUI rebuilds `RichChatInputBar` (and its
// `@State` `text`/`attachments`) when the user switches
// conversations. Without this the composer is structurally
// identical across sessions and SwiftUI happily reuses the
// instance, leaking the unsent draft into the new session.
// A stable fallback id covers the brief "no session
// selected" window using `UUID()` here would mint a
// fresh value per render and trash the composer on every
// body re-eval.
RichChatInputBar(
onSend: onSend,
isEnabled: isEnabled,
commands: richChat.availableCommands,
showCompressButton: richChat.supportsCompress && !richChat.hasBroaderCommandMenu
)
.id(richChat.sessionId ?? "scarf.chat.no-session")
}
.background(ScarfColor.backgroundPrimary)
}