Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ this file.
dedup, LRU eviction, settings, image file store, stats, doctor checks, OCR
text extraction, and shared text analysis (color/case/Base64/URL/JWT/epoch).
**No AppKit/SwiftUI imports** (Foundation + CoreGraphics/ImageIO +
UniformTypeIdentifiers + CryptoKit + Vision allowed — Vision powers the
injectable `OCREngine`).
UniformTypeIdentifiers + CryptoKit + CoreImage + Vision allowed — Vision
powers the injectable `OCREngine`, CoreImage the QR generator).
- `ClapApp` (executable): NSApplication accessory app. Pasteboard monitor,
Carbon global hotkey (configurable), SwiftUI floating panel (Classic/Media/
Shell/Favs tabs), menu bar item, settings window.
Expand Down Expand Up @@ -350,8 +350,9 @@ byte-size eviction, pinned immunity, clear, search (terms, phrase, type
filter), regex search incl. invalid pattern error, ByteSize parse/format,
SearchQuery.parse, retention, OCR seam (mocked engine stores searchable text),
injected-clock determinism, text analysis (color/case/transform/JWT/epoch),
TextSummaries, ImageFormats, CLI ArgParser/OutputFormatter, and the app's
AppState logic (hover-selection gate, tab→query mapping).
TextSummaries, ImageFormats, QR generation, JSON detection, color format
rendering, backup export/restore round-trip, CLI ArgParser/OutputFormatter,
and the app's AppState logic (hover-selection gate, tab→query mapping).

CI (`.github/workflows/ci.yml`) enforces three gates on every push:
`swift build -Xswiftc -warnings-as-errors`, full `swift test`, and a zero-
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
- **Screenshot OCR & Search** — Apple Vision extracts text from screenshots in the background; search inside images (`⌘F`) or copy text with one click.
- **Global Snippet Expansion** — Assign trigger abbreviations (e.g. `;email`, `!zoom`, `brb`) to saved snippets to auto-expand them anywhere as you type.
- **Permanent Favorites & Snippets** — Bookmark canned replies, email signatures, code snippets, and commands (`⌘S` / `⌘3`).
- **Developer Smart Cards** — Automatic previews and one-click actions for Base64, URL encoding, JWT tokens, and Unix timestamps.
- **Developer Smart Cards** — Automatic previews and one-click actions for Base64, URL encoding, JWT tokens, Unix timestamps, **JSON** (pretty/minify), **QR codes** (scan-to-phone), and **color formats** (HEX/RGB/HSL).
- **Text Case & Encoding Transforms** — Convert text on the fly (`camelCase`, `snake_case`, Base64, URL encode/decode).
- **Smart Color Swatch Detection** — Recognizes `#hex`, `rgb()`, `rgba()`, `hsl()` color codes with live inline circle swatches.
- **Search Match Highlighting** — High-contrast match highlighting across list items and preview pane for terms, phrases, and regex.
Expand Down Expand Up @@ -139,6 +139,7 @@ clap add <text> | - # Insert an entry (alias: clap
echo "piped" | clap add - # Insert from a pipe
clap delete <id> | --text <str> | --regex <pat> # Delete entries (alias: clap out)
clap pin <id> / clap unpin <id> # Pin/unpin entries
clap backup <dir> / clap restore <dir> # Full-history backup & restore
clap clear [--force] # Wipe history (preserves pinned)
clap stats [--json] # Storage and activity metrics
clap config get [key] / set <key> <val> # Manage limits, retention, exclusions
Expand Down
18 changes: 18 additions & 0 deletions Sources/ClapApp/AppState+Pasteboard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ extension AppState {
/// Returns false when an image copy failed (panel stays open so the user
/// sees that nothing happened).
private func writeToPasteboard(_ entry: ClipboardEntry) async -> Bool {
let succeeded = await writeToPasteboardInner(entry)
if succeeded { CopyFeedback.play() }
return succeeded
}

private func writeToPasteboardInner(_ entry: ClipboardEntry) async -> Bool {
let pasteboard = NSPasteboard.general
switch entry.type {
case .text:
Expand Down Expand Up @@ -110,6 +116,18 @@ extension AppState {
return image
}

/// Copies generated image data (e.g. a QR PNG) to the pasteboard. No
/// monitor coordination: the pasteboard monitor captures it as a new
/// image entry, mirroring copyTransformedText's behavior for text.
func copyGeneratedImage(_ data: Data) {
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
if pasteboard.setData(data, forType: .png) {
CopyFeedback.play()
}
IPC.post(.storeChanged)
}

/// Loads the full-resolution image for preview rendering (not cached).
func fullImage(for entry: ClipboardEntry) async -> NSImage? {
guard let url = await store.imageFileURL(for: entry) else { return nil }
Expand Down
13 changes: 13 additions & 0 deletions Sources/ClapApp/CopyFeedback.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import AppKit

/// Sensory confirmation for successful copies: a subtle system sound plus a
/// trackpad haptic tick. Both are best-effort — silence on any failure.
enum CopyFeedback {
private static let sound = NSSound(named: "Pop")

static func play() {
sound?.play()
NSHapticFeedbackManager.defaultPerformer.perform(
.alignment, performanceTime: .now)
}
}
Loading
Loading