mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
M7 #14 (pass-2): keep ACP session alive across tab switches
Pass-2 observation: "when a user switches away from chat and comes
back, there is a loading time — should we keep it open so there
isn't a reload needed?"
Removed the .onDisappear { controller.stop() } hook. TabView unmounts
tab content on switch (disappear fires), but @State keeps the
ChatController alive — so dropping the SSH exec channel + re-
opening on next appear was costing a ~1-2s reconnect every time
the user bounced Dashboard → Chat → Memory → Chat.
Cleanup still happens correctly because ChatController's lifetime
is tied to ChatView's parent (ScarfGoTabRoot). When the user
Disconnects/Forgets from the More tab, RootModel flips out of
.connected, the whole tab root unmounts, and the controller + its
ACPClient tear down via .deinit. Background termination is handled
by iOS naturally.
A comment in the file documents why we no longer tear down on
.onDisappear — easy to re-add if a future iPad / multi-window
variant wants explicit idle-pause behaviour.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -93,9 +93,22 @@ struct ChatView: View {
|
|||||||
coordinator?.pendingResumeSessionID = nil
|
coordinator?.pendingResumeSessionID = nil
|
||||||
Task { await controller.startResuming(sessionID: sessionID) }
|
Task { await controller.startResuming(sessionID: sessionID) }
|
||||||
}
|
}
|
||||||
.onDisappear {
|
// Deliberately NOT tearing down the ACP session on .onDisappear.
|
||||||
Task { await controller.stop() }
|
// `TabView` unmounts tab content when the user switches tabs
|
||||||
}
|
// (disappear fires), but `@State var controller` keeps the
|
||||||
|
// ChatController alive across those switches, so dropping the
|
||||||
|
// SSH exec channel + re-opening on next appear would cost the
|
||||||
|
// user a ~1-2s reconnect every time they hop to Dashboard
|
||||||
|
// and back. The ACPClient stays open; the controller cleans up
|
||||||
|
// properly when:
|
||||||
|
// - the user Disconnects / Forgets the server (RootModel
|
||||||
|
// flips out of .connected, whole tab root unmounts, and
|
||||||
|
// ChatController.deinit + transport teardown runs),
|
||||||
|
// - or the app goes to background (iOS will terminate the
|
||||||
|
// socket eventually if memory pressure hits anyway).
|
||||||
|
// If a future iPad / multi-window variant wants to explicitly
|
||||||
|
// pause idle connections, add a coordinator-driven stop() on
|
||||||
|
// app-lifecycle phase changes instead.
|
||||||
.overlay {
|
.overlay {
|
||||||
if case .failed(let msg) = controller.state {
|
if case .failed(let msg) = controller.state {
|
||||||
errorOverlay(msg)
|
errorOverlay(msg)
|
||||||
|
|||||||
Reference in New Issue
Block a user