feat(ios): P1-B — W7 UI wave: deep links, timeline, quick-reply, diff, projects, session switcher, thumbnails, lock-screen push
T-iOS-22: DeepLinkRouter (full-field whitelist, cold-start stash, route(from:) for push-tap reuse), 21 tests T-iOS-24: TimelineSheet mirroring web render() order; disabled→empty-state; reuses AwayDigest onExpand T-iOS-25: QuickReply chips (built-ins mirror quick-reply.ts via KeyByteMap; visible iff live gate && !readOnly) T-iOS-27: read-only DiffScreen + App-layer DiffFetcher (RO no-Origin; APIClient fold-in noted for T-iOS-38 owner) T-iOS-26: Projects list/detail — grouping byte-identical to web group keys (prefs-shared collapse state), prefs-clobber defenses (no blind PUT on empty base; adopt server echo), claude\r bootstrap T-iOS-23: UnreadLedger + TitleSanitizer (SessionCore, +15 tests), lastOutputAt decode, list-boundary re-sanitize T-iOS-29: new-in-cwd (untrusted cwd, no bootstrap re-injection) + exited-session reopen; fixes stale-controller SwiftTerm view bug via .id(controller.id) T-iOS-28: offscreen SwiftTerm thumbnail pipeline (LRU 32, concurrency gate 2, 256KiB cap, grid clamp) T-iOS-21: PushRegistrar (WEBTERM_GATE category: Allow=.authenticationRequired, no .foreground) + NotificationActionHandler (whitelisted payload, token never persisted, bg-task-wrapped POST, 403 fallback) CRITICAL fix (verify-found boot crash): @Sendable literals on UN completion closures — MainActor-inherited closures trapped Swift 6 executor check on UN's background queue; boot re-verified (no new crash reports, permission prompt reached, privacy shade correctly covering during system alert) Verified: 261 pkg + 247 app + 10 integration tests green; 7/7 semantics checks; Owns audit clean
This commit is contained in:
@@ -28,6 +28,10 @@ public struct LiveSessionInfo: Sendable, Equatable {
|
||||
public let rows: Int
|
||||
/// Latest statusLine telemetry, if any (B2).
|
||||
public let telemetry: StatusTelemetry?
|
||||
/// Server ms timestamp of the last PTY output (== createdAt until first
|
||||
/// output). OPTIONAL additive field (T-iOS-37, src/types.ts:259-261) —
|
||||
/// pre-P1 servers omit it; nil means "no unread data source" (T-iOS-23).
|
||||
public let lastOutputAt: Int?
|
||||
|
||||
public init(
|
||||
id: UUID,
|
||||
@@ -38,7 +42,8 @@ public struct LiveSessionInfo: Sendable, Equatable {
|
||||
cwd: String?,
|
||||
cols: Int,
|
||||
rows: Int,
|
||||
telemetry: StatusTelemetry?
|
||||
telemetry: StatusTelemetry?,
|
||||
lastOutputAt: Int? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.createdAt = createdAt
|
||||
@@ -49,12 +54,14 @@ public struct LiveSessionInfo: Sendable, Equatable {
|
||||
self.cols = cols
|
||||
self.rows = rows
|
||||
self.telemetry = telemetry
|
||||
self.lastOutputAt = lastOutputAt
|
||||
}
|
||||
}
|
||||
|
||||
extension LiveSessionInfo: Decodable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id, createdAt, clientCount, status, exited, cwd, cols, rows, telemetry
|
||||
case lastOutputAt
|
||||
}
|
||||
|
||||
public init(from decoder: any Decoder) throws {
|
||||
@@ -71,6 +78,7 @@ extension LiveSessionInfo: Decodable {
|
||||
// Optional/nullable fields: wrong type degrades to nil (tolerant).
|
||||
cwd = try? container.decode(String.self, forKey: .cwd)
|
||||
telemetry = try? container.decode(StatusTelemetry.self, forKey: .telemetry)
|
||||
lastOutputAt = try? container.decode(Int.self, forKey: .lastOutputAt)
|
||||
}
|
||||
|
||||
/// Decode a `/live-sessions` response body.
|
||||
|
||||
Reference in New Issue
Block a user