max / goingson
- Co-Authored-By
- Claude Opus 4.7 (1M context) <noreply@anthropic.com>
68 files changed,
+6116 insertions,
-1505 deletions
| @@ -19,17 +19,20 @@ | |||
| 19 | 19 | - [ ] Windows: `cargo tauri build` → verify `.msi`, code-sign with Authenticode, test on Windows | |
| 20 | 20 | - [ ] Linux: AppImage (x86_64 + aarch64) | |
| 21 | 21 | ||
| 22 | - | ### Mobile (iOS TestFlight — keep in scope, near completion) | |
| 22 | + | ### Mobile (iOS TestFlight Internal only — external + Android deferred post-launch) | |
| 23 | 23 | See `todo_mobile.md` for full breakdown. Launch requires: | |
| 24 | 24 | - [x] iOS TestFlight upload working — v0.3.3 delivered 2026-05-17 (icon fix; v0.3.1 had Tauri default logo) | |
| 25 | - | - [ ] Android emulator smoke (`cargo tauri android dev`) + CRUD verified on mobile WebView | |
| 26 | - | - [ ] Physical device testing (iOS + Android) — run mobile P0+P2 checklist in `docs/human_testing.md` | |
| 27 | - | - [ ] Safe area insets across device models, keyboard-doesn't-obscure-inputs, background/foreground transitions | |
| 28 | - | - [ ] iOS internal testing: invite phone Apple ID into ASC Users and Access (Developer role), add to TestFlight Internal group, install + smoke-test on v0.3.3 | |
| 25 | + | - [x] iOS internal testing: phone Apple ID invited + added to TestFlight Internal group, build installed on own device (2026-05-19) | |
| 26 | + | - [ ] Physical device testing (iOS) — run mobile P0+P2 checklist in `docs/human_testing.md` | |
| 27 | + | - [ ] Safe area insets across device models, keyboard-doesn't-obscure-inputs, background/foreground transitions — verify on installed build | |
| 29 | 28 | - [ ] Resolve Missing Compliance prompt on v0.3.3 build (encryption answer — HTTPS-only exempt). **Plist key added 2026-05-18** in `gen/apple/goingson-desktop_iOS/Info.plist` (`ITSAppUsesNonExemptEncryption = false`); future uploads won't re-prompt. The currently-stuck v0.3.3 build still needs the answer set once via App Store Connect UI (TestFlight → build → Encryption: "Uses only exempt encryption"). | |
| 30 | - | - [ ] Add Privacy Policy page to GoingsOn project on MNW (URL: `https://makenot.work/p/goingson#section-privacy-policy`) | |
| 31 | - | - [ ] iOS External Testing: add build, fill Beta App Information, submit for Beta App Review, enable Public Link | |
| 32 | - | - [ ] Android release: Google Play Developer account ($25), release AAB, Play Console listing, submit | |
| 29 | + | ||
| 30 | + | Post-launch (out of launch scope): | |
| 31 | + | - [ ] (post-launch) Android emulator smoke (`cargo tauri android dev`) + CRUD verified on mobile WebView | |
| 32 | + | - [ ] (post-launch) Physical device testing (Android) | |
| 33 | + | - [ ] (post-launch) Add Privacy Policy page to GoingsOn project on MNW (URL: `https://makenot.work/p/goingson#section-privacy-policy`) | |
| 34 | + | - [ ] (post-launch) iOS External Testing: add build, fill Beta App Information, submit for Beta App Review, enable Public Link | |
| 35 | + | - [ ] (post-launch) Android release: Google Play Developer account ($25), release AAB, Play Console listing, submit | |
| 33 | 36 | ||
| 34 | 37 | Explicitly **out of launch scope** (defer until after public launch): | |
| 35 | 38 | - All of Sprint: Backup & Export (current backup works for primary data types) | |
| @@ -41,6 +44,47 @@ | |||
| 41 | 44 | ||
| 42 | 45 | --- | |
| 43 | 46 | ||
| 47 | + | ## UX audit sweep (phased, post-launch) | |
| 48 | + | ||
| 49 | + | Audit complete 2026-05-19/20. **124 findings** across 6 surfaces, **4 charter rules** promoted, lint guards enforce 7 rules clean. See `docs/ux-audit/phase-7.md` for the roll-up; per-phase reports at `docs/ux-audit/phase-{0..7}.md`; charter at `docs/design-system.md`. Audit phases archived to `todo_done.md`. | |
| 50 | + | ||
| 51 | + | ### Audit backlog execution (Tier 1–6, per `phase-7.md` Part C) | |
| 52 | + | ||
| 53 | + | - [x] **Tier 1 — safety nets** (5/5). Bulk-undo across tasks/emails/contacts; selection clears on filter change; send-with-delay (undo-send); attachment-size warning at 25 MB; recurring-event scope confirm. | |
| 54 | + | - [x] **Tier 2 — trust-state surfaces** (4/4). Sync indicator label + state-by-color-alone fix; About / version in Settings; pagination + total counts; Account section now surfaces "Signed in as {email} ({username})" inside Cloud Sync via `sync_account_info`. | |
| 55 | + | - [x] **Tier 3 — mobile correctness** (5/5). Hide Kanban on touch; swipe peek-labels; bottom-nav long-press → pill picker; iOS meta tags + theme-color sync; `window.prompt` killed. | |
| 56 | + | - [x] **Tier 4 — URL-mirrored filter state** (1/1). `js/query-state.js` helper; wired into tasks, emails, contacts. Closes Phase 1 #9 / Phase 2 #10 / Phase 3 #8 / Phase 5 search-persistence in one helper. | |
| 57 | + | - [x] **Tier 5 — feature gaps** (4/4). All-day events, event snooze, contact sub-collection edit, and event reminders all wired end-to-end. | |
| 58 | + | - [~] **Tier 6 — architecture** (2.17/3). Side-drawer task detail (`#task-detail-drawer`, J/K keyboard nav, row-active marker) and settings overlay (`#settings-overlay`, Esc-to-close, backdrop dismiss) both landed 2026-05-20. Compose unification staged out in `docs/ux-audit/compose-migration.md`; **stage 1 of 6 landed 2026-05-20** — new `js/compose-form.js` owns the SendEmailInput payload shape, attachment caps, and validation. Both modal (`emails.js`) and desktop window (`compose.html`) call into it; the `to` vs `toAddress` double-emit shim is gone. Stages 2-6 are independently shippable; one per release during soft launch. | |
| 59 | + | ||
| 60 | + | **Backend trio + frontend wirings landed 2026-05-20** (migration 049, +9 Tauri commands, 4 new tests, ~3 frontend surfaces): | |
| 61 | + | - [x] Event snooze: migration adds `snoozed_until` + rebuilt sync triggers. `snooze_event` / `unsnooze_event` / `list_snoozed_events` commands. `EventResponse` exposes `isSnoozed` + `snoozedUntil`. Event detail modal has Snooze / Unsnooze toggle + "Snoozed until …" line. `snooze.js` generalised to three item types via `ITEM_LABEL` / `apiFor()` / `reloadFor()` helpers. | |
| 62 | + | - [x] Contact sub-collection edit: `update_contact_{email,phone,social_handle,custom_field}` commands. `SUB_COLLECTIONS` map extended with `updateCommand` + `prefill`; `buildSubCollectionFormHtml(type, cid, editingId?)` routes add vs edit. Edit-contact modal rows now carry inline Edit + Remove buttons. Pre-existing reload race (`load()` not awaited before `open*()`) fixed inline. | |
| 63 | + | - [x] MNW account info: new `GET /api/v1/sync/account` (server) + `get_account_info()` (synckit-client) + `sync_account_info` Tauri command. Surfaced inline in Cloud Sync (chose not to add a separate sidebar item — the data only exists because of sync). | |
| 64 | + | ||
| 65 | + | **Event reminders landed 2026-05-20** (migration 050, scheduler in `notifications.rs`, 12 new tests): | |
| 66 | + | - [x] Schema: `reminder_offsets_seconds TEXT` JSON column on events + rebuilt sync triggers + `apply.rs` column list. | |
| 67 | + | - [x] Scheduler: `check_event_reminders` runs each 60s tick; tracks `(event_id, offset)` pairs; bootstrap-on-first-tick suppresses backfill spam after app restart; skips snoozed events. | |
| 68 | + | - [x] UI: `REMINDER_PRESETS` (At time / 5m / 15m / 30m / 1h / 1d before) checkbox group in new/edit event forms; "Reminders: …" line on event detail modal. | |
| 69 | + | - [x] `sanitize_reminder_offsets` strips negatives, dedupes, sorts, caps at 8. | |
| 70 | + | - Known limitations (post-launch follow-ups, not blockers): recurring events fire reminders only against the template's anchor `start_time`, not virtual instances; reminder fire state is in-memory (close the app around a fire time and you miss it). | |
| 71 | + | ||
| 72 | + | **Tier 5 follow-up worth doing if you ship more broadly:** | |
| 73 | + | - [ ] Snoozed-events list view (the `list_snoozed_events` endpoint exists; nothing renders it yet — parity with the snoozed-tasks list). | |
| 74 | + | ||
| 75 | + | ### Charter rules now enforced in code (not just docs) | |
| 76 | + | 1. No state-by-color-alone (sync indicator paired with label; swipe peek-labels carry semantic colors + text) | |
| 77 | + | 2. URL-mirrored filter state (tasks/emails/contacts) | |
| 78 | + | 3. Bulk-undo everywhere (7 call sites) | |
| 79 | + | 4. No native browser dialogs (`scripts/lint-frontend.sh` rule #7; `showPromptDialog` helper) | |
| 80 | + | ||
| 81 | + | ### Deferred deliberately | |
| 82 | + | - [ ] **Step 4 — `renderRow` primitive — DEFERRED.** Re-evaluate if a future phase identifies parallel-markup as the real friction; until then, per-kind row renderers are fine (they all consume canonical CSS classes). See `docs/ux-audit/remediation-plan.md`. | |
| 83 | + | ||
| 84 | + | Out of scope for the audit: smart-feature behavior (forbidden by Apps/CLAUDE.md), full WCAG audit, performance. Recommendations are post-launch work; nothing here blocks ship. | |
| 85 | + | ||
| 86 | + | --- | |
| 87 | + | ||
| 44 | 88 | ## Sprint: Backup & Export | |
| 45 | 89 | ||
| 46 | 90 | Backup system has both coverage and performance problems (Run 24 cross-cutting concern). |
| @@ -236,3 +236,34 @@ | |||
| 236 | 236 | - [x] Attachment sending — MIME multipart via lettre, file picker in compose window + modal, multiple files | |
| 237 | 237 | - [x] Labels / folders — local labels (migration 043), folder/label filter dropdowns, move to folder (IMAP + local), label editing | |
| 238 | 238 | - [x] Notifications — per-account opt-in (migration 044), off by default, fires from auto-sync scheduler when new emails saved | |
| 239 | + | ||
| 240 | + | --- | |
| 241 | + | ||
| 242 | + | ## UX Audit sweep — Phase 0 through Phase 7 (2026-05-19/20) | |
| 243 | + | ||
| 244 | + | Multi-phase audit of the frontend. All artifacts under `docs/ux-audit/`; charter at `docs/design-system.md`; lint guards at `scripts/lint-frontend.sh`. | |
| 245 | + | ||
| 246 | + | **Phase 0 + remediation:** | |
| 247 | + | - [x] Phase 0 — design-system conformance audit. `docs/ux-audit/phase-0.md` + `docs/design-system.md`. | |
| 248 | + | - [x] Consolidation pre-plan. `docs/ux-audit/remediation-plan.md` — 10 steps. | |
| 249 | + | - [x] Step 1 — Toast styling moved into CSS. | |
| 250 | + | - [x] Step 2 — Updater/keycaps/var-fallback hex removed. | |
| 251 | + | - [x] Step 3 — `renderFormField` primitive + form-modal/settings/settings-sync/email-accounts migrated. | |
| 252 | + | - [x] Step 5 — Empty-state consolidation. | |
| 253 | + | - [x] Step 6 — Layout utilities + style-attr sweep; lint reports clean. | |
| 254 | + | - [x] Step 7 — `compose.html` embedded styles reconciled. | |
| 255 | + | - [x] Step 8 — Theme coverage sweep. `docs/ux-audit/theme-coverage.md`. | |
| 256 | + | - [x] Step 9 — `window.confirm()` calls removed. | |
| 257 | + | - [x] Step 10 — Lint guards at `scripts/lint-frontend.sh` (7 rules). | |
| 258 | + | - Step 4 (`renderRow`) deliberately deferred — kept active in todo.md. | |
| 259 | + | ||
| 260 | + | **Surface audits (124 total findings across 6 surfaces):** | |
| 261 | + | - [x] Phase 1 — Shell & navigation. 17 findings (3 critical). | |
| 262 | + | - [x] Phase 2 — Tasks surface. 18 findings (3 critical). | |
| 263 | + | - [x] Phase 3 — Compose & email. 21 findings (3 critical). | |
| 264 | + | - [x] Phase 4 — Events & calendar. 23 findings (4 critical). | |
| 265 | + | - [x] Phase 5 — Projects, contacts, settings. 23 findings (4 critical). | |
| 266 | + | - [x] Phase 6 — Mobile parity sweep. 22 findings (3 critical). Verdict: mobile is ~70 % parallel implementation, ~30 % CSS restyle. | |
| 267 | + | - [x] Phase 7 — Cross-cutting + theme conformance + roll-up. 4 meta-patterns promoted to charter rules (state-by-color-alone, URL-mirrored filter state, bulk-undo, native-dialogs-forbidden). Landed in this commit: `GoingsOn.ui.showPromptDialog`, `bulkTag` off `window.prompt`, `no-native-dialogs` lint rule, cross-cutting rules section in `design-system.md`. | |
| 268 | + | ||
| 269 | + | Recommendations are post-launch; nothing in the audit blocks ship. Tier 1–6 ship order in `phase-7.md` Part C. |
| @@ -1,17 +1,17 @@ | |||
| 1 | 1 | # GoingsOn - Mobile Port | |
| 2 | 2 | ||
| 3 | - | Done: Phases 1-7 (CSS, touch, navigation, views, build config, tab bar, distribution setup); touch-native UX rework (paint, reschedule, week carousel); polish (tap targets, scroll lock, modal cutoffs, icon, provider hints, segmented events view). Active: None. Next: Internal TestFlight install + smoke test on a real device. | |
| 3 | + | Done: Phases 1-7 (CSS, touch, navigation, views, build config, tab bar, distribution setup); touch-native UX rework (paint, reschedule, week carousel); polish (tap targets, scroll lock, modal cutoffs, icon, provider hints, segmented events view); iOS TestFlight internal install on phone (2026-05-19). Active: None. External TestFlight + Android deferred post-launch. | |
| 4 | 4 | ||
| 5 | 5 | --- | |
| 6 | 6 | ||
| 7 | 7 | ## Remaining | |
| 8 | 8 | ||
| 9 | 9 | ### Build & Test | |
| 10 | - | - [ ] Test on Android emulator (`cargo tauri android dev`) | |
| 11 | - | - [ ] All CRUD operations verified on mobile WebView | |
| 10 | + | - [ ] (post-launch) Test on Android emulator (`cargo tauri android dev`) | |
| 11 | + | - [ ] All CRUD operations verified on mobile WebView (iOS — on installed TestFlight build) | |
| 12 | 12 | ||
| 13 | 13 | ### Polish | |
| 14 | - | - [ ] Physical device testing (iOS + Android) | |
| 14 | + | - [ ] Physical device testing (iOS); (post-launch) Android | |
| 15 | 15 | - [x] Safe area insets on various device models (notched, non-notched) — 2026-05-16: timer-widget bottom now uses `calc(52px + env(safe-area-inset-bottom))`; body + fixed UI respect `safe-area-inset-left/right` for landscape. Verify on device. | |
| 16 | 16 | - [x] Virtual scroller performance on mobile — 2026-05-16: short-circuit re-renders when visible range unchanged; removed redundant O(N) walks per scroll tick. Verify on device with long lists. | |
| 17 | 17 | - [x] VoiceOver / TalkBack accessibility — 2026-05-16: `mobile-more-btn` gets `aria-expanded`/`aria-haspopup`/`aria-controls`; popover is `role="menu"` with `aria-hidden` toggle; action sheet now traps focus + restores on close + closes on Escape. Spot-check with VoiceOver. | |
| @@ -60,31 +60,31 @@ | |||
| 60 | 60 | - [x] Answer encryption export-compliance prompt — set via API to `usesNonExemptEncryption: false` (exempt; standard HTTPS/system crypto) | |
| 61 | 61 | ||
| 62 | 62 | #### Internal testing (immediate, for own device) | |
| 63 | - | - [ ] App Store Connect → Users and Access → invite phone's Apple ID (role: Developer) | |
| 64 | - | - [ ] Accept invitation from phone's Apple ID | |
| 65 | - | - [ ] TestFlight → Internal Testing → "+" group → add phone Apple ID → add build | |
| 66 | - | - [ ] Install TestFlight on phone, accept invite, install build, smoke-test | |
| 63 | + | - [x] App Store Connect → Users and Access → invite phone's Apple ID (role: Developer) | |
| 64 | + | - [x] Accept invitation from phone's Apple ID | |
| 65 | + | - [x] TestFlight → Internal Testing → "+" group → add phone Apple ID → add build | |
| 66 | + | - [x] Install TestFlight on phone, accept invite, install build, smoke-test | |
| 67 | 67 | ||
| 68 | - | #### External testing (public link, slower first time) | |
| 68 | + | #### External testing (public link, slower first time) — POST-LAUNCH | |
| 69 | 69 | - [x] Privacy policy drafted at `docs/privacy-policy.md` | |
| 70 | - | - [ ] Add Privacy Policy page to GoingsOn project on MNW (dashboard → Settings → Pages); URL will be `https://makenot.work/p/goingson#section-privacy-policy`. Pages feature shipped in MNW v0.5.17. | |
| 71 | - | - [ ] TestFlight → External Testing → "+" group → add v0.3.1 build | |
| 72 | - | - [ ] Fill in Beta App Information: description, feedback email, test notes ("no login required for core features") | |
| 73 | - | - [ ] Submit for Beta App Review (first time: ~24-48h; subsequent builds: minutes via automated screening) | |
| 74 | - | - [ ] Once approved, enable Public Link | |
| 75 | - | - [ ] Push at least one build per quarter — TestFlight builds expire after 90 days | |
| 70 | + | - [ ] (post-launch) Add Privacy Policy page to GoingsOn project on MNW (dashboard → Settings → Pages); URL will be `https://makenot.work/p/goingson#section-privacy-policy`. Pages feature shipped in MNW v0.5.17. | |
| 71 | + | - [ ] (post-launch) TestFlight → External Testing → "+" group → add v0.3.1 build | |
| 72 | + | - [ ] (post-launch) Fill in Beta App Information: description, feedback email, test notes ("no login required for core features") | |
| 73 | + | - [ ] (post-launch) Submit for Beta App Review (first time: ~24-48h; subsequent builds: minutes via automated screening) | |
| 74 | + | - [ ] (post-launch) Once approved, enable Public Link | |
| 75 | + | - [ ] (post-launch) Push at least one build per quarter — TestFlight builds expire after 90 days | |
| 76 | 76 | ||
| 77 | - | ### Android | |
| 77 | + | ### Android — POST-LAUNCH | |
| 78 | 78 | ```bash | |
| 79 | 79 | ./dist/release-android.sh # release AAB | |
| 80 | 80 | ./dist/release-android.sh --apk # release APK | |
| 81 | 81 | ./dist/release-android.sh --debug # debug APK | |
| 82 | 82 | ``` | |
| 83 | - | - [ ] Google Play Developer account ($25 one-time) | |
| 84 | - | - [ ] Release AAB build + test | |
| 85 | - | - [ ] Play Console listing (title, description, screenshots) | |
| 86 | - | - [ ] Test on emulator + physical device | |
| 87 | - | - [ ] Play Store submission | |
| 83 | + | - [ ] (post-launch) Google Play Developer account ($25 one-time) | |
| 84 | + | - [ ] (post-launch) Release AAB build + test | |
| 85 | + | - [ ] (post-launch) Play Console listing (title, description, screenshots) | |
| 86 | + | - [ ] (post-launch) Test on emulator + physical device | |
| 87 | + | - [ ] (post-launch) Play Store submission | |
| 88 | 88 | ||
| 89 | 89 | --- | |
| 90 | 90 |
| @@ -3,9 +3,17 @@ | |||
| 3 | 3 | <head> | |
| 4 | 4 | <meta charset="UTF-8"> | |
| 5 | 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> | |
| 6 | + | <!-- Phase 7 Tier 3 #13 — iOS / PWA chrome integration. | |
| 7 | + | theme-color is updated by js/themes.js when the theme changes so the | |
| 8 | + | iOS status bar and Android browser chrome match the active surface. --> | |
| 9 | + | <meta name="theme-color" content="#E0E4FA" id="meta-theme-color"> | |
| 10 | + | <meta name="apple-mobile-web-app-capable" content="yes"> | |
| 11 | + | <meta name="apple-mobile-web-app-status-bar-style" content="default"> | |
| 12 | + | <meta name="apple-mobile-web-app-title" content="GoingsOn"> | |
| 6 | 13 | <title>GoingsOn</title> | |
| 7 | 14 | <link rel="icon" type="image/svg+xml" href="favicon.svg"> | |
| 8 | 15 | <link rel="icon" type="image/png" sizes="32x32" href="../icons/32x32.png"> | |
| 16 | + | <link rel="apple-touch-icon" href="../icons/128x128.png"> | |
| 9 | 17 | <link rel="stylesheet" href="css/styles.css"> | |
| 10 | 18 | </head> | |
| 11 | 19 | <body> | |
| @@ -30,6 +38,7 @@ | |||
| 30 | 38 | <div class="header-actions"> | |
| 31 | 39 | <button class="sync-indicator" id="sync-indicator" onclick="GoingsOn.settings.openCloudSync()" title="Cloud Sync" aria-label="Cloud sync status" style="display:none;"> | |
| 32 | 40 | <span class="sync-dot" id="sync-dot"></span> | |
| 41 | + | <span class="sync-label" id="sync-label"></span> | |
| 33 | 42 | </button> | |
| 34 | 43 | <button class="settings-btn" onclick="GoingsOn.search.open()" title="Search (Cmd+K)" aria-label="Search">Search <kbd class="kbd-hint">⌘K</kbd></button> | |
| 35 | 44 | <button class="settings-btn" onclick="GoingsOn.settings.open()" title="Settings" aria-label="Open settings">Settings</button> | |
| @@ -106,6 +115,7 @@ | |||
| 106 | 115 | Waiting Only | |
| 107 | 116 | </label> | |
| 108 | 117 | <div class="filter-actions"> | |
| 118 | + | <span id="task-count" class="filter-count" aria-live="polite"></span> | |
| 109 | 119 | <button class="btn btn-link" onclick="GoingsOn.tasks.clearFilters()">Clear filters</button> | |
| 110 | 120 | </div> | |
| 111 | 121 | </div> | |
| @@ -171,7 +181,7 @@ | |||
| 171 | 181 | </div> | |
| 172 | 182 | <button class="btn btn-secondary" id="edit-project-btn" onclick="GoingsOn.projects.editCurrent()">Edit Project</button> | |
| 173 | 183 | </div> | |
| 174 | - | <p id="project-dashboard-description" style="color: var(--text-secondary); margin-bottom: 1rem;"></p> | |
| 184 | + | <p id="project-dashboard-description" class="project-dashboard-desc"></p> | |
| 175 | 185 | <div id="project-milestones-section" class="milestones-section"></div> | |
| 176 | 186 | <div class="project-dashboard-grid"> | |
| 177 | 187 | <div class="dashboard-column"> | |
| @@ -207,7 +217,7 @@ | |||
| 207 | 217 | <button class="btn btn-sm btn-primary" id="project-attach-btn">+ Attach</button> | |
| 208 | 218 | </div> | |
| 209 | 219 | <div id="project-attachments-list" class="dashboard-list"> | |
| 210 | - | <div class="empty-dashboard-list">No attachments</div> | |
| 220 | + | <div class="empty-state empty-state--dashboard">No attachments</div> | |
| 211 | 221 | </div> | |
| 212 | 222 | </div> | |
| 213 | 223 | </div> | |
| @@ -251,13 +261,9 @@ | |||
| 251 | 261 | <input type="date" id="day-plan-date" class="day-plan-date-picker" onchange="GoingsOn.dayPlan.onDatePickerChange()"> | |
| 252 | 262 | <span id="day-plan-date-display" class="day-plan-date-display"></span> | |
| 253 | 263 | </div> | |
| 254 | - | <div class="view-toggle" id="day-plan-review-toggle" data-plan-pane="day-plan-pane" data-review-pane="day-review-pane"> | |
| 255 | - | <button class="view-toggle-btn active" data-mode="plan" onclick="GoingsOn.planReviewToggle.setMode('day', 'plan')" title="Schedule your day">Plan</button> | |
| 256 | - | <button class="view-toggle-btn" data-mode="review" onclick="GoingsOn.planReviewToggle.setMode('day', 'review')" title="Reflect on your day">Review</button> | |
| 257 | - | </div> | |
| 264 | + | <span id="day-review-status-badge" class="review-status hidden"></span> | |
| 258 | 265 | </div> | |
| 259 | - | <!-- Plan pane --> | |
| 260 | - | <div id="day-plan-pane" class="day-plan-content"> | |
| 266 | + | <div class="day-plan-content"> | |
| 261 | 267 | <div class="day-plan-main" id="day-plan-container"> | |
| 262 | 268 | <p class="timeline-hint">Click and drag across time slots to schedule blocks</p> | |
| 263 | 269 | <div class="timeline-container" id="timeline-container"> | |
| @@ -280,13 +286,13 @@ | |||
| 280 | 286 | <div id="unscheduled-tasks" class="sidebar-task-list" role="list"> | |
| 281 | 287 | <!-- Virtual scroller renders items here --> | |
| 282 | 288 | </div> | |
| 289 | + | <div id="day-accomplished-inline" class="day-accomplished-inline"></div> | |
| 283 | 290 | </div> | |
| 284 | 291 | </div> | |
| 285 | - | <!-- Review pane --> | |
| 286 | - | <div id="day-review-pane" class="hidden"> | |
| 287 | - | <div id="day-review-content" class="day-review-inline"> | |
| 288 | - | <p style="color: var(--text-secondary);">Loading...</p> | |
| 289 | - | </div> | |
| 292 | + | <div class="finish-review-bar"> | |
| 293 | + | <button class="btn btn-primary finish-review-btn" id="day-finish-review-btn" onclick="GoingsOn.dayPlanSchedule.openFinishReviewModal()"> | |
| 294 | + | Finish & Review | |
| 295 | + | </button> | |
| 290 | 296 | </div> | |
| 291 | 297 | </div> | |
| 292 | 298 | ||
| @@ -294,10 +300,6 @@ | |||
| 294 | 300 | <div id="weekly-review-view" class="subview hidden" role="tabpanel" aria-labelledby="weekly-review-tab"> | |
| 295 | 301 | <div class="page-header"> | |
| 296 | 302 | <h2 class="page-title">Weekly Review</h2> | |
| 297 | - | <div class="view-toggle" id="week-plan-review-toggle" data-plan-pane="week-plan-pane" data-review-pane="week-review-pane"> | |
| 298 | - | <button class="view-toggle-btn active" data-mode="plan" onclick="GoingsOn.planReviewToggle.setMode('week', 'plan')" title="Schedule your week">Plan</button> | |
| 299 | - | <button class="view-toggle-btn" data-mode="review" onclick="GoingsOn.planReviewToggle.setMode('week', 'review')" title="Reflect on your week">Review</button> | |
| 300 | - | </div> | |
| 301 | 303 | </div> | |
| 302 | 304 | <div id="weekly-review-content" class="weekly-review-content"> | |
| 303 | 305 | <div class="skeleton-shimmer" aria-label="Loading weekly review"> | |
| @@ -317,10 +319,7 @@ | |||
| 317 | 319 | <button class="btn btn-secondary" onclick="GoingsOn.monthlyReview.nextMonth()" title="Next month">→</button> | |
| 318 | 320 | <span id="monthly-review-month-display" class="monthly-review-month-display"></span> | |
| 319 | 321 | </div> | |
| 320 | - | <div class="view-toggle" id="month-plan-review-toggle" data-plan-pane="month-plan-pane" data-review-pane="month-review-pane"> | |
| 321 | - | <button class="view-toggle-btn active" data-mode="plan" onclick="GoingsOn.planReviewToggle.setMode('month', 'plan')" title="Set goals for the month">Plan</button> | |
| 322 | - | <button class="view-toggle-btn" data-mode="review" onclick="GoingsOn.planReviewToggle.setMode('month', 'review')" title="Reflect on your month">Review</button> | |
| 323 | - | </div> | |
| 322 | + | <span id="month-review-status-badge" class="review-status hidden"></span> | |
| 324 | 323 | </div> | |
| 325 | 324 | <div id="monthly-review-content" class="monthly-review-content"> | |
| 326 | 325 | <div class="skeleton-shimmer" aria-label="Loading monthly review"> | |
| @@ -432,6 +431,7 @@ | |||
| 432 | 431 | <select class="form-select" id="email-label-filter" onchange="GoingsOn.emails.filterByLabel(this.value)" style="width: auto; min-width: 120px;"> | |
| 433 | 432 | <option value="">All labels</option> | |
| 434 | 433 | </select> | |
| 434 | + | <span id="email-count" class="filter-count" aria-live="polite"></span> | |
| 435 | 435 | </div> | |
| 436 | 436 | <div id="email-bulk-actions" class="bulk-actions-bar hidden" role="toolbar" aria-label="Bulk email actions"> | |
| 437 | 437 | <span id="email-bulk-count" class="bulk-count">0 selected</span> | |
| @@ -506,10 +506,17 @@ | |||
| 506 | 506 | </div><!-- /messages-view --> | |
| 507 | 507 | ||
| 508 | 508 | <!-- Settings View (standalone, not a tab group) --> | |
| 509 | - | <div id="settings-view" class="view hidden"> | |
| 509 | + | </main> | |
| 510 | + | </div><!-- /app-body --> | |
| 511 | + | ||
| 512 | + | <!-- Settings Overlay (Phase 7 Tier 6 — settings as modeless drawer) --> | |
| 513 | + | <div id="settings-overlay" class="settings-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="settings-overlay-title" aria-hidden="true"> | |
| 514 | + | <div class="settings-overlay-backdrop" onclick="GoingsOn.settings.goBack()" aria-hidden="true"></div> | |
| 515 | + | <div id="settings-view" class="view settings-overlay-card"> | |
| 510 | 516 | <div class="settings-page-layout"> | |
| 511 | 517 | <nav class="settings-sidebar"> | |
| 512 | - | <button class="settings-back-btn" onclick="GoingsOn.settings.goBack()" aria-label="Go back">← Back</button> | |
| 518 | + | <button class="settings-back-btn" onclick="GoingsOn.settings.goBack()" aria-label="Close settings">← Close</button> | |
| 519 | + | <h2 class="visually-hidden" id="settings-overlay-title">Settings</h2> | |
| 513 | 520 | <div class="settings-nav-items"> | |
| 514 | 521 | <button class="settings-nav-item active" data-section="appearance" onclick="GoingsOn.settings.showSection('appearance')">Appearance</button> | |
| 515 | 522 | <button class="settings-nav-item" data-section="notifications" onclick="GoingsOn.settings.showSection('notifications')">Notifications</button> | |
| @@ -517,16 +524,15 @@ | |||
| 517 | 524 | <button class="settings-nav-item" data-section="plugins" onclick="GoingsOn.settings.showSection('plugins')">Plugins</button> | |
| 518 | 525 | <button class="settings-nav-item" data-section="sync" onclick="GoingsOn.settings.showSection('sync')">Cloud Sync</button> | |
| 519 | 526 | <button class="settings-nav-item" data-section="data" onclick="GoingsOn.settings.showSection('data')">Import & Export</button> | |
| 527 | + | <button class="settings-nav-item" data-section="about" onclick="GoingsOn.settings.showSection('about')">About</button> | |
| 520 | 528 | </div> | |
| 521 | 529 | </nav> | |
| 522 | 530 | <div class="settings-content" id="settings-content"> | |
| 523 | 531 | <!-- Populated by JS --> | |
| 524 | 532 | </div> | |
| 525 | 533 | </div> | |
| 526 | - | </div><!-- /settings-view --> | |
| 527 | - | ||
| 528 | - | </main> | |
| 529 | - | </div><!-- /app-body --> | |
| 534 | + | </div> | |
| 535 | + | </div><!-- /settings-overlay --> | |
| 530 | 536 | ||
| 531 | 537 | <!-- Modal --> | |
| 532 | 538 | <div id="modal-overlay" class="modal-overlay hidden" role="dialog" aria-modal="true" aria-labelledby="modal-title"> | |
| @@ -545,6 +551,21 @@ | |||
| 545 | 551 | <!-- Content populated dynamically by JS --> | |
| 546 | 552 | </div> | |
| 547 | 553 | ||
| 554 | + | <!-- Task Detail Drawer (Phase 7 Tier 6 — side-drawer task detail) --> | |
| 555 | + | <aside id="task-detail-drawer" class="task-drawer" role="dialog" aria-modal="false" aria-labelledby="task-drawer-title" aria-hidden="true"> | |
| 556 | + | <div class="task-drawer-header"> | |
| 557 | + | <button class="btn btn-sm btn-secondary task-drawer-close" onclick="GoingsOn.taskOverview.close()" title="Close (Esc)" aria-label="Close task detail">x</button> | |
| 558 | + | <h2 class="task-drawer-title" id="task-drawer-title">Task</h2> | |
| 559 | + | <div class="task-drawer-actions" id="task-drawer-actions"></div> | |
| 560 | + | </div> | |
| 561 | + | <div class="task-drawer-content" id="task-drawer-content"> | |
| 562 | + | <div class="skeleton-shimmer" aria-label="Loading task detail"> | |
| 563 | + | <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line long"></div><div class="skeleton-line medium"></div></div></div> | |
| 564 | + | <div class="skeleton-row"><div class="skeleton-lines"><div class="skeleton-line medium"></div><div class="skeleton-line short"></div></div></div> | |
| 565 | + | </div> | |
| 566 | + | </div> | |
| 567 | + | </aside> | |
| 568 | + | ||
| 548 | 569 | <!-- Mobile Bottom Tab Bar (hidden on desktop) --> | |
| 549 | 570 | <nav id="mobile-tab-bar" class="mobile-tab-bar" role="tablist" aria-label="Mobile navigation"> | |
| 550 | 571 | <button class="mobile-tab active" data-view="work" role="tab" aria-selected="true"> | |
| @@ -575,11 +596,6 @@ | |||
| 575 | 596 | </div> | |
| 576 | 597 | </div> | |
| 577 | 598 | ||
| 578 | - | <!-- Third-party libraries --> | |
| 579 | - | <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js" | |
| 580 | - | integrity="sha512-BNaRQnYJYiPSqHHDb58B0yaPfCu+Wgds8Gp/gU33kqBtgNS4tSPHuGibyoeqMV/TJlSKda6FXzoEyYGjTReTEA==" | |
| 581 | - | crossorigin="anonymous" | |
| 582 | - | referrerpolicy="no-referrer"></script> | |
| 583 | 599 | ||
| 584 | 600 | <!-- Namespace (must load first) --> | |
| 585 | 601 | <script src="js/goingson.js"></script> | |
| @@ -592,6 +608,7 @@ | |||
| 592 | 608 | <script src="js/components.js"></script> | |
| 593 | 609 | <script src="js/form-modal.js"></script> | |
| 594 | 610 | <script src="js/themes.js"></script> | |
| 611 | + | <script src="js/query-state.js"></script> | |
| 595 | 612 | ||
| 596 | 613 | <!-- Utility Managers --> | |
| 597 | 614 | <script src="js/cache.js"></script> | |
| @@ -622,6 +639,7 @@ | |||
| 622 | 639 | <script src="js/attachments.js"></script> | |
| 623 | 640 | <script src="js/autocomplete.js"></script> | |
| 624 | 641 | <script src="js/address-highlight.js"></script> | |
| 642 | + | <script src="js/compose-form.js"></script> | |
| 625 | 643 | <script src="js/tasks.js"></script> | |
| 626 | 644 | <script src="js/task-overview.js"></script> | |
| 627 | 645 | <script src="js/events.js"></script> |
| @@ -265,6 +265,7 @@ | |||
| 265 | 265 | commands::sync_setup_encryption_new, | |
| 266 | 266 | commands::sync_setup_encryption_existing, | |
| 267 | 267 | commands::sync_update_settings, | |
| 268 | + | commands::sync_account_info, | |
| 268 | 269 | commands::sync_subscription_status, | |
| 269 | 270 | commands::sync_subscribe, | |
| 270 | 271 | commands::list_themes, |
| @@ -585,6 +585,7 @@ | |||
| 585 | 585 | commands::sync_setup_encryption_new, | |
| 586 | 586 | commands::sync_setup_encryption_existing, | |
| 587 | 587 | commands::sync_update_settings, | |
| 588 | + | commands::sync_account_info, | |
| 588 | 589 | commands::sync_subscription_status, | |
| 589 | 590 | commands::sync_subscribe, | |
| 590 | 591 | // Themes |