mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
M9 #3: flush UserHomeCache on soft disconnect
Full ConnectedServerRegistry was scoped out of this phase — SwiftUI view lifecycle already tears down transports via .onDisappear when ScarfGoTabRoot unmounts on state transition to .serverList. Adding a formal registry that tracks every active transport per ServerID is complexity without proven UX payoff right now (can revisit post pass-2 if users hit stale-connection bugs). One real cleanup we should always do on soft disconnect: invalidate the shared UserHomeCache entry for the server we're leaving. The cache lives forever otherwise, and a hypothetical scenario where the remote user's home directory changes between sessions would surface as SFTP paths resolving to the wrong directory. Rare, but free to fix. `RootModel.softDisconnect()` now calls the new static `ServerContext.invalidateCachedHome(forServerID:)` before flipping state to `.serverList`. Static form is a convenience for callers that have the ServerID in hand but not a full ServerContext (avoids forcing a round-trip through config store just to rebuild the context we're already discarding). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -219,6 +219,13 @@ extension ServerContext {
|
|||||||
public static func invalidateCaches(for contextID: ServerID) async {
|
public static func invalidateCaches(for contextID: ServerID) async {
|
||||||
await UserHomeCache.shared.invalidate(contextID: contextID)
|
await UserHomeCache.shared.invalidate(contextID: contextID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Static convenience for callers that have the ServerID but not
|
||||||
|
/// a full ServerContext (e.g. RootModel.softDisconnect). Mirrors
|
||||||
|
/// the instance method above.
|
||||||
|
public static func invalidateCachedHome(forServerID id: ServerID) async {
|
||||||
|
await UserHomeCache.shared.invalidate(contextID: id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Convenience file I/O via the right transport
|
// MARK: - Convenience file I/O via the right transport
|
||||||
|
|||||||
@@ -182,14 +182,19 @@ final class RootModel {
|
|||||||
state = .connected(id, config, key)
|
state = .connected(id, config, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Soft disconnect: close any live transport but keep stored
|
/// Soft disconnect: return to the server list without wiping
|
||||||
/// credentials. Returns to the server list so the user can tap
|
/// credentials. Per-view controllers (ChatController,
|
||||||
/// another server (or the same one again).
|
/// IOSDashboardViewModel, etc.) tear down their transports via
|
||||||
|
/// SwiftUI `.onDisappear` when ScarfGoTabRoot unmounts; on next
|
||||||
|
/// connect we get fresh transports. We also flush the shared
|
||||||
|
/// UserHomeCache entry for the server we're leaving so a future
|
||||||
|
/// reconnect doesn't reuse a stale `$HOME` probe (minor, but
|
||||||
|
/// matters if the remote user's home directory changed — rare
|
||||||
|
/// but possible on shared hosts).
|
||||||
func softDisconnect() async {
|
func softDisconnect() async {
|
||||||
// Transport teardown is owned by ConnectedServerRegistry
|
if case .connected(let id, _, _) = state {
|
||||||
// (added in 3.3); for now the per-view controllers own their
|
await ServerContext.invalidateCachedHome(forServerID: id)
|
||||||
// own lifecycles via .onDisappear, so this is mostly a state
|
}
|
||||||
// change. The registry commit will thread through here.
|
|
||||||
state = .serverList
|
state = .serverList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user