UI fixes
Some checks failed
CI / Test And Build (push) Has been cancelled

This commit is contained in:
Akshay Kolli
2026-07-08 01:13:02 -04:00
parent c7316105c7
commit d86d392c3a
46 changed files with 17543 additions and 1561 deletions

View File

@@ -9,9 +9,12 @@ ClipBored is a single-process AppKit utility built with Swift Package Manager.
- `ClipboardMonitorService` polls `NSPasteboard.changeCount` on a utility queue with adaptive active/idle intervals.
- `ClipboardStore` keeps the in-memory item list and persists rows to SQLite on a serial queue.
- `ClipboardCacheService` stores bounded image previews under Application Support and keeps a small `NSCache`.
- `ClipboardCloudSyncService` resolves the app-private iCloud ubiquity container when sync is enabled and pushes or pulls the portable archive file.
- `ShortcutManager` registers Carbon hotkeys for app-wide commands.
- `ClipboardPanelController` owns the bottom panel lifecycle and target-app tracking.
- `ClipboardPanelController` owns the side panel lifecycle, Dock-aware frame planning, configured left/right placement, and target-app tracking.
- `ClipboardPanelViewModel` filters, sorts, selects, copies, pastes, pins, organizes, deletes, opens, and reveals items.
- `LinkPreviewWindowController` opens selected HTTP(S) links in an ephemeral WebKit preview window instead of handing them to another browser.
- `OnboardingWindowController` shows the first-run setup assistant for shortcut, retention, system entry points, launch-at-login, iCloud sync, and Accessibility permission choices.
- `SettingsWindowController` exposes native controls for capture, privacy, performance, shortcuts, and data management.
## Data Flow
@@ -20,7 +23,7 @@ ClipBored is a single-process AppKit utility built with Swift Package Manager.
2. Source app metadata is checked against ignored apps.
3. Pasteboard content is normalized into a `ClipboardItem`.
4. Sensitive text is skipped when exclusion is enabled.
5. Copied images run local Vision OCR only when `Search in image labels` is enabled.
5. Copied images run local Vision OCR only when `Search in image labels` is enabled; image cards can also run the same local OCR on demand from their quick actions.
6. The store deduplicates, preserves pinned and collection-assigned items, enforces limits, and persists the mutation.
7. The panel view model receives store updates and recomputes the visible list.
@@ -46,10 +49,16 @@ Restorable non-image payloads such as audio clips, rich text, and PDFs are store
Legacy JSON import still exists for migration from early builds.
Textual SQLite fields, including optional collection names and image OCR text, are encrypted and decrypted at the `ClipboardStore` boundary. App-managed image cache files, URL preview thumbnails, audio clips, rich text sidecars, and PDF attachments are encrypted and decrypted at the `ClipboardCacheService` boundary. The encryption key is stored in Keychain when available, with an owner-only app-local fallback key if Keychain access blocks or fails. Full history clears remove the local fallback key when present and reset cached key state after SQLite deletion succeeds. Runtime `ClipboardItem` values remain plaintext in memory so search, duplicate detection, copy, paste, organization, and cache cleanup operate normally. Opening or revealing encrypted media creates a temporary decrypted copy for macOS handoff; stale temporary previews are cleared on launch, cache/history clear, and quit.
Portable `.clipboredarchive` files are JSON exports created by `ClipboardArchiveService`. They preserve item metadata and include decrypted bytes for app-managed image, URL-thumbnail, audio, video, rich-text, and PDF sidecars so a different Mac can re-cache them under its own storage directory and encryption key. External file references remain path-based and are not copied into the archive.
Optional iCloud Sync uses that same archive format at `Documents/ClipBored/ClipBored.clipboredarchive` inside the app-private ubiquity container. It is disabled by default, requires a signed build with iCloud entitlement access, pulls once when enabled at launch, and debounces pushes after local store changes. Shared Pinboard collaboration is not implemented.
Textual SQLite fields, including optional collection names and image OCR text, are encrypted and decrypted at the `ClipboardStore` boundary. App-managed image cache files, URL preview thumbnails, audio clips, rich text sidecars, and PDF attachments are encrypted and decrypted at the `ClipboardCacheService` boundary. The encryption key is stored in Keychain when available, with an owner-only app-local fallback key if Keychain access blocks or fails. Full history clears remove the local fallback key when present and reset cached key state after SQLite deletion succeeds. Runtime `ClipboardItem` values remain plaintext in memory so search, duplicate detection, copy, paste, organization, archive export/import, and cache cleanup operate normally. Opening or revealing encrypted media creates a temporary decrypted copy for macOS handoff; stale temporary previews are cleared on launch, cache/history clear, and quit. Link previews are user-triggered and use a non-persistent WebKit data store.
## Size And Power Constraints
The release build intentionally avoids SwiftUI, Combine, Swift Concurrency, third-party packages, bundled media, and app resources beyond `Info.plist`.
The build script uses `-Osize`, whole-module optimization, disabled reflection metadata, linker dead stripping, symbol stripping, and hardened-runtime signing. The current public targets, enforced by `scripts/build-macos-app.sh`, are a 1 MiB executable and a 1.8 MB app bundle.
The side shelf is anchored to the current screen's visible frame and can be placed on the left or right edge. It uses compact horizontal rows in a vertical list; the active or hovered row expands in place while the panel stays clear of side Docks and reserves bottom Dock space for content padding.
The build script uses `-Osize`, whole-module optimization, disabled reflection metadata, linker dead stripping, symbol stripping, and hardened-runtime signing. The current public targets, enforced by `scripts/build-macos-app.sh`, are 2 MiB gates for both the executable and app bundle.

View File

@@ -10,7 +10,7 @@ Run:
./scripts/check.sh
```
This runs the unit test suite, builds `build/ClipBored.app`, applies an ad-hoc hardened-runtime signature, enforces size gates, and verifies the app signature.
This runs the unit test suite, builds `build/ClipBored.app`, applies an ad-hoc hardened-runtime signature, enforces the 2 MiB executable and bundle size gates, and verifies the app signature.
## Local Archive
@@ -40,6 +40,10 @@ export DEVELOPER_ID_APPLICATION="Developer ID Application: Example, Inc. (TEAMID
The script rebuilds the app, re-signs it with hardened runtime and timestamping, verifies the signature, and writes `build/ClipBored.zip`.
## iCloud Sync Entitlements
The default local and release scripts do not add iCloud entitlements. `Sync history with iCloud` will report unavailable in those builds. To ship iCloud Sync, sign with an entitlement file that grants the app's ubiquity container, then repeat the signature, smoke, and notarization checks.
## Notarization
Preferred: configure a notarytool keychain profile once:

View File

@@ -1,6 +1,6 @@
# Roadmap
This roadmap keeps future work aligned with the project's constraints: small executable, low idle power, local-only storage, native macOS UI, and no feature regressions.
This roadmap keeps future work aligned with the project's constraints: small executable, low idle power, local-first storage, native macOS UI, and no feature regressions.
## Near Term
@@ -10,12 +10,14 @@ This roadmap keeps future work aligned with the project's constraints: small exe
## Privacy And Security
- Keep improving secure cleanup semantics for cleared cache/history/key material where macOS storage behavior allows it.
- Keep the current no-network/no-telemetry posture unless the project explicitly changes direction.
- Keep the current no-telemetry posture. Keep remote movement limited to explicit user-controlled sync/export paths.
- Add encrypted archive and iCloud-sync payload options before treating sync archives as safe for high-risk clipboard history.
## Product Polish
- Improve keyboard focus states and VoiceOver labels.
- Add import/export only if the storage and privacy story remains clear.
- Consider optional password-protected archive exports if migration needs outgrow owner-only local archive files.
- Design true shared Pinboard collaboration separately from private iCloud archive sync.
## Performance

View File

@@ -1,10 +1,10 @@
# Security Notes
ClipBored is designed as a local macOS utility. Its primary privacy promise is that clipboard data stays on the machine.
ClipBored is designed as a local-first macOS utility. Its default privacy promise is that clipboard data stays on the machine unless iCloud Sync is explicitly enabled.
## Current Protections
- No networking or telemetry in production source.
- No telemetry or background networking in production source.
- No shell/process execution.
- No Apple Events scripting.
- Hardened runtime is applied by the local build script, and the release script supports Developer ID signing plus notarization when credentials are configured.
@@ -14,7 +14,10 @@ ClipBored is designed as a local macOS utility. Its primary privacy promise is t
- If Keychain access blocks or fails, ClipBored uses an owner-only app-local fallback key so clipboard capture and persistence continue without a Keychain UI stall.
- Full history clears remove the app-local fallback key when present and reset cached key state after the database clear succeeds.
- App-owned storage directories are restricted to the current user, and saved history/cache files are written with owner-only permissions where the filesystem supports POSIX modes.
- Archive exports are written with owner-only permissions where supported.
- iCloud Sync is off by default and uses the app-private ubiquity container only when entitlement access is available.
- ClipBored marks its own pasteboard writes so copy/paste actions from history are not re-captured as new clipboard events.
- The clipboard panel can be configured to opt out of screenshots, screen sharing, and screen recordings.
- Sensitive-content exclusion can skip common high-risk values:
- private key blocks
- bearer tokens
@@ -37,10 +40,14 @@ ClipBored is designed as a local macOS utility. Its primary privacy promise is t
- The app-local fallback key prevents plaintext app-managed history/media files, but it does not protect against a process or user account that can read the full ClipBored Application Support directory before history is cleared.
- Thumbnailing, opening, or revealing encrypted images, audio clips, video clips, or PDFs creates temporary decrypted preview files so macOS can hand them to system media APIs or other apps. ClipBored clears stale preview files on launch, cache/history clear, and quit.
- Existing plaintext SQLite rows and legacy sidecar files are migrated when encryption becomes available, but system snapshots, backups, live temporary previews, or filesystem remnants may retain older plaintext copies.
- Portable `.clipboredarchive` files and iCloud sync archives are not encrypted by ClipBored. They include recoverable clipboard metadata and app-managed attachment bytes so they can be imported on another Mac; store and transmit them like sensitive backups.
- iCloud Sync relies on the user's private iCloud account and Apple's ubiquity container transport/storage. ClipBored does not add end-to-end archive encryption, conflict resolution beyond whole-archive import, or shared Pinboard access control.
- The local development build is ad-hoc signed; use `scripts/release-macos-app.sh` with Developer ID credentials for notarized distribution builds.
- Accessibility permission is required for automatic paste simulation.
- Screen-sharing privacy applies to ClipBored's panel window, not to other apps, system clipboard state, or filesystem history.
- Sensitive-content detection is heuristic and can miss novel formats or produce false positives.
- Local image OCR is opt-in through `Search in image labels`; recognized text stays local but can still contain sensitive clipboard-derived content.
- Automatic local image OCR is opt-in through `Search in image labels`; users can also run local OCR explicitly from an image card. Recognized text stays local but can still contain sensitive clipboard-derived content.
- User-triggered link preview loads the selected HTTP(S) URL in a non-persistent WebKit view. The destination site can still receive the request and normal browser-visible metadata for that preview load.
- Local filesystem access by another process or user account with sufficient permissions can expose metadata, fallback keys, and live temporary decrypted previews.
## Release Hardening Checklist
@@ -50,5 +57,5 @@ ClipBored is designed as a local macOS utility. Its primary privacy promise is t
- Verify `codesign --verify --deep --strict --verbose=2 build/ClipBored.app`.
- Verify hardened runtime appears in `codesign -d --verbose=4 build/ClipBored.app`.
- For distribution, verify `xcrun stapler validate build/ClipBored.app` and `spctl --assess --type execute --verbose=4 build/ClipBored.app`.
- Confirm no new `URLSession`, process execution, Apple Events, telemetry, or remote sync APIs were introduced.
- Confirm no new `URLSession`, process execution, Apple Events, or telemetry APIs were introduced; keep WebKit use limited to explicit link preview and keep sync limited to app-private iCloud ubiquity APIs.
- Review any new persistence paths for unencrypted sensitive data.

View File

@@ -12,18 +12,20 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
2. Quit any running ClipBored copy.
3. Open `build/ClipBored.app`.
4. Confirm ClipBored appears in the menu bar when `Show ClipBored in the menu bar` is enabled.
4. With a fresh preferences profile, confirm the setup assistant appears before the clipboard panel; choose the open shortcut, Keep History retention, menu-bar/Dock presence, launch-at-login, iCloud sync, and Accessibility option, then finish setup.
5. Reopen ClipBored and confirm the setup assistant does not reappear.
6. Confirm ClipBored appears in the menu bar when `Show ClipBored in the menu bar` is enabled.
## Capture
1. Copy plain text from TextEdit, Notes, or a browser.
2. Open the panel with `Command + Option + V`.
2. Open the panel with the configured open shortcut.
3. Confirm the copied text appears in Most Recent.
4. Copy a URL and confirm it appears as a Link; if the source provides a local preview image, confirm the Link card uses that preview.
5. Copy an image and confirm it appears as an Image with a thumbnail.
4. Copy a URL and confirm it appears as a Link with a browser-style site preview; if the source provides a local preview image, confirm the Link card uses that image preview instead and that tall shelves give the preview more room.
5. Copy an image and confirm it appears as an Image with a thumbnail and a centered dimension overlay.
6. Enable `Search in image labels`, copy an image containing readable text, and confirm searching for that text finds the Image.
7. Copy a sound clip and confirm it appears as Audio.
8. Copy a movie or video clip and confirm it appears as Video.
7. Copy a sound clip and confirm it appears as Audio with an album-style artwork tile.
8. Copy a movie or video clip and confirm it appears as Video with a player-style preview and centered format pill.
9. Copy a PDF or PDF selection and confirm it appears as a PDF.
10. Copy one Finder file and confirm it appears as a File.
11. Copy multiple Finder files at once and confirm they appear as one grouped File item with the file count.
@@ -34,44 +36,54 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
1. Open the panel and confirm the search field is focused.
2. Type a query and confirm results filter immediately.
3. Type a structured query such as `pinboard:"Client Work","Read Later" type:image,pdf` and confirm only clips from those collections and content types remain.
4. Clear the search field, press `Space`, and confirm the selected previewable clip opens in Quick Look instead of inserting a blank query.
3. Press `Command + F` to focus search, press it again to show filters, then add Type, Device, and Pinboard filters and confirm they appear as structured tokens. Type a structured query such as `pinboard:"Client Work","Read Later" type:image,pdf device:<part of this Mac's name>` and confirm only clips from those collections, content types, and the copied-on Mac remain.
4. Clear the search field, press `Space`, and confirm a selected web link opens in ClipBored's built-in browser preview while non-link previewable clips open in Quick Look instead of inserting a blank query.
5. Use arrow keys to move selection while the search field is focused.
6. Tab to collection chips and press `Space` or `Return`; confirm the focused chip is selected and the visible focus state is clear. Use Left/Right, Home, and End to move through the chip rail, including custom collections and Stack when present.
7. Tab to cards; confirm the focused card gets a clear focus border, `Return` pastes or copies it, and `Space` opens Quick Look for text, links, files, and media.
8. With a card focused, use Left/Right, Page Up/Page Down, Home, and End; confirm selection and focus move together across the shelf.
9. With a card or collection chip focused, type a normal character and confirm focus returns to search with that character inserted and results filtered.
10. Use a mouse wheel or two-finger vertical scroll over the card shelf and a crowded collection rail; confirm each pans horizontally, clamps at both ends, and shows subtle edge fades only where more content is hidden.
11. Right-click a filtered result and choose Show in Clipboard, or press `Command + G`, and confirm search clears while the same card stays selected in Most Recent.
12. Press `Esc` once with a non-empty search while the search field, a card, or a collection chip is focused and confirm search clears without closing the panel.
13. Press `Esc` again and confirm the panel closes.
14. Reopen the panel, change sort segments, and confirm each segment updates results.
15. Press `Shift + Command + N` or the collection rail `+`, enter `Client Work`, choose a color, and confirm a Client Work chip appears with 0 clips and an empty collection view.
16. Return to Clipboard, select a card, use its Collect button to choose Client Work, and confirm the Client Work chip count increases.
17. Select the Client Work chip and confirm the rail filters to assigned items, cards use the Client Work name/color in their headers, and the collection/color/assignment persists after quitting and reopening ClipBored.
18. Right-click the Client Work chip, choose Edit Collection..., rename it, change its color, and confirm the chip and assigned card headers update.
19. Confirm collection chips with 0 clips do not show a visible count pill, while chips with clips still show their counts.
20. Right-click a media, file, link, PDF, audio, or text card, choose Rename..., give it a title, and confirm the card title and search results use the custom title while paste/copy still uses the original payload.
21. Double-click an item and confirm it attempts to paste or falls back to copy without creating a duplicate history entry.
22. Right-click a card, use Capture Rules to ignore its source app, copy from that app again, and confirm the new item is skipped.
23. Drag an unassigned card onto the renamed collection chip and confirm the chip count increases and the card appears when that collection is selected.
24. Resize or test on a narrow display and confirm the bottom shelf switches to compact cards that still show two recent clips cleanly.
25. Select a file, rich text, or URL card and confirm the selected-card rail exposes `Paste Plain Text`, the corner source/kind badge remains visible, and on a narrow shelf secondary actions collapse behind `More` instead of overflowing the card.
26. Confirm card footers do not show `Unknown` for clips without a source app, and confirm used clips show their usage count beside the source app.
27. Confirm card headers use readable relative ages such as `3 minutes ago` or `2 hours ago`, including when viewing a named collection.
28. Confirm the selected card shows a green corner Stack control, the action rail does not duplicate Stack, and clips added to Stack keep a visible corner indicator when selection moves away.
29. Confirm single-line text cards do not repeat the same text in both title and body, while multi-line text cards show the remaining lines below the first line.
30. Confirm the Pinned empty state points to the Pin action instead of a plain-key shortcut.
31. Confirm each card's source or type badge reads as an attached header-corner tile instead of a small floating icon.
32. Confirm built-in collection chips use recognizable glyphs, while custom collection chips keep color-dot swatches.
33. Confirm cards from known apps show app identity in the header tile, falling back to source initials when an app icon is unavailable.
34. Confirm multi-file cards show a stacked file preview, while single-file cards keep the regular file layout.
35. Confirm the shelf chrome uses one row with compact search, collection chips, and utility buttons; typing a search expands the search field without pushing cards out of view.
36. Copy a color swatch from a design tool and confirm it appears as a Color card, can be filtered with the Colors chip, and copies back as both a color and hex text.
37. Copy a code snippet from an editor and confirm it appears as a Code card, remains visible in the Text chip, can be isolated with the Code chip or `type:code`, and copies back as plain text.
38. Copy a video/movie clip and confirm it appears as a Video card, uses a movie-frame thumbnail when available, filters with the Videos chip or `type:video`, `type:movie`, and `mp4`, previews/opens as a temp movie, and copies back as movie data.
39. Filter to a few clips, right-click a card or the Stack chip, choose Add Visible Clips to Stack, and confirm only the visible clips are queued once in shelf order.
40. With multiple text-like clips in Stack, choose Copy Stack as Text or Paste Stack as Text and confirm the queued text is written in stack order with blank lines between clips and consumed from Stack.
6. Tab to the search controls, collection `+`, toolbar buttons, and collection chips; confirm VoiceOver help explains the matching actions and shortcuts. Press `Space` or `Return` on a focused chip and confirm it is selected and the visible focus state is clear. Use Left/Right, Home, and End to move through the chip rail, including custom collections and Stack when present, and confirm VoiceOver help mentions those keys plus Pinboard/Stack context actions where available.
7. Tab to cards; confirm the focused card gets a clear focus border, `Return` pastes or copies it, `Command + C` copies it, `Shift + Return` and `Command + Shift + V` paste or copy it as plain text, and `Space` or `Command + Y` opens the built-in browser for web links or Quick Look for text, files, and media.
8. With a card focused, press `Command + F` and confirm focus returns to search; press `Command + E` on a text/code clip and confirm the edit dialog opens. On a Mac with Writing Tools available, confirm the dialog offers Writing Tools and keeps the saved clip as plain text. Press `Command + R` and confirm the rename dialog opens.
9. With a card focused, use Left/Right, Page Up/Page Down, Home, End, `Command + Up`, and `Command + Down`; confirm selection and focus move together across the shelf. Select two clips, press `Delete`, confirm both disappear, then press `Command + Z` and confirm both return selected.
10. With a card or collection chip focused, type a normal character and confirm focus returns to search with that character inserted and results filtered.
11. Use a mouse wheel or two-finger vertical scroll over the card shelf and a crowded collection rail; confirm each pans horizontally, clamps at both ends, and shows subtle edge fades only where more content is hidden, with collection-chip labels fading cleanly instead of hard-clipping at the utility buttons.
12. Right-click a filtered result and choose Show in Clipboard, or press `Command + G` with the result card focused, and confirm search clears while the same card stays selected in Most Recent. Press `Command + O` on a focused link, file, or media card and confirm it opens.
13. Press `Esc` once with a non-empty search while the search field, a card, or a collection chip is focused and confirm search clears without closing the panel.
14. Press `Esc` again and confirm the panel closes.
15. Reopen the panel, change sort segments, and confirm each segment updates results.
16. Press `Shift + Command + N` or the collection rail `+`, enter `Client Work`, choose a color, and confirm a Client Work chip appears with 0 clips and an empty collection view.
17. Press `Command + N` or the shelf pencil button, enter text, and confirm a new text clip appears selected in the active shelf; on a Mac with Writing Tools available, confirm the new-text dialog offers Writing Tools. Repeat while Client Work is selected and confirm the clip is created in that collection.
18. Return to Clipboard, select a card, use its Collect button to choose Client Work, and confirm the Client Work chip count increases.
19. Select the Client Work chip and confirm the rail filters to assigned items, cards use the Client Work name/color in their headers, and the collection/color/assignment persists after quitting and reopening ClipBored. Confirm collection-assigned clips stay in Client Work even as normal clipboard history rolls over.
20. Create a second collection, then press `Command + Right` and `Command + Left`; confirm selection moves between collections and wraps around.
21. Right-click the Client Work chip, choose Edit Collection..., rename it, change its color, and confirm the chip and assigned card headers update.
22. Right-click a custom Pinboard chip, choose Export Pinboard..., save a `.clipboredarchive`, import it into a fresh test profile from Settings > Data, and confirm only that Pinboard's clips, empty Pinboard state, and color are restored.
23. Confirm collection chips with 0 clips do not show a visible count pill, while chips with clips still show their counts.
24. Right-click a media, file, link, PDF, audio, or text card, choose Rename..., give it a title, and confirm the card title and search results use the custom title while paste/copy still uses the original payload.
25. Right-click an image card or focus its action rail, choose `Rotate Image`, and confirm the preview updates while the title, Pinboard, source app, and searchable image text remain. Then choose `Extract Text` on an image containing text and confirm the card shows the extracted text and `Copy Plain Text` can copy it.
26. Double-click an item and confirm it attempts to paste or falls back to copy without creating a duplicate history entry.
27. Right-click a card, use Capture Rules to ignore its source app, copy from that app again, and confirm the new item is skipped.
28. Drag an unassigned card onto the renamed collection chip and confirm the chip count increases and the card appears when that collection is selected.
29. Open the panel and confirm it appears as a vertical side shelf with compact horizontal rows; hover a row and confirm it expands in place. On a multi-display setup, open from the global shortcut with the pointer on each display and confirm the shelf opens on that display; click the menu-bar icon and confirm it opens on the menu-bar icon's display. Switch Spaces or use a full-screen app and confirm the shelf opens on the active Space instead of following every desktop.
30. Switch Settings > General > Panel > Shelf side between Left and Right. Reopen the panel after each change and confirm it slides from the configured side and keeps the category row centered.
31. Select a file, rich text, or URL card, then hover or keyboard-focus it and confirm the action rail exposes `Paste Plain Text`, the corner source/kind badge remains visible, and on a narrow shelf secondary actions collapse behind `More` instead of overflowing the card.
32. Confirm card footers do not show `Unknown` for clips without a source app, confirm used clips show their usage count beside the source app, and confirm clips synced or imported from another Mac show that copied-on device in the footer.
33. Confirm card headers use readable relative ages such as `3 minutes ago` or `2 hours ago`, including when viewing a named collection.
34. Confirm the selected card shows a green corner Stack control, the hover/focus action rail does not duplicate Stack, and clips added to Stack keep a visible corner indicator when selection moves away.
35. Confirm text cards use a quiet paper-style body, single-line text cards do not repeat the same text in both title and body, and multi-line text cards show the remaining lines below the first line with a subtle bottom fade.
36. Confirm the Pinned empty state points to the Pin action instead of a plain-key shortcut.
37. Confirm each card's source or type badge reads as an attached header-corner tile instead of a small floating icon.
38. Confirm built-in collection chips use recognizable glyphs, while custom collection chips keep color-dot swatches.
39. Confirm cards from known apps show app identity in the header tile, falling back to source initials when an app icon is unavailable.
40. Confirm single-file and PDF cards show a centered document-cover preview with a file-type pill, while multi-file cards show a stacked file preview.
41. Confirm the shelf chrome uses one row with compact search, collection chips, and separate soft utility icon buttons instead of a heavy grouped block; typing a search expands the search field without pushing cards out of view.
42. Confirm the top collection rail reads as a quiet translucent strip, the selected collection is a subtle pill, and the active card visibly floats above neighboring cards while the rest stay docked in the shelf.
43. Copy a color swatch from a design tool and confirm it appears as a centered paint-chip Color card, can be filtered with the Colors chip, and copies back as both a color and hex text.
44. Copy a code snippet from an editor and confirm it appears as a Code card, remains visible in the Text chip, can be isolated with the Code chip or `type:code`, and copies back as plain text.
45. Copy a video/movie clip and confirm it appears as a Video card, uses a movie-frame thumbnail when available, filters with the Videos chip or `type:video`, `type:movie`, and `mp4`, previews/opens as a temp movie, and copies back as movie data.
46. Press `Shift + Command + C`, confirm the Stack chip appears active with 0 clips, copy two text snippets, and confirm Stack count increments and the Stack view shows them in copy order. Press `Shift + Command + C` again and confirm capture stops.
47. Filter to a few clips, right-click a card or the Stack chip, choose Add Visible Clips to Stack, and confirm only the visible clips are queued once in shelf order.
48. With multiple text-like clips in Stack, choose Copy Stack as Text or Paste Stack as Text and confirm the queued text is written in stack order with blank lines between clips and consumed from Stack.
49. Command-click non-adjacent cards and Shift-click a range; confirm the status count changes to selected clips, selected cards remain highlighted while hovering, and the card menu offers Paste Selection, Copy Selection, Paste Selection as Text, Copy Selection as Text, and Add Selection to Stack.
50. With a card focused, press `Shift` with Left/Right, Page Up/Page Down, Home, or End to extend the range, then press `Command + A` and confirm every visible card is selected without changing the active card.
## Copy And Paste
@@ -89,12 +101,15 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
## Settings
1. Open Settings with `Command + ,`.
2. Change history length, default sort, polling profile, cache limit, ignored apps, and allowed content types; quit and reopen the app; confirm settings persist.
2. Change Shelf side, Keep History, history length, default sort, polling profile, cache limit, ignored apps, and allowed content types; quit and reopen the app; confirm settings persist.
3. Change the open-panel shortcut and confirm the old shortcut no longer opens the panel and the new shortcut does.
4. Toggle `Pause clipboard capture`, copy text, and confirm paused capture does not record it.
4. Toggle `Pause clipboard capture` or press `Command + T`, copy text, and confirm paused capture does not record it; press `Command + T` again and confirm capture resumes.
5. Toggle `Exclude likely secrets`, copy a representative token, and confirm it is not recorded.
6. Use `Open Accessibility Settings` and confirm System Settings opens to the permission area or fallback settings app.
7. Use `Clear Clipboard History` and `Clear Thumbnail Cache`; confirm each shows a warning confirmation before deleting data.
6. Toggle `Hide panel from screen sharing and recordings`, open the clipboard panel, and confirm it is omitted from a macOS screenshot or screen recording; disable it and confirm capture works normally again.
7. Use `Open Accessibility Settings` and confirm System Settings opens to the permission area or fallback settings app.
8. Use Settings > Data > `Export Archive...`, save a `.clipboredarchive`, then import it into a fresh or cleared test profile and confirm text, Pinboard assignments, image previews, and PDF/audio/video/rich-text clips reappear; confirm external file-reference clips still point at their original paths.
9. In an ad-hoc local build, turn on Settings > Data > `Sync history with iCloud` and confirm the status reports iCloud Sync unavailable. In a signed build with an iCloud entitlement, use `Sync Now`, then restore into a fresh test profile and confirm text, Pinboard assignments, and app-managed attachments reappear.
10. Use `Clear Clipboard History` and `Clear Thumbnail Cache`; confirm each shows a warning confirmation before deleting data.
## Storage And Privacy
@@ -102,18 +117,21 @@ Use this checklist before a release or after changes to panel, pasteboard, setti
2. Confirm `history.sqlite` exists after capture.
3. Copy unique text and confirm `strings ~/Library/Application\ Support/ClipBored/history.sqlite | grep "unique text"` does not find it.
4. Copy uniquely identifiable rich text/audio/video/PDF data and confirm `strings ~/Library/Application\ Support/ClipBored/attachments/* | grep "unique text"` does not find it.
5. If `history-encryption.key` exists, confirm it is readable only by the current user.
6. Confirm image files are under `images/` and rich text/audio/video/PDF attachments are under `attachments/`.
7. Confirm app storage is local to `~/Library/Application Support/ClipBored`.
8. Open or reveal an encrypted image/audio/video/PDF, then quit ClipBored and confirm `/tmp/ClipBored/Previews` is removed.
9. Use `Clear Clipboard History` and confirm saved history, app-managed attachments, temporary previews, and `history-encryption.key` are removed when that fallback key exists.
10. Confirm quitting with `Clear history on quit` enabled removes history and app-managed cache/attachment files.
5. Export an archive with unique test content and confirm the archive file is treated as sensitive backup material because it is portable and not encrypted by ClipBored.
6. If iCloud Sync is enabled in a signed build, confirm `ClipBored.clipboredarchive` in the app-private iCloud container is treated as sensitive backup material because it is portable and not encrypted by ClipBored.
7. If `history-encryption.key` exists, confirm it is readable only by the current user.
8. Confirm image files are under `images/` and rich text/audio/video/PDF attachments are under `attachments/`.
9. Confirm app storage is local to `~/Library/Application Support/ClipBored` when iCloud Sync is off.
10. Open or reveal an encrypted image/audio/video/PDF, then quit ClipBored and confirm `/tmp/ClipBored/Previews` is removed.
11. Use `Clear Clipboard History` and confirm saved history, app-managed attachments, temporary previews, and `history-encryption.key` are removed when that fallback key exists.
12. Confirm quitting with `Clear history on quit` enabled removes history and app-managed cache/attachment files.
## Launch And Lifecycle
1. Enable Launch at Login, log out and back in, and confirm ClipBored starts.
2. Disable Launch at Login and confirm it no longer starts after the next login.
3. Right-click the menu-bar icon and confirm the status menu opens with capture state, clip count, Show Clipboard, Settings, Pause/Resume Capture, and Quit.
3. Right-click the menu-bar icon and confirm the status menu opens with capture state, clip count, Show Clipboard, Settings, Pause/Resume Capture, Pause for 5 Minutes, Pause for 30 Minutes, Pause for 1 Hour, and Quit.
4. Control-click the menu-bar icon and confirm the same status menu opens without toggling the panel.
5. Toggle Pause/Resume Capture from the status menu and confirm the status row changes.
6. Quit ClipBored from the menu bar and confirm no `ClipBored` process remains.
5. Choose `Pause for 5 Minutes`, confirm the status detail shows a timed pause and copied text is not recorded, then choose `Resume Capture`.
6. Toggle manual Pause/Resume Capture from the status menu and confirm the status row changes.
7. Quit ClipBored from the menu bar and confirm no `ClipBored` process remains.

11
docs/thingstofix.md Normal file
View File

@@ -0,0 +1,11 @@
1. When hovering over a copied item, the options that appear on hover obscure the text.
2. When hovering over an item, key board arrow navigation breaks.
3. There needs to be some kind of animation? or smooothening effect when switching categories.
4. The search bar is broken when compressed, and clicking elsewhere should compress it again.
5. The search filter should just be the categories selected. Select categories with cmd.
6. There're a lot of categories, if there's nothing in them, don't show the categories by default.
7. There is a resize bar at the top lip of the window, don't bother with it. it doesn't allow resizing anywa.yz
8. Get rid of new text clip button. Don't need it.
9. Get rid of compact mode.
10. Get rid of close window. Don't need it. We use the macro from the keyboard.
11. Get rid of the status bar.