Skip to content

fix(windows): tray notification copy, Claude Code disable modal, Claude Desktop 3P detection#180

Merged
5 commits merged into
mainfrom
fix/windows-tray-followups
Jun 24, 2026
Merged

fix(windows): tray notification copy, Claude Code disable modal, Claude Desktop 3P detection#180
5 commits merged into
mainfrom
fix/windows-tray-followups

Conversation

@stuffbucket

@stuffbucket stuffbucket commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Three Windows-only fixes from hands-on testing of the v0.4.34/-beta builds. macOS is unaffected by all three (each change is platform-gated or touches only the Windows branch).

1. Startup notification copy + arrow (shell/src-tauri/src/lib.rs)

The "Maximal is running" toast pointed up at a menu bar that doesn't exist on Windows. Platform-gated the body:

  • macOS: Look for the Maximal icon in your menu bar ↑ (unchanged)
  • Windows/other: Maximal is running in your system tray ↓

2. "Restart Claude Code" modal on disable (AppCard.tsx + new platform.ts)

On Windows, a running Claude Code session keeps routing through the proxy until restarted (it reads its base URL at launch; macOS picks the change up live). Disabling the Claude Code toggle on Windows only now shows a modal (reusing the existing ConfirmDialog) telling the user to /exit and relaunch. Confirm proceeds; Cancel reverts the controlled switch. macOS and all other toggles are byte-for-byte unchanged. Closes #178.

3. Claude Desktop 3P dir + detection (claude-desktop-3p-config.ts, apps.ts)

Two bugs surfaced by an investigation of Anthropic's admin-deployment docs:

  • Wrong drive: getClaude3pDir() wrote the 3P configLibrary to %APPDATA%\Claude-3p (Roaming), but Anthropic locates it under %LOCALAPPDATA%\Claude-3p (Local) — so the config landed where Claude Desktop never reads it. On macOS both halves share ~/Library/Application Support; on Windows the consumer config (Roaming) and the 3P dir (Local) diverge. Fixed to %LOCALAPPDATA%.
  • Circular detection: the Apps route detected Claude Desktop via getClaude3pDir() existence — but that dir only exists after maximal writes it, so Claude read as not-installed until configured. Switched to the existing, already-tested claudeAppInstalled() (probes %LOCALAPPDATA%\AnthropicClaude + the WindowsApps\Claude.exe shim; /Applications/Claude.app on macOS — same as before).

Deferred (documented in memory, not blockers): Windows managed/enterprise config is registry-based (HKLM\SOFTWARE\Policies\Claude, managed > local) — we write only the local configLibrary (correct for unmanaged/dev); and MSIX/Store-build path virtualization under %LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\… is not yet enumerated.

Validation

Full suite 1025 pass / 0 fail · check:fast clean · shell tsc clean · build:ui bundles. Test build cut as v0.4.35-beta.1 (prerelease, not Latest) for hands-on Windows verification of all four fixes (these three + the merged models-prime-on-sign-in #177).

Round 2 — second Windows test pass (fan-out investigation)

Three more issues from hands-on testing. macOS remains unaffected (each change is platform-gated, macOS-side, or Windows-only).

4. Claude Desktop MSIX/Store detection (configure-claude-desktop.ts)

The card still showed "Not installed" on a real Windows install. Root cause: the only candidates were the legacy Squirrel paths (%LOCALAPPDATA%\AnthropicClaude + the WindowsApps\Claude.exe alias). New Windows installs are MSIX/Store, which creates neither — they live under %LOCALAPPDATA%\Packages\Claude_<hash>. Added the known MSIX package dir as a candidate plus a Packages scan for the Claude_ / AnthropicPBC.Claude family prefix (hashed family names defeat any fixed path). macOS /Applications/Claude.app and the "can't tell → don't block" path on unknown platforms are untouched. 5 new injected-platform tests.

5. Splash render glitch on Windows (shell/src-tauri/src/lib.rs)

The transparent splash showed an empty outline for seconds before the brand fill appeared. Classic WebView2 cold-start: the native surface is presented before the compositor draws its first frame. Build the splash hidden and .show() it from on_page_load once the DOM reports Finished. macOS/WKWebView paints in lockstep so it fires immediately there — no regression.

6. Notification click → open Settings (shell/src-tauri/src/lib.rs)

  • macOS: broadened the RunEvent::Reopen handler — clicking the "Maximal is running" banner (or the Dock icon) with no visible windows now opens Settings (account section when signed out, plain Settings otherwise).
  • Windows: the installed tauri-plugin-notification (2.3.3) show() is fire-and-forget — no toast-activation callback exists on desktop at this version. Per maintainer decision, accepted as a limitation for now: tray left-click already opens Settings and the toast body points there. Making the Windows toast itself clickable would require direct tauri-winrt-notification activation (AUMID + COM) or a plugin swap — tracked as a follow-up, not in this PR.

Validation (round 2)

Full suite 1028 pass / 0 fail · lint clean · tsc clean · cargo check clean.

macOS copy (menu bar ↑) is unchanged; only the non-macOS branch gets
"Maximal is running in your system tray ↓".
…ndows

On Windows a running Claude Code session keeps routing through the proxy
until restarted (it reads its base URL at launch); macOS picks the change
up live. Show a modal (reusing ConfirmDialog) before disabling, Windows
only, telling the user to /exit and relaunch. Closes #178.
…etection

Two Windows-only bugs surfaced by hands-on testing (macOS unaffected):

1. getClaude3pDir wrote the 3P configLibrary to %APPDATA%\Claude-3p
   (Roaming), but Anthropic's docs locate it under %LOCALAPPDATA%\Claude-3p
   (Local) — so the config landed where Claude Desktop never reads it. On
   macOS both halves share ~/Library/Application Support; on Windows the
   consumer config (Roaming %APPDATA%\Claude) and the 3P dir (Local) diverge.

2. The settings Apps route detected Claude Desktop via getClaude3pDir()
   existence — circular, since that dir only exists after maximal writes it,
   so Claude read as not-installed until configured. Switch to the existing
   claudeAppInstalled() (probes %LOCALAPPDATA%\AnthropicClaude + the
   WindowsApps launcher shim; /Applications/Claude.app on macOS — same as
   before there).

Refs the Claude Desktop 3P config path investigation (Anthropic admin-deploy
docs: configLibrary under Local; managed config is registry HKLM/HKCU).
New Windows installs are MSIX, not Squirrel — they don't create
%LOCALAPPDATA%\AnthropicClaude or always drop the WindowsApps alias, so
the Apps card showed 'Not installed' on a real install. Add the known
MSIX package dir (Packages\Claude_pzs8sxrjxfjjc) as a candidate and scan
the Packages dir for the Claude_/AnthropicPBC.Claude family prefix
(hashed family names mean no fixed path catches every install). macOS
and the unknown-platform 'can't tell → don't block' path are untouched.
On Windows/WebView2 the native surface is presented before the
compositor draws its first frame, so the transparent splash showed an
empty outline for hundreds of ms–seconds before the brand-red fill
popped in. Build the splash hidden and .show() it from on_page_load once
the DOM reports Finished. macOS/WKWebView paints in lockstep with show
so this fires immediately there — no regression.

Also broaden the macOS Reopen handler: clicking the 'Maximal is running'
banner (or the Dock icon) with no visible windows now opens Settings —
account section when signed out, plain Settings otherwise. Desktop
notifications can't carry a routable click (plugin show() is
fire-and-forget), so Reopen is the lever on macOS. On Windows the
plugin (2.3.3) exposes no toast-activation callback; tray left-click
already opens Settings and the toast body points there.
@stuffbucket stuffbucket closed this pull request by merging all changes into main in 1164d79 Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows] Disabling the Claude Code toggle doesn't take effect until Claude Code is restarted

1 participant