Skip to content

Commit 7763717

Browse files
Copilotneongreen
authored andcommitted
copilot - text-annotator mac tool
1 parent 7a3716b commit 7763717

20 files changed

Lines changed: 3131 additions & 0 deletions

.github/CI_GUIDELINES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ jobs:
108108
|---------|----------|---------------|--------|
109109
| `dissect` | Go | `.github/workflows/dissect.yml` | ✅ Active |
110110
| `markdown-format` | Go | `.github/workflows/markdown-format.yml` | ✅ Active |
111+
| `text-annotator` | Swift | `.github/workflows/text-annotator.yml` | ✅ Active |
111112
| `diagram-dsl` | TypeScript | - | 🔜 Pending |
112113
| `want` | - | - | 🔜 Pending |
113114

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: text-annotator
2+
3+
on:
4+
push:
5+
paths:
6+
- 'text-annotator/**'
7+
- '.github/workflows/text-annotator.yml'
8+
pull_request:
9+
paths:
10+
- 'text-annotator/**'
11+
- '.github/workflows/text-annotator.yml'
12+
13+
jobs:
14+
build:
15+
runs-on: macos-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Swift
22+
run: swift --version
23+
24+
- name: Build project
25+
working-directory: text-annotator
26+
run: swift build
27+
28+
- name: Build release
29+
working-directory: text-annotator
30+
run: swift build -c release

text-annotator/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc
9+
*.xcodeproj

text-annotator/ARCHITECTURE.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# Text Annotator - Architecture
2+
3+
## Overview
4+
5+
Text Annotator is a native macOS utility built with Swift and AppKit. It uses system-level APIs to provide global keyboard shortcut functionality and text capture capabilities.
6+
7+
## Components
8+
9+
### 1. AppDelegate.swift
10+
11+
The main application controller that manages:
12+
13+
#### Status Bar Integration
14+
- Creates a menu bar status item with a note icon
15+
- Provides manual trigger point for annotation
16+
17+
#### Global Hotkey Registration
18+
- Uses Carbon Events API to register `Cmd+Shift+A`
19+
- Installs event handler to respond to hotkey presses
20+
- Uses `EventHotKeyID` with signature "TXAN" (Text Annotator)
21+
22+
#### Text Capture
23+
- Implements system-wide text selection capture
24+
- Saves and restores clipboard to avoid interference
25+
- Uses `CGEvent` to simulate `Cmd+C` keyboard event
26+
27+
#### Accessibility Permissions
28+
- Requests permissions on first launch using `AXIsProcessTrustedWithOptions`
29+
- Required for both hotkey registration and clipboard simulation
30+
31+
### 2. AnnotationWindow.swift
32+
33+
The popup window interface that provides:
34+
35+
#### Window Configuration
36+
- Modal-style window with `.floating` level (stays on top)
37+
- Fixed size (500x300) with centered positioning
38+
- Standard window controls (close, minimize)
39+
40+
#### UI Components
41+
- **Text Display**: Read-only scrollable view for selected text
42+
- **Annotation Field**: Single-line text input with auto-focus
43+
- **Buttons**: Save and Cancel with keyboard shortcuts
44+
- **Helper Text**: Shows keyboard shortcut hint
45+
46+
#### Data Persistence
47+
- Implements JSON file operations
48+
- Loads existing annotations from `~/.text-annotations.json`
49+
- Appends new annotations to array
50+
- Uses `JSONSerialization` for encoding/decoding
51+
52+
#### Keyboard Handling
53+
- Implements `NSTextFieldDelegate` to intercept `Cmd+Enter`
54+
- Maps `Escape` key to cancel action
55+
- Handles validation before saving
56+
57+
## Technologies Used
58+
59+
### Apple Frameworks
60+
61+
- **Cocoa/AppKit**: Native macOS UI framework
62+
- **Carbon Events**: Legacy API for global hotkey registration
63+
- **Accessibility API**: For checking/requesting permissions
64+
- **Core Graphics**: For simulating keyboard events
65+
66+
### Swift Language Features
67+
68+
- **@main**: Application entry point
69+
- **@objc**: Objective-C interoperability for selectors
70+
- **Delegation**: NSWindowDelegate, NSTextFieldDelegate patterns
71+
- **Auto Layout**: Constraint-based UI layout
72+
73+
## Data Flow
74+
75+
```
76+
User Action (Cmd+Shift+A)
77+
78+
Carbon Event Handler
79+
80+
AppDelegate.showAnnotationWindow()
81+
82+
AppDelegate.getSelectedText()
83+
├─ Save clipboard
84+
├─ Simulate Cmd+C
85+
├─ Read clipboard
86+
└─ Restore clipboard
87+
88+
AnnotationWindow(selectedText: ...)
89+
90+
User enters annotation + Cmd+Enter
91+
92+
AnnotationWindow.saveAnnotation()
93+
94+
AnnotationWindow.saveToJSON()
95+
├─ Load existing JSON
96+
├─ Append new entry
97+
└─ Write to file
98+
99+
Window closes
100+
```
101+
102+
## Security Considerations
103+
104+
### Permissions Required
105+
106+
1. **Accessibility**: Required for:
107+
- Global hotkey registration
108+
- Keyboard event simulation
109+
- System-wide text capture
110+
111+
2. **No Network Access**: App is fully local
112+
3. **No Analytics**: No data collection or telemetry
113+
114+
### Privacy
115+
116+
- All data stored locally in user's home directory
117+
- No cloud sync or external transmission
118+
- User has full control over JSON file
119+
120+
## File System
121+
122+
```
123+
~/.text-annotations.json # User data (annotations)
124+
TextAnnotator.app/ # Application bundle
125+
├── Contents/
126+
│ ├── MacOS/
127+
│ │ └── TextAnnotator # Executable
128+
│ ├── Info.plist # App metadata
129+
│ └── Resources/ # (none currently)
130+
```
131+
132+
## Build System
133+
134+
- **Swift Package Manager**: Used for build configuration
135+
- **Package.swift**: Defines executable target
136+
- **Minimum Platform**: macOS 12.0
137+
- **Build Output**: `.build/release/TextAnnotator`
138+
139+
## Limitations
140+
141+
1. **macOS Only**: Uses platform-specific APIs (Cocoa, Carbon)
142+
2. **Text Selection**: Only works with selectable text
143+
3. **Clipboard-based**: May not work with clipboard-blocking apps
144+
4. **Single Instance**: No mechanism to prevent multiple instances
145+
146+
## Future Enhancements
147+
148+
Potential improvements:
149+
150+
- Search/filter annotations within the app
151+
- Export to different formats (CSV, Markdown)
152+
- Tags or categories for annotations
153+
- Sync with cloud storage
154+
- Configurable hotkey
155+
- Rich text support
156+
- Image capture support
157+
- Custom JSON file location
158+
- Import/merge annotations
159+
160+
## Testing
161+
162+
Since this is a GUI application with system-level integration:
163+
164+
- **Manual Testing**: Required on macOS
165+
- **Permissions**: Test with and without Accessibility access
166+
- **Edge Cases**:
167+
- Empty selections
168+
- Very long text
169+
- Special characters
170+
- Clipboard conflicts
171+
- Multiple rapid activations
172+
173+
## Dependencies
174+
175+
- **No External Dependencies**: Pure Swift + system frameworks
176+
- **Swift 5.9+**: Language requirement
177+
- **macOS 12+**: Platform requirement

0 commit comments

Comments
 (0)