Commit Graph

51 Commits

Author SHA1 Message Date
bvandeusen c9ddcd0f60 fix(ui): viewer modal — haze background through to the image, fit-to-view at zoom 1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 21:21:02 -04:00
bvandeusen 95bc761a69 fix(ui): TopNav uses 1fr/auto/1fr grid so Gallery/Showcase action buttons don't shift the centered links
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 21:16:37 -04:00
bvandeusen d6eba8e4bd feat(ui): redesign /subscriptions as v-data-table with expandable source rows (GS-style)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 10:17:17 -04:00
bvandeusen 6f68bf5fa7 feat(ui): bump thumbnail sizes 1.5x, make Settings fluid, add subscription_count stat
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 23:18:22 -04:00
bvandeusen a9b354780b fc5: LegacyMigrationCard — file uploads + step buttons + active-run + history; slotted into MaintenancePanel
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 09:04:24 -04:00
bvandeusen ab2847ad33 fc3f: ArtistCard — preview row + name + subscription chip + image count, clicks to /artist/:slug
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:15:06 -04:00
bvandeusen b1a358c413 fc3e: PostCard — header + title + truncated-desc + thumbnail strip + attachment chips
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:56:14 -04:00
bvandeusen a4f960c22c fc3e: PostsFilterBar — artist autocomplete + platform v-select with URL-driven hydration
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:55:45 -04:00
bvandeusen 60492da2c2 fc3d: Settings — Download scheduling fieldset (default interval / retention / warning threshold)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:05:16 -04:00
bvandeusen 32b7ad143b fc3d: SourceHealthDot — green/amber/red/grey badge with tooltip; embed in SourceRow
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:04:44 -04:00
bvandeusen 95df9be60e feat(fc3c): SettingsView — Downloader section (rate limit + validate-files toggle)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 20:48:05 -04:00
bvandeusen f309a1e79e feat(fc3c): /subscriptions Check Now button — wires SourceRow → store.checkNow
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 20:47:36 -04:00
bvandeusen d35605ab73 feat(fc3c): /downloads view + DownloadEventRow + DownloadDetailModal + FilterPills
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 20:46:48 -04:00
bvandeusen 408971a798 fix(fc3b): SourceFormDialog + SubscriptionsView read platforms store; drop sources.loadPlatforms
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:39:44 -04:00
bvandeusen a0203f4727 feat(fc3b): /credentials view + ExtensionKeyBar + PlatformCredentialRow + UploadDialog
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:38:32 -04:00
bvandeusen 72b072e6b3 feat(fc3a): SourceFormDialog (structured+JSON tabs) + ArtistCreateDialog
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:57:50 -04:00
bvandeusen 79d6d74637 feat(fc3a): SubscriptionsView + ArtistSection + SourceRow + router
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:57:13 -04:00
bvandeusen 61b623de48 feat(integrity): ImageViewer badge for corrupt/unverified status
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 17:54:25 -04:00
bvandeusen cba662a900 feat(attachments): downloadable attachments in ProvenancePanel + PostInfoHeader
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:17:14 -04:00
bvandeusen 9d61f0da44 feat(provenance): drop artist tag-kind affordances from the UI
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 21:37:18 -04:00
bvandeusen 8abdaa4393 feat(provenance): modal sidebar stacks ProvenancePanel above Tags
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:17:42 -04:00
bvandeusen 7e904f41b5 feat(provenance): always-on artist label on gallery thumbnails
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:17:17 -04:00
bvandeusen 06f4c81418 feat(provenance): PostInfoHeader for the post-filtered gallery
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:17:02 -04:00
bvandeusen b69d637b77 feat(provenance): ProvenancePanel — peer post cards (read-only)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:16:46 -04:00
bvandeusen c408ffd5fc feat(phash): ImportFiltersForm exposes phash_threshold
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 22:07:44 -04:00
bvandeusen d00379905e feat(reader): Read entry points — TagCard icon, TagsView route, SeriesManageView button
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:31:40 -04:00
bvandeusen f52c31367a feat(reader): immersive series-read route + route-aware AppShell (suppress TopNav)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:29:21 -04:00
bvandeusen 886284d182 feat(series): SeriesManageView + /series/:tagId route + TagCard manage affordance
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 23:38:20 -04:00
bvandeusen af2598451c feat(nav): health dot beside wordmark + #fc-nav-actions per-view slot
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 19:39:36 -04:00
bvandeusen 82689e10bc feat(bulk): IR-style BulkEditorPanel + GalleryView select toggle and wiring
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:05:33 -04:00
bvandeusen bff9af1478 feat(bulk): GalleryItem select-mode click + checkbox/order-badge overlay
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:04:29 -04:00
bvandeusen a50701ee6d feat(frontend): inline tag rename, merge confirm dialog, TagsView wiring
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 13:42:46 -04:00
bvandeusen 062a87e968 feat(ui): drop active-link underline + redundant page-title headers 2026-05-15 23:27:38 -04:00
bvandeusen 9bb801a566 refactor(ui): AppShell = TopNav + content slot (drop left drawer/v-main) 2026-05-15 23:14:20 -04:00
bvandeusen 18ad61265e feat(ui): IR-style gradient-fade TopNav (brand, centered links, health) 2026-05-15 23:13:42 -04:00
bvandeusen a984149ee2 feat(fc2c-i): tag directory view with previews, filter, search 2026-05-15 21:13:26 -04:00
bvandeusen c17c4b1667 feat(fc2c-i): showcase view with shortest-column masonry 2026-05-15 21:12:53 -04:00
bvandeusen cd7721fb03 feat(fc2b): Settings Maintenance tab
MaintenancePanel hosts: backfill + centroid recompute trigger cards,
the five suggestion-threshold sliders (autosave on slider release),
the allowlist table (inline editable min_confidence, delete), and the
alias table (mapping display, delete). Wired as a third Settings tab,
ML settings loaded lazily when the tab opens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:57:42 -04:00
bvandeusen 2a21ede912 feat(fc2b): wire SuggestionsPanel + rename into TagPanel; reject-on-remove
TagPanel now renders SuggestionsPanel below the current-tags area and
adds a per-chip kebab → Rename… (TagRenameDialog). modal store's
removeTag now also POSTs suggestions/dismiss after the delete so removing
an auto-applied tag records a per-image rejection and the allowlist
maintenance sweep won't re-apply it (closes the remove→re-apply loop
identified in the spec).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:56:22 -04:00
bvandeusen 5ae2154e88 feat(fc2b): AliasPickerDialog + TagRenameDialog
AliasPicker: debounced autocomplete scoped to the prediction's category
(artist/character map to tag kinds; copyright searches unscoped),
returns the chosen canonical tag id. RenameDialog: PATCH /api/tags/<id>,
surfaces 409 collisions with the FC-2c merge hint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:55:40 -04:00
bvandeusen a8cc6a27dc feat(fc2b): suggestions store + modal panel components
Store: load per-image suggestions, accept (creates the tag first for
raw/creates_new_tag suggestions, then accepts by id), aliasAccept,
dismiss (client-side hide for raw tags), success toasts folded in.
Panel: people/sources groups always open, General collapsed by default;
alias picker dialog wired; shimmer skeleton while loading. SuggestionItem
shows score %, +new badge for raw tags, kebab menu. AliasPickerDialog
referenced (lands in Task 15).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:55:10 -04:00
bvandeusen 90686e6deb chore(fc2a): polish pass — toasts, loading skeletons, focus guards, mobile breakpoints
AppSnackbar mounts once at the app root and exposes a window.__fcToast
function the stores call from error paths. This avoids prop-drilling a
toast emitter through every component while keeping the snackbar
component itself testable in isolation.

GalleryGrid renders shimmer-skeleton placeholders on initial load so the
first paint isn't empty. Skeleton uses the same auto-fill grid columns
as the real items so layout doesn't shift when content arrives.

Modal arrow nav now ignores text-entry elements so typing in the tag
autocomplete doesn't navigate prev/next. Small-screen breakpoint
(<600px) tightens gallery thumbnails to 120px min.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:36:25 -04:00
bvandeusen dcf3af88bd feat(fc2a): assemble ImageViewer modal — Teleported, focused, keyboard-navigable
Teleport mounts the modal under <body> so it can break out of the
gallery container's stacking context. Body overflow is locked while open
so background scroll doesn't compete with pan/zoom.

Keyboard: left/right arrows navigate prev/next (preventDefault so they
don't also scroll the body), Esc closes, Tab is trapped within the
modal by browser default since the modal is focused on mount.

TagPanel renders kind-colored chips with the close (×) affordance for
removal, and hosts TagAutocomplete + FandomPicker for additions. Below
900px the panel drops below the media area instead of beside it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:34:49 -04:00
bvandeusen 89fee260a6 feat(fc2a): add tag store, TagAutocomplete, and FandomPicker
TagAutocomplete: kind selector + debounced (200ms) search + keyboard nav
(up/down/enter/esc). When the operator types a character that doesn't
exist, the create flow first opens FandomPicker so the new character tag
lands with a valid fandom_id (otherwise the API rejects it).

FandomPicker lists existing fandoms (cached after first load) with an
inline create-new affordance, so the operator never has to leave the modal
to manage fandom hierarchies.

Tag store also exposes a kind→icon→color mapping that the TagPanel reuses
in Task 22 — keeping chip colors visually distinct per kind without per-app
accent collisions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:34:17 -04:00
bvandeusen 0faeebf3aa feat(fc2a): add ImageCanvas (pan/zoom) and VideoCanvas (with format gate)
ImageCanvas mounts an <img> wrapped in the usePanZoom composable —
spreading its handlers onto the container element. Zoom resets when src
changes so prev/next nav doesn't carry zoom state into the next image.

VideoCanvas plays MP4/WebM/Ogg/MOV natively. Non-playable formats render
a friendly explainer with a download fallback, naming the actual MIME so
operators know what they're dealing with, and pointing forward at FC-2e
where transcoding lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:33:41 -04:00
bvandeusen 899b193085 feat(fc2a): add TimelineSidebar and assemble GalleryView
GalleryView wires the grid + timeline + modal together. The URL is the
source of truth for which image (if any) is open — clicking an item pushes
?image=N; closing the modal pops it. This makes deep links shareable and
the back button work intuitively.

Below 900px viewport, the timeline drops below the grid as a horizontal
strip so it doesn't compete with thumbnail space on mobile.

Modal store + ImageViewer are placeholders here; real implementations land
in Batch 5 (Tasks 19–22).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:32:50 -04:00
bvandeusen 708c033627 feat(fc2a): add GalleryGrid with infinite scroll and date headers
Grid uses CSS grid auto-fill with 160px minimums so it adapts naturally
from phone to large displays. Date headers render once per (year, month)
group; the API's date_groups payload tells us where to slot them without
client-side grouping. IntersectionObserver with rootMargin: 600px loads
the next page well before the sentinel reaches the viewport.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:32:11 -04:00
bvandeusen da89fe6be2 feat(fc2a): add gallery Pinia store, GalleryItem, and EmptyState
Gallery store handles cursor pagination, date-group merging across pages,
tag filter, timeline buckets, and jump-to-month. Stale response detection
via an inflightId counter prevents out-of-order page additions when the
user toggles filters quickly.

GalleryItem is a square thumbnail card with hover/focus accent outline,
keyboard activation (Enter/Space → open), video badge for video MIME types,
and a broken-image fallback if the thumbnail URL fails to load.

EmptyState points operators to /settings?tab=import so the empty path is
self-guiding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:31:53 -04:00
bvandeusen 968a9e14e3 feat(fc2a): implement Settings Import tab components
ImportTriggerPanel shows an active-batch progress indicator when scan_directory
is running, or a "Quick scan" button otherwise. Deep scan deferred to FC-2d
is called out in the panel text so it's not a surprise.

ImportFiltersForm autosaves on blur/change so there's no Submit button. The
transparency and single-color sliders gate on their respective switches.

ImportTaskList uses v-data-table-virtual for performance on long histories,
with status filter, retry-failed, and a clear-completed dialog with age
buckets. Status chips are color-coded via FabledDesignSystem semantic
tokens (success/warning/error/accent/info).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:31:22 -04:00
bvandeusen 3bcff142f5 feat(fc2a): add SettingsView shell with Overview tab (SystemStatsCards)
Overview tab shows total images/tags/storage/pending/failed using
Fraunces for the big numbers. Inline alert nudges the operator to the
Import tab when pending tasks exist. Polls /api/system/stats every 5s
while the tab is visible (pauses when the document is hidden).

Import tab references three placeholders (TriggerPanel/FiltersForm/
TaskList); real implementations land in Task 15.

Router replaces the placeholder view for /settings with SettingsView.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:30:27 -04:00