Transcript Incremental Projection
Nucleic-Session: 0FFD007B-0696-4517-9429-129C7B0FD5AC Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -509,6 +509,14 @@ struct TranscriptList: View {
|
|||||||
/// row churn.
|
/// row churn.
|
||||||
@State private var prewarmTask: Task<Void, Never>?
|
@State private var prewarmTask: Task<Void, Never>?
|
||||||
|
|
||||||
|
/// How many projected rows the pre-warm has already covered, so each later trigger snapshots
|
||||||
|
/// only the *new* rows instead of re-walking (and re-hashing) the whole transcript on every
|
||||||
|
/// row that lands — which would quietly re-introduce an O(N) main-thread pass per row. Held
|
||||||
|
/// in a box (not `@State` value) because updating it from `body`-adjacent code must not
|
||||||
|
/// invalidate the view.
|
||||||
|
private final class PrewarmProgress { var count = 0 }
|
||||||
|
@State private var prewarmProgress = PrewarmProgress()
|
||||||
|
|
||||||
private var items: [TranscriptItem] {
|
private var items: [TranscriptItem] {
|
||||||
projectionCache.items(for: events, showRaw: showRaw, showLockEvents: showLockEvents)
|
projectionCache.items(for: events, showRaw: showRaw, showLockEvents: showLockEvents)
|
||||||
}
|
}
|
||||||
@@ -519,11 +527,16 @@ struct TranscriptList: View {
|
|||||||
/// away, jittering the load-in. Snapshot the message bodies here on the main actor (a cheap read
|
/// away, jittering the load-in. Snapshot the message bodies here on the main actor (a cheap read
|
||||||
/// of the memoized projection), then parse them on a background task so that first layout finds
|
/// of the memoized projection), then parse them on a background task so that first layout finds
|
||||||
/// the caches already warm. Idempotent and self-cancelling; the parse results are the same
|
/// the caches already warm. Idempotent and self-cancelling; the parse results are the same
|
||||||
/// whichever thread fills the (thread-safe) caches.
|
/// whichever thread fills the (thread-safe) caches. Incremental: only rows beyond the last
|
||||||
|
/// covered count are snapshotted (coalescing can shuffle nearby indices, but a missed body just
|
||||||
|
/// parses on first layout as before — the warm is an optimization, never a correctness gate).
|
||||||
private func prewarmMarkdown() {
|
private func prewarmMarkdown() {
|
||||||
let bodies: [String] = items.compactMap {
|
let current = items
|
||||||
|
if current.count < prewarmProgress.count { prewarmProgress.count = 0 } // stream reset
|
||||||
|
let bodies: [String] = current[prewarmProgress.count...].compactMap {
|
||||||
if case .message(_, let text) = $0.kind { return text } else { return nil }
|
if case .message(_, let text) = $0.kind { return text } else { return nil }
|
||||||
}
|
}
|
||||||
|
prewarmProgress.count = current.count
|
||||||
guard !bodies.isEmpty else { return }
|
guard !bodies.isEmpty else { return }
|
||||||
prewarmTask?.cancel()
|
prewarmTask?.cancel()
|
||||||
prewarmTask = Task.detached(priority: .utility) {
|
prewarmTask = Task.detached(priority: .utility) {
|
||||||
|
|||||||
Reference in New Issue
Block a user