Commit graph

112 commits

Author SHA1 Message Date
5c6aa02998 fix(avocet): restore drag aura color feedback via updateAura in useCardAnimation 2026-03-08 07:14:24 -07:00
9302644259 feat(avocet): wire Anime.js card animation into EmailCardStack
Replace CSS keyframe dismiss classes and inline cardStyle/deltaX/deltaY
with useCardAnimation composable — pickup/setDragPosition/snapBack/animateDismiss
are now called from pointer event handlers and a dismissType watcher.
2026-03-08 07:07:58 -07:00
b68c176278 feat(avocet): add useCardAnimation composable with Anime.js
TDD: 8 tests written first (red), then composable implemented (green).
Adapts to Anime.js v4 API: 2-arg animate(), object-param spring(),
utils.set() for instant drag-position updates without cache desync.
2026-03-08 06:52:27 -07:00
d02c937ff1 feat(avocet): add animejs v4 dependency 2026-03-08 06:47:50 -07:00
611f510547 docs: add privacy policy reference 2026-03-05 20:59:37 -08:00
1a95d4d580 fix(avocet): ball escapes overflow clip, floats above header/footer with z-index + transparency 2026-03-05 15:14:24 -08:00
351703d9db fix(avocet): grid pinned to viewport with height 100dvh + card ball floats above finger at scale 0.55 2026-03-05 15:07:58 -08:00
d7cd01a8da feat(avocet): add velocity-based fling detection to toss gesture (option B: speed + alignment) 2026-03-05 14:55:10 -08:00
8947dc5d05 feat(avocet): add toss-zone overlays and grid-rise animation to LabelView 2026-03-05 13:41:52 -08:00
fc8cb9a8bd feat(avocet): replace swipe+HTML5-drag with unified pointer-events toss gesture 2026-03-05 10:38:52 -08:00
cac02b2c5f feat(avocet): replace HTML5 drag events on LabelBucketGrid with hoveredBucket prop 2026-03-05 10:10:48 -08:00
8a2df0e2f8 feat: card crumples to small ball on drag pickup so buckets expand fully 2026-03-04 12:38:46 -08:00
33f5e0d8a1 fix: keyboard shortcuts now work after labels load (lazy keymap evaluation)
useLabelKeyboard now accepts labels as Label[] | (() => Label[]).
The keymap is rebuilt on every keypress from the getter result instead of
being captured once at construction time — so keys 1–9 now fire correctly
after the async /api/config/labels fetch completes.

LabelView passes () => labels.value so the reactive ref is read lazily.

New test: 'evaluates labels getter on each keypress' covers the async-load
scenario (empty list → no match; push a label → key fires).
2026-03-04 12:32:25 -08:00
43ef2ff8d2 fix: pin bucket grid to bottom of viewport with sticky footer; prevents mis-click from layout shift 2026-03-04 12:26:04 -08:00
c4498a8190 feat: implement FetchView — SSE progress bars, account selection, targeted fetch 2026-03-04 12:23:58 -08:00
6b6205e4ed feat: implement StatsView — label distribution bars, file info, download 2026-03-04 12:21:21 -08:00
9ef2c1251d feat: implement SettingsView — IMAP account management, test connection, display toggles 2026-03-04 12:20:30 -08:00
c94d271f4c feat: add useApiSSE helper for Server-Sent Events connections 2026-03-04 12:17:46 -08:00
2a48ab0f03 feat: add Vue Router + stow-able AppSidebar; stub Fetch/Stats/Settings views 2026-03-04 12:12:26 -08:00
07407117a5 feat: add GET /api/fetch/stream SSE endpoint for real-time IMAP progress 2026-03-04 12:05:23 -08:00
e5e66b09cc feat: add POST /api/accounts/test endpoint 2026-03-04 12:04:42 -08:00
47a2178ee4 feat: add GET /api/stats and GET /api/stats/download endpoints 2026-03-04 12:04:11 -08:00
3f0cd7e837 feat: add GET/POST /api/config endpoints for IMAP account management 2026-03-04 12:03:40 -08:00
8a0545a6e7 feat: extract IMAP logic to app/imap_fetch.py for reuse by API 2026-03-04 11:42:22 -08:00
dc92ecff5f fix: bucket grid now renders 3x3+1 numpad layout on all screen sizes 2026-03-04 11:31:36 -08:00
8d2fdf6299 fix: UndoToast now emits expire after 5s so toast self-dismisses 2026-03-04 11:29:03 -08:00
3788254abd fix: prevent blank page on rebuild and queue drain on skip/discard
Two bugs fixed:

1. Blank white page after vue SPA rebuild: browsers cached old index.html
   referencing old asset hashes. Assets are deleted on rebuild, causing
   404s for JS/CSS -> blank page. Fix: serve index.html with
   Cache-Control: no-cache so browsers always fetch fresh HTML.
   Hashed assets (/assets/chunk-abc123.js) remain cacheable forever.

2. Queue draining to empty on skip/discard: handleSkip and handleDiscard
   never refilled the local queue buffer. After enough skips, store.current
   went null and the empty state showed (blank-looking). Fix: both handlers
   now call fetchBatch() when queue drops below 3, matching handleLabel.

Also: sync classifier_adapters LABELS to match current 10-label schema
(new_lead + hired, remove unrelated).

48 Python tests pass, 48 frontend tests pass.
2026-03-03 19:26:34 -08:00
cb9ebb805c fix(avocet): normalize queue schema + bind to 0.0.0.0 for LAN access
- Add _item_id() (content hash) + _normalize() to map legacy JSONL fields
  (from_addr/account/no-id) to Vue schema (from/source/id)
- All mutating endpoints now look up by _normalize(x)[id] — handles both
  stored-id (test fixtures) and content-hash (real data) transparently
- Change uvicorn bind from 127.0.0.1 to 0.0.0.0 so LAN clients can connect
2026-03-03 18:43:00 -08:00
5ac64b3429 fix(avocet): start-api polls port instead of sleeping 1s — avoids false-success on slow start 2026-03-03 18:11:53 -08:00
2fdafc1d10 fix(avocet): strip HTML from email bodies — stdlib HTMLParser, no deps 2026-03-03 16:28:18 -08:00
65d9f6089e feat(avocet): easter eggs — hired confetti, century mark, clean sweep, midnight labeler, cursor trail 2026-03-03 16:24:47 -08:00
5cf5fe9c43 feat(avocet): manage.sh start-api / stop-api / open-api commands 2026-03-03 16:23:56 -08:00
8e3d263847 feat(avocet): LabelView — wires store, API, card stack, keyboard, easter eggs
Implements Task 13: LabelView.vue wires together the label store, API
fetch, card stack, bucket grid, keyboard shortcuts, haptics, motion
preference, and three easter egg badges (on-a-roll, speed round, fifty
deep). App.vue updated to mount LabelView and restore hacker-mode theme
on load. 3 new LabelView tests; all 48 tests pass, build clean.
2026-03-03 16:21:07 -08:00
05d12a1417 feat(avocet): LabelBucketGrid bucket-mode CSS — spring expansion, glow on drop 2026-03-03 16:19:29 -08:00
97437f39c9 feat(avocet): EmailCardStack — swipe gestures, depth shadows, dismissal classes 2026-03-03 16:16:09 -08:00
5f03db20dc feat(avocet): UndoToast — 5-second countdown, undo button, accessible 2026-03-03 16:13:02 -08:00
2fd101f382 feat(avocet): useLabelKeyboard — 1-9, h, S, D, U, ? shortcuts 2026-03-03 16:12:58 -08:00
452730bb98 feat(avocet): LabelBucketGrid — numpad layout, bucket-mode expansion, drag drop 2026-03-03 16:04:31 -08:00
f5aca77ff6 feat(avocet): EmailCard component — subject, from/date, body preview, expand/collapse 2026-03-03 16:03:01 -08:00
7edcb089a9 feat(avocet): useApi, useMotion, useHaptics, useEasterEgg (Konami/hacker mode)
- useApiFetch: typed fetch wrapper with network/http error discrimination
- useMotion: reactive localStorage override for rich-animation toggle, respects OS prefers-reduced-motion
- useHaptics: label/discard/skip/undo vibration patterns, gated on rich mode
- useKonamiCode + useHackerMode: 10-key Konami sequence → hacker theme, persisted in localStorage
- test-setup.ts: jsdom matchMedia stub so useMotion imports cleanly in Vitest
- smoke.test.ts: import smoke tests for all 4 composables (12 tests, all passing)
2026-03-03 15:58:43 -08:00
50dd4c2f45 feat(avocet): Pinia label store with queue, lastAction, easter egg counter 2026-03-03 15:54:44 -08:00
b10c337214 fix(avocet): align theme with Peregrine design system — full token set, dark mode, self-hosted fonts 2026-03-03 15:52:38 -08:00
a9e5c0d8f3 feat(avocet): CircuitForge base theme + Avocet Slate Teal/Russet colors 2026-03-03 15:49:07 -08:00
02efd5fb1d feat(avocet): Vite + Vue 3 + UnoCSS + Vitest scaffold 2026-03-03 15:46:58 -08:00
01cc908eab fix(avocet): undo — commit-then-clear order, empty-records guard, skip dedup, stronger test 2026-03-03 15:41:58 -08:00
f4facc6484 feat(avocet): discard, undo, labels config, static serving — backend complete 2026-03-03 15:35:01 -08:00
5912b73705 feat(avocet): POST /api/skip endpoint 2026-03-03 15:21:32 -08:00
efd9d69692 fix(avocet): store original item in _last_action; add requirements.txt 2026-03-03 15:16:54 -08:00
ce202d97ea feat(avocet): POST /api/label endpoint 2026-03-03 15:14:04 -08:00
6556e3fef0 fix(avocet): queue_with_items fixture uses api._DATA_DIR to avoid implicit tmp_path coupling 2026-03-03 15:03:57 -08:00