Comments, phase 3 — search, the thread find, announcements, and a11y
Board search reaches comment bodies through a search-owned transient
index: the first live-query keystroke sweeps comments/*/index.md
off-actor (.draft and comments/.trash excluded), keystrokes re-filter
in memory, the index discards on clear — the snapshot stays O(cards).
⌘F routes by focus: the comments pane gets an app-owned find bar
spanning the whole rendered thread (next/prev cross rows with
wraparound); body and composer keep NSTextFinder; Find Next/Previous
graduate from FutureCommands. Foreign comment changes speak
path-shaped beside the announcer's ladder ("New comment on 'X'",
plural folds), narrowed by EchoLedger receipts consumed through
CommentPath.classify — and that read fixed a latent footprint bug
where a comment receipt resolved against the card's attachment
listing, read .absent, and classified the user's own write as
foreign. The pane completes its a11y story: flattened comment
elements with Edit/Delete/Reveal custom actions (un-flattening
during inline edit), phrase-table vocabulary, labeled composer and
sort control, and an audit over the open pane on a comment-seeded
fixture (runnable only where automation permission exists).
Claude-Session: https://claude.ai/code/session_01SR4XGjmBE16ZUYWpfFHXwY
This commit is contained in:
@@ -83,6 +83,21 @@ extension BoardStore {
|
||||
return CommentThread.loadDraft(inCard: card.folder)
|
||||
}
|
||||
|
||||
/// **Which of this card's comments the app itself just wrote** — the ledger's receipts, classified
|
||||
/// by path shape and retired (`EchoLedger.vouchedComments(inCard:cardPath:)`).
|
||||
///
|
||||
/// The card window asks this on every landed reload, before deciding whether its thread's changes
|
||||
/// are worth announcing: "app-mediated echoes never announce" (10-accessibility.md ▸ Live board
|
||||
/// announcements) needs a per-comment answer, and the board reload cannot give one because comments
|
||||
/// are not in the snapshot it compares.
|
||||
///
|
||||
/// `[]` for a card that is gone — the same vanished-target answer every other card-scoped call
|
||||
/// gives, and the conservative direction: nothing vouched for means everything speaks.
|
||||
public func vouchedComments(inCard id: ItemID) -> Set<ItemID> {
|
||||
guard let card = commentSubject(id) else { return [] }
|
||||
return echoes.vouchedComments(inCard: card.folder, cardPath: card.path)
|
||||
}
|
||||
|
||||
// MARK: The draft
|
||||
|
||||
/// Saves the composer's draft — one bracket, no step.
|
||||
|
||||
Reference in New Issue
Block a user