Skip to content

fix: vertical-text regression, toggle chevron clicks, thumbnail click reliability - #1

Merged
rikiyanai merged 1 commit into
masterfrom
fix/toggle-screenshot-ux
Jul 20, 2026
Merged

rikiyanai merged 1 commit into
masterfrom
fix/toggle-screenshot-ux

Conversation

@rikiyanai

@rikiyanai rikiyanai commented Jul 20, 2026 •

Copy link
Copy Markdown
Owner

Fixes and UX polish on the toggle lists + screenshot sidebar feature:

  • no-wrap regression: disable widthTracksTextView before setting containerSize (timing-dependent race clamped the container to 10pt -> one character per line), plus a self-healing guard in updateWidth()
  • toggle lists: start expanded on creation, inserted placeholder title is 'Toggle', chevron gutter moved into the container view (NSScrollView drops hit-testing for custom subviews, so chevron clicks were silently lost)
  • screenshots: watch the Cmd+Shift+3/4 save folder, content-hash dedup (no duplicates on re-copy), sidebar hidden by default, file path under each entry, click copies the path, 4px drag threshold (jittered clicks were swallowed as micro-drags), clickCount from the event (currentEvent crashes on non-mouse events)

Full root-cause trail in docs/FAILURE_LOG.md (2026-07-21).


Note

Medium Risk
Touches core NSTextView layout (no-wrap), toggle rendering/hit-testing, and screenshot import/dedup; regressions could break editing UX or miss captures, but changes are localized AppKit UI with documented mitigations.

Overview
Fixes a timing-dependent no-wrap regression where widthTracksTextView had to be turned off before setting infinite containerSize; otherwise the text container collapsed to ~10pt and every line wrapped at one character. Adds a self-healing guard in updateWidth() and documents the root cause in docs/FAILURE_LOG.md.

Toggle lists now treat the selection as the body with the line above as title (or insert Toggle), start expanded, enable Toggle List for any non-empty selection, and add a MarkerGutterView chevron gutter in the container (not inside NSScrollView) so collapse clicks actually hit-test.

Screenshot sidebar defaults hidden, reloads when the popover opens, watches pasteboard + macOS screenshot folder with stable-file import, FNV-1a dedup, path labels under thumbs, single-click copies file path (not image), double-click inserts markdown, 4px drag threshold so clicks aren’t swallowed, and click count from mouseUp instead of NSApp.currentEvent.

Reviewed by Cursor Bugbot for commit 62f102b. Bugbot is set up for automated code reviews on this repo. Configure here.

… reliability

- no-wrap: disable widthTracksTextView before setting containerSize
  (timing-dependent race clamped container to 10pt -> 1 char per line),
  plus self-healing guard in updateWidth()
- toggles: start expanded, inserted title 'Toggle', chevron gutter moved
  to container view (NSScrollView drops custom-subview hit-testing)
- screenshots: watch Cmd+Shift+3/4 save folder, content-hash dedup,
  sidebar off by default, path labels, click copies file path,
  4px drag threshold (jitter clicks were swallowed as micro-drags),
  clickCount passed from event (currentEvent crashes on non-mouse events)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 4 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 62f102b. Configure here.

Comment thread TermiNotesAppKit.swift
if let prev = pendingSizes[name], prev == size, size > 0 {
knownFiles.insert(name)
pendingSizes.removeValue(forKey: name)
importFile(at: url)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Desktop import marked too early

Medium Severity

In checkWatchDir, each screenshot filename is added to knownFiles before importFile(at:) runs. If reading the file or copying into the app screenshots directory fails, that name stays marked as handled and the watcher never retries, so the image never appears in the sidebar.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 62f102b. Configure here.

Comment thread TermiNotesAppKit.swift
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd-HHmmss"
let stamp = fmt.string(from: Date())
let stamp = Self.timestamp(for: Date())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hash stored before PNG saved

Medium Severity

checkPasteboard inserts the image content hash into knownHashes before data.write(to:) succeeds. A failed write leaves the hash recorded with no sidebar file, so later pasteboard copies of the same screenshot are treated as duplicates and ignored.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 62f102b. Configure here.

Comment thread TermiNotesAppKit.swift
n += 1
}
try? FileManager.default.copyItem(at: url, to: dest)
onCapture?(dest)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hash before copy completes

Medium Severity

importFile adds the content hash to knownHashes before copyItem(at:to:) finishes. If the copy fails, the hash remains and the desktop file was already marked in knownFiles, so that screenshot cannot be imported later.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 62f102b. Configure here.

Comment thread TermiNotesAppKit.swift
self?.check()
self?.checkPasteboard()
self?.checkWatchDir()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dedup race at startup

Low Severity

ScreenshotWatcher.start() loads existing image hashes on a background queue while the one-second timer begins polling the pasteboard immediately. A clipboard capture in that window can pass dedup before those hashes are merged on the main thread, creating duplicate sidebar entries for the same image.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 62f102b. Configure here.

@rikiyanai
rikiyanai merged commit 3a3afa9 into master Jul 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant