Skip to content

Commit ef5c50f

Browse files
pmaxhoganclaude
andauthored
Comprehensive UI/UX overhaul + tray i18n/icon fix + CLI tests (#37)
* chore(github): add issue templates; Issues as backlog source of truth Add .github/ISSUE_TEMPLATE/ (config.yml + bug_report + feature_request) so future Driven tasks are filed as GitHub Issues. Establishes GitHub Issues as the source of truth for not-yet-done work, replacing the ad-hoc backlog list. Templates default-apply the bug / enhancement labels and prompt for the Why-it-matters + Next-action structure used across the migrated backlog issues. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * test(cli): end-to-end driven-cli verification + fixes Actually exercise the driven-cli binary end-to-end and prove every subcommand works, per the M-slice "actually test the CLI" brief. What was done: - Ran the built binary: top-level --help / --version, each subcommand --help (auth, dump-refresh-token, sync, status, history, verify), and the clap error paths (no subcommand, unrecognized subcommand, missing required args). All parse and print sane help with correct exit codes. - Exercised the OFFLINE inspect subcommands (status / history / verify) end-to-end against throwaway temp state databases seeded through driven-core's public StateRepo surface (the same path the GUI app uses to create state.db), then reopened by the actual binary. New integration test crates/driven-cli/tests/cli.rs (assert_cmd + predicates + tempfile) with REAL assertions - 20 tests: - --help lists every subcommand; --version prints the version. - every subcommand --help parses. - auth / sync / dump-refresh-token required-argument error paths (these need live Google creds + a real gitignored refresh token to RUN, so only their parsing + error paths are covered here; the live auth/sync round-trip is exercised by the real-Drive e2e contract suite). - status / history / verify against missing, empty, and seeded DBs: missing DB exits 1 with a helpful message; empty DB reports no sources / no activity; seeded DB shows the source name + per-status counts and all activity levels; history --errors-only filters out INFO; history --limit caps rows newest-first. - verify exits 0 on a clean / empty DB and non-zero (exit 1) when a corrupt / error file row is present (scriptable contract). Added assert_cmd + predicates as dev-dependencies (tempfile already present); Cargo.lock updated accordingly. Bugs found: none. Running every subcommand surfaced no panics, wrong exit codes, broken arg parsing, or bad output - the CLI behaves correctly, so no source fix to crates/driven-cli was needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * feat(ui): design-system foundation, teal accent, nav IA, first-run wizard Comprehensive UI-CORE shell pass (design system + app shell + nav IA + first-run auto-open), not a whack-a-mole of individual fixes. Foundation (style.css): add the mandatory @layer base that declares the app's own light/dark background, text color, and color-scheme, plus a teal accent-color on checkboxes/radios. The app never declared these before, so the webview fell back to OS-dark native defaults - the root cause of the unreadable dropdowns / invisible text on a dark-theme OS. This is the single most important contrast fix. tailwind.config.ts: alias the whole teal scale as `brand` (brand-700 === teal-700, the icon's deep teal) so a future rebrand is one line; teal-* keeps working unchanged. App.vue top nav: apply the IA fix. The top nav was Activity | Accounts | Sources | Rules | Restore | About, but Accounts/Sources/Rules are also subtabs inside Settings - duplicated and confusing. Collapse to Activity | Settings | Restore | About with a teal "Driven" wordmark, teal active/hover link states, aria-current, focus-visible rings, a subtle bottom border, and responsive wrap. "Settings" stays active for /settings, /accounts, /sources, /rules. router.ts: add the /settings route (Settings.vue tab="accounts"); keep /accounts, /sources, /rules for tray deep-links + in-page subtabs. Add a one-shot first-run guard: on launch with zero accounts the app opens /setup instead of /activity; with accounts it lands /activity. Account presence is read via the same list_accounts IPC AccountList.vue uses. The guard self-removes after the first navigation (never traps the user on /setup), only diverts the default landing (deep-links honoured), and falls through to /activity on IPC failure (never crashes). Add DESIGN_SPEC.md capturing the palette, exact class strings, and the IA + first-run decisions, and router-first-run.test.ts (9 cases) covering the firstRunTarget decision and the guard end-to-end. Verified in ui/: pnpm install, lint, build (vue-tsc + vite), test:unit (190 pass), format:check - all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * feat(ui): Activity + Restore UX polish, empty-state dropdowns, teal accent Comprehensive design-system pass over the two screenshotted views. - Apply the DRIVEN design system consistently: every select/input/search box carries an explicit dark-mode-readable background + text color and teal focus rings; primary actions (Search, Restore) are teal, secondary (Clear, Pick destination, Load more, Export bundle) are bordered, destructive (Cancel restore) is red. Replace the emerald primary/progress fill with teal; emerald is kept only for per-file "done" success status text. - Empty dropdowns explain themselves: the Activity source + event-type filters and the Restore source select render a disabled, non-selectable placeholder ("No sources yet - add one in Settings" / "No events logged yet") and the select is :disabled when there are zero real options. - Consistent card/panel styling for summary stat tiles, the filters panel, the file list, and the restore progress panel; dashed empty-state cards; an intentional breadcrumb (ancestors are teal links, the current folder is plain text); a Restore subtitle + a no-sources empty state. - Add activity.* / restore.* i18n keys for the new strings. - Add vitest coverage for the empty-dropdown behavior (Activity + Restore). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * feat(ui): OAuth setup walkthrough + open sign-in in the system browser Fix the broken "Sign in with Google": the setup store no longer relies on window.open (which does not reliably reach the system browser in a Tauri v2 webview, so the OAuth consent page never opened). It now opens the consent URL via the official @tauri-apps/plugin-opener openUrl, awaited, with the opener still injectable for tests. A failed auto-open is no longer a dead end: connectAccount captures the consent URL and moves to awaitingCallback before opening, records a dedicated auth.browser_open_failed code on failure, and the credentials step renders a manual "open the sign-in page / copy this link" fallback (new openAuthUrl action). Add a detailed, collapsible first-run walkthrough to the credentials step that teaches a non-technical user how to create their own Google OAuth Client ID and secret with the current Google Cloud Console / Google Auth Platform button names (verified via web search), including the Testing-status 7-day refresh token caveat. All copy is seeded under wizard.step2.*. Apply the Driven design system (teal primary CTAs, zinc secondary, card panels, teal focus rings, dark-mode-readable inputs/selects) across SetupWizard, CredentialsWalkthrough, and RecoveryPhraseReveal, keeping every data-testid and t() key intact. Add/adjust setup-store vitest coverage for the default opener path, the open-failure path, and the manual re-open fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * fix(app): resolve rust-i18n keys (tray/notifications), real tray icon, wire opener plugin Three backend fixes in the driven-app crate. (1) i18n raw keys. locales/en-US.yml declared `_version: 2` while written in the v1 (per-locale, direct-string) format. Under rust-i18n 4.x the v2 parser treats each leaf key as a LOCALE name, so nothing resolved under "en-US" and every `t!()` returned the raw key - the tray menu showed "tray.sync_now" etc. and the tooltip/app name were unresolved. Declared the file `_version: 1` (the format it is actually in; nested YAML maps flatten to dotted keys like `tray.tooltip.idle`). Added real regression tests in tray.rs that assert the ACTUAL resolved text AND that it differs from the raw key (the old key==key tray tests could not catch this), plus a test that a non-en locale falls back to the en-US English strings. (2) Blank tray icon. tray.rs generated flat solid-colour RGBA tiles, so the tray showed an unrecognisable square. Now decodes the real Driven brand mark (white road-to-cloud on teal) from the committed icons/64x64.png via `Image::from_bytes` (new tauri `image-png` feature), cached once, and draws a per-state status badge (blue=syncing, amber=paused, orange=network, red=error) so each state stays recognisable AND distinct. Idle is the plain mark. Falls back to the flat tile only if the compiled-in PNG fails to decode (no panic). Kept the state-machine + severity + tooltip tests honest and added icon tests (badge applied/distinct/dimensions, no key==key traps). (3) Opener plugin (Rust half of the sign-in fix). Added tauri-plugin-opener = "2", registered `tauri_plugin_opener::init()` in lib.rs, and granted `opener:default` in capabilities/default.json so the frontend `openUrl()` can open the OAuth consent URL in the system browser. Verified: cargo fmt -p driven-app -- --check, cargo clippy -p driven-app -- -D warnings, cargo test -p driven-app all pass (198 unit + 8 integration). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * feat(ui): Settings/About/components UX polish + teal accent Comprehensive UX polish of the VIEWS-B surfaces, applying the Driven design system (teal accent #0F766E = teal-700) consistently and fixing dark-OS readability (every native select/input/textarea now carries explicit light/dark surface + text colors instead of falling back to OS-dark defaults). - Settings.vue: teal SUBTAB active class on the Accounts|Sources|Rules subtabs; Rules form grouped into card/panel sections (Power and network, Schedule, Performance and bandwidth, Backup hooks, Privacy) with headings; every control uses the shared SELECT/INPUT class; teal day-of-week toggle active state + teal-accent checkboxes. All data-testids preserved. - About.vue: card-based layout; the update banner is teal (emerald reserved for success status); teal primary Check/Install actions; teal-accent channel select + telemetry checkbox; teal release-note links. - AccountList.vue / SourceTable.vue: friendly empty-state cards with a teal CTA; account/source rows rendered as readable cards; canonical primary/secondary/destructive buttons; teal-accent checkboxes. - AddSourceWizard.vue: design-system modal, buttons, selects, textareas; empty-dropdown placeholder ("No accounts yet - connect one first") that disables the account select when there are zero accounts; teal step indicator. - ChangelogModal.vue: card border + teal-focus close affordance. - en-US.json: new keys under settings.*, about.* (sections/empty-state/ no-accounts/about headings). - Tests: new views-b-polish.test.ts covering the empty-state cards + CTAs, the empty account-dropdown placeholder, and the teal active subtab. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m * docs(readme): replace screenshot placeholder with real dark-mode wizard shots Captured from the integrated UX overhaul running in dark mode (the user's actual OS theme): the first-run setup wizard and the bring-your-own Google OAuth credentials walkthrough. Replaces the README screenshot placeholder (audit item A1, partial - a populated dashboard shot can be added from a live install later). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1ebd52e commit ef5c50f

39 files changed

Lines changed: 3302 additions & 832 deletions
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
name: Bug report
3+
about: Report something that is not working as expected
4+
title: ""
5+
labels: bug
6+
assignees: ""
7+
---
8+
9+
## What happened
10+
A clear description of the bug and the actual behavior.
11+
12+
## Expected behavior
13+
What you expected to happen instead.
14+
15+
## Steps to reproduce
16+
1.
17+
2.
18+
3.
19+
20+
## Environment
21+
- OS + version:
22+
- Driven version:
23+
- Install method (installer / portable / built from source):
24+
25+
## Why it matters
26+
Impact on users / data safety / blocking other work.
27+
28+
## Next action
29+
The concrete first step toward a fix (investigate X, add a test, etc.).

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Issue template chooser configuration.
2+
# GitHub Issues is the source of truth for not-yet-done Driven tasks.
3+
blank_issues_enabled: true
4+
contact_links:
5+
- name: Driven backlog (tracking)
6+
url: https://github.com/pmaxhogan/driven/issues
7+
about: Browse existing backlog issues before filing a new one to avoid duplicates.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request / enhancement
3+
about: Propose a new feature, improvement, or backlog task
4+
title: ""
5+
labels: enhancement
6+
assignees: ""
7+
---
8+
9+
## Summary
10+
A clear, one-line description of the feature or task.
11+
12+
## Why it matters
13+
The user value or engineering motivation. What breaks or stays painful without it.
14+
15+
## Next action
16+
The concrete first step (design, spike, implement X, etc.).
17+
18+
## Notes
19+
Related issues, design references (DESIGN/ROADMAP section), V2 vs V1 scope, or any
20+
constraints. Add the relevant priority:* / area:* / status:* labels.

Cargo.lock

Lines changed: 180 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ folders stay the single source of truth. With per-source client-side encryption
1010
turned on, file names and contents are encrypted on your machine before they
1111
ever leave it, so Google stores only ciphertext.
1212

13-
> Screenshot placeholder: a labelled screenshot of the main window and the
14-
> restore browser will be added here. For now, see the design docs under
15-
> `design/` for the intended UI.
13+
![Driven's first-run setup wizard in dark mode: a teal-accented welcome step with the top navigation (Activity, Settings, Restore, About).](docs/screenshots/setup-wizard-dark.png)
14+
15+
Driven uses your own Google OAuth credentials, so your files never pass through
16+
anyone else's servers. The first-run wizard includes a step-by-step, plain-English
17+
guide to creating that credential in the Google Cloud Console:
18+
19+
![The credentials step with an expanded, numbered walkthrough for creating a Google OAuth client ID and secret.](docs/screenshots/oauth-walkthrough-dark.png)
1620

1721
## Features
1822

0 commit comments

Comments
 (0)