Files
ReadViewSDK/Sources/RDEpubReaderView/EPUBUI/ReaderController/RDEPUBReaderState.swift
T
2026-07-27 21:43:13 +08:00

79 lines
2.1 KiB
Swift

import UIKit
/// M-01: All properties must be accessed exclusively from the main thread.
/// This is currently enforced by convention — all verified access paths are main-thread-only.
/// Adding @MainActor would formalize this but requires iOS 15+ and Swift concurrency throughout.
/// For now, rely on the audit-verified access patterns and consider @MainActor in a future refactor.
final class RDEPUBReaderState {
var parser: RDEPUBParser?
var publication: RDEPUBPublication?
var readingSession: RDEPUBReadingSession?
var textBook: RDEPUBTextBook?
var bookPageMap: RDEPUBBookPageMap?
var activeBookmarks: [RDEPUBBookmark] = []
var activeHighlights: [RDEPUBHighlight] = []
// Session-only decorations (for search/AI focus) are never persisted.
var transientHighlights: [RDEPUBHighlight] = []
var currentBookIdentifier: String?
var paginationToken = UUID()
var searchState: RDEPUBSearchState?
var pendingPageMapUpdates: [RDEPUBPendingPageMapUpdate] = []
var lastTextPaginationPageSize: CGSize?
var lastMetadataParseWallClockMs: Int = 0
var lastMetadataParseConcurrency: Int = 0
var selectionState: RDEPUBSelectionState = .idle
var isRepaginating: Bool = false
var didStartInitialLoad: Bool = false
var isExternalTextBook: Bool = false
var textFileURL: URL?
let textBookCache = RDEPUBTextBookCache()
var currentSelection: RDEPUBSelection? {
get { selectionState.selection }
set {
if let newValue, !newValue.isEmpty {
selectionState = .selected(newValue)
} else {
selectionState = .idle
}
}
}
var activePages: [EPUBPage] {
readingSession?.activePages ?? []
}
var activeChapters: [EPUBChapterInfo] {
readingSession?.activeChapters ?? []
}
func replaceActiveSnapshot(_ snapshot: RDEPUBReadingSession.PaginationSnapshot) {
readingSession?.setActiveSnapshot(snapshot)
}
func clearActiveSnapshot() {
readingSession?.resetRuntimeState()
}
}