Skip to content

Implement Windows system tray features and design specifications#49

Merged
laplace-anon merged 11 commits into
masterfrom
feat/system-tray
Jun 26, 2026
Merged

Implement Windows system tray features and design specifications#49
laplace-anon merged 11 commits into
masterfrom
feat/system-tray

Conversation

@laplace-anon

@laplace-anon laplace-anon commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added a Windows/Linux system tray with normal/unread (red-dot) icons, live tooltip updates, and a tray menu to open the app or quit.
    • Closing the main window now hides it to the tray (Windows/Linux), while full exit remains available via menu/shortcut.
    • Added a one-time “still running in the tray” notification hint.
  • Bug Fixes
    • Improved app restore behavior for second-instance launches and notification clicks.
  • Chores
    • Added a typecheck script and updated lint/build configuration for generated tray icon assets.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ae0a3ec5-e4b4-4585-b9f0-f557d32b2a73

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0ce71 and acff577.

📒 Files selected for processing (1)
  • src/tray.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/tray.ts

📝 Walkthrough

Walkthrough

Adds generated tray icons, a tray controller, and main-process wiring for Windows/Linux hide-to-tray behavior and unread updates.

Changes

Windows/Linux system tray

Layer / File(s) Summary
Tray assets and generator
docs/superpowers/plans/2026-06-26-windows-system-tray.md, docs/superpowers/specs/2026-06-26-windows-system-tray-design.md, .eslintrc.json, biome.jsonc, package.json, scripts/generate-icons.ts, src/assets/tray-icons.generated.ts
Tray icon generation adds dev/prod normal and unread PNGs, embeds them in TRAY_ICONS, and updates lint and script config for the generated module.
Tray controller
docs/superpowers/plans/2026-06-26-windows-system-tray.md, docs/superpowers/specs/2026-06-26-windows-system-tray-design.md, src/tray.ts
A new tray module creates the tray, restores and focuses the main window, updates unread state, and shows the tray hint notification.
Main-process wiring
docs/superpowers/plans/2026-06-26-windows-system-tray.md, docs/superpowers/specs/2026-06-26-windows-system-tray-design.md, src/main.ts
src/main.ts now delegates focus handling to the tray helper, hides the window to tray on Windows/Linux close when not quitting, routes unread counts to the tray helper, and wires tray creation, teardown, and the quit menu item.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 43.75% 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 accurately summarizes the main change: adding Windows/Linux system tray support alongside design/spec updates.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/system-tray

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

@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Windows and Linux system tray support for the desktop app. The main changes are:

  • Generated tray icon assets and an embedded icon module.
  • New tray module for create, destroy, focus, unread, and hint behavior.
  • Window close now hides to tray on Windows and Linux.
  • Unread counts now update the tray tooltip and red-dot icon.
  • Shared focus handling for tray clicks, second-instance launches, and notification clicks.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
src/tray.ts Adds the tray lifecycle, unread indicator updates, focus helper, and guarded one-time hint behavior.
src/main.ts Wires tray creation, hide-to-tray close behavior, explicit quit paths, unread updates, and shared focus handling.
scripts/generate-icons.ts Generates tray images and writes the embedded icon module only when both required icon sets are present.

Reviews (4): Last reviewed commit: "fix: construct tray prefs store lazily i..." | Re-trigger Greptile

Comment thread scripts/generate-icons.ts Outdated
Comment thread src/tray.ts Outdated

@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: 2

🧹 Nitpick comments (2)
src/assets/tray-icons.generated.ts (1)

7-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strip volatile PNG metadata before embedding.

These data URLs still carry PNG text chunks like date:create / date:modify, so rerunning the icon generator will rewrite this committed module even when the pixels are unchanged. Strip metadata in the generator before base64-encoding to keep the generated output deterministic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/assets/tray-icons.generated.ts` around lines 7 - 12, The generated tray
icon data URLs still include volatile PNG metadata, which makes the committed
module change on every regeneration. Update the icon generation flow used for
tray-icons.generated.ts so it strips non-image metadata such as date:create and
date:modify before base64 encoding, and ensure the generator produces
deterministic output for both normal and unread assets.
docs/superpowers/specs/2026-06-26-windows-system-tray-design.md (1)

112-118: 🩺 Stability & Availability | 🔵 Trivial

Please attach the Windows/Linux verification results before merge.

This change hardcodes close-to-tray behavior on Windows/Linux, and the spec already notes those paths cannot be exercised on the macOS dev machine. I don't see evidence in this PR that the checklist was actually run, so the highest-risk flows are still unverified.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-06-26-windows-system-tray-design.md` around lines
112 - 118, The verification plan is missing the requested Windows/Linux test
evidence, so update the spec section and PR notes to include the actual
verification results before merging. Use the “Verification plan” block in the
document to record the outcomes for the Windows tray/close-to-tray flows and the
Linux smoke test, including whether each checklist item passed. If the results
are not yet available, keep the plan explicit about blocking merge until the
Windows/Linux checks are attached.
🤖 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 `@scripts/generate-icons.ts`:
- Around line 165-176: generateTrayIcons() should fail closed instead of only
logging when ImageMagick or file generation fails, because
generateTrayIconModule() can otherwise build a partial TRAY_ICONS set from stale
files. Update the tray icon flow in generateTrayIcons(),
generateTrayIconModule(), and the TRAY_ICONS-producing path so any missing or
failed tray asset generation aborts the build and prevents emitting a module
unless both tray.png and tray-unread.png exist for every required variant.

In `@src/main.ts`:
- Around line 335-341: The main window close handler is still treating
update-driven exits as normal closes because `isQuitting` is not set early
enough, so the tray-hide logic in `mainWindow.on('close')` can block
`autoUpdater.quitAndInstall()`. Update the quit flow by setting `isQuitting`
when `autoUpdater.on('before-quit-for-update')` fires, or immediately before
calling `quitAndInstall()`, so the `close` handler in `src/main.ts` lets the app
exit cleanly during updates.

---

Nitpick comments:
In `@docs/superpowers/specs/2026-06-26-windows-system-tray-design.md`:
- Around line 112-118: The verification plan is missing the requested
Windows/Linux test evidence, so update the spec section and PR notes to include
the actual verification results before merging. Use the “Verification plan”
block in the document to record the outcomes for the Windows tray/close-to-tray
flows and the Linux smoke test, including whether each checklist item passed. If
the results are not yet available, keep the plan explicit about blocking merge
until the Windows/Linux checks are attached.

In `@src/assets/tray-icons.generated.ts`:
- Around line 7-12: The generated tray icon data URLs still include volatile PNG
metadata, which makes the committed module change on every regeneration. Update
the icon generation flow used for tray-icons.generated.ts so it strips non-image
metadata such as date:create and date:modify before base64 encoding, and ensure
the generator produces deterministic output for both normal and unread assets.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 71f9dd2c-a0ef-45d1-b343-ed38263f4695

📥 Commits

Reviewing files that changed from the base of the PR and between de09c71 and 4e72d21.

⛔ Files ignored due to path filters (4)
  • src/assets/icons/dev/tray-unread.png is excluded by !**/*.png
  • src/assets/icons/dev/tray.png is excluded by !**/*.png
  • src/assets/icons/prod/tray-unread.png is excluded by !**/*.png
  • src/assets/icons/prod/tray.png is excluded by !**/*.png
📒 Files selected for processing (9)
  • .eslintrc.json
  • biome.jsonc
  • docs/superpowers/plans/2026-06-26-windows-system-tray.md
  • docs/superpowers/specs/2026-06-26-windows-system-tray-design.md
  • package.json
  • scripts/generate-icons.ts
  • src/assets/tray-icons.generated.ts
  • src/main.ts
  • src/tray.ts

Comment thread scripts/generate-icons.ts
Comment thread src/main.ts
- clearInvalidConfig: true so a corrupt app-prefs file self-heals to
  defaults instead of throwing at startup
- wrap maybeShowTrayHint in try/catch so a best-effort hint can never
  bubble an error out of the window 'close' handler
Comment thread src/tray.ts Outdated
- generateTrayIcons() now exits non-zero on an ImageMagick/file failure
  instead of only logging, so a half-written set can't feed the module
- generateTrayIconModule() now requires both tray.png and tray-unread.png
  for every required variant (dev + prod) and aborts (exit 1) without
  emitting, instead of silently building a partial/stale TRAY_ICONS
Comment thread src/tray.ts Outdated
new Store() reads+writes the prefs file on construction, which can throw
on a filesystem error (unreadable/locked path, or a path that is a
directory). At module load that would crash the main process before any
window opens, and clearInvalidConfig only heals malformed content, not
filesystem errors. Construct lazily inside maybeShowTrayHint's existing
try/catch so such failures disable the hint instead of crashing startup.
@laplace-anon laplace-anon merged commit 8e6c971 into master Jun 26, 2026
7 checks passed
@laplace-anon laplace-anon deleted the feat/system-tray branch June 26, 2026 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant