Skip to content

Conversation

@developerEhsan
Copy link
Owner

@developerEhsan developerEhsan commented Aug 9, 2025

Summary by CodeRabbit

  • New Features

    • Cross-platform paste simulation and a global shortcut to open the copy widget.
  • Bug Fixes

    • Added permissions to resolve a code-scanning alert.
  • Refactor

    • Improved main-process error handling, clipboard monitoring, renderer routing (hash history), and tray labels/branding.
  • Chores

    • Bumped to 1.2.0, migrated scripts/tooling to Bun, upgraded many dependencies, simplified helper script, updated CI workflows, and added pre-merge approval to auto-merge.

dependabot bot and others added 30 commits April 14, 2025 00:53
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.14.0 to 22.14.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.14.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/types/node-22.14.1

chore(deps-dev): bump @types/node from 22.14.0 to 22.14.1
Bumps [@radix-ui/react-label](https://github.com/radix-ui/primitives) from 2.1.2 to 2.1.3.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-label"
  dependency-version: 2.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-label-2.1.3

chore(deps): bump @radix-ui/react-label from 2.1.2 to 2.1.3
Bumps [@radix-ui/react-scroll-area](https://github.com/radix-ui/primitives) from 1.2.3 to 1.2.4.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-scroll-area"
  dependency-version: 1.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-scroll-area-1.2.4

chore(deps): bump @radix-ui/react-scroll-area from 1.2.3 to 1.2.4
Bumps [@radix-ui/react-alert-dialog](https://github.com/radix-ui/primitives) from 1.1.6 to 1.1.7.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-alert-dialog"
  dependency-version: 1.1.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-alert-dialog-1.1.7

chore(deps): bump @radix-ui/react-alert-dialog from 1.1.6 to 1.1.7
Bumps [@radix-ui/react-context-menu](https://github.com/radix-ui/primitives) from 2.2.6 to 2.2.7.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-context-menu"
  dependency-version: 2.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-context-menu-2.2.7

chore(deps): bump @radix-ui/react-context-menu from 2.2.6 to 2.2.7
Bumps [@radix-ui/react-select](https://github.com/radix-ui/primitives) from 2.1.6 to 2.1.7.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-select"
  dependency-version: 2.1.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-select-2.1.7

chore(deps): bump @radix-ui/react-select from 2.1.6 to 2.1.7
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.2 to 5.8.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](microsoft/TypeScript@v5.8.2...v5.8.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/typescript-5.8.3

chore(deps-dev): bump typescript from 5.8.2 to 5.8.3
Bumps [@radix-ui/react-dialog](https://github.com/radix-ui/primitives) from 1.1.6 to 1.1.7.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-dialog"
  dependency-version: 1.1.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-dialog-1.1.7

chore(deps): bump @radix-ui/react-dialog from 1.1.6 to 1.1.7
Bumps [@radix-ui/react-switch](https://github.com/radix-ui/primitives) from 1.1.3 to 1.1.4.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-switch"
  dependency-version: 1.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-switch-1.1.4

chore(deps): bump @radix-ui/react-switch from 1.1.3 to 1.1.4
Bumps [@radix-ui/react-label](https://github.com/radix-ui/primitives) from 2.1.3 to 2.1.4.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-label"
  dependency-version: 2.1.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-label-2.1.4

chore(deps): bump @radix-ui/react-label from 2.1.3 to 2.1.4
Bumps [@radix-ui/react-switch](https://github.com/radix-ui/primitives) from 1.1.4 to 1.2.2.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-switch"
  dependency-version: 1.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-switch-1.2.2

chore(deps): bump @radix-ui/react-switch from 1.1.4 to 1.2.2
Bumps [@electron-toolkit/preload](https://github.com/alex8088/electron-toolkit/tree/HEAD/packages/preload) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/alex8088/electron-toolkit/releases)
- [Changelog](https://github.com/alex8088/electron-toolkit/blob/master/packages/preload/CHANGELOG.md)
- [Commits](https://github.com/alex8088/electron-toolkit/commits/[email protected]/packages/preload)

---
updated-dependencies:
- dependency-name: "@electron-toolkit/preload"
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/electron-toolkit/preload-3.0.2

chore(deps): bump @electron-toolkit/preload from 3.0.1 to 3.0.2
Bumps [drizzle-kit](https://github.com/drizzle-team/drizzle-orm) from 0.30.6 to 0.31.0.
- [Release notes](https://github.com/drizzle-team/drizzle-orm/releases)
- [Commits](https://github.com/drizzle-team/drizzle-orm/compare/[email protected]@0.31.0)

---
updated-dependencies:
- dependency-name: drizzle-kit
  dependency-version: 0.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/drizzle-kit-0.31.0

chore(deps-dev): bump drizzle-kit from 0.30.6 to 0.31.0
Bumps [@radix-ui/react-toast](https://github.com/radix-ui/primitives) from 1.2.7 to 1.2.10.
- [Changelog](https://github.com/radix-ui/primitives/blob/main/release-process.md)
- [Commits](https://github.com/radix-ui/primitives/commits)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-toast"
  dependency-version: 1.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/radix-ui/react-toast-1.2.10

chore(deps): bump @radix-ui/react-toast from 1.2.7 to 1.2.10
Bumps [@electron-toolkit/eslint-config-ts](https://github.com/alex8088/electron-toolkit/tree/HEAD/packages/eslint-config-ts) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/alex8088/electron-toolkit/releases)
- [Changelog](https://github.com/alex8088/electron-toolkit/blob/master/packages/eslint-config-ts/CHANGELOG.md)
- [Commits](https://github.com/alex8088/electron-toolkit/commits/[email protected]/packages/eslint-config-ts)

---
updated-dependencies:
- dependency-name: "@electron-toolkit/eslint-config-ts"
  dependency-version: 3.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…opment/electron-toolkit/eslint-config-ts-3.1.0

chore(deps-dev): bump @electron-toolkit/eslint-config-ts from 3.0.0 to 3.1.0
…/development/actions/checkout-5

chore(deps): bump actions/checkout from 4 to 5
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (5)
.github/workflows/auto-merge.yml (2)

20-20: Remove unnecessary checkout for gh pr operations

Checking out the repo isn’t required for gh pr review/merge. Dropping it speeds up the job and reduces surface area.

Apply this diff to remove the checkout step:

-      - uses: actions/checkout@v5
+

26-26: Split commands and prefer GH_TOKEN; align with prior suggestion

Chaining with && hides which subcommand failed. Also, gh defaults to GH_TOKEN; set it explicitly. This mirrors the earlier review feedback.

Apply this diff to split commands and use GH_TOKEN:

-        env:
-          PR_URL: ${{github.event.pull_request.html_url}}
-          GITHUB_TOKEN: ${{secrets.PAT}}
-        run: gh pr review --approve "$PR_URL" && gh pr merge --delete-branch --auto --merge "$PR_URL"
+        env:
+          PR_URL: ${{ github.event.pull_request.html_url }}
+          GH_TOKEN: ${{ secrets.PAT }}
+        run: |
+          gh pr review --approve "$PR_URL"
+          gh pr merge --auto --merge --delete-branch "$PR_URL"

Additionally, consider removing the checkout step as noted above.

package.json (3)

29-30: Normalize mac/linux build scripts to reuse main build

These duplicate electron-vite build logic instead of reusing "build", unlike win/unpack.

Apply:

-    "build:mac": "electron-vite build && electron-builder --mac",
-    "build:linux": "electron-vite build && electron-builder --linux",
+    "build:mac": "bun run build && electron-builder --mac",
+    "build:linux": "bun run build && electron-builder --linux",

24-24: Fix quoting in build script; ‘&&’ won’t execute inside quotes

As written, the shell won’t interpret &&. Also, scope GENERATE_SOURCEMAP to the build command only.

Apply:

-    "build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
+    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",

25-25: Replace ‘bun rebuild’ with Electron-aware rebuild

Bun doesn’t provide a stable bun rebuild for native Electron modules like better-sqlite3. Use electron-rebuild (or rely on electron-builder install-app-deps).

Apply:

-    "rebuild:drizzle": "bun rebuild better-sqlite3",
+    "rebuild:drizzle": "electron-rebuild",

Note: Add @electron/rebuild as a devDependency:

npm i -D @electron/rebuild
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99e54ee and b3af0c8.

📒 Files selected for processing (4)
  • .github/workflows/auto-merge.yml (1 hunks)
  • .github/workflows/pr-check.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • package.json (3 hunks)
🔇 Additional comments (6)
.github/workflows/release.yml (1)

20-20: Checkout v5 upgrade looks good

actions/checkout@v5 is compatible and brings perf and maintenance wins. No issues spotted.

.github/workflows/pr-check.yml (1)

17-17: Checkout v5 upgrade looks good

Consistent with the release workflow. No concerns.

package.json (4)

3-3: Version bump to 1.2.0 looks fine

No issues with the semantic version progression.


21-21: Typecheck script moved to Bun; ensure CI installs Bun

Scripts now depend on Bun; CI must install Bun before running these.

Confirm by updating the workflows as suggested, or let me open a PR to add oven-sh/setup-bun to both workflows.


27-28: Good: platform scripts reuse main build

Windows and unpack correctly pipe through bun run build to avoid duplication.


29-30: Ubuntu 24 support: verify electron-builder targets meet your distro needs

Default --linux targets may not produce all desired artifacts (e.g., AppImage, deb). If Ubuntu 24 is a primary goal, ensure your electron-builder config includes appropriate targets.

Would you like me to add linux targets (AppImage, deb) to electron-builder config or package.json build config?

steps:
- name: Check out Git repository
uses: actions/checkout@v4
uses: actions/checkout@v5
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Workflow uses pnpm but build script invokes Bun; add Bun setup or builds will fail

Your package.json "build" script calls bun run typecheck. On windows-latest, Bun isn’t installed by default, so pnpm build will fail at runtime. Add a Bun setup step before the Build step.

Proposed step (insert after Node setup, before Install Dependencies):

- name: Setup Bun
  uses: oven-sh/setup-bun@v2
  with:
    bun-version: 1.2.x

Optionally, keep pnpm for install (fine), or migrate install to Bun in a follow-up.

🤖 Prompt for AI Agents
.github/workflows/release.yml around line 20: the workflow checks out code but
fails to set up Bun which is required because package.json's build script calls
"bun run typecheck"; add a setup step for Bun after the Node setup and before
the Install Dependencies step to ensure Bun is available at runtime (use
oven-sh/setup-bun@v2 and specify a bun-version like 1.2.x); you can keep pnpm
for installs or later switch installs to Bun, but the immediate fix is to add
the Bun setup step so pnpm build won’t fail on windows-latest.

💡 Verification agent

🧩 Analysis chain

Verify lockfile consistency (pnpm vs bun) to ensure caching works

The workflow caches pnpm’s store via pnpm-lock.yaml. If you’ve migrated fully to Bun, pnpm-lock.yaml may be stale or absent, degrading cache effectiveness.

Run this script to check which lockfiles exist:


🏁 Script executed:

#!/bin/bash
# Inspect presence of pnpm and bun lockfiles and report
set -euo pipefail
found_any=0
if fd -a 'pnpm-lock.yaml' | wc -l | grep -q '^[1-9]'; then
  echo "Found pnpm-lock.yaml:"
  fd -a 'pnpm-lock.yaml'
  found_any=1
else
  echo "No pnpm-lock.yaml found."
fi

if fd -a 'bun.lockb' | wc -l | grep -q '^[1-9]'; then
  echo "Found bun.lockb:"
  fd -a 'bun.lockb'
  found_any=1
else
  echo "No bun.lockb found."
fi

if [[ $found_any -eq 0 ]]; then
  echo "No known lockfiles found."
fi

Length of output: 313


Lockfiles missing – caching in release.yml will always miss

The release workflow’s cache step relies on a lockfile (pnpm-lock.yaml or bun.lockb) to key restores/saves, but no lockfile was detected in the repo. Without one, your CI cache will never hit, slowing down installs.

Please ensure your project tracks the correct lockfile and update .github/workflows/release.yml accordingly:

  • If you’ve migrated to Bun:
    • Commit bun.lockb to source control
    • Replace the pnpm cache step with something like:
      - uses: actions/cache@v3
        with:
          path: ~/.bun/cache
          key: ${{ runner.os }}-bun-${{ hashFiles('bun.lockb') }}
  • If you’re still using pnpm:
    • Add pnpm-lock.yaml to your repo
    • Make sure the cache step uses:
      - uses: actions/cache@v3
        with:
          path: ~/.pnpm-store
          key: ${{ runner.os }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}

File needing updates:

  • .github/workflows/release.yml (cache step around line 20)
🤖 Prompt for AI Agents
.github/workflows/release.yml around line 20: the workflow's cache step hashes a
lockfile that is not present in the repo so cache restores will always miss; fix
by either committing the correct lockfile and updating the cache step to
reference it—if your project uses Bun, add bun.lockb to source control and
replace the pnpm cache action with a cache that keys on hashFiles('bun.lockb')
and points to Bun's cache directory (~/.bun/cache); if you use pnpm, add
pnpm-lock.yaml to source control and ensure the cache step keys on
hashFiles('pnpm-lock.yaml') and caches pnpm's store path (~/.pnpm-store).

dependabot bot and others added 8 commits August 18, 2025 00:52
Bumps [@tiptap/extension-color](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/extension-color) from 2.26.1 to 3.2.0.
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/develop/packages/extension-color/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/HEAD/packages/extension-color)

---
updated-dependencies:
- dependency-name: "@tiptap/extension-color"
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/tiptap/extension-color-3.2.0

chore(deps): bump @tiptap/extension-color from 2.26.1 to 3.2.0
Bumps [@tiptap/pm](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/pm) from 2.26.1 to 3.2.0.
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/develop/packages/pm/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/HEAD/packages/pm)

---
updated-dependencies:
- dependency-name: "@tiptap/pm"
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/tiptap/pm-3.2.0

chore(deps): bump @tiptap/pm from 2.26.1 to 3.2.0
Bumps [react-day-picker](https://github.com/gpbl/react-day-picker) from 9.8.1 to 9.9.0.
- [Release notes](https://github.com/gpbl/react-day-picker/releases)
- [Changelog](https://github.com/gpbl/react-day-picker/blob/main/CHANGELOG.md)
- [Commits](gpbl/react-day-picker@v9.8.1...v9.9.0)

---
updated-dependencies:
- dependency-name: react-day-picker
  dependency-version: 9.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/react-day-picker-9.9.0

chore(deps): bump react-day-picker from 9.8.1 to 9.9.0
Bumps [@tiptap/extension-text-style](https://github.com/ueberdosis/tiptap/tree/HEAD/packages/extension-text-style) from 2.26.1 to 3.2.0.
- [Release notes](https://github.com/ueberdosis/tiptap/releases)
- [Changelog](https://github.com/ueberdosis/tiptap/blob/develop/packages/extension-text-style/CHANGELOG.md)
- [Commits](https://github.com/ueberdosis/tiptap/commits/HEAD/packages/extension-text-style)

---
updated-dependencies:
- dependency-name: "@tiptap/extension-text-style"
  dependency-version: 3.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/tiptap/extension-text-style-3.2.0

chore(deps): bump @tiptap/extension-text-style from 2.26.1 to 3.2.0
@developerEhsan
Copy link
Owner Author

Need to improve the validate windows Build on PR to support linux as well with bun

dependabot bot and others added 4 commits August 25, 2025 00:24
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.539.0 to 0.541.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.541.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 0.541.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/lucide-react-0.541.0

chore(deps): bump lucide-react from 0.539.0 to 0.541.0
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.541.0 to 0.542.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/0.542.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 0.542.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/lucide-react-0.542.0

chore(deps): bump lucide-react from 0.541.0 to 0.542.0
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
package.json (3)

27-30: Normalize platform builds via the main build

Reuse the fixed main build script for macOS/Linux like Windows to keep behavior consistent.

-    "build:mac": "electron-vite build && electron-builder --mac",
-    "build:linux": "electron-vite build && electron-builder --linux",
+    "build:mac": "bun run build && electron-builder --mac",
+    "build:linux": "bun run build && electron-builder --linux",

24-24: Build script is quoted; && won’t execute

Shell treats the whole command as a single string. Move cross-env to just the build step and remove quotes.

-    "build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
+    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",

25-25: Use Electron-aware rebuild, not bun rebuild

Bun doesn’t provide a stable native-module rebuild for Electron. Use @electron/rebuild (or rely solely on electron-builder install-app-deps).

-    "rebuild:drizzle": "bun rebuild better-sqlite3",
+    "rebuild:drizzle": "electron-rebuild"

Dev dependency to add:

  • @electron/rebuild
🧹 Nitpick comments (3)
package.json (3)

30-30: Clarify Linux targets for Ubuntu 24 builds

If you intend to ship .deb and AppImage, specify targets explicitly.

-    "build:linux": "bun run build && electron-builder --linux",
+    "build:linux": "bun run build && electron-builder --linux deb appimage",

CI (Ubuntu 24.04) prerequisites for native modules/electron-builder:

  • sudo apt-get update
  • sudo apt-get install -y build-essential python3 pkg-config

28-30: Add CI scripts to validate Windows + Linux builds with Bun

To address “validate windows Build on PR to support linux as well with bun”, add CI-friendly scripts and a matrix.

Suggested scripts:

+    "ci:build:win": "bun run build:win -- --publish=never",
+    "ci:build:linux": "bun run build:linux -- --publish=never",

GitHub Actions (sketch):

  • os: [windows-latest, ubuntu-24.04]
  • uses: oven-sh/setup-bun@v2
  • bun install
  • bun run ci:build:win / ci:build:linux

131-136: Pin toolchain and runtime: declare Bun as package manager/engine

Improves reproducibility across Linux/Windows CI.

   "bun": {
     "onlyBuiltDependencies": [
       "electron",
       "esbuild"
     ]
   },
+  "packageManager": "[email protected]",
+  "engines": {
+    "bun": ">=1.1.0"
+  }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4b583c7 and 8028bf4.

📒 Files selected for processing (1)
  • package.json (3 hunks)
🔇 Additional comments (1)
package.json (1)

97-129: React bundling confirmed – no changes needed
The renderer config doesn’t externalize React (no external/noExternal or optimizeDeps overrides, and externalizeDepsPlugin is only used in main/preload), so React is bundled into the packaged app. Keeping react and react-dom in devDependencies is correct.

dependabot bot and others added 6 commits September 8, 2025 00:21
Bumps [electron](https://github.com/electron/electron) from 37.4.0 to 38.0.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/main/docs/breaking-changes.md)
- [Commits](electron/electron@v37.4.0...v38.0.0)

---
updated-dependencies:
- dependency-name: electron
  dependency-version: 38.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/electron-38.0.0

chore(deps-dev): bump electron from 37.4.0 to 38.0.0
Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](actions/stale@v9...v10)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: '10'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Bumps [actions/labeler](https://github.com/actions/labeler) from 5 to 6.
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](actions/labeler@v5...v6)

---
updated-dependencies:
- dependency-name: actions/labeler
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
…/development/actions/stale-10

chore(deps): bump actions/stale from 9 to 10
…/development/actions/labeler-6

chore(deps): bump actions/labeler from 5 to 6
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
package.json (2)

27-30: Deduplicate platform build scripts; reuse the main build.

Route macOS/Linux builds through the normalized build script (already done for Windows) to keep flags consistent and ensure typecheck runs.

Apply:

-    "build:unpack": "bun run build && electron-builder --dir",
-    "build:win": "bun run build && electron-builder --win",
-    "build:mac": "electron-vite build && electron-builder --mac",
-    "build:linux": "electron-vite build && electron-builder --linux",
+    "build:unpack": "bun run build && electron-builder --dir",
+    "build:win": "bun run build && electron-builder --win",
+    "build:mac": "bun run build && electron-builder --mac",
+    "build:linux": "bun run build && electron-builder --linux",

24-24: Build script quoting breaks the ‘&&’ chain; move cross-env to the build command only.

As written, the shell won’t interpret && inside quotes, so typecheck never runs. Fix by removing the outer quotes and scoping GENERATE_SOURCEMAP to electron-vite only.

Apply:

-    "build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
+    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",
🧹 Nitpick comments (2)
.github/workflows/label.yml (1)

19-23: Upgrade to actions/labeler@v6 looks fine; keep pull_request_target safe and pin the action.

  • Security: Using pull_request_target is appropriate here since you only label PRs, but avoid checking out or executing PR code in this workflow. This prevents “pwn requests”/secret exfiltration issues. (securitylab.github.com, blog.gitguardian.com)
  • Maintenance: When bumping the labeler version while still using pull_request_target, GitHub runs the workflow from the base branch. If config changes accompany the bump, temporarily switch this workflow to on: pull_request to validate, then revert. (github.com)
  • Supply‑chain: Pin to the v6 commit SHA for immutability (keep a comment with the semver tag).

Apply:

-      - uses: actions/labeler@v6
+      - uses: actions/labeler@<commit-sha> # v6

Confirm no step (or composite action) in this job checks out the PR’s head SHA or runs untrusted code. If you need to test v6 config in this PR, temporarily switch to on: [pull_request], merge, then revert to pull_request_target. (github.com, securitylab.github.com)

package.json (1)

1-136: CI suggestion: validate Windows and Ubuntu builds with Bun (per PR comment).

Add a PR workflow that installs Bun, caches deps, runs bun run build, and smoke‑packages per OS. This catches Linux‑specific native rebuilds and Windows packaging regressions.

Example .github/workflows/pr-build.yml:

name: PR Build (Win + Linux)
on:
  pull_request:
    branches: [ master, development ]
jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        os: [ubuntu-24.04, windows-latest]
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v5
      - uses: oven-sh/setup-bun@v1
        with:
          bun-version: 1.2.5
      - name: Install deps
        run: bun install --frozen-lockfile
      - name: Typecheck + build
        run: bun run build
      - name: Pack (no publish)
        run: |
          if [ "${{ runner.os }}" = "Linux" ]; then
            bun run build:unpack
          else
            bun run build:unpack
          fi
        shell: bash

Notes:

  • Use build:unpack (electron-builder --dir) for PRs to avoid distro-specific packaging toolchains; a separate release workflow can produce AppImage/deb/rpm.
  • If you need full Linux artifacts, apt-get install rpm fakeroot dpkg libarchive-tools beforehand.
  • Keep labeler on pull_request_target but never run untrusted code there. (securitylab.github.com)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8028bf4 and d1500e2.

📒 Files selected for processing (3)
  • .github/workflows/issue-stale.yml (1 hunks)
  • .github/workflows/label.yml (1 hunks)
  • package.json (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/issue-stale.yml
🔇 Additional comments (2)
package.json (2)

131-136: Bun onlyBuiltDependencies: confirm native deps strategy for Linux.

You’ve limited Bun builds to ["electron","esbuild"]. That’s fine if you rely on electron-builder install-app-deps/@electron/rebuild for native modules like better-sqlite3. Just confirm contributors don’t expect bun install to prebuild better-sqlite3 locally, especially on Ubuntu 24. If they do, document the rebuild script in CONTRIBUTING.md.


22-22: LGTM: typecheck via Bun.

The consolidated typecheck script using Bun to call the two tsc projects is clear and cross‑platform.

"build": "cross-env GENERATE_SOURCEMAP=false \"pnpm run typecheck && electron-vite build\"",
"rebuild:drizzle": "pnpm rebuild better-sqlite3",
"build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
"rebuild:drizzle": "bun rebuild better-sqlite3",
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace ‘bun rebuild’ with Electron-aware rebuild to support native modules on Linux/Win.

Bun doesn’t provide a dedicated bun rebuild for Electron-native modules; standard practice is @electron/rebuild to match Electron’s ABI (v38 here). This avoids runtime “NODE_MODULE_VERSION” mismatches for better-sqlite3 across Linux distros and Windows. (electronjs.org)

Apply:

-    "rebuild:drizzle": "bun rebuild better-sqlite3",
+    "rebuild:drizzle": "electron-rebuild -f -w better-sqlite3",

Also add the dev dependency:

{
  "devDependencies": {
    "@electron/rebuild": "^3.6.0"
  }
}

Note: postinstall already runs electron-builder install-app-deps, which helps rebuild; keeping an explicit script is still useful locally/CI. (electronjs.org)

🤖 Prompt for AI Agents
In package.json around line 25, the npm script uses "bun rebuild better-sqlite3"
which doesn't rebuild native modules against Electron's ABI; replace that script
with an Electron-aware rebuild command (use @electron/rebuild targeting Electron
ABI v38) and add "@electron/rebuild": "^3.6.0" to devDependencies so native
modules like better-sqlite3 are rebuilt correctly on Linux/Windows for Electron;
keep postinstall as-is but include the explicit script for local/CI usage.

developerEhsan and others added 4 commits September 13, 2025 13:01
Bumps [react-day-picker](https://github.com/gpbl/react-day-picker) from 9.9.0 to 9.10.0.
- [Release notes](https://github.com/gpbl/react-day-picker/releases)
- [Changelog](https://github.com/gpbl/react-day-picker/blob/main/CHANGELOG.md)
- [Commits](gpbl/react-day-picker@v9.9.0...v9.10.0)

---
updated-dependencies:
- dependency-name: react-day-picker
  dependency-version: 9.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
…evelopment/react-day-picker-9.10.0

chore(deps): bump react-day-picker from 9.9.0 to 9.10.0
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
package.json (2)

131-136: Include better‑sqlite3 in Bun’s onlyBuiltDependencies for Linux dev installs.

Without this, Bun may skip the native build during install; dev runs can fail before electron-builder’s postinstall rebuild kicks in.

   "bun": {
     "onlyBuiltDependencies": [
       "electron",
-      "esbuild"
+      "esbuild",
+      "better-sqlite3"
     ]
   }

1-12: Declare engines and packageManager for reproducible CI (Node/Bun versions).

Locks CI to known toolchain versions across Linux/Win/macOS.

 {
   "name": "treo",
   "version": "1.2.0",
+  "packageManager": "[email protected]",
+  "engines": {
+    "node": ">=20.10 <23",
+    "bun": ">=1.1.0"
+  },
♻️ Duplicate comments (2)
package.json (2)

25-25: Use @electron/rebuild for Electron ABI-safe native rebuilds (better‑sqlite3).

Bun’s generic rebuild won’t target Electron’s ABI; prefer electron-rebuild.

Apply:

-    "rebuild:drizzle": "bun rebuild better-sqlite3",
+    "rebuild:native": "electron-rebuild -f -w better-sqlite3",

Also add the dev dependency:

   "devDependencies": {
+    "@electron/rebuild": "^3.6.0",

29-30: Normalize platform builds to reuse main build (align with build:win).

Call the centralized build script to keep parity across platforms.

-    "build:mac": "electron-vite build && electron-builder --mac",
-    "build:linux": "electron-vite build && electron-builder --linux",
+    "build:mac": "bun run build && electron-builder --mac",
+    "build:linux": "bun run build && electron-builder --linux",
🧹 Nitpick comments (3)
package.json (3)

13-36: Add CI validation scripts for Linux with Bun (hook up in workflows).

Matches the PR ask to “validate Windows build on PR to support Linux as well with bun.”

   "scripts": {
+    "ci:validate:linux": "bun i --frozen-lockfile && bun run typecheck && electron-vite build && electron-builder --linux --dir",
+    "ci:validate:win": "bun i --frozen-lockfile && bun run typecheck && electron-vite build && electron-builder --win --dir",

Wire these in pr-check.yml matrix (linux/windows) to catch Ubuntu 24 issues early.


30-30: Optionally pin explicit Linux targets for broader distro coverage.

If relying on electron-builder defaults is insufficient for Ubuntu 24 and others, consider explicit targets (e.g., AppImage, deb).

-    "build:linux": "bun run build && electron-builder --linux",
+    "build:linux": "bun run build && electron-builder --linux appimage deb",

Verify against your electron-builder config to avoid duplicate target definitions.


25-25: Name the script generically since it rebuilds native deps, not Drizzle.

-    "rebuild:drizzle": "electron-rebuild -f -w better-sqlite3",
+    "rebuild:native": "electron-rebuild -f -w better-sqlite3",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1500e2 and ef700f0.

📒 Files selected for processing (1)
  • package.json (3 hunks)
🔇 Additional comments (1)
package.json (1)

38-96: Audit breaking changes: Zod v4 & TipTap v3 — verification incomplete

Attempted checks failed to scan source files: ripgrep returned "unrecognized file type: tsx" (no .ts/.tsx search performed) and typecheck could not run because bun is not installed. package.json does contain zod ^4.0.17 and @tiptap/react ^3.1.0.

Run locally and paste outputs:

  • rg -n --hidden -g '!node_modules' -g '/*.ts' -g '/*.tsx' -C2 '\bzod\b'
  • rg -n --hidden -g '!node_modules' -g '/*.ts' -g '/*.tsx' -C1 '@tiptap/'
  • rg -n --hidden -g '!node_modules' -g '/*.ts' -g '/*.tsx' -C2 '@tanstack/react-(query|router)'
  • npm run typecheck --if-present (or bun run typecheck if bun is available)

Also search code for zod-specific patterns to audit: errorMap / message / invalid_type_error / required_error, z.intersection(), optional/nullable instance checks, object passthrough/strict/catchall; and verify TipTap extension import/usage changes.

package.json Outdated
"dev": "electron-vite dev",
"build": "cross-env GENERATE_SOURCEMAP=false \"pnpm run typecheck && electron-vite build\"",
"rebuild:drizzle": "pnpm rebuild better-sqlite3",
"build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix quoted build chain; env var currently not applied to electron-vite and will fail on Windows shells.

The quotes make the whole chain a single argument to cross-env; also GENERATE_SOURCEMAP won’t apply to the second command.

Apply:

-    "build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
+    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"build": "cross-env GENERATE_SOURCEMAP=false \"bun run typecheck && electron-vite build\"",
"build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",
🤖 Prompt for AI Agents
In package.json around line 24, the build script currently wraps the whole chain
in quotes so cross-env receives a single argument and GENERATE_SOURCEMAP is not
applied to the second command (breaking on Windows); remove the quotes and
ensure cross-env is applied to both commands (e.g. run cross-env
GENERATE_SOURCEMAP=false before bun run typecheck and again before electron-vite
build, separated by &&) so the env var is correctly set for each spawned
process.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/src/note-editor/extensions/color/color.ts (1)

10-14: Incorrect return value in handleKeyDown may cause unexpected behavior.

The handleKeyDown handler returns false, which in ProseMirror's plugin system means "do not prevent default behavior." However, after calling unsetColor(), you likely want to prevent the default Enter key behavior to avoid inserting a new line while the color command is being executed.

Apply this diff to return true to prevent default behavior:

-            return false
+            return true

Alternatively, if you want to allow default behavior after unsetting color, remove the return statement entirely or explicitly document why false is correct here.

♻️ Duplicate comments (6)
.github/workflows/auto-merge.yml (1)

20-28: Consider removing checkout and using GH_TOKEN for gh CLI.

The checkout step is unnecessary for gh pr operations, and the GitHub CLI should use GH_TOKEN with your PAT instead of GITHUB_TOKEN for better authentication.

Apply this diff:

-      - uses: actions/checkout@v5
-
       - name: Enable auto-merge for Dependabot PRs
         env:
           PR_URL: ${{github.event.pull_request.html_url}}
-          GITHUB_TOKEN: ${{secrets.PAT}}
+          GH_TOKEN: ${{secrets.PAT}}
         run: |
           gh pr review --approve "$PR_URL"
           gh pr merge --auto --merge --delete-branch "$PR_URL"
lint-staged.config.js (1)

3-13: Excellent refactor: now scopes to staged files.

The dynamic function correctly filters staged files and runs commands only where needed. This addresses the performance concern from the previous review.

package.json (2)

24-24: Fix the build script: move typecheck outside cross-env scope.

The current structure runs typecheck with GENERATE_SOURCEMAP=false applied, which is unnecessary. More importantly, cross-env should only wrap the electron-vite build command for proper environment variable scoping.

Apply this diff:

-    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",
+    "build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",

Wait, let me reconsider. The current line 24 shows:

"build": "bun run typecheck && cross-env GENERATE_SOURCEMAP=false electron-vite build",

This is actually correct now (not quoted as in past review). Let me check if there's still an issue...

Actually, this looks correct. The previous review mentioned quotes around the whole chain, but the current code doesn't have that issue. I should skip commenting on this.

[pending]
Need to reconsider - the code looks correct
[actions]
Skip this comment, code is already fixed
-->


25-25: Use @electron/rebuild for proper native module compilation.

bun rebuild doesn't rebuild native modules against Electron's ABI. For better-sqlite3 to work correctly across platforms (especially Linux and Windows), use @electron/rebuild to match Electron's ABI (v38).

Apply this diff:

-    "rebuild:drizzle": "bun rebuild better-sqlite3",
+    "rebuild:drizzle": "electron-rebuild -f -w better-sqlite3",

Also add the dev dependency:

   "devDependencies": {
+    "@electron/rebuild": "^3.6.0",
     "@commitlint/cli": "^19.8.1",
src/main/utils/simulate-paste-command.ts (1)

7-51: Return value does not reflect actual success.

The function returns true immediately after spawning the process (line 51), before the process completes. Callers cannot determine if the paste actually succeeded. This matches the past review concern.

Consider refactoring to return a Promise<boolean>:

-export function simulatePasteCommand(): boolean {
+export function simulatePasteCommand(): Promise<boolean> {
   const platform = process.platform

   const commands: Record<string, { shell: string; args: string[] }> = {
     // ... existing config ...
   }

   const config = commands[platform]
   if (!config) {
     console.error('Unsupported OS:', platform)
-    return false
+    return Promise.resolve(false)
   }

-  const proc = spawn(config.shell, config.args)
-
-  proc.on('error', (err) => {
-    console.error('Paste simulation failed:', err.message)
-  })
-
-  proc.stderr.on('data', (data) => {
-    console.error('stderr:', data.toString())
-  })
-
-  proc.on('exit', (code) => {
-    if (code !== 0) {
-      console.warn(`Paste command exited with code ${code}`)
-    }
-  })
-  return true
+  return new Promise<boolean>((resolve) => {
+    const proc = spawn(config.shell, config.args)
+    
+    proc.on('error', (err) => {
+      console.error('Paste simulation failed:', err.message)
+      resolve(false)
+    })
+    
+    proc.stderr.on('data', (data) => {
+      console.error('stderr:', data.toString())
+    })
+    
+    proc.on('exit', (code) => {
+      if (code !== 0) {
+        console.warn(`Paste command exited with code ${code}`)
+        resolve(false)
+      } else {
+        resolve(true)
+      }
+    })
+  })
 }
src/main/index.ts (1)

146-160: Path traversal and synchronous I/O vulnerabilities.

This handler remains vulnerable to path traversal attacks (matching the past review concern). An attacker can supply fileData.name like ../../.bashrc to write outside the intended directory.

Apply these fixes:

+import { writeFile } from 'fs/promises'

 ipcMain.handle(
   'handle-selected-file',
   async (_event, fileData: { name: string; buffer: ArrayBuffer }) => {
     try {
       const buffer = Buffer.from(fileData.buffer)
       const userData = app.getPath('userData')
-      const targetPath = join(userData, fileData.name)
+      
+      // Sanitize filename to prevent directory traversal
+      const safeName = basename(fileData.name).replace(/[^a-zA-Z0-9._-]/g, '_')
+      const targetPath = join(userData, safeName)
+      
+      // Prevent overwrites
+      if (existsSync(targetPath)) {
+        throw new Error('File already exists')
+      }
+      
-      writeFileSync(targetPath, buffer)
+      await writeFile(targetPath, buffer)
       return targetPath
     } catch (e) {
       console.error('Error handling selected file:', e)
-      return ''
+      throw e  // or return { success: false, error: e.message }
     }
   }
 )
🧹 Nitpick comments (5)
src/renderer/src/note-editor/components/section/three.tsx (1)

131-139: Consider applying the same key pattern to the nested color map.

While the outer palette map now correctly uses palette.label as the key, the inner color map still uses index on line 136. For consistency and to fully embrace React best practices, consider using a stable identifier for the color buttons as well.

Apply this diff to use a stable key:

-      {palette.colors.map((color, index) => (
+      {palette.colors.map((color) => (
         <MemoizedColorButton
           color={color}
           inverse={inverse}
           isSelected={selectedColor === color.cssVar}
-          key={index}
+          key={color.cssVar}
           onClick={onColorChange}
         />
       ))}

The cssVar property is unique across all colors and provides a stable identifier for React's reconciliation algorithm.

src/main/utils/simulate-paste-command.ts (1)

36-50: Add timeout protection for spawned processes.

If the spawned process hangs (e.g., xdotool waiting for an X server or PowerShell taking too long), the operation will never complete. Add a timeout (e.g., 5 seconds) to fail gracefully.

Example with timeout (applies after converting to Promise):

return new Promise<boolean>((resolve) => {
  const proc = spawn(config.shell, config.args)
  
  const timeout = setTimeout(() => {
    proc.kill()
    console.error('Paste command timed out')
    resolve(false)
  }, 5000) // 5 second timeout
  
  proc.on('error', (err) => {
    clearTimeout(timeout)
    console.error('Paste simulation failed:', err.message)
    resolve(false)
  })
  
  proc.on('exit', (code) => {
    clearTimeout(timeout)
    resolve(code === 0)
  })
})
src/main/index.ts (3)

38-40: LGTM! webSecurity logic improved.

Using import.meta.env.PROD correctly enables webSecurity in production and disables it in development. This addresses the past review concern about using import.meta.env.DEV ? false : true.

For defense-in-depth, consider adding a runtime assertion after window creation to fail fast if webSecurity is accidentally disabled in production:

if (import.meta.env.PROD && !mainWindow.webContents.getWebPreferences().webSecurity) {
  console.error('FATAL: Production build with webSecurity disabled')
  app.exit(1)
}

47-47: Use application-specific app user model ID.

The generic ID 'com.electron' should be replaced with your application's unique identifier (e.g., 'com.treo.app' or 'com.yourdomain.treo') for proper Windows taskbar grouping and notification association.

-  electronApp.setAppUserModelId('com.electron')
+  electronApp.setAppUserModelId('com.treo.app')

189-204: Acknowledged limitation: Clipboard polling.

The comment notes future refactoring. Current polling approach has known issues:

  1. CPU inefficiency: Polling every second wastes resources
  2. Text-only: Ignores image/file clipboard changes
  3. Race conditions: Rapid clipboard changes within 1 second may be lost

Consider migrating to an event-based approach using a library like clipboard-event or Electron's native clipboard change events (if available in your Electron version):

// Example with clipboard-event (requires installation)
import clipboardListener from 'clipboard-event'

clipboardListener.startListening()
clipboardListener.on('change', async () => {
  const currentContent = clipboard.readText()
  if (currentContent && currentContent !== previousContent) {
    try {
      await db.insert(clipboardSchema).values({ type: 'text', content: currentContent })
      previousContent = currentContent
      copyWidgetWindow.webContents.send('refresh-data')
    } catch (e) {
      console.error('Error inserting clipboard content:', e)
    }
  }
})

Or check if Electron has added native clipboard monitoring in recent versions.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ef700f0 and 3aa09ec.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .github/workflows/auto-merge.yml (1 hunks)
  • .github/workflows/pr-check.yml (2 hunks)
  • electron.vite.config.ts (2 hunks)
  • lint-staged.config.js (1 hunks)
  • package.json (2 hunks)
  • src/main/index.ts (2 hunks)
  • src/main/utils/paste-from-clipboard.ts (1 hunks)
  • src/main/utils/simulate-paste-command.ts (1 hunks)
  • src/renderer/src/note-editor/components/bubble-menu/link-bubble-menu.tsx (2 hunks)
  • src/renderer/src/note-editor/components/section/three.tsx (2 hunks)
  • src/renderer/src/note-editor/extensions/color/color.ts (1 hunks)
  • src/renderer/src/note-editor/hooks/use-editor.ts (4 hunks)
  • src/renderer/src/routes/settings/_settings.account.tsx (1 hunks)
  • src/renderer/src/routes/settings/_settings.appearance.tsx (1 hunks)
  • src/renderer/src/routes/settings/_settings.notifications.tsx (1 hunks)
  • src/renderer/src/routes/settings/_settings.profile.tsx (1 hunks)
  • src/renderer/src/windows/copy-widget/app/index.tsx (2 hunks)
  • tsconfig.node.json (1 hunks)
  • tsconfig.web.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/renderer/src/note-editor/components/bubble-menu/link-bubble-menu.tsx (1)
src/renderer/src/note-editor/components/link/link-edit-block.tsx (1)
  • LinkEditBlock (15-87)
src/main/index.ts (6)
src/main/drizzle/db.ts (2)
  • runMigrate (37-37)
  • db (37-37)
src/main/utils/create-window.ts (1)
  • createWindow (11-41)
src/main/drizzle/schema.ts (1)
  • clipboardSchema (14-21)
src/types/database.ts (1)
  • SearchClipboardParams (13-19)
src/main/utils/clipboard-operations.ts (1)
  • searchClipboard (7-40)
src/main/utils/simulate-paste-command.ts (1)
  • simulatePasteCommand (7-52)
src/renderer/src/note-editor/hooks/use-editor.ts (1)
src/renderer/src/note-editor/utils.ts (1)
  • fileToBase64 (114-127)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Dependabot
  • GitHub Check: Dependabot
🔇 Additional comments (24)
src/renderer/src/routes/settings/_settings.account.tsx (1)

55-60: LGTM! Error key migration is correct.

The switch from required_error to error for dob and language fields is valid and aligns with the broader refactor across settings forms in this PR.

src/renderer/src/routes/settings/_settings.appearance.tsx (1)

30-35: LGTM! Error key migration is correct.

The switch from required_error/invalid_type_error to error for theme and font fields is valid and aligns with the broader refactor across settings forms in this PR.

src/renderer/src/routes/settings/_settings.profile.tsx (1)

36-38: LGTM! Error key migration and shorthand usage are correct.

The switch from z.string({ required_error: '...' }).email() to z.email({ error: '...' }) is valid, more concise, and aligns with the broader refactor across settings forms in this PR.

src/renderer/src/routes/settings/_settings.notifications.tsx (1)

24-25: LGTM! Error key migration and const assertion are correct.

The switch from required_error to error for the type field is valid. The addition of as const improves type inference by making the enum values literal types, which aligns with TypeScript best practices.

src/renderer/src/note-editor/components/section/three.tsx (2)

151-151: LGTM! Type assertion improves type safety.

The explicit as string cast correctly narrows the type of the color attribute, and the fallback to the default foreground color handles the undefined case properly.


202-205: Excellent refactor! Using stable identifiers as keys.

Switching from array index to palette.label as the key follows React best practices. The palette labels are unique and stable, which ensures proper component reconciliation and avoids potential rendering issues if the array order changes.

src/renderer/src/note-editor/components/bubble-menu/link-bubble-menu.tsx (2)

4-4: LGTM! Import path updated for TipTap v3.

The import path change from @tiptap/react to @tiptap/react/menus aligns with TipTap v3's package restructuring.

Based on learnings


92-95: LGTM! Props updated for TipTap v3 BubbleMenu API.

The prop renames (tippyOptionsoptions, onHiddenonHide) correctly align with TipTap v3's updated BubbleMenu API.

Based on learnings

src/renderer/src/note-editor/hooks/use-editor.ts (2)

2-2: LGTM: Explicit type annotation improves type safety.

Adding the explicit Extensions type import and return type annotation for createExtensions improves type safety and makes the code more maintainable.

Also applies to: 38-38


154-155: TextStyle has no downstream dependencies; remove the commented imports and delete color.ts if unused.

tsconfig.web.json (1)

10-10: LGTM!

Adding moduleResolution: "bundler" aligns with the Vite/bundler-based build setup and the broader migration to bun.

tsconfig.node.json (1)

5-5: LGTM!

Adding moduleResolution: "bundler" maintains consistency with tsconfig.web.json and aligns with the bundler-based build strategy.

src/renderer/src/windows/copy-widget/app/index.tsx (1)

32-55: LGTM!

Caching listEndRef.current in a local variable prevents potential stale-closure issues and ensures the cleanup function references the same DOM node that was observed.

electron.vite.config.ts (1)

4-4: LGTM!

The refactor from TanStackRouterVite to tanstackRouter improves naming consistency. The plugin configuration remains functionally identical.

Also applies to: 35-35

.github/workflows/pr-check.yml (1)

13-27: LGTM: Multi-platform matrix and bun migration.

The workflow now correctly targets both Windows and Linux, and the bun setup resolves the previous review concern about missing bun installation.

package.json (3)

27-30: LGTM: Platform build scripts normalized.

All platform-specific build scripts now correctly reuse the main build script, eliminating duplication and ensuring consistency.


3-3: Version bump and bun migration look good.

The version change to 1.2.0 is appropriate for the Linux support feature addition, and the bun configuration block correctly specifies onlyBuiltDependencies.

Also applies to: 132-137


115-115: No deprecated React or Electron APIs detected.
Search across .ts/.tsx files shows no React.VFC/defaultProps/legacy lifecycles or Electron remote/webPreferences usage.

src/main/utils/paste-from-clipboard.ts (2)

3-6: LGTM! Clear deprecation notice.

The deprecation notice clearly indicates the function is Windows-only and should be removed after ensuring it's not used elsewhere.


8-17: Confirm no remaining usages of pasteFromClipboard
No references found outside its own export (and a commented‐out line in src/main/index.ts), so the deprecated function is no longer used.

src/main/index.ts (4)

96-118: LGTM! Robust error handling in IPC handlers.

Both handlers properly wrap database operations in try-catch blocks and return meaningful error information to the renderer. The fallback to empty array in fetch-texts prevents renderer-side crashes.


171-177: Handler assumes paste succeeds immediately.

The handler returns true before the paste operation completes. Once simulatePasteCommand is updated to return Promise<boolean> (per earlier comment), this handler should await the result.

-  ipcMain.handle('paste', () => {
+  ipcMain.handle('paste', async () => {
     copyWidgetWindow.minimize()
     copyWidgetWindow.hide()
-    // pasteFromClipboard()
-    simulatePasteCommand()
-    return true
+    const success = await simulatePasteCommand()
+    return success
   })

Note: This change depends on refactoring simulatePasteCommand to return a Promise.


211-218: LGTM! Correct macOS lifecycle handling.

The activate handler properly recreates the main window if it was closed or shows the existing window. This follows standard macOS app behavior.


221-231: LGTM! Proper app lifecycle management.

Both handlers follow platform conventions:

  • Windows/Linux: Quit when all windows closed
  • macOS: Keep running when all windows closed (handled by activate event above)

Global shortcut cleanup prevents resource leaks.

Comment on lines +55 to +73
# - name: Verify Build Output (Windows)
# if: runner.os == 'Windows'
# shell: bash
# run: |
# if [[ -z $(find dist -type f -name "*.exe") ]]; then
# echo "❌ Windows build output (.exe) not found! Skipping release."
# exit 1
# fi
# echo "✅ Windows build output found!"

# - name: Verify Build Output (Linux)
# if: runner.os == 'Linux'
# shell: bash
# run: |
# if [[ -z $(find dist -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \)) ]]; then
# echo "❌ Linux build output not found! Skipping release."
# exit 1
# fi
# echo "✅ Linux build output found!"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Uncomment and fix the build verification steps.

The commented-out verification steps defeat the purpose of this PR, which explicitly aims to validate multi-platform builds. Without these checks, the workflow cannot confirm that build artifacts are generated correctly for Windows and Linux.

Apply this diff to restore and fix the verification:

-      # - name: Verify Build Output (Windows)
-      #   if: runner.os == 'Windows'
-      #   shell: bash
-      #   run: |
-      #     if [[ -z $(find dist -type f -name "*.exe") ]]; then
-      #       echo "❌ Windows build output (.exe) not found! Skipping release."
-      #       exit 1
-      #     fi
-      #     echo "✅ Windows build output found!"
-
-      # - name: Verify Build Output (Linux)
-      #   if: runner.os == 'Linux'
-      #   shell: bash
-      #   run: |
-      #     if [[ -z $(find dist -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \)) ]]; then
-      #       echo "❌ Linux build output not found! Skipping release."
-      #       exit 1
-      #     fi
-      #     echo "✅ Linux build output found!"
+      - name: Verify Build Output (Windows)
+        if: runner.os == 'Windows'
+        shell: bash
+        run: |
+          if [[ -z $(find dist -type f -name "*.exe") ]]; then
+            echo "❌ Windows build output (.exe) not found!"
+            exit 1
+          fi
+          echo "✅ Windows build output found!"
+
+      - name: Verify Build Output (Linux)
+        if: runner.os == 'Linux'
+        shell: bash
+        run: |
+          if [[ -z $(find dist -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \)) ]]; then
+            echo "❌ Linux build output not found!"
+            exit 1
+          fi
+          echo "✅ Linux build output found!"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# - name: Verify Build Output (Windows)
# if: runner.os == 'Windows'
# shell: bash
# run: |
# if [[ -z $(find dist -type f -name "*.exe") ]]; then
# echo "❌ Windows build output (.exe) not found! Skipping release."
# exit 1
# fi
# echo "✅ Windows build output found!"
# - name: Verify Build Output (Linux)
# if: runner.os == 'Linux'
# shell: bash
# run: |
# if [[ -z $(find dist -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \)) ]]; then
# echo "❌ Linux build output not found! Skipping release."
# exit 1
# fi
# echo "✅ Linux build output found!"
- name: Verify Build Output (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
if [[ -z $(find dist -type f -name "*.exe") ]]; then
echo "❌ Windows build output (.exe) not found!"
exit 1
fi
echo "✅ Windows build output found!"
- name: Verify Build Output (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
if [[ -z $(find dist -type f \( -name "*.AppImage" -o -name "*.deb" -o -name "*.rpm" \)) ]]; then
echo "❌ Linux build output not found!"
exit 1
fi
echo "✅ Linux build output found!"
🤖 Prompt for AI Agents
.github/workflows/pr-check.yml around lines 55 to 73: restore the commented-out
Windows and Linux "Verify Build Output" steps and correct their shell syntax and
conditionals so they run only on the appropriate runner and fail the job when
artifacts are missing; specifically, re-enable each step with the if: runner.os
== 'Windows' (or 'Linux'), use shell: bash and a multi-line run block that uses
find with proper escaping and quoting (e.g., for Windows look for "*.exe", for
Linux check for "*.AppImage" or "*.deb" or "*.rpm"), echo a failure message and
exit 1 if none found, and echo success when found — keep the step names and
logic identical but ensure the find expressions are correctly escaped for GitHub
Actions bash and the if conditions are present.

Comment on lines 125 to 144
ipcMain.handle('save-file', async (_event, filePath) => {
const userDataPath = app.getPath('userData')
const fileName = basename(filePath)
const newFilePath = join(userDataPath, 'assets', fileName)

// Ensure assets directory exists
if (!existsSync(join(userDataPath, 'assets'))) {
mkdirSync(join(userDataPath, 'assets'), { recursive: true })
try {
const userDataPath = app.getPath('userData')
const fileName = basename(filePath)
const newFilePath = join(userDataPath, 'assets', fileName)

if (!existsSync(join(userDataPath, 'assets'))) {
mkdirSync(join(userDataPath, 'assets'), { recursive: true })
}

copyFileSync(filePath, newFilePath)
await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })

return { success: true, path: newFilePath }
} catch (e) {
const msg = e instanceof Error ? e.message : 'Unknown Error Occured while saving File'
console.error('Error saving file:', e)
return { success: false, error: msg }
}

copyFileSync(filePath, newFilePath)
await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })

return { success: true, path: newFilePath }
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use async file operations and validate input paths.

The current implementation has several concerns:

  1. Synchronous I/O blocks the event loop (line 135): copyFileSync can freeze the UI during large file copies.
  2. No validation of input path (line 125): filePath could be a symlink or other malicious path.
  3. No overwrite protection (line 135): Existing files in assets/ are silently replaced.

Apply these improvements:

+import { copyFile } from 'fs/promises'
+import { realpath } from 'fs/promises'

 ipcMain.handle('save-file', async (_event, filePath) => {
   try {
+    // Validate input path
+    const resolvedPath = await realpath(filePath)
+    if (!existsSync(resolvedPath)) {
+      return { success: false, error: 'File does not exist' }
+    }
+
     const userDataPath = app.getPath('userData')
-    const fileName = basename(filePath)
+    const fileName = basename(resolvedPath)
+    
+    // Sanitize filename to prevent directory traversal
+    const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, '_')
+    if (safeName !== fileName) {
+      console.warn(`Sanitized filename from "${fileName}" to "${safeName}"`)
+    }
+    
-    const newFilePath = join(userDataPath, 'assets', fileName)
+    const newFilePath = join(userDataPath, 'assets', safeName)

     if (!existsSync(join(userDataPath, 'assets'))) {
       mkdirSync(join(userDataPath, 'assets'), { recursive: true })
     }

-    copyFileSync(filePath, newFilePath)
+    // Check for existing file
+    if (existsSync(newFilePath)) {
+      return { success: false, error: 'File already exists in assets directory' }
+    }
+    
+    // Use async copy
+    await copyFile(resolvedPath, newFilePath)
     await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })

     return { success: true, path: newFilePath }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ipcMain.handle('save-file', async (_event, filePath) => {
const userDataPath = app.getPath('userData')
const fileName = basename(filePath)
const newFilePath = join(userDataPath, 'assets', fileName)
// Ensure assets directory exists
if (!existsSync(join(userDataPath, 'assets'))) {
mkdirSync(join(userDataPath, 'assets'), { recursive: true })
try {
const userDataPath = app.getPath('userData')
const fileName = basename(filePath)
const newFilePath = join(userDataPath, 'assets', fileName)
if (!existsSync(join(userDataPath, 'assets'))) {
mkdirSync(join(userDataPath, 'assets'), { recursive: true })
}
copyFileSync(filePath, newFilePath)
await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })
return { success: true, path: newFilePath }
} catch (e) {
const msg = e instanceof Error ? e.message : 'Unknown Error Occured while saving File'
console.error('Error saving file:', e)
return { success: false, error: msg }
}
copyFileSync(filePath, newFilePath)
await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })
return { success: true, path: newFilePath }
})
// At the top of src/main/index.ts, add:
import { copyFile, realpath } from 'fs/promises'
ipcMain.handle('save-file', async (_event, filePath) => {
try {
// Validate input path
const resolvedPath = await realpath(filePath)
if (!existsSync(resolvedPath)) {
return { success: false, error: 'File does not exist' }
}
const userDataPath = app.getPath('userData')
const fileName = basename(resolvedPath)
// Sanitize filename to prevent directory traversal
const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, '_')
if (safeName !== fileName) {
console.warn(`Sanitized filename from "${fileName}" to "${safeName}"`)
}
const newFilePath = join(userDataPath, 'assets', safeName)
if (!existsSync(join(userDataPath, 'assets'))) {
mkdirSync(join(userDataPath, 'assets'), { recursive: true })
}
// Check for existing file
if (existsSync(newFilePath)) {
return { success: false, error: 'File already exists in assets directory' }
}
// Use async copy instead of blocking copyFileSync
await copyFile(resolvedPath, newFilePath)
await db.insert(clipboardSchema).values({ type: 'file', content: newFilePath })
return { success: true, path: newFilePath }
} catch (e) {
const msg = e instanceof Error ? e.message : 'Unknown Error Occured while saving File'
console.error('Error saving file:', e)
return { success: false, error: msg }
}
})

Comment on lines +24 to +27
linux: {
shell: 'xdotool',
args: ['key', 'ctrl+v']
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Document and validate the Linux xdotool dependency.

For Ubuntu 24 support (per PR objectives), ensure users know to install xdotool. Consider adding a runtime check to provide a helpful error message if xdotool is missing.


🏁 Script executed:

#!/bin/bash
# Description: Check if xdotool requirement is documented in README or installation docs

# Search for xdotool mentions in documentation
fd -e md -e txt | xargs rg -l 'xdotool'

# Check if there's a dependencies or installation section
fd README.md | xargs rg -A 10 -i 'install|depend|require|prerequisite'

Length of output: 344


Document the Linux xdotool dependency and add runtime validation.

  • Add “xdotool” under “Prerequisites” in README/installation docs
  • In simulate-paste-command.ts, check for xdotool at runtime and surface a clear error if it’s missing
🤖 Prompt for AI Agents
In src/main/utils/simulate-paste-command.ts around lines 24 to 27, the Linux
entry assumes xdotool is present; add a runtime check that validates xdotool is
installed (e.g., spawn sync/exec of "which xdotool" or "command -v xdotool") and
if not found throw a clear Error explaining xdotool is required and pointing to
installation instructions; also update the README/installation docs to list
"xdotool" under Prerequisites with a short install command (apt/yum/homebrew)
and ensure the runtime error message references that README section.

{showEdit ? (
<LinkEditBlock
className="w-full min-w-80 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
className="w-full min-w-80 rounded-md bordser bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Fix typo in className: "bordser" → "border".

The className contains a typo "bordser" that should be "border". This will prevent the border styling from being applied correctly.

Apply this diff to fix the typo:

-          className="w-full min-w-80 rounded-md bordser bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
+          className="w-full min-w-80 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden"

Run the following script to check for other instances of this typo:


🏁 Script executed:

#!/bin/bash
# Description: Search for other instances of "bordser" typo in the codebase

rg -n "bordser" --type=tsx --type=ts --type=jsx --type=js

Length of output: 27


Rerun search for “bordser” across all files to confirm no other instances:


🏁 Script executed:

#!/bin/bash
# Search entire repository for the typo "bordser"
rg -n "bordser"

Length of output: 196


Fix typo in className: “bordser” → “border”
This typo prevents the border styling from applying. Apply:

-          className="w-full min-w-80 rounded-md bordser bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
+          className="w-full min-w-80 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className="w-full min-w-80 rounded-md bordser bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
className="w-full min-w-80 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden"
🤖 Prompt for AI Agents
In src/renderer/src/note-editor/components/bubble-menu/link-bubble-menu.tsx
around line 99, the className string contains a typo "bordser" which prevents
the border styling from applying; replace "bordser" with "border" in that
className and save the file (also scan adjacent className tokens for any other
misspellings while you're there).

addProseMirrorPlugins() {
return [
...(this.parent?.() || []),
// ...(this.parent?.() || []),
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Commented-out parent plugins may break inherited functionality.

Commenting out this.parent?.() || [] removes all plugins from the base @tiptap/extension-color extension. This could break color functionality that relies on those plugins (e.g., color input commands, color state tracking).

Additionally, the AI summary indicates that the Color and TextStyle extensions are commented out in use-editor.ts (lines 154-155), making this extension effectively dead code.

Recommendation:

  1. If the Color extension is no longer needed, remove this file entirely rather than leaving commented-out code.
  2. If you intend to keep the Color extension, restore the parent plugins and ensure the extension is uncommented in use-editor.ts.

Run the following script to verify if the Color extension is used anywhere else in the codebase:


🏁 Script executed:

#!/bin/bash
# Description: Search for usages of the Color extension in the codebase.

# Search for imports or references to the Color extension
rg -n --type=ts --type=tsx -C3 'from.*color.*color' -g '!**/node_modules/**'
rg -n --type=ts --type=tsx -C3 '\bColor\b' -g '!**/node_modules/**' -g '!src/renderer/src/note-editor/extensions/color/color.ts'

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Search for imports of the Color extension file
rg -nC3 'from\s+.*extensions/color/color' -g '*.ts' -g '*.tsx' -g '!**/node_modules/**'

# Search for any other references to the Color identifier outside its own file
rg -nC3 '\bColor\b' -g '*.ts' -g '*.tsx' -g '!**/node_modules/**' -g '!src/renderer/src/note-editor/extensions/color/color.ts'

Length of output: 1554


🏁 Script executed:

#!/bin/bash
# Display the Color extension file with context to inspect handleKeyDown
sed -n '1,200p' src/renderer/src/note-editor/extensions/color/color.ts

Length of output: 488


Remove or re-enable the unused Color extension
The Color extension in src/renderer/src/note-editor/extensions/color/color.ts is commented out in src/renderer/src/note-editor/hooks/use-editor.ts (lines 154–155), making it dead code. Delete this file if unused, or uncomment its usage and restore ...(this.parent?.() || []) in addProseMirrorPlugins().

🤖 Prompt for AI Agents
In src/renderer/src/note-editor/extensions/color/color.ts around line 7, the
addProseMirrorPlugins method contains a commented-out parent spread (//
...(this.parent?.() || [])) and the extension is unused in use-editor.ts; either
delete this Color extension file if it is not needed, or re-enable it by
uncommenting the parent spread in addProseMirrorPlugins and restoring the
extension usage in src/renderer/src/note-editor/hooks/use-editor.ts (uncomment
the import and inclusion lines around 154–155) so the plugin chain is preserved;
after making the chosen change, remove any stale imports/exports, run the
build/tests/linter, and ensure no references to the deleted file remain.

Comment on lines 129 to 134
files.forEach(async (file) => {
const src = await fileToBase64(file)
editor.commands.insertContentAt(pos, {
type: 'image',
attrs: { src }
attrs: { src: await fileToBase64(file) }
})
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Async forEach does not await promises, causing race conditions.

Using await inside forEach does not wait for the promises to resolve. The forEach callback is not async, so the await is effectively ignored, and images may be inserted out of order or fail silently.

Apply this diff to properly await all file conversions:

-    onDrop: (editor, files, pos) => {
-      files.forEach(async (file) => {
-        editor.commands.insertContentAt(pos, {
-          type: 'image',
-          attrs: { src: await fileToBase64(file) }
-        })
-      })
+    onDrop: async (editor, files, pos) => {
+      for (const file of files) {
+        const src = await fileToBase64(file)
+        editor.commands.insertContentAt(pos, {
+          type: 'image',
+          attrs: { src }
+        })
+      }
     },

Alternatively, if you want parallel processing:

-    onDrop: (editor, files, pos) => {
-      files.forEach(async (file) => {
-        editor.commands.insertContentAt(pos, {
-          type: 'image',
-          attrs: { src: await fileToBase64(file) }
-        })
-      })
+    onDrop: async (editor, files, pos) => {
+      const srcs = await Promise.all(files.map(file => fileToBase64(file)))
+      srcs.forEach((src, index) => {
+        editor.commands.insertContentAt(pos, {
+          type: 'image',
+          attrs: { src }
+        })
+      })
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
files.forEach(async (file) => {
const src = await fileToBase64(file)
editor.commands.insertContentAt(pos, {
type: 'image',
attrs: { src }
attrs: { src: await fileToBase64(file) }
})
})
onDrop: async (editor, files, pos) => {
for (const file of files) {
const src = await fileToBase64(file)
editor.commands.insertContentAt(pos, {
type: 'image',
attrs: { src }
})
}
},
🤖 Prompt for AI Agents
In src/renderer/src/note-editor/hooks/use-editor.ts around lines 129 to 134, the
current files.forEach with await inside it doesn't actually wait for
fileToBase64 results, causing race conditions; change the loop to either (a) a
for...of async loop and await fileToBase64 for each file before calling
editor.commands.insertContentAt to preserve insertion order, or (b) map files to
an array of fileToBase64 promises and await Promise.all to process conversions
in parallel and then iterate the resolved base64 results to call
editor.commands.insertContentAt; ensure you await the overall operation so
callers know when insertion is complete.

Comment on lines 137 to 142
files.forEach(async (file) => {
const src = await fileToBase64(file)
editor.commands.insertContent({
type: 'image',
attrs: { src }
attrs: { src: await fileToBase64(file) }
})
})
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Async forEach does not await promises, causing race conditions.

Same issue as in onDrop: using await inside forEach does not wait for the promises to resolve. The images may be inserted out of order or fail silently.

Apply this diff to properly await all file conversions:

-    onPaste: (editor, files) => {
-      files.forEach(async (file) => {
-        editor.commands.insertContent({
-          type: 'image',
-          attrs: { src: await fileToBase64(file) }
-        })
-      })
+    onPaste: async (editor, files) => {
+      for (const file of files) {
+        const src = await fileToBase64(file)
+        editor.commands.insertContent({
+          type: 'image',
+          attrs: { src }
+        })
+      }
     },

Alternatively, if you want parallel processing:

-    onPaste: (editor, files) => {
-      files.forEach(async (file) => {
-        editor.commands.insertContent({
-          type: 'image',
-          attrs: { src: await fileToBase64(file) }
-        })
-      })
+    onPaste: async (editor, files) => {
+      const srcs = await Promise.all(files.map(file => fileToBase64(file)))
+      srcs.forEach(src => {
+        editor.commands.insertContent({
+          type: 'image',
+          attrs: { src }
+        })
+      })
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
files.forEach(async (file) => {
const src = await fileToBase64(file)
editor.commands.insertContent({
type: 'image',
attrs: { src }
attrs: { src: await fileToBase64(file) }
})
})
onPaste: async (editor, files) => {
for (const file of files) {
const src = await fileToBase64(file)
editor.commands.insertContent({
type: 'image',
attrs: { src }
})
}
},
Suggested change
files.forEach(async (file) => {
const src = await fileToBase64(file)
editor.commands.insertContent({
type: 'image',
attrs: { src }
attrs: { src: await fileToBase64(file) }
})
})
onPaste: async (editor, files) => {
const srcs = await Promise.all(files.map(file => fileToBase64(file)))
srcs.forEach(src => {
editor.commands.insertContent({
type: 'image',
attrs: { src }
})
})
},
🤖 Prompt for AI Agents
In src/renderer/src/note-editor/hooks/use-editor.ts around lines 137 to 142, the
code uses files.forEach(async file => { await fileToBase64(file);
editor.commands.insertContent(...) }) which does not await the async callbacks
and can cause out-of-order inserts or silent failures; change this to either (A)
sequentially await using a for...of loop so each fileToBase64 is awaited before
inserting to preserve order, or (B) perform conversions in parallel by mapping
files to Promises (files.map(f => fileToBase64(f))), await Promise.all to get an
array of base64 strings, then iterate that array to call
editor.commands.insertContent in the desired order; also ensure the enclosing
function is async so you can await these operations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants