Skip to content

Phase 1: Windows Integration — file associations, default reader, store-aware updates (v1.2.7) - #91

Merged
sparshsam merged 9 commits into
mainfrom
feat/windows-integration
Aug 3, 2026
Merged

Phase 1: Windows Integration — file associations, default reader, store-aware updates (v1.2.7)#91
sparshsam merged 9 commits into
mainfrom
feat/windows-integration

Conversation

@sparshsam

Copy link
Copy Markdown
Owner

Summary

Completes Phase 1: Windows Integration for OpenReader (target release v1.2.7).

v1.2.5 — File Association Fix

  • MSIX .pdf windows.fileTypeAssociation + Inno ChangesAssociations=yes
  • Single-source version injector (scripts/inject_version.py) across main.py, the MCP package, and both MSIX manifests; build-msix.ps1 derives its default version from the manifest
  • Recent-files *** settings-key migration; changelog dedupe; tests/test_packaging.py

v1.2.6 — Default Reader Experience

  • pdfreader_lib/win_default_apps.py — reads the Windows UserChoice ProgID and resolves ownership via the registered open command / AppUserModelId
  • Settings dialog (Default Apps section); first-launch prompt
  • Fix: ProgIDs now resolved across HKCU + HKLM (admin Inno installs register OpenReaderPDF under HKLM) — the false "not the default" recovery warning no longer appears when OpenReader is the default; Settings shows a confirmation and a neutral Open Default Apps action

v1.2.7 — Store-Aware Updates

  • Install-source detection via GetCurrentPackageFamilyName (Windows package API)
  • Store/MSIX installs never query GitHub; GitHub installs keep release checks with persisted Skip This Version; clean offline handling
  • Build version precedence: explicit → exact Git tag → source __version__ (no regression to an older tag or 0.0.0-dev)

Test evidence

  • Full suite: 138 passed, 18 skipped, 0 failed
  • py_compile clean · bash -n clean
  • All authoritative version sources agree at 1.2.7 / 1.2.7.0

Manual validation (Inno test build, Windows)

Open with ✓ · Default apps ✓ · selectable as default ✓ · double-click opens ✓ · second PDF routes to existing instance ✓ · first-launch prompt ✓

Store / MSIX note

The signed Store MSIX cannot be produced locally (Store signing only, frozen identity preserved). Post-release acceptance steps are in docs/store-acceptance-checklist.md. This PR makes no tag, GitHub Release, or Microsoft Store submission.

sparshsam and others added 9 commits August 2, 2026 13:30
- MSIX manifest declares a .pdf file-type association (windows.fileTypeAssociation), so Store/MSIX installs appear under Open with and Default apps.
- Inno installer sets ChangesAssociations=yes to refresh the association cache.
- scripts/inject_version.py now propagates one version across main.py, the MCP package, and both MSIX manifests; build-msix.ps1 derives its default version from the manifest so it cannot drift.
- Migrate recent files from the accidentally-named "***" settings key to "recentFiles", preserving existing users' history.
- Add tests/test_packaging.py validating the .pdf association, frozen identity, and cross-source version alignment.

Co-Authored-By: Claude <noreply@anthropic.com>
- Add pdfreader_lib/win_default_apps.py: reads the Windows UserChoice ProgID for .pdf, resolves ownership via the AppUserModelId (MSIX) or the OpenReaderPDF ProgID (legacy installer), and opens the Default Apps page. Never writes the default — Windows keeps the final confirmation.
- Add first-launch prompt (Set as default / Maybe later / Do not ask again), persisted in QSettings.
- Add Settings dialog (File -> Settings) with a Files / Default Apps section showing the current PDF default, a Set-default button, and a recovery message when the association isn't registered.
- Add tests/test_win_default_apps.py with an in-memory fake winreg covering Inno and MSIX detection, non-Windows neutrality, friendly-name lookup, and the Default Apps launcher.

Co-Authored-By: Claude <noreply@anthropic.com>
- Add pdfreader_lib/install_source.py detecting source / MSIX-Store / Setup.exe / portable installs.
- Store/MSIX installs no longer query GitHub: the Software Updates dialog shows a Store-managed message with an Open Microsoft Store button.
- GitHub installs keep release detection: current -> latest, release notes, persisted Skip This Version (updateSkipVersion), and a last-checked timestamp.
- Clean offline handling with Try Again; silent launch checks never re-notify a skipped release.
- Align all version sources to 1.2.7 via scripts/inject_version.py.
- Changelog entries for v1.2.5-v1.2.7 and release/updater docs updated to match the new mechanics.
- Update stale README/subprocess tests to reflect current behaviour (Store-primary docs, no subprocess usage).

Co-Authored-By: Claude <noreply@anthropic.com>
…very state

- win_default_apps.py: resolve ProgIDs across both HKCU and HKLM (the hives HKCR merges). An admin Inno install registers OpenReaderPDF under HKLM\Software\Classes, so association_registered() previously returned False and Settings showed a false recovery warning even when OpenReader was the default.
- Ownership is now resolved defensively: exact Inno ProgID, a registered shell\open\command invoking OpenReader.exe, or AppUserModelId == AUMID.
- Settings shows "OpenReader is the default PDF reader" with a neutral "Open Default Apps" action when default; recovery appears only when OpenReader is neither default nor registered.
- Extract filter_pdf_paths() as a testable application-boundary seam.

Co-Authored-By: Claude <noreply@anthropic.com>
- install_source.py: detect packaged (MSIX/Store) execution through GetCurrentPackageFamilyName — the process-level AppX identity — rather than assuming a WindowsApps filename. The path check remains as a fallback for environments where the API is unavailable.

Co-Authored-By: Claude <noreply@anthropic.com>
… an older tag

- build_windows.ps1 / build_macos.sh / build-windows.yml: use (1) explicit build/workflow version, (2) exact Git tag on HEAD, (3) the authoritative source __version__ from main.py. Ordinary branch builds no longer regress the embedded version to the nearest older tag or 0.0.0-dev; CI test builds append -test to the source version.
- .gitignore: ignore test-builds/ so downloaded workflow artifacts can't be committed.

Co-Authored-By: Claude <noreply@anthropic.com>
- Version comparison: 1.2.7-test never reports v1.2.4 as newer; malformed/missing remote versions → json_error; unparseable current version falls back safely.
- Path boundary: filter_pdf_paths keeps spaces/Unicode/parentheses/long paths; IPC JSON round-trip preserves Unicode.

Co-Authored-By: Claude <noreply@anthropic.com>
- CHANGELOG: record the detection fix, package-API detection, and build version-precedence fix.
- docs/store-acceptance-checklist.md: exact post-release Store/MSIX validation steps (frozen identity, file association, default reader, updates) for the signed Store build that cannot be produced locally.
- docs/updater-architecture.md: note GetCurrentPackageFamilyName-based detection.

Co-Authored-By: Claude <noreply@anthropic.com>
…de error

- Add --source-version mode to scripts/inject_version.py: reads main.py as UTF-8 and prints __version__ without modifying anything.
- build-windows.yml / build_macos.sh / build_windows.ps1 now call it instead of an inline python -c regex, which raised UnicodeDecodeError on Windows (cp1252 default) when reading main.py's non-ASCII content.

Co-Authored-By: Claude <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 3, 2026

Copy link
Copy Markdown

Deploying reader with  Cloudflare Pages  Cloudflare Pages

Latest commit: a5d5ee5
Status: ✅  Deploy successful!
Preview URL: https://68130d6c.reader-bsl.pages.dev
Branch Preview URL: https://feat-windows-integration.reader-bsl.pages.dev

View logs

@sparshsam
sparshsam merged commit 1daae44 into main Aug 3, 2026
7 checks passed
@sparshsam
sparshsam deleted the feat/windows-integration branch August 3, 2026 01:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant