74 lines
2.2 KiB
Swift
74 lines
2.2 KiB
Swift
import Foundation
|
|
|
|
public enum SessionState: String, Codable, Sendable {
|
|
case open // accepting captures
|
|
case archived // its PDF has been built and sent; kept forever, never deleted
|
|
}
|
|
|
|
/// The manifest persisted as session.json alongside the PNGs.
|
|
public struct CaptureSession: Codable, Sendable, Identifiable, Equatable {
|
|
public let id: UUID
|
|
public let createdAt: Date
|
|
public private(set) var state: SessionState
|
|
public private(set) var captures: [Capture]
|
|
/// Set when the PDF is built, so a re-send reuses the same file.
|
|
public private(set) var pdfFileName: String?
|
|
|
|
public init(
|
|
id: UUID,
|
|
createdAt: Date,
|
|
state: SessionState,
|
|
captures: [Capture],
|
|
pdfFileName: String?
|
|
) {
|
|
self.id = id
|
|
self.createdAt = createdAt
|
|
self.state = state
|
|
self.captures = captures
|
|
self.pdfFileName = pdfFileName
|
|
}
|
|
|
|
public var isEmpty: Bool {
|
|
captures.isEmpty
|
|
}
|
|
|
|
/// max(sequence)+1, or 1 when empty.
|
|
public var nextSequence: Int {
|
|
(captures.map(\.sequence).max() ?? 0) + 1
|
|
}
|
|
|
|
/// Value-semantic: returns a new session; does not mutate `self`.
|
|
public func appending(_ capture: Capture) -> CaptureSession {
|
|
CaptureSession(
|
|
id: id,
|
|
createdAt: createdAt,
|
|
state: state,
|
|
captures: captures + [capture],
|
|
pdfFileName: pdfFileName
|
|
)
|
|
}
|
|
|
|
/// Value-semantic: returns a new session; does not mutate `self`.
|
|
/// Sequence numbers of remaining captures are left unchanged.
|
|
public func removing(captureID: UUID) -> CaptureSession {
|
|
CaptureSession(
|
|
id: id,
|
|
createdAt: createdAt,
|
|
state: state,
|
|
captures: captures.filter { $0.id != captureID },
|
|
pdfFileName: pdfFileName
|
|
)
|
|
}
|
|
|
|
/// Value-semantic: returns a new session; does not mutate `self`.
|
|
public func markArchived(pdfFileName: String) -> CaptureSession {
|
|
CaptureSession(
|
|
id: id,
|
|
createdAt: createdAt,
|
|
state: .archived,
|
|
captures: captures,
|
|
pdfFileName: pdfFileName
|
|
)
|
|
}
|
|
}
|