Search indicator:
- SearchProgress.vue: indeterminate amber progress bar + status line
+ 4 staggered skeleton cards shown while loading=true and no results yet
(fills the previously-blank results area during initial scrape phase)
- Re-search badge: blue "Re-searching…" pill in toolbar when loading=true
over existing stale results (distinct from the amber enrichment badge)
Candycore theme:
- New [data-candycore="active"] CSS block; palette sourced from
snipe_v0_Neon_IPad_Paint.jpeg — purple-black sky, lavender primary,
cyan glow, yellow crown, bubblegum pink text
- useCandycoreMode.ts: word trigger ("neon", typed outside form fields),
ascending arpeggio audio, localStorage persistence, restore on reload
- Mutually exclusive with Snipe Mode (each deactivates the other)
- Added :not([data-candycore="active"]) guards to existing dark/light
theme override selectors so they don't stomp on Candycore
Phase 2 (snipe#4): after bulk-reporting sellers to eBay T&S, Snipe now
persists which sellers were reported so cards show a muted "Reported to
eBay" badge and users aren't prompted to re-report the same seller.
- migration 012 adds reported_sellers table (user DB, UNIQUE on seller)
- Store.mark_reported / list_reported methods
- POST /api/reported + GET /api/reported endpoints
- reported store (frontend) with optimistic update + server persistence
- reportSelected wires into store after opening eBay tabs
Phase 3 prep (snipe#4): community blocklist share toggle
- Settings > Community section: "Share blocklist with community" toggle
(visible only to signed-in cloud users, default OFF)
- Persisted as community.blocklist_share user preference
- Backend community signal publish now gated on opt-in preference;
privacy-by-architecture: sharing is explicit, never implicit
Adds user-controlled theme selection independent of OS preference:
- useTheme composable: sets data-theme="dark"|"light" on <html>,
persisted to localStorage as snipe:theme. Follows the same pattern
as useSnipeMode.
- theme.css: [data-theme="dark"] and [data-theme="light"] explicit
attribute selectors override @media (prefers-color-scheme: light).
Media query updated to :root:not([data-theme="dark"]) so it has no
effect when the user has forced dark on a light-OS machine.
- App.vue: restoreTheme() called in onMounted alongside restoreSnipeMode.
- SettingsView: Appearance section with System/Dark/Light segmented
button group.
- api/main.py: GET /api/feedback/status + POST /api/feedback — creates
Forgejo issues; disabled (503) when FORGEJO_API_TOKEN unset, 403 in
demo mode; includes view, version, platform context in issue body
- FeedbackButton.vue: 2-step modal (type → review → submit); probes
/api/feedback/status on mount, stays hidden until confirmed enabled
- App.vue: mount FeedbackButton with current route name as view context;
import useRoute for reactive route name tracking
- .env.example: document FORGEJO_API_TOKEN / FORGEJO_REPO / FORGEJO_API_URL