Skip to content

Notes: fix cross-project move, add right-click menu (desktop) + move-to-project & fixes (mobile) - #84

Merged
ddutchie merged 8 commits into
mainfrom
ddutchie/notesfixes
Jul 13, 2026
Merged

ddutchie merged 8 commits into
mainfrom
ddutchie/notesfixes

Conversation

@ddutchie

@ddutchie ddutchie commented Jul 13, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Notes fixes and enhancements across desktop and mobile. Fixes the bug where moving a note between projects didn't stick (it reappeared in the old project), adds a right-click context menu for notes on desktop, and brings note-move-between-projects to mobile (both a long-press action menu and a chat tool). Also fixes two mobile chat issues (resume ghost bands, too-low agent step limit) and a project-icon rendering bug in the move-to-project pickers.

Type of change

  • Bug fix
  • New feature
  • Refactor / code quality
  • Docs / changelog
  • Tests

Screenshots / recording

Checklist

  • npm run type-check:all passes
  • npm run lint passes
  • npm test passes (runs npm run compile first so electron/bundle-guard.test.ts actually executes — npm run test:bundle to run just that)
  • npm run test:e2e passes (run before merging UI changes or cutting a release)
  • No hardcoded colours — CSS variables only (var(--accent), var(--text-primary), etc.)
  • No text-[Npx] pixel font classes — rem equivalents only (text-[0.714rem], text-xs, etc.)
  • New IPC handlers wrapped in handle() and return IpcResult<T>
  • New DB migrations appended (not edited) in schema.ts — n/a (no schema change; reuses existing columns)
  • New SQL goes in electron/db/queries.ts — single source of truth (imported by both Electron main process and MCP server); never construct a Database instance outside db/client.ts (Electron) or mcp-server.ts (MCP runtime)
  • New dependencies or devDependencies added to ROLE_MAP in scripts/generate-licenses.js and licenses.json regenerated — n/a (no new deps)
  • New MCP tools registered in electron/mcp/tools/index.ts dispatch + electron/lib/tool-schemas.ts Zod schema — n/a (mobile chat tool only; not an MCP tool)
  • If you added/removed a --external:<pkg> flag in the compile script — n/a

Notes for reviewer

Desktop — note move (fix(desktop): persist note move between projects)

  • Root cause: updateNote() in electron/db/queries.ts had no project_id/workspace_id in its UPDATE, so note.update({ projectId }) was silently dropped. The row (and its .md file, left in the old project folder) kept the old project, so a refresh / file re-scan / device sync resurfaced the note.
  • New moveNoteToProject query + db:note:moveToProject IPC handler (writes both columns, deletes the old-project .md, rewrites under the new project, recomputes relationships/embeddings). Store action + move undo/redo routed through it. New query unit tests added.
  • Please sanity-check the two-device sync round-trip if you can — I couldn't exercise it locally. The row now carries the correct project_id in its full-row op and the old file is removed, so it should land and stay.

Desktop — right-click menu

  • NoteListItem / ArchivedNoteListItem wrapped in the shared ContextMenu primitive (same pattern as kanban/card.tsx); mirrors the hover ⋯ dropdown. Worth confirming a right-click opens the menu without also triggering the row's onClick.
  • Fixed MoveNoteModal rendering a project's Lucide icon name as text (e.g. "Briefcase") → now uses <ProjectIcon>.

Mobile

  • New moveNoteToProject query (DB-only, no .md files) + move_note_to_project chat tool. This is the first way to move a note between projects on mobile — there was no manual UI either.
  • Long-press a note row → native action sheet (Pin/Unpin, Move to project, Move to folder, Delete), with a reusable NotePickerSheet. Only touch-tested via type/lint here; a device check of the long-press + pickers would be good.
  • Chat: raised MAX_TURNS 8 → 30 (matches desktop); resume-repaint key to clear iOS Liquid-Glass ghost bands after backgrounding.

Changelogs: changelogs/v2.4.10.md (desktop) and mobile/changelogs/v0.1.3.md (mobile, the pending release ahead of 0.1.2).

Summary by CodeRabbit

  • New Features
    • Added right-click menus for desktop notes, including archived notes.
    • Added mobile long-press actions for pinning, moving, and deleting notes.
    • Added project and folder pickers on mobile.
    • Chat can now move notes between projects.
  • Improvements
    • Moving notes now reliably updates their project location and supports persistent undo/redo.
    • Project icons display correctly in move dialogs.
    • Improved iOS chat rendering when returning to the app.
    • Increased Chat’s research step limit.

ddutchie added 7 commits July 13, 2026 16:27
updateNote's UPDATE had no project_id/workspace_id, so moving a note
between projects was silently dropped — the row (and its .md file, left
in the old project folder) kept the old project, and a refresh / file
re-scan / device sync resurfaced the note where it started.

Add a dedicated moveNoteToProject query + db:note:moveToProject IPC
handler that writes both columns, deletes the old-project .md file, and
rewrites it under the new project. Route the store action and move
undo/redo through it. Covered by new query tests.
… icons

Notes now open their actions menu on right-click (Pin/Unpin, Reveal,
Archive, Move to folder, Move to project, Delete), mirroring the hover
ellipsis dropdown via the shared ContextMenu primitive. Archived notes
get a right-click Restore / Delete permanently menu too.

Also fix MoveNoteModal rendering a project's Lucide icon NAME as text
(e.g. 'Briefcase', 'Rocket') — now draws it via ProjectIcon.
Chat stopped after only 8 steps ('couldn't finish in a reasonable
number of steps'), too few for introspective research that chains many
single-tool reads. Match the desktop default of 30 and clarify the
exhaustion message.
Returning from background left translucent vertical bands over the
transcript — an iOS snapshot artifact where the composer's native Liquid
Glass layer samples a stale backdrop until the next paint. Bump a key on
the AppState 'active' transition to remount the scroll content and force
a repaint. Also register move_note_to_project in the tool-ref map so its
chip is tappable.
Mobile had no way — manual or via chat — to move a note to another
project. Add a moveNoteToProject query (updates project_id + workspace_id;
DB-only, no .md files) and a move_note_to_project chat tool.

Add a long-press action menu on note rows (native action sheet / Alert)
with Pin/Unpin, Move to project, Move to folder, Delete, plus a reusable
NotePickerSheet for the project/folder pickers. Project options render
their Lucide icon via ProjectIcon (not the raw name).
@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ddutchie, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 reviews.

How do review 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 refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 171aacf2-c1b5-41da-a423-1800e993180e

📥 Commits

Reviewing files that changed from the base of the PR and between 15cd934 and 21e3166.

📒 Files selected for processing (9)
  • electron/db/queries.test.ts
  • electron/db/queries.ts
  • electron/ipc/db-handlers.ts
  • electron/preload.ts
  • mobile/app/(tabs)/chat/index.tsx
  • mobile/src/chat/agent.ts
  • mobile/src/chat/tools.ts
  • mobile/src/components/NotePickerSheet.tsx
  • mobile/src/screens/ProjectScreen.tsx
📝 Walkthrough

Walkthrough

Changes

Desktop note workflows

Layer / File(s) Summary
Desktop note actions and project picker
src/components/notes/notes-view/*
Note rows and archived rows gain right-click actions, and project icons use the shared ProjectIcon component.
Desktop project-move persistence
electron/db/*, electron/ipc/*, electron/preload.ts, src/store/slices/notes.ts, src/lib/commands/note-commands.ts, tests/fixtures/ipc-mock.ts, changelogs/v2.4.10.md
Project moves now update database ownership, relocate markdown files, refresh indexing state, and persist through undo/redo. Tests cover durable ownership and timestamp updates.

Mobile note workflows

Layer / File(s) Summary
Mobile project-move contract
mobile/src/db/queries.ts, mobile/src/chat/tools.ts, mobile/changelogs/v0.1.3.md
Mobile database and chat-tool paths support validated moves between projects and workspaces.
Mobile note actions and pickers
mobile/src/screens/ProjectScreen.tsx, mobile/src/components/NotePickerSheet.tsx
Long-press actions provide pinning, deletion, and project or folder movement through bottom-sheet pickers.

Mobile chat behavior

Layer / File(s) Summary
Chat agent and resume handling
mobile/src/chat/agent.ts, mobile/app/(tabs)/chat/index.tsx, mobile/changelogs/v0.1.3.md
The agent limit increases from 8 to 30 turns, project-move navigation is recognized, and chat content remounts after foreground resume.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NoteListItem
  participant notesSlice
  participant ElectronAPI
  participant db_note_moveToProject
  participant WorkspaceSync
  NoteListItem->>notesSlice: select destination project
  notesSlice->>ElectronAPI: moveToProject(noteId, projectId, workspaceId)
  ElectronAPI->>db_note_moveToProject: invoke db:note:moveToProject
  db_note_moveToProject->>WorkspaceSync: relocate note markdown file
  db_note_moveToProject->>notesSlice: return updated note
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clearly related to the main changes: cross-project move fixes, desktop right-click menus, and mobile note-moving fixes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ddutchie/notesfixes

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 8

🤖 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 `@electron/db/queries.test.ts`:
- Around line 229-234: Strengthen the “bumps version and updated_at” test around
moveNoteToProject by asserting that the moved note’s version increases from
before.version and that updatedAt is strictly later than before.updatedAt,
rather than using a non-strict comparison. Preserve the existing setup and
verify both promised changes.

In `@electron/db/queries.ts`:
- Around line 276-280: Update moveNoteToProject to look up the destination
project by projectId before updating the note, reject the operation when the
project is missing, and use the project's authoritative workspaceId in the
UPDATE instead of the caller-provided workspaceId. Preserve the existing
timestamp and version updates.

In `@electron/ipc/db-handlers.ts`:
- Around line 256-266: Make the relocation flow around suppressNextChange,
q.moveNoteToProject, deleteNoteFile, and writeNoteFile failure-safe: stage the
destination file before committing the database move, then remove the old file
only after the move succeeds. Add compensating cleanup and database/file
rollback for every filesystem or database failure so ownership and Markdown
files remain consistent, preserving the dashboard exclusion.

In `@mobile/app/`(tabs)/chat/index.tsx:
- Around line 133-147: Restrict the resumeKey update in the AppState change
handler to iOS only, using the platform check already available in the
component. Preserve the active-transition remount behavior on iOS while leaving
Android scroll state unchanged.

In `@mobile/src/chat/agent.ts`:
- Line 244: Update the final message construction around finalText so exhausting
MAX_TURNS always reports the turn-limit message, regardless of whether an
earlier tool-requesting turn produced text; do not let finalText suppress the
limit notification.

In `@mobile/src/chat/tools.ts`:
- Around line 176-183: Update the move_note_to_project tool’s run handler to
adapt the successful q.moveNoteToProject result from projectId/workspaceId to
the documented project_id/workspace_id field names, while preserving error
behavior and the existing input handling.

In `@mobile/src/components/NotePickerSheet.tsx`:
- Around line 64-70: Update the selected row handling in NotePickerSheet’s
renderItem so the row whose item.value equals selectedValue is disabled. Pass
the disabled state to Pressable and ensure onSelect cannot be triggered for that
row, while preserving normal selection behavior for other destinations.

In `@mobile/src/screens/ProjectScreen.tsx`:
- Around line 186-195: Update onPickProject so that when moveNoteToProject
returns an error, it displays the error and returns immediately before closing
the picker or clearing actionNote. Keep the success haptic and existing state
reset/load flow for successful moves.
🪄 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 Plus

Run ID: 0c17d788-adad-4b3c-9900-ab6cfc44160f

📥 Commits

Reviewing files that changed from the base of the PR and between c6a2cea and 15cd934.

📒 Files selected for processing (19)
  • changelogs/v2.4.10.md
  • electron/db/queries.test.ts
  • electron/db/queries.ts
  • electron/ipc/db-handlers.ts
  • electron/ipc/registry.test.ts
  • electron/preload.ts
  • mobile/app/(tabs)/chat/index.tsx
  • mobile/changelogs/v0.1.3.md
  • mobile/src/chat/agent.ts
  • mobile/src/chat/tools.ts
  • mobile/src/components/NotePickerSheet.tsx
  • mobile/src/db/queries.ts
  • mobile/src/screens/ProjectScreen.tsx
  • src/components/notes/notes-view/ArchivedNoteListItem.tsx
  • src/components/notes/notes-view/MoveNoteModal.tsx
  • src/components/notes/notes-view/NoteListItem.tsx
  • src/lib/commands/note-commands.ts
  • src/store/slices/notes.ts
  • tests/fixtures/ipc-mock.ts

Comment thread electron/db/queries.test.ts
Comment thread electron/db/queries.ts Outdated
Comment thread electron/ipc/db-handlers.ts
Comment thread mobile/app/(tabs)/chat/index.tsx
Comment thread mobile/src/chat/agent.ts Outdated
Comment thread mobile/src/chat/tools.ts
Comment thread mobile/src/components/NotePickerSheet.tsx
Comment thread mobile/src/screens/ProjectScreen.tsx
- desktop moveNoteToProject resolves the target project's workspace itself
  and rejects a missing project (no more caller-supplied workspace mismatch)
- db:note:moveToProject relocation is now failure-safe: write the new-project
  file first, roll the DB move back if it fails, best-effort delete the old file
- strengthen the query test (version increases, strictly later updatedAt) and
  cover authoritative-workspace + missing-project rejection
- mobile: restrict chat resume-remount to iOS (Android keeps scroll state)
- mobile: exhausting MAX_TURNS always reports the limit (append to partial text)
- mobile: move_note_to_project adapts result to project_id/workspace_id
- mobile: NotePickerSheet disables the already-current row
- mobile: onPickProject surfaces move errors and keeps the picker open
@ddutchie
ddutchie merged commit 17a2d65 into main Jul 13, 2026
6 checks passed
@ddutchie
ddutchie deleted the ddutchie/notesfixes branch July 13, 2026 21:00
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