feat: graph view overhaul, Windows focus-loss fix, Cmd+/ shortcuts, welcome revamp (v0.5.3)#56
Conversation
…elcome revamp (v0.5.3)
|
Warning Review limit reached
More reviews will be available in 49 minutes and 20 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more credits in the billing tab to continue. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughPaperCache v0.5.3 adds Rust-backed reminders and timers, rewrites the graph view as a lazy-loaded 3D WebGL view, and updates shortcut, onboarding, window, and release metadata flows. It also adds timer UI/store state, toast notifications, a regex-based editor plugin, and versioned onboarding and documentation updates. ChangesDesktop feature rollout
Sequence Diagram(s)sequenceDiagram
participant TimersPage
participant useTimerStore
participant tauriApi
participant notifications_rs
participant AppStore
participant OSNotification
TimersPage->>useTimerStore: addTimer(durationMs, label)
TimersPage->>tauriApi: scheduleTimer(id, durationMs, label)
tauriApi->>notifications_rs: invoke schedule_timer
notifications_rs-->>OSNotification: show timer notification
notifications_rs-->>TimersPage: emit timer-complete(id)
TimersPage->>useTimerStore: completeTimer(id)
TimersPage->>AppStore: addToast(success message)
sequenceDiagram
participant useReminders
participant tauriApi
participant notifications_rs
participant AppStore
participant localStorage
useReminders->>tauriApi: scheduleReminders(reminders)
tauriApi->>notifications_rs: invoke schedule_reminders
notifications_rs-->>notifications_rs: spawn delayed reminder tasks
notifications_rs-->>useReminders: emit reminder-fired(key)
useReminders->>localStorage: store notified key
useReminders->>AppStore: addToast(reminder message)
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (1)
src/hooks/useReminders.test.ts (1)
97-126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the toast side effect in the fired-reminder test too.
This hook now does two user-visible things on
reminder-fired: it persists the notified key and it pushes an in-app toast. The current test only checks localStorage, so the toast path can break without coverage catching it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/hooks/useReminders.test.ts` around lines 97 - 126, The reminder-fired test in useReminders only verifies persistence in localStorage and misses the toast side effect. Update the test around useReminders and the captured reminder-fired callback to also assert that the in-app toast path is triggered, mocking or spying on the toast notification helper used by the hook. Keep the existing notified key assertion and add a clear expectation that the toast is shown when the event is received.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@AUDIT_LOG.md`:
- Line 33: The audit log has a duplicate heading that triggers MD024 and creates
ambiguous anchors. Update the repeated “2026-06-24 - (Uncommitted)” section in
AUDIT_LOG.md so each heading is unique, either by renaming the second heading or
merging its content into the existing section. Keep the section structure
consistent with the surrounding date-based headings.
In `@CHANGELOG.md`:
- Around line 40-43: Move the four feature bullets currently listed under the
v0.5.2 changelog entry into the v0.5.3 section so the release history matches
this PR’s scope. Update the relevant release headings in CHANGELOG.md and keep
the existing feature wording intact while relocating the entries for Native OS
Reminder Notifications, Countdown Timers, DSL Regex Parsing Engine, and WebGL
Graph View under the correct version block.
In `@src-tauri/src/commands/notifications.rs`:
- Around line 101-132: The timer replacement logic in the notifications command
is not atomic: the old handle is removed from timer_handles before the new
tokio::spawn handle is inserted, which lets cancel_timer miss the new timer and
leave it running. Update the timer registration flow in the affected timer
scheduling function so cancellation of any existing handle and insertion of the
new handle happen within one write-lock critical section on state.timer_handles,
using the existing id and handle management in notifications.rs.
- Around line 33-74: The reminder replacement logic in the schedule_reminders
flow is not atomic because the existing handles are drained before the new
reminder tasks are inserted into reminder_handles, allowing cancel_all_reminders
or another schedule_reminders call to race and leave orphaned tasks running.
Update the schedule_reminders handling so the new tokio::spawn handles are
created first and then swapped into state.reminder_handles under a single write
lock, replacing the old set in one operation and ensuring any overlapping
cancel/replace call cannot miss newly scheduled reminders.
In `@src-tauri/src/lib.rs`:
- Around line 83-104: The blur handling in the Focused(false) branch still uses
a one-shot boolean delay, so it can hide the window after the first 200ms even
if focus keeps changing. Update the logic in the tauri::WindowEvent::Focused
handler to use a generation counter or another cancelable/debounced mechanism
instead of pending + a spawned sleeper, so each new unfocus supersedes any
earlier hide task. Make sure only the latest unfocus event in the w/w2 path is
allowed to call hide(), and keep the is_dialog_open guard intact.
In `@src/App.tsx`:
- Around line 61-67: The auto-dismiss logic in the useEffect inside App.tsx is
rescheduling timers for every toast whenever the toasts array changes, which
resets older toasts’ lifetimes. Update the toast lifecycle handling so each
toast is timed independently when it is added, and only that toast’s timer is
created/cleared by removeToast or the toast creation path. Use the existing
App/toasts/removeToast flow to locate the effect and refactor it so later list
changes do not recreate timers for already-visible toasts.
In `@src/components/TimersPage.tsx`:
- Around line 160-183: The timer creation flow in handleCreate and handlePreset
keeps a local timer even if window.electronAPI.scheduleTimer fails because
addTimer() is called first and the returned promise is ignored. Update
TimersPage so scheduleTimer is awaited and errors are handled; either call
addTimer only after a successful backend schedule, or remove/rollback the timer
entry if scheduling rejects. Keep handleRemove unchanged except for any needed
consistency with the new success/failure flow.
In `@src/GraphView.tsx`:
- Around line 384-397: The Escape/close affordance is inconsistent in GraphView:
the button labeled Esc still triggers the graph-level onClose even when search
is open. Update the button behavior in GraphView so its click handler mirrors
the Escape key logic by closing search when showSearch is true and only calling
onClose when search is not open. Keep the existing showSearch conditional label
and wire the button action to the same state-based close path used for keyboard
Escape handling.
- Around line 144-180: The force setup in GraphView can run before ForceGraph3D
has mounted because it is wrapped in Suspense, so fgRef.current may be null and
the forces never get applied on the initial open. Update the useEffect in
GraphView to retry or defer the force configuration until the ref is ready, and
keep the existing d3Force setup for centerX, centerY, folderX, folderY, charge,
and collision inside that ready check so the simulation is reheated once the
graph instance exists.
- Around line 196-204: The 3D focus flow in focusOnNode uses the wrong API by
calling centerAt and delaying cameraPosition, which is unnecessary for
ForceGraph3D. Update focusOnNode to use fg.cameraPosition directly to move the
camera to the target node, and remove the centerAt call and the setTimeout
wrapper so the search focus happens immediately and consistently.
In `@src/hooks/useGlobalHotkey.ts`:
- Around line 131-139: The generated slash-commands note is stale because it
omits the new /timer entry. Update the shortcuts markdown content produced by
useGlobalHotkey so the Slash Commands list includes /timer alongside the
existing /ai, /check, /task, /var, /globvar, and /ctx items, keeping the
generated Shortcuts.md note in sync with the available commands.
In `@src/hooks/useReminders.ts`:
- Around line 48-56: Serialize reminder updates in useReminders so overlapping
scheduleReminders calls cannot overwrite a newer reminder snapshot with stale
data. Update the useEffect path that builds pending from
collectFutureReminders(notes) and invokes window.electronAPI.scheduleReminders
to queue requests or attach a monotonically increasing version/token, and only
let the latest call win before prevNotesRef.current is advanced.
- Around line 59-87: The useEffect in useReminders still leaks the
reminder-fired listener when cleanup runs before listen() resolves, causing
duplicate handlers on remount. Add a disposed flag inside the effect, set it
during the return cleanup, and in the listen<string>('reminder-fired', ...)
promise resolution (where unlisten is assigned) immediately call the returned
unsubscriber if the effect has already been cleaned up; keep the existing
cleanup calling unlisten?.() and window.electronAPI.cancelReminders().
In `@src/lib/editor/dslPlugin.ts`:
- Around line 66-87: The match loop in dslPlugin’s regex processing can hang on
zero-length matches because gre.exec(text) may not advance when a rule matches
an empty string. Update the logic inside the while loop to advance gre.lastIndex
after an empty match, or validate and skip zero-width rules before entering the
loop, so the rule handling around rule.onMatch, Decoration.widget, and
Decoration.mark cannot spin forever.
In `@src/store/useTimerStore.ts`:
- Around line 72-88: The pause/resume flow in useTimerStore currently only
mutates Zustand state, so the backend timer schedule remains on the original
deadline and can still emit timer-complete while paused or drift after resume.
Update pauseTimer and resumeTimer to use a backend-aware contract from the timer
page (for example cancel the scheduled timer and reschedule it with the new
deadline), or otherwise gate these actions off until that backend support
exists. Use the existing pauseTimer and resumeTimer methods as the integration
points so the UI state and backend schedule stay in sync.
In `@src/types.d.ts`:
- Around line 19-22: The reminder scheduling API currently uses unknown[] for
scheduleReminders, which allows malformed payloads to compile and only fail
later at the IPC boundary. Define and reuse a shared TypeScript reminder payload
type representing the deserialized { key, label, dueAt } shape, then update both
the scheduleReminders signature in types.d.ts and the corresponding API surface
in src/api.ts to use that concrete type so frontend/backend drift is caught at
compile time.
---
Nitpick comments:
In `@src/hooks/useReminders.test.ts`:
- Around line 97-126: The reminder-fired test in useReminders only verifies
persistence in localStorage and misses the toast side effect. Update the test
around useReminders and the captured reminder-fired callback to also assert that
the in-app toast path is triggered, mocking or spying on the toast notification
helper used by the hook. Keep the existing notified key assertion and add a
clear expectation that the toast is shown when the event is received.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c2769da8-b1b4-4f98-96a6-d0a5eb465a7d
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (31)
.gitignoreAUDIT_LOG.mdCHANGELOG.mdREADME.mdfeatures.mdnotes/New Features in v0.5.3.mdpackage.jsonsrc-tauri/Cargo.tomlsrc-tauri/capabilities/default.jsonsrc-tauri/src/commands/fs.rssrc-tauri/src/commands/mod.rssrc-tauri/src/commands/notifications.rssrc-tauri/src/commands/shortcuts.rssrc-tauri/src/lib.rssrc-tauri/tauri.conf.jsonsrc/App.csssrc/App.tsxsrc/GraphView.tsxsrc/api.tssrc/components/MainActionMenu.tsxsrc/components/TimersPage.tsxsrc/hooks/useGlobalHotkey.tssrc/hooks/useReminders.test.tssrc/hooks/useReminders.tssrc/lib/editor/dslPlugin.tssrc/lib/editor/extensions.tssrc/lib/editor/slashCommands.tssrc/setupTests.tssrc/store/useAppStore.tssrc/store/useTimerStore.tssrc/types.d.ts
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. The branch was updated while autofix was in progress. Please try again. |
…tcuts without tables
Welcome.md is now a concise central hub linking to separate onboarding/ topic notes (Editor, Commands, Graph, AI, Tasks, Customization) via the internal file link system. Each topic note has prev/next/back links for guided navigation. Version-marker rewrite logic preserves updates on version changes. Added explicit scroll-to-top on note switch for file links. Moved onboarding cleanup to dedicated Rust command.
…ble debounce, and more
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/types.d.ts (1)
1-5: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winReuse this exported reminder payload everywhere.
src/hooks/useReminders.tsstill has a localReminderPayloaddeclaration. Importing this shared type there avoids future frontend/backend contract drift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/types.d.ts` around lines 1 - 5, The reminder payload shape is duplicated, and src/hooks/useReminders.ts still declares its own local ReminderPayload instead of using the shared exported type. Update useReminders to import ReminderPayload from the shared types definition and remove the local declaration so the hook and the rest of the app rely on the same contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/src/commands/fs.rs`:
- Around line 200-207: The onboarding file handling in write_onboarding_file and
remove_onboarding_files is overwriting or deleting user-editable content during
version changes. Update the logic so existing editable notes/templates like
Welcome.md and customized command files are preserved, and limit cleanup to only
generated or obsolete files instead of removing the entire commands directory.
Use the existing write_onboarding_file, remove_onboarding_files, and any
version-checking flow that passes is_new_version to distinguish safe
initialization from user-modified content.
- Around line 325-327: Update the onboarding text generated in fs.rs so the
Graph.md copy describes the new 3D WebGL graph instead of the old 2D knowledge
graph. Locate the write_onboarding_file call for "onboarding/Graph.md" and
change the wording in that formatted string to say 3D consistently with the new
graph experience, keeping the rest of the onboarding content unchanged.
In `@src-tauri/src/commands/notifications.rs`:
- Line 56: The reminder registration logic in
notifications::start_reminder_listener should not replace an existing JoinHandle
for the same reminder.key without stopping the old task. Before or during the
new_handles.insert call, detect when a key already exists, abort the previous
JoinHandle, and then store the new one so duplicate reminder keys do not leave
uncancellable tasks running.
In `@src-tauri/src/lib.rs`:
- Around line 91-101: The delayed hide path in `src-tauri/src/lib.rs` only
checks `is_dialog_open` before `std::thread::spawn`, so a dialog opened during
the 200ms debounce can still be hidden. Update the hide logic inside the spawned
closure to re-check the current dialog state right before calling `w2.hide()`,
using the same state source used by the outer guard, and only hide when the
dialog is still closed. Keep the existing generation check (`gen.fetch_add`,
`g2.load`, `gen_at_spawn`) and add the final state check in the delayed hide
branch.
In `@src/store/useTimerStore.ts`:
- Around line 80-84: The resumeTimer handler in useTimerStore is incorrectly
marking the timer as completed, which makes paused timers finish immediately on
resume. Update resumeTimer so it does not set status to completed; instead
either disable pause/resume actions until backend support exists or implement a
proper cancel-and-reschedule flow using the timer id so the UI state stays
aligned with backend deadlines.
---
Nitpick comments:
In `@src/types.d.ts`:
- Around line 1-5: The reminder payload shape is duplicated, and
src/hooks/useReminders.ts still declares its own local ReminderPayload instead
of using the shared exported type. Update useReminders to import ReminderPayload
from the shared types definition and remove the local declaration so the hook
and the rest of the app rely on the same contract.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c627de79-656d-4399-aa88-3ab839496d04
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (16)
AUDIT_LOG.mdCHANGELOG.mdpackage.jsonsrc-tauri/src/commands/fs.rssrc-tauri/src/commands/notifications.rssrc-tauri/src/lib.rssrc/App.tsxsrc/GraphView.tsxsrc/api.tssrc/components/Editor.tsxsrc/components/TimersPage.tsxsrc/hooks/useGlobalHotkey.tssrc/hooks/useReminders.tssrc/lib/editor/dslPlugin.tssrc/store/useTimerStore.tssrc/types.d.ts
✅ Files skipped from review due to trivial changes (2)
- CHANGELOG.md
- AUDIT_LOG.md
🚧 Files skipped from review as they are similar to previous changes (7)
- src/hooks/useGlobalHotkey.ts
- src/lib/editor/dslPlugin.ts
- src/hooks/useReminders.ts
- src/App.tsx
- package.json
- src/GraphView.tsx
- src/components/TimersPage.tsx
…alog on hide, dedupe reminders type
Summary
Graph View Overhaul
CircleGeometry) that properly occlude edges behind them (renderOrder: 1in transparent pass withdepthWrite: true)Cmd+Ffuzzy search inside graph view with arrow-key navigation and camera fly-tod3-forcecentroid attractionCross-Platform Fixes
AtomicBool+std::thread::spawn). macOS retains immediate hide.Welcome.md(revamped with full feature overview) instead of looking for a new-features note.New Shortcut
Cmd+/(orCmd+?): Opens or auto-creates aShortcuts.mdnote listing all keyboard shortcuts and slash commands.Documentation
CHANGELOG.md,features.md,README.mdupdatednotes/New Features in v0.5.3.mdcreatedAUDIT_LOG.mdupdatedSummary by CodeRabbit
/timercommand in the editor.