Commit Graph
127 Commits
Author SHA1 Message Date
tiennm99 fa889c176a docs: pin the release dry run to a branch carrying the Tauri workflow 2026-10-21 18:00:29 +07:00
tiennm99 08e61e6755 docs: refresh Cargo.lock in the release dry-run steps 2026-10-21 17:52:56 +07:00
tiennm99 13fae90fd8 docs: record the cleanup and docs status and the open parity checks 2026-10-21 17:45:00 +07:00
tiennm99 2671d5d89e docs: cover the version source, signing-key custody, dry run and legacy rollback in the release process 2026-10-21 17:45:00 +07:00
tiennm99 37aa3cd2be docs: document Linux support, the WebView2 requirement and the Tauri build in the README 2026-10-21 17:45:00 +07:00
tiennm99 fdf30ac005 docs: describe the credentials path for every OS in the local credentials reader 2026-10-21 17:45:00 +07:00
tiennm99 9a9b01ff07 ci: scope the updater signing key to signing steps and split the legacy publish job
The signing key moves from job-level to step-level env, so npm install scripts, setup actions and crate build scripts never see it. Linux compiles without the key and signs in a separate tauri bundle step. The legacy rollback builds and signs under a read-only, unpersisted token with the locked Tauri CLI, and a separate job holds the write token to publish.
2026-10-21 17:29:56 +07:00
tiennm99 81f29f2e4f ci: publish only plain vX.Y.Z tags so suffixed dry-run tags stay drafts 2026-10-21 17:19:23 +07:00
tiennm99 e712978ff6 docs: record the release pipeline status and legacy-client checks 2026-10-21 17:11:57 +07:00
tiennm99 6c7771e04c docs: describe the release assets, their name contract and the residual update risk 2026-10-21 17:06:21 +07:00
tiennm99 94019a13a3 ci: add a Windows-only legacy release workflow for rollback 2026-10-21 17:06:05 +07:00
tiennm99 435797ad91 ci: release a signed Windows exe, Linux AppImage and deb with latest.json 2026-10-21 17:06:05 +07:00
tiennm99 14bdf95bc0 ci: add a yamllint config for the workflow files 2026-10-21 17:06:04 +07:00
tiennm99 51d20b16b1 build: generate the updater latest.json and guard the release asset set 2026-10-21 16:58:48 +07:00
tiennm99 94722f2741 ci: refuse a release while the updater public key is empty 2026-10-21 16:45:27 +07:00
tiennm99 4918a5e3bd docs: note the green CI run for the updater 2026-10-21 16:35:20 +07:00
tiennm99 2397d48682 docs: record the updater status and decisions 2026-10-21 16:27:07 +07:00
tiennm99 31cca4cdda build: refuse a signed build that lacks the updater public key
With TAURI_SIGNING_PRIVATE_KEY set, the build script now requires a
non-empty plugins.updater.pubkey (from tauri.conf.json or a --config
override). A release without it could never verify, and so never install,
a later update.
2026-10-21 16:24:35 +07:00
tiennm99 d5fe3d8f27 feat: check and apply updates through the Tauri updater plugin
The plugin fetches latest.json and downloads the platform entry, verifying
its minisign signature. The suffix-ignoring version comparison moves to
core::version and drives the plugin comparator; a manifest without an entry
for this platform counts as up to date. The Windows portable exe swaps
itself in with self_replace, an AppImage goes through the plugin install,
and both relaunch with --updated-to. A package-manager install keeps
checking but greys the apply item.

The GitHub API lookup, the WinHTTP download and the --apply-update helper
are gone, along with the sha2 dependency they needed.
2026-10-21 16:24:32 +07:00
tiennm99 43e0d825a7 docs: record the fullscreen auto-hide status and decisions 2026-10-21 16:02:18 +07:00
tiennm99 8d7a07b237 feat: hide the bubbles while another app is fullscreen
A 1.5 s thread asks the platform whether the foreground window is a
fullscreen window of another process and feeds the result through the
visibility state machine. Windows keeps the proven evaluation with an
own-process check in place of the bubble class check; Linux reads the
EWMH active window state over X11; native Wayland and macOS report false.
2026-10-21 15:58:02 +07:00
tiennm99 9c7ade8ea3 fix: reload the panel for browser keys only after its first page load 2026-10-21 15:44:00 +07:00
tiennm99 388305de04 docs: record the details panel status and decisions 2026-10-21 15:34:01 +07:00
tiennm99 2180efaf85 feat: draw the details panel from the payload and suppress webview shortcuts 2026-10-21 15:29:26 +07:00
tiennm99 768fb1e4ab feat: toggle a details panel window from bubble clicks with focus dismissal and live refresh 2026-10-21 15:29:26 +07:00
tiennm99 e805f8de8f fix: keep the dark default on Linux when the portal states no theme preference 2026-10-21 15:12:40 +07:00
tiennm99 1370c15048 fix: size reset bubbles for the primary monitor before placing them 2026-10-21 14:57:42 +07:00
tiennm99 0d35c87d1e docs: record the bubble window and UI status and decisions 2026-10-21 14:44:04 +07:00
tiennm99 094b6bdcb0 feat: draw the bubble from the payload in HTML, CSS and SVG
The stadium pill holds SVG usage and time rings, pill-shaped tail bars and
the payload's texts, laid out in physical px from canvasW, canvasH and dpi
with the GDI bubble's formulas (ui/layout.js, unit-tested). The palette is
CSS custom properties per theme; fills come from Rust. The ring arc, weekly
fill and weekly percent pulse at 95% and above on an 80 ms step, and the
time progress advances every minute.

Only the pill takes pointer input, so the corners are dead. A press that
moves 3 physical px starts an OS drag after arming the move end; an earlier
release is a click. Right-click opens the native menu and Ctrl+wheel resizes.
2026-10-21 14:40:18 +07:00
tiennm99 340464de58 feat: build the bubble windows with snapping, no-activate show and visibility state
Each enabled live provider gets a transparent, undecorated, always-on-top
bubble webview, created hidden at its exact physical size and its saved or
default position, clamped into the work area. It is shown without taking
focus once the page reports ready, or 1.5 s after creation.

On Windows a subclass hook reports move ends, setting changes (theme
recheck and reclamp) and display changes, answers WM_MOUSEACTIVATE with
MA_NOACTIVATE, and bubbles are shown and hidden only through
SW_SHOWNOACTIVATE and SW_HIDE. Elsewhere a 250 ms debounce armed by the
page's drag start ends the drag; on X11 it waits while Button1 is held.
Move end snaps once and saves the position; resize, clamp and reset only
move the windows. Native Wayland skips positioning.

User show/hide goes through a pure visibility state shared with the coming
fullscreen auto-hide, and the saved widget_visible now applies at startup.
A theme change reaches open bubbles. The unused os module is removed.
2026-10-21 14:40:13 +07:00
tiennm99 4da57949ee fix: register the tray click handler app-wide and probe unversioned AppIndicator names
A per-icon tray handler runs while Tauri holds the per-icon listener
table; the inline refresh could build a missing icon that locks the same
table. The app-level handler avoids that. The AppIndicator probe now
matches the tray backend's backcompat names, which some AppImages need,
and keeps the loaded library open.
2026-10-21 14:16:02 +07:00
tiennm99 bee9565c35 docs: keep the menu and alerts phase open until the Windows toast check passes 2026-10-21 14:05:06 +07:00
tiennm99 974d9c1afd fix: build bubbles off event handlers, snapshot tray state on the main thread, keep Windows autostart per user
Building a webview window inside a menu or window event handler deadlocks
on Windows, so provider toggles and the Destroyed recreate now build the
bubble on a short-lived thread, serialised so only one of them creates it.

refresh_shell now takes its state snapshot inside the main-thread closure,
so a refresh queued by the poll worker cannot re-apply a tree older than
one a menu click already applied.

On Windows the start-at-login entry is written through auto-launch in
current-user mode with the quoted exe path, so an elevated run can no
longer write an all-users entry with an unquoted path that a normal run
cannot remove. Linux and macOS keep the autostart plugin.
2026-10-21 14:05:06 +07:00
tiennm99 17d77bde82 docs: record the menu, tray, alerts and autostart status and decisions 2026-10-21 13:46:45 +07:00
tiennm99 f2063bda4f feat: add tray icons, the native context menu, notifications and start at login
Each enabled live provider gets a tray icon with the usage badge, a four-line tooltip and the context menu; a left click toggles the widget. Menus are rebuilt from state after every click so native check marks stay right, and a bubble right-click pops the same menu.

Alerts go through the notification plugin. On Windows the app id is registered under HKCU with a name and icon first, so a portable exe without a Start-menu shortcut can show toasts.

Start at login uses the autostart plugin under the Run value name earlier releases wrote, so an existing entry is picked up as is. On Linux the tray is skipped when no AppIndicator library loads instead of aborting.
2026-10-21 13:45:59 +07:00
tiennm99 539f26019b feat: render the tray badge as straight RGBA for Tauri tray icons 2026-10-21 13:45:49 +07:00
tiennm99 a395c66248 docs: record the app runtime status and decisions 2026-10-21 13:24:58 +07:00
tiennm99 83f60d1c1c feat: run the app on a Tauri runtime with shared state and commands
run() keeps the pre-builder order: diagnostic log, the Windows WebView2 guard
(a message box with the download link, then exit 0), the --wait-pid wait
capped at 15 s, GDK_BACKEND=x11 under Wayland when Xwayland is present, and
the single-instance plugin registered first with a no-op callback.

setup() loads the settings, drops positions on missing monitors, reads the
theme, cleans up after earlier updates, starts the scheduler and polls. The
state sits behind one mutex reached only through with_state, so no Tauri call
runs under the lock. The poll worker keeps the in-flight gate, applies the
results, runs the CLI credential refresh and pushes bubble payloads from the
main thread.

Commands: get_bubble_state, get_strings, log_js and bubble_ready. Bubble
windows ignore close requests; Restart saves the settings and exits only once
the new instance spawned. The scaffold window now renders its payload as JSON.

The Win32 app module is removed.
2026-10-21 13:20:15 +07:00
tiennm99 6d84f33e59 feat: add the scheduler thread for polls, countdowns and update checks
One std thread owns the poll, countdown and update-check deadlines and is fed
over an mpsc channel. The deadline rules are a pure struct tested with
fabricated instants; the thread hands each due action to a host trait.

An update check that fires stays disarmed until the check reports back, and
only that report re-arms the full interval, so the automatic check repeats
instead of running once. Changing the interval checks at once when the last
check is older than the new interval.
2026-10-21 13:19:37 +07:00
tiennm99 607a3103d3 feat: parse the CLI flags, wait for the previous instance and clean up after updates
The argv parser accepts --diagnose, --wait-pid and --updated-to and ignores
anything else, including --apply-update, which no released version passes to
the downloaded binary. Arguments are read lossily, so a non-UTF-8 argument no
longer panics.

The wait for a parent pid polls kill(pid, 0) on Unix and waits on the process
handle on Windows, capped by the caller. The Windows platform module gains the
WebView2 runtime probe, an error message box and the theme read.

handoff::relaunch spawns the AppImage or the current executable detached with
--wait-pid and returns the spawn error to the caller. The startup cleanup of
<exe>.old.* siblings and staged updater executables moves out of the Win32
update module.
2026-10-21 13:19:15 +07:00
tiennm99 4ca4f075f3 docs: fix a duplicated phrase in the data layer proxy notes 2026-10-21 13:00:57 +07:00
tiennm99 b3afcdc04e fix: skip SOCKS environment proxies so an HTTP or system proxy applies
ureq is built without socks-proxy, so an ALL_PROXY=socks5h entry failed
every request and a socks5 entry silently connected directly, while also
suppressing the Windows system proxy. Pick the first HTTP or HTTPS proxy
from the environment ourselves, keep NO_PROXY on it, and fall back to the
system proxy when none is usable.
2026-10-21 13:00:50 +07:00
tiennm99 b8e672f750 fix: give the refresh CLI the search PATH and reject non-HTTP system proxies 2026-10-21 12:52:22 +07:00
tiennm99 91d2741028 docs: record the data layer status and decisions 2026-10-21 12:45:52 +07:00
tiennm99 9e2666ff0e feat: port the data layer to ureq with the Windows system proxy
Replace the WinHTTP client with a ureq agent that keeps the same
Client/Response surface: status errors come back as responses, gzip,
60 s connect / 30 s receive / 120 s total timeouts, rustls with the
platform verifier and a per-request User-Agent override.

Environment proxies come from ureq. On Windows, when none is set, the
static Internet Settings proxy is read from HKCU and parsed by a pure
core module (per-scheme ProxyServer, ProxyOverride globs and <local>);
bypassed hosts go through a direct agent. PAC/WPAD is not evaluated.

The usage providers and credential sources compile again on every
platform. Refresh keeps the Windows candidates and CREATE_NO_WINDOW;
Unix spawns claude/codex from PATH plus the usual per-user install
directories and reaps the child on a detached thread. An empty
CODEX_HOME now counts as unset and a float expiresAt is truncated
instead of ignored.

Fixture tests cover the OAuth usage body, rate-limit headers (including
a 429 over loopback), the ChatGPT envelope, ISO 8601 edge cases,
credential JSON and proxy strings. An ignored live_poll test polls the
real providers.
2026-10-21 12:41:08 +07:00
tiennm99 10c43d76af docs: record the portable core status and decisions 2026-10-21 12:24:08 +07:00
tiennm99 76ee0203cb feat: add the portable state, payload and menu model
Poll results, threshold crossings and the alert cooldown now return
values instead of calling the tray, so they run under unit tests. The
bubble and panel payloads carry every display string and colour from
Rust, and the context menu is a plain tree with string ids that parse
back into commands. The update-check schedule and countdown delay are
plain functions of the stored times.
2026-10-21 12:23:53 +07:00
tiennm99 bc1a098875 refactor: move settings, strings, colours and geometry into a portable core
Settings, the English strings, the colour ramp and the bubble geometry no
longer touch Win32 types, so they compile and test on every platform.
Snapping, clamping, default placement, panel placement and the monitor
probe take plain rects; settings loading is split into parsing and an
offscreen check fed with the monitor list. ProviderId now serialises as
its slug.
2026-10-21 12:23:15 +07:00
tiennm99 d8f339208d fix: list the desktop icons in bundle.icon
The bundler has no icon fallback, so an empty list breaks the AppImage
step and ships a deb without hicolor icons. Put icon.png first so it stays
the default window icon on Linux and macOS, and bundle the deb in the
Linux CI row to catch a broken list before release.
2026-10-21 12:04:54 +07:00
tiennm99 ffaa6c17a9 docs: record the Tauri scaffold status and decisions 2026-10-21 11:56:30 +07:00