Skip to content

v0.2.0: Check for Updates everywhere + popover Settings shortcut#19

Merged
mariomeyer merged 4 commits into
mainfrom
phase-4-followups-5
May 23, 2026
Merged

v0.2.0: Check for Updates everywhere + popover Settings shortcut#19
mariomeyer merged 4 commits into
mainfrom
phase-4-followups-5

Conversation

@mariomeyer
Copy link
Copy Markdown
Member

Summary

Surfaces the auto-updater across every entry point a user might reach for it, plus a Settings shortcut from the popover.

Four commits:

  1. `feat(menu): "Check for Updates…" in menus + CHANGELOG link` — adds the macOS-standard menu item to both the Stint app menu (between About and Settings) and the tray right-click menu. Bridges via a module-level signal in `updates.ts` so the request lands even if UpdatesPanel mounts after the event. Also: when the manifest's notes is the literal "see CHANGELOG.md" placeholder, render as an `` to GitHub at the right release tag.
  2. `feat(about): show update-available badge next to version` — small emerald pill next to the version field, consuming the existing `useUpdateBanner()` signal. Passive (not clickable) — About is a low-frequency informational surface, not an action surface.
  3. `feat(popover): Settings cogwheel + update-available indicator` — adds a cogwheel button to the popover footer (between "Open Stint →" and "Solidtime ↗") that opens the main window at /settings. Plus a one-line "Update available: vX.Y.Z → open Settings" row above the footer that only renders when an update is available. Popover users rarely open the main window — this was the biggest gap in update visibility.
  4. `chore(updater): dev preview mode via STINT_DEV_VERSION_OVERRIDE` — short-circuits `check_for_updates` in dev when the env var is set, returns synthetic data so all the new affordances can be previewed without editing tauri.conf.json or cutting a fake release. Production users never set the env var, so dormant in shipped binaries.

Three `feat:` + one `chore:` → semrelease cuts v0.2.0 (minor bump, fitting "Phase 4 complete" milestone).

Test plan

  • `cargo fmt --check`, `cargo clippy --workspace --all-targets -D warnings`, `cargo test --workspace --test-threads=1` all green
  • `pnpm typecheck` + `pnpm test run` (224/224) clean
  • Manual verification via `STINT_DEV_VERSION_OVERRIDE=0.0.1 scripts/dev-app.sh`:
    • Top-of-window banner renders
    • App menu has "Check for Updates…" item
    • Tray right-click has same
    • About page shows "v0.1.5 available" pill next to version
    • Popover shows update-available row + cogwheel button in footer
    • Settings → Updates panel shows "Install" button, notes line is a real link to GitHub CHANGELOG
  • CI green on this branch
  • On merge: v0.2.0 publishes through the full pipeline (tap, install.sh, latest.json)
  • Existing v0.1.5 installs see "v0.2.0 available" and can install + restart cleanly

Merge via "Create a merge commit" per standard.

Adds the macOS-standard "Check for Updates…" item to both the Stint app
menu (between About and Settings) and the tray right-click menu. Both
entries open the main window, navigate to /settings, and fire a
\`check-for-updates\` Tauri event.

A module-level signal in ui/src/lib/updates.ts (\`checkRequested\`)
bridges the event to UpdatesPanel: App.tsx's listener calls
\`requestCheckForUpdates()\` on receipt, which increments a counter that
UpdatesPanel watches via createEffect. Using a module-level signal
rather than a per-component one means the request lands even if the
panel mounts after the event arrives — createEffect runs on first
mount with the current counter value.

Also: when the manifest's notes field is the placeholder string
"see CHANGELOG.md", render it as an actual link to the GitHub
CHANGELOG.md at the right release tag rather than dumping plain text.
Custom notes (anything other than the placeholder) still render as a
\`<pre>\` block, leaving room for richer notes later.
Adds a small emerald pill ("v0.2.0 available") next to the version
field in the About page identity card. Passive — clicking it doesn't
do anything; it's strictly informational. Consumes the existing
\`useUpdateBanner()\` signal so it shares the 24h auto-poll cadence
rather than introducing a new check.

The About page is low-frequency, so making the badge clickable would
feel off — it's a "what is this app" surface, not an action surface.
Users who want to act on the update have the top-of-window banner,
the menu/tray "Check for Updates…" entries, and the popover indicator.
Two additions to the popover, both targeting the same gap: popover
users rarely open the main window, so neither the top-of-window update
banner nor the existing "Open Stint →" affordance reaches them
effectively.

1. Cogwheel button in the footer (between "Open Stint →" and
   "Solidtime ↗") that opens the main window and emits a navigate
   event to /settings. Same effect as menu/tray "Settings…" entries
   from inside the popover.

2. Conditional "Update available: vX.Y.Z → open Settings" link as a
   one-line row above the footer. Only renders when
   \`useUpdateBanner()\` reports an available update. Click → same
   path as the cogwheel: main window + /settings.

The popover and main window are separate webview contexts in Tauri,
so each runs its own \`useUpdateBanner\` polling instance. Bandwidth
impact is trivial (one GitHub fetch per 24h per window) and the
duplication keeps the code simple — no cross-webview signal sharing.
Adds a dev-only escape hatch in check_for_updates: when the
\`STINT_DEV_VERSION_OVERRIDE\` env var is set to a valid semver string,
short-circuits the network check and returns synthetic
\`available: true\` data. Lets a maintainer preview the new update
affordances — About badge, popover indicator, Settings panel state
machine — without editing tauri.conf.json or shipping a fake release.

Usage:
  STINT_DEV_VERSION_OVERRIDE=0.0.1 scripts/dev-app.sh

\`install_update\` is deliberately NOT mocked. Clicking Install while
the override is active hits the real updater and fails with
"no update available" since the actual running version equals the
manifest version. That's correct — don't let the preview path
accidentally exercise the real install on a dev build.

Adds semver = "1.0" as a stint-app dep (gated on the updater feature)
for parsing the env var. Tauri's updater stack already pulls semver
transitively, so no net dependency change.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fa29450c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +87 to +88
if (checkRequested() > 0) {
void check();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Consume check requests instead of replaying them on every remount

checkRequested is treated as a permanent boolean (> 0) rather than a consumable counter, so after the first menu/tray-triggered request this effect will call check() on every future UpdatesPanel mount even when no new request happened. In practice, opening Settings later will keep issuing unexpected network update checks and UI state flips from stale requests; the panel should track the last handled counter value (or reset/consume it) so only new increments trigger checks.

Useful? React with 👍 / 👎.

@mariomeyer mariomeyer merged commit ae6728f into main May 23, 2026
2 checks passed
@mariomeyer
Copy link
Copy Markdown
Member Author

🎉 This PR is included in version 0.2.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant