Skip to content

Commit ecc1706

Browse files
angusbezzinaclaude
andcommitted
feat(overlay): explicit point/frame selection modes (VRT-cne0.11)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2 parents 73d0102 + 66425a2 commit ecc1706

9 files changed

Lines changed: 540 additions & 224 deletions

Sources/AnnotKit/Overlay/AnnotationSession.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,28 @@ public final class AnnotationSession: ObservableObject {
1616
case annotating
1717
}
1818

19+
/// Which gesture the catcher interprets: click a point, or draw a frame around
20+
/// what you mean. Explicit rather than inferred from how far a press travelled —
21+
/// an implicit branch means the mode you get depends on how steady your hand was,
22+
/// so a jittery click silently plants a FRAMED note bound to whatever container
23+
/// the pointer sat in. Making it a chosen tool means the user always knows which
24+
/// outcome a press can produce before they make it.
25+
///
26+
/// Nested here (rather than beside ``SelectionGesture``) because it is session
27+
/// state the UI binds to; `nonisolated` so the pure ``SelectionGesture/resolve``
28+
/// can switch on it without hopping to the main actor.
29+
public nonisolated enum SelectionTool: Sendable, Hashable {
30+
case point
31+
case frame
32+
}
33+
1934
@Published public private(set) var mode: Mode = .idle
35+
/// The active selection tool. A user PREFERENCE, not per-session state:
36+
/// ``stop()``, ``clear()`` and capturing a note deliberately leave it alone, so
37+
/// a user who chose frame mode does not silently get dropped back to clicking
38+
/// after every note. ``point`` is the default so existing muscle memory (click
39+
/// the thing, type the note) is untouched for anyone who never opens the picker.
40+
@Published public private(set) var tool: SelectionTool = .point
2041
/// The retained set of captured notes. Grows via ``addNote(comment:selectedText:screenshot:)``
2142
/// and is emptied ONLY by ``clear()`` — ``export()`` and copy read it without
2243
/// mutating it, so the same set survives repeated copy/export.
@@ -99,6 +120,14 @@ public final class AnnotationSession: ObservableObject {
99120

100121
public func start() { mode = .annotating }
101122

123+
/// Switch which gesture the catcher interprets. Deliberately touches NOTHING
124+
/// else: an open composer, the current selection and the retained notes all
125+
/// survive, because changing how you will pick the NEXT target says nothing
126+
/// about the note you are in the middle of writing. Discarding a half-typed
127+
/// comment because the user reached for the other tool would be the kind of
128+
/// data loss nobody reports — they just stop using the picker.
129+
public func setTool(_ tool: SelectionTool) { self.tool = tool }
130+
102131
public func stop() {
103132
mode = .idle
104133
hovered = nil

Sources/AnnotKit/Overlay/MarqueeDrag.swift

Lines changed: 0 additions & 67 deletions
This file was deleted.

0 commit comments

Comments
 (0)