Files
hapi/ios/Packages/HapiKit/Sources/HapiProtocol/Models/MessagesResponse.swift
T
weishu 5ef4304a4a fix: synchronize read state across web and native clients
Track readable content revisions and durable read cursors in the hub. Acknowledge only rendered foreground tails, persist offline read operations, and preserve newer manual unread choices across devices.

Migrate existing history to a read baseline and cover pagination receipts with shared native conformance fixtures.
2026-11-01 09:52:51 +08:00

73 lines
2.4 KiB
Swift

import Foundation
/// Cursor block of a `GET /api/sessions/:id/messages` response.
///
/// Mirrors `MessagesResponse['page']` (`shared/src/apiTypes.ts`); full cursor
/// semantics in `docs/api/client-contract/pagination.md`. Every cursor is a
/// `(seq, at)` pair — both halves travel together.
public struct MessagesPage: Codable, Equatable, Sendable {
public enum Direction: String, Codable, Sendable {
case latest
case before
case after
}
public var readThroughRevision: Int?
public var direction: Direction
public var limit: Int
/// Server's current epoch for this session; a mismatch on your next
/// `after` request yields a `reset: true` latest page.
public var epoch: Int
/// `true` ⇒ discard the local window, this page replaces it.
public var reset: Bool
public var nextBeforeSeq: Int?
public var nextBeforeAt: Int?
public var nextAfterSeq: Int?
public var nextAfterAt: Int?
/// Newest position at snapshot time (inclusive catch-up bound).
public var snapshotHeadSeq: Int?
public var snapshotHeadAt: Int?
/// More rows exist in the requested direction.
public var hasMore: Bool
public init(
readThroughRevision: Int? = nil,
direction: Direction,
limit: Int,
epoch: Int,
reset: Bool,
nextBeforeSeq: Int? = nil,
nextBeforeAt: Int? = nil,
nextAfterSeq: Int? = nil,
nextAfterAt: Int? = nil,
snapshotHeadSeq: Int? = nil,
snapshotHeadAt: Int? = nil,
hasMore: Bool
) {
self.readThroughRevision = readThroughRevision
self.direction = direction
self.limit = limit
self.epoch = epoch
self.reset = reset
self.nextBeforeSeq = nextBeforeSeq
self.nextBeforeAt = nextBeforeAt
self.nextAfterSeq = nextAfterSeq
self.nextAfterAt = nextAfterAt
self.snapshotHeadSeq = snapshotHeadSeq
self.snapshotHeadAt = snapshotHeadAt
self.hasMore = hasMore
}
}
/// Envelope of `GET /api/sessions/:id/messages`.
public struct MessagesResponse: Codable, Equatable, Sendable {
/// Ascending display order.
public var messages: [DecryptedMessage]
public var page: MessagesPage
public init(messages: [DecryptedMessage], page: MessagesPage) {
self.messages = messages
self.page = page
}
}