Skip to content

Add Windows support with an MSI installer - #1

Merged
Arylmera merged 1 commit into
mainfrom
claude/windows-msi-installer-7933k9
Jul 16, 2026
Merged

Add Windows support with an MSI installer#1
Arylmera merged 1 commit into
mainfrom
claude/windows-msi-installer-7933k9

Conversation

@Arylmera

Copy link
Copy Markdown
Owner

What

Brings FileFlow to Windows, distributed as an MSI installer, while keeping macOS the primary platform. Built test-first: every new cross-platform behaviour landed as a failing test before its implementation, and all the Windows logic that can be pure (parsing, command building, name sanitization) lives in fileflow-core so it is unit-tested on every platform — no Windows host needed to catch regressions.

Core (fileflow-core) — TDD, 24 new tests

  • expand("~/…") now falls back to %USERPROFILE% when $HOME is absent; the pure body expand_with_home is directly tested.
  • New fileflow_core::windows module (pure, compiled everywhere):
    • parses Get-CimInstance Win32_Volume … | ConvertTo-Json output — volume GUID (the Windows analogue of the macOS volume UUID that decides which card rule fires), drive letter, label, removable/fixed kind; handles PowerShell's single-object collapse and letter-less recovery partitions;
    • injection-safe eject script builder (rejects anything but X:) using the Shell.Application COM verb — the same path as Explorer's Eject;
    • explorer_select_arg for reveal-in-Explorer;
    • sanitize_segment: makes rendered folder/file names legal on NTFS/exFAT (invalid chars, trailing dots/spaces, reserved device names like CON), applied by layout::render/render_filename on Windows builds only.
  • ingest::eject dispatches per platform: diskutil (macOS), PowerShell (Windows), explicit EjectUnsupported elsewhere.
  • Photos import fails loudly with PhotosUnsupported off macOS — a Photos rule can never silently strand files.

Tauri shell

  • volume.rs split per platform behind one API: /Volumes + diskutil -plist on macOS; PowerShell Win32_Volume JSON on Windows (spawned with CREATE_NO_WINDOW, plist dep now macOS-only); inert stubs elsewhere.
  • Drive arrivals: FSEvents watcher on macOS; on Windows a gentle 5s polling thread feeds the same diffing worker (identical downstream flow, incl. the safety spine).
  • Boot-volume protection maps to %SystemDrive% on Windows (never ejected/wiped).
  • reveal_in_finder opens Finder on macOS, Explorer (/select,) on Windows; new get_platform command; Full Disk Access heuristics and the tray "Import to Photos now" item are macOS-gated.

MSI installer + guard rails

  • bundle.windows config: stable WiX upgradeCode (so upgrades replace instead of duplicating) and webviewInstallMode: downloadBootstrapper (fresh Windows 10 machines get WebView2 automatically).
  • npm run build:msitarget/release/bundle/msi/FileFlow_x.y.z_x64_en-US.msi.
  • New bundle_conf_tests.rs guards the installer config in CI on every platform: upgrade code is a real GUID, WebView2 mode set, a .ico icon is listed, and tauri.conf.json/package.json versions stay in lockstep.

UI

  • The frontend asks the shell for its platform once: off macOS the Apple Photos flow is hidden (add button, destination option, copy), the Dock toggles disappear, and "menu bar" wording becomes "system tray". An existing photos rule (config copied from a Mac) still renders instead of blanking the select.

CI

  • New windows-latest job: cargo test --workspace, cargo clippy -D warnings, then builds the MSI and uploads it as an artifact — the installer is proven buildable on every PR.

Verification

  • cargo test -p fileflow-core: 56 tests green (32 existing + 24 new).
  • cargo clippy --workspace --all-targets --target x86_64-pc-windows-msvc -- -D warnings: clean (whole workspace cross-checked for the Windows target).
  • tsc --noEmit + vite build: clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DJTErYrYaCuGdv2uB4obBB


Generated by Claude Code

Core (all TDD'd, pure and testable on every platform):
- expand(~) now falls back to %USERPROFILE% (expand_with_home is the pure body)
- new fileflow_core::windows module: Win32_Volume JSON parsing (volume GUID,
  drive letter, removable/fixed kind), injection-safe eject script builder,
  Explorer /select argument, Windows-safe name sanitization
- layout: render sanitizes segments on Windows (render_windows_safe testable
  everywhere); render_filename sanitizes the stem on Windows
- ingest::eject dispatches per platform (diskutil / PowerShell Shell.Application);
  explicit EjectUnsupported elsewhere
- Photos import fails loudly with PhotosUnsupported off macOS

Tauri shell:
- volume.rs split per platform: /Volumes + diskutil on macOS, PowerShell
  Win32_Volume on Windows (no console flash), stubs elsewhere
- drive arrivals: FSEvents watcher on macOS, gentle polling thread on Windows
- reveal opens Finder or Explorer; new get_platform command
- Full Disk Access heuristics and the tray Photos item are macOS-gated

MSI + guard rails:
- bundle.windows with stable WiX upgradeCode and WebView2 downloadBootstrapper
- npm run build:msi; config guarded by core tests (upgrade code, webview mode,
  .ico icon, version lockstep with package.json)

CI runs the full test/clippy gauntlet on windows-latest and builds the MSI as
an artifact. README documents Windows install, build, and file locations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DJTErYrYaCuGdv2uB4obBB
@Arylmera
Arylmera marked this pull request as ready for review July 16, 2026 15:51
@Arylmera
Arylmera merged commit f4b231e into main Jul 16, 2026
2 checks passed
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.

2 participants