81 Commits

Author SHA1 Message Date
Estrella Pan
9d5b1c3998 fix(renamer): safely replace higher revisions (#1078) 2026-07-13 01:36:17 +02:00
Estrella Pan
e8bcece42f feat(parser): add selectable preview engine 2026-07-12 21:07:33 +02:00
Estrella Pan
81cfa41c26 fix: address authentication review findings 2026-07-10 11:56:42 +02:00
Estrella Pan
42ccb7611b feat: persist multi-user authentication 2026-07-10 00:52:39 +02:00
Estrella Pan
618464a450 feat(config): user-configurable TMDB API key + Network settings panel (#975, #1042)
Backend: add network.tmdb_api_key (empty = fall back to the built-in
shared key, read live like tmdb_base_url); the config API masks it
automatically.

WebUI: the network section existed backend-only since #1042 — expose
it as a Network settings panel (TMDB API URL, TMDB API key,
Bangumi API URL) with types, initConfig defaults, i18n, and mocks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pz1EmcTPzjgEpkGQWzb8AQ
2026-07-07 18:05:53 +02:00
Estrella Pan
1b928ee326 feat(rss): setting to disable orphan-torrent tracking
New bangumi_manage.track_orphans toggle (default on = current
behavior). When off, refresh_rss no longer persists unmatched torrents
(bangumi_id NULL orphan records): they are re-matched in memory each
tick (cheap, no network — the analyser dedups via bangumi rules, not
torrent records), and a rule added later can retroactively pick up
episodes still in the feed, which persisted orphans used to block
forever. Season-collect flows still persist their NULL records for
feed dedup and are not gated.

WebUI: "Track Unmatched Torrents" switch in Settings -> Manage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pz1EmcTPzjgEpkGQWzb8AQ
2026-07-07 12:15:06 +02:00
Estrella Pan
d91686486b refactor(webui): rework torrent-management UI to Soft Ink ab-* layer
Post-rebase rework addressing review findings on #1051 (the branch
predated the component-system migration):

- Replace retired ab-popup confirm with the useConfirm() promise hook
- Replace NButton and bare <button> with ab-button / ab-icon-button;
  badge pills with ab-tag / ab-badge marks; empty state with ab-empty;
  drop hardcoded colors for theme variables
- Make the per-bangumi page's route param reactive with a NaN guard,
  and remount the list on param change
- Add a "View torrents" entry point in the rule edit dialog
- Reload the torrent list in finally so partial batch-delete failures
  don't leave stale rows
- Align the orphan card title across locales; regenerate dts files

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pz1EmcTPzjgEpkGQWzb8AQ
2026-07-07 10:58:58 +02:00
Estrella Pan
679bd2621c feat: manage bangumi torrents and orphan torrents (port of #1020)
Port zhushanwen321's torrent-management feature (#1020) from the 3.2 sync
architecture to the 3.3 async design.

Backend:
- TorrentDatabase: search_orphans / count_orphans / delete_orphans / delete_obj
- bangumi API: list/delete endpoints for per-bangumi torrents and orphan
  torrents (bangumi_id IS NULL); literal /torrents/orphans routes registered
  before /{bangumi_id}/torrents

WebUI:
- Others card on the bangumi list with orphan count badge
- Torrent list pages (per-bangumi and orphans) with multi-select,
  batch delete, and clear-all confirm dialog

The PR's mikan_parser and rss/analyser fixes are not ported: 3.3-dev
already handles failed poster downloads and missing elements.

Co-authored-by: zhushanwen321 <zhushanwen321@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-07 10:48:07 +02:00
Estrella Pan
378acc90cb feat(webui): NexusPHP PT-site preset for search providers
Add PT (private-tracker) support via the existing RSS-based search
pipeline. The Add Search Provider dialog gains a "PT Site (NexusPHP)"
mode that builds a torrentrss.php search template from base URL +
passkey + optional category ID (e.g. Audiences.me anime = 402), so
search -> subscribe -> auto-download -> rename works end-to-end on
NexusPHP trackers with no backend changes.

- webui/src/utils/nexusphp.ts: URL-template builder (vitest-covered)
- config-search-provider.vue: segmented custom/NexusPHP add dialog
  with live URL preview; en + zh-CN strings
- backend test_nexusphp_rss.py: regression tests proving NexusPHP
  torrentrss output (enclosure and linktype=dl variants) parses
  through the generic rss_parser path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JhTduCYBGeHETU7dSWoh37
2026-07-07 10:19:26 +02:00
Estrella Pan
e309301dd6 refactor(webui): complete ab-* migration, retire legacy components
Migrate the remaining surfaces: all seven ab-popup call sites to
ab-modal (footer slots, sm sizing), every ab-label to ab-field, all
raw ab-input-shortcut inputs to the ab-input component (textareas get
local Soft Ink styles), rss mobile list to ab-list with loading
skeleton, and de-tint the hand-rolled warning callouts (hairline +
ink, per the no-tinted-boxes rule). Wire aria-live into pull-refresh.

Delete dead code: ab-popup, ab-adaptive-modal, ab-label, ab-data-list,
ab-add, ab-button-multi, ab-image, ab-rule, ab-swipe-container (+
orphaned stories); drop the ab-input/input-error UnoCSS shortcuts.
Add stories for the full universal set and document the final
22-component catalog in DESIGN.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-06 11:38:59 +02:00
Estrella Pan
6e5cb2ca07 feat(webui): Soft Ink universal component set
Overlays: ab-modal (adaptive dialog/sheet on headlessui, focus trap,
footer slot), promise-based useConfirm + host, ab-tooltip. Forms:
ab-field (label/description/error/aria wiring), ab-input component
(affixes, clearable, password reveal), ab-select/ab-switch wrappers,
ab-segmented underline tabs; ab-setting rebuilt on them with new
description/error/required props. Display: ab-tag v2 (semantic marks,
ink text, no truncation), ab-status v2 (4 states + label/detail),
ab-badge, ab-progress (scaleX fill), ab-container footer slot,
accessible animated ab-fold-panel. Feedback: ab-alert (hairline, bold
lead word), inverted-ink toast theme, ab-empty, ab-skeleton, ab-list
(selection, loading, density), ab-toolbar. All with vitest coverage
and Storybook stories; bottom sheet gains footer slot and drops
hard-coded overlay/z-index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-06 11:15:16 +02:00
Estrella Pan
e6d39e5624 feat: in-app notification center and LLM provider plugin framework
Two 3.3 platform features sharing core infra (notification events, DB
migrations/wiring, config model, API registration), committed together
because they cannot be split at file granularity without broken
intermediate builds.

Notification center:
- New `inboxmessage` table (migration 16) + repo with coalescing
  (unread rows with the same dedup_key increment a count; `once` kinds
  like update_available notify per-version) and 500-row pruning.
- SystemEvent contract (kind/severity/dedup_key/payload) with new
  DownloaderUnavailable / UpdateAvailable / UpdateApplied events;
  NotificationManager.send_event persists to the inbox first, then
  broadcasts to external providers only when notification.enable.
- SSE `notification` frames driven by an in-process revision counter;
  REST endpoints for list/unread-count/read/read-all/delete/clear.
- Wire-ups: qBittorrent auth now reports last_auth_error
  (credentials|banned|unreachable) and stops retrying rejected
  credentials to avoid a WebUI IP ban; the startup wait loop aborts
  early on credential errors and emits a notification; a 24h
  update-check tick surfaces new versions; apply/rollback emit results.
- WebUI bell + unread badge + dropdown inbox (severity, coalesce count,
  relative time, deep links), SSE-driven with a 30s poll fallback.

LLM provider plugin framework + subscription auth:
- LLMParser refactored to a thin facade over a provider adapter
  contract + registry; the three built-ins (openai/anthropic/gemini)
  move to adapters with zero behaviour change (existing tests unchanged).
- base_url presets for zai/minimax/deepseek/kimi (mainland + overseas)
  reusing the OpenAI-compatible adapter, with a json_object structured-
  output fallback for providers without json_schema.
- Downloadable signed plugins: catalog + installer clone the update
  system's ed25519 verify / zip-slip-guarded extract pipeline (unsigned
  refused, catalog signed against downgrade); versioned-module-name
  loader hot-loads without restart.
- Subscription auth: `llmcredential` table (migration 17) stores OAuth
  tokens server-side only (never sent to the frontend); device-flow
  auth runs a server-side polling task keyed by an opaque handle so the
  device_code stays off the wire; AuthExpiredError trips the breaker and
  notifies. Two grey-area device-flow plugins (github-copilot,
  codex-chatgpt) under plugins/, flagged at-your-own-risk.
- WebUI: grouped provider select (built-in/preset/subscription/
  downloadable), install with risk confirmation, device-flow connect
  dialog, connected-account chip.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-06 09:43:45 +02:00
Estrella Pan
6f72cfe1df perf(startup): defer LLM SDK imports and gate the volume chown
Two things dominated container start:

- The LLM SDKs (anthropic + openai + google-genai) imported at module load
  via parser.analyser/__init__ → llm.py, costing ~0.7s on every boot even
  though the LLM parser is off by default. Move those three heavy imports
  into the provider branch of __init__ and each _parse_* method, so they
  load only when an LLMParser is actually built. Measured: importing
  parser.analyser drops 782ms → 203ms; none of the SDKs are in sys.modules
  after the startup import chain. httpx/httpx_socks stay module-level (cheap,
  and the proxy tests patch them by module path).

- entrypoint.sh ran `chown -R /app/data /app/config` unconditionally every
  start — O(files), which a large poster cache on a NAS turns into the
  dominant startup cost. Walk the tree only when ownership needs fixing
  (first run, changed PUID/PGID, or a wrong-owned volume root), tracked by a
  marker; the legacy bangumi.json migration chowns its one file explicitly so
  the gate can't miss it. /home/ab (image-internal, tiny) is still chowned
  every time.

Also regenerates the auto-imports dts for onResponseError (exported for the
401 test in the previous commit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-04 19:16:49 +02:00
Estrella Pan
620b4f5ecc feat(webui): config/log redesign, log dedup, 3.3 UI alignment, LLM model list
Config page redesigned to a section-rail layout (search + per-section
dirty dots, single column), a save bar that names the restart and
double-confirms save/discard, and a navigate-away guard. Log page
redesigned with a health strip (+ jump-to-first-problem), a unified
toolbar (level chips with counts + text search), severity-only row
colour (fixes the dark-mode 3.53:1 contrast failure), an extracted
module column, and overflow-wrap word handling.

Log deduplication: fix the queue log handler using Python's default
formatter (source of the "INFO::module.x:" duplicate prefix on every
line), strip 245 hand-written [Tag] prefixes, drop double-logged
offset-scan/calendar completion lines, demote "Config loaded" to DEBUG.

3.3 feature/UI alignment: aria2 selectable in Config + wizard (with an
aria2 JSON-RPC connection test), preferred group/resolution and
episode_type surfaced in the rule editor (migrations v10/v12), update
auto_check switch with immediate persistence (no restart).

LLM: model input is now a searchable/free-text select that fetches the
provider's model list on demand (new POST /api/v1/config/llm/models);
timeout/cache/concurrency/circuit-breaker tuning fields; default model
gpt-4o-mini -> gpt-5-mini (discontinued).

Accessibility: real <label for> on config controls, aria-labels on
switches/selects, aria-pressed on log chips, 44px touch targets.
Unify delete confirms to NPopconfirm; password inputs; copy fixes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FAxVyRwrY7z5NotTtgnwVs
2026-07-04 07:42:10 +02:00
Estrella Pan
b34fa62403 feat(update): in-app auto-update via volume-backed overlay
Adds one-click update from the settings page so routine updates no
longer require pulling a new Docker image.

- CI attaches update-bundle-<version>.zip (+ .sha256) to each release:
  backend module tree, built webui, and a manifest; the image bakes
  /app/IMAGE_VERSION as the baseline
- boot_overlay.py (shipped in the image, outside /app/module so it can
  never overwrite its own deciding logic) runs from entrypoint before
  the app starts: if a persisted overlay in /app/config/updates is
  newer than the image it tree-replaces /app/module and /app/dist and
  runs `uv sync` when the lockfile changed; if the image is newer it
  clears the stale overlay. Applied via the config volume, so updates
  survive container recreate; a newer pulled image always wins
- GET/POST /api/v1/update/{check,apply,rollback} (auth-gated, repo
  pinned to EstrellaXD/Auto_Bangumi): check queries GitHub releases
  with a stable/beta channel; apply downloads, verifies sha256, stages,
  promotes current->backup, then exits the process so Docker restarts
  into the overlay; rollback swaps the backup back. Progress streams
  over the existing SSE channel
- Settings card (Log page) shows current/latest, release notes, channel
  toggle, update + rollback, with a restart:unless-stopped requirement
  note; compose examples updated

Requires restart: unless-stopped for self-restart (documented; no
Docker-socket fallback). 1043 backend tests, mypy 0, ruff clean; 135
frontend tests, vue-tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTnuEgR78cBk32bLNKar3z
2026-07-03 09:22:34 +02:00
Estrella Pan
93d3f1a947 feat(parser): multi-provider LLM parser with selectable fallback/primary mode
Generalizes the OpenAI-only title parser into a provider-dispatching
LLMParser (openai-compatible / Anthropic / Gemini) with a parse-mode
switch:

- fallback (default): regex parser runs first, LLM only rescues titles
  the regex can't handle — minimal LLM spend
- primary: LLM parses every title first, regex is the safety net so no
  title is dropped on LLM failure

The openai provider takes a base_url, covering any OpenAI-compatible
endpoint (DeepSeek, Ollama, LM Studio, OpenRouter, OneAPI). Anthropic
uses structured JSON output with refusal handling; Gemini uses
response_mime_type=application/json.

Config auto-migrates the legacy experimental_openai section into a new
llm section on load (migrated users get mode=primary, preserving their
original LLM-first behavior); the old section is kept for downgrade
safety and llm.api_key is redacted by the config API. Settings page
swaps the OpenAI panel for an LLM panel with provider + mode selects.

1018 backend tests, mypy 0, ruff clean; 131 frontend tests, vue-tsc clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTnuEgR78cBk32bLNKar3z
2026-07-03 08:51:01 +02:00
Estrella Pan
3baf1c72b3 refactor(webui): split oversized components, adopt naive-ui primitives, add SSE
Extract useBangumiRuleForm + shared preview/tag/rss-link/filter/offset
components out of ab-add-rss.vue and ab-edit-rule.vue, and split
calendar.vue into calendar-board/calendar-day-column/calendar-card/
calendar-mobile-list/calendar-rule-list-popup. Replace the bespoke
ab-button/ab-select/ab-switch/ab-checkbox primitives with themed
NButton/NSelect/NSwitch (naive-ui) across the app and delete the now-
unused wrappers. Add a backend SSE endpoint (GET /api/v1/events/stream)
streaming status/downloader/log ticks, and a shared useEventStream
composable that the status/downloader/log polling loops prefer over
their interval fetch, falling back to polling when SSE is unavailable
or the tab is hidden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTnuEgR78cBk32bLNKar3z
2026-07-02 19:48:46 +02:00
Estrella Pan
b57d3c49ae feat(security): add security config UI and improve auth/MCP security
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 17:19:14 +01:00
Estrella Pan
a0bf878b7e feat(calendar): add drag-and-drop to assign unknown bangumi to weekdays
Allow users to drag bangumi cards from the "Unknown" section into weekday
columns in the calendar view. Manual assignments are locked so calendar
refresh from Bangumi.tv doesn't overwrite them. A reset button lets users
unlock and send cards back to Unknown.

Backend:
- Add weekday_locked field to Bangumi model (migration v9)
- Add PATCH /api/v1/bangumi/{id}/weekday endpoint
- Skip locked items in refresh_calendar()

Frontend:
- Add vuedraggable for smooth drag-and-drop
- Pin indicator and unpin button on manually-assigned cards
- Drop zone highlighting during drag
- i18n strings for drag/pin/unpin

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:21:00 +01:00
Estrella Pan
5f604e94fd perf(logging): optimize logging with rotation, async I/O, and lazy formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:10:56 +01:00
Estrella Pan
48bf570697 feat(notification): redesign system to support multiple providers
- Add NotificationProvider base class with send() and test() methods
- Add NotificationManager for handling multiple providers simultaneously
- Add new providers: Discord, Gotify, Pushover, generic Webhook
- Migrate existing providers (Telegram, Bark, Server Chan, WeChat Work) to new architecture
- Add API endpoints for testing providers (/notification/test, /notification/test-config)
- Auto-migrate legacy single-provider configs to new multi-provider format
- Update WebUI with card-based multi-provider settings UI
- Add test button for each provider in settings
- Generic webhook supports template variables: {{title}}, {{season}}, {{episode}}, {{poster_url}}

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 20:58:42 +01:00
Estrella Pan
2fb82a5a27 refactor(setup): remove redundant media library step from wizard
The media library path is now taken directly from the downloader path
field, eliminating the unnecessary separate step.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 20:11:44 +01:00
Estrella Pan
f764279a51 fix(webui): improve mobile UI/UX layout and responsiveness
Mobile Layout Fixes:
- Fix config page horizontal overflow by adding min-width: 0 constraints
- Fix sticky action buttons positioning on config page
- Add loading states to config save/cancel buttons
- Reduce topbar padding and icon spacing for mobile
- Make search button fill space between logo and action icons
- Fix search modal header layout with close button visibility

Component Improvements:
- ab-topbar: Flex search button with "Click to search" text on mobile
- ab-status-bar: Reduce button sizes and gaps on mobile
- ab-fold-panel: Add max-width and overflow constraints
- ab-setting: Add max-width: 100% to prevent input overflow
- ab-search-modal: Reduce padding and element sizes on mobile
- ab-mobile-nav: Increase label font-size from 10px to 11px
- ab-sidebar: Fix toggle animation (rotateY → rotate)

Calendar & Bangumi Pages:
- Add lazy loading to poster images for better performance
- Move unknown air day items to separate section below grid
- Add actionable CTA button to empty state with useAddRss hook

Login Page:
- Add will-change: transform for background animation performance

i18n:
- Add click_to_search translation key for mobile search button
- Add add_rss_btn translation for empty state CTA

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 23:09:53 +01:00
Estrella Pan
66c7127f21 feat(offset): add automatic season/episode offset detection
- Add offset detector to identify season mismatches between RSS and TMDB
- Only suggest season_offset (user sets episode_offset manually)
- Add background scanner for existing bangumi rules
- Add detect-offset and dismiss-review API endpoints
- Add warning banner in edit dialog with auto-detect button
- Add iOS-style notification badge for needs_review items
- Yellow badge with "!" for warnings, purple badge for multi-rule count
- Combined badge shows "! | 2" when both conditions apply
- Yellow glow animation on cards needing review
- Highlight warning items in rule selection popup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 21:03:18 +01:00
Estrella Pan
c044b65fef chore: bump version to 3.2.0-beta.9
Fix TypeScript error in ab-search-bar.vue and include pending changes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:29:12 +01:00
Estrella Pan
22870b8ae3 feat(auth): support usernameless passkey login (discoverable credentials)
- Change resident key requirement from PREFERRED to REQUIRED during registration
- Add discoverable authentication options (empty allowCredentials)
- Add verify_discoverable_authentication method in WebAuthn service
- Update auth strategy to lookup user from credential when username not provided
- Make username optional in frontend passkey login flow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 19:23:39 +01:00
Estrella Pan
55b15ea8fe feat: add bangumi archive and episode offset features (#958)
* feat: add bangumi archive and episode offset features

Archive Feature:
- Add archived field to Bangumi model with database migration (v4)
- Add archive/unarchive API endpoints (PATCH /bangumi/archive/{id})
- Add auto-archive for ended series via TMDB metadata refresh
- Add collapsible archived section in UI with visual styling
- Add archive/unarchive button in edit rule popup

Episode Offset Feature:
- Extract series_status and season_episode_counts from TMDB API
- Add suggest-offset API endpoint with auto-detection logic
- Apply offset in renamer gen_path() for episode numbering
- Add offset field with "Auto Detect" button in rule editor
- Look up offset from database when renaming files

The offset auto-detection calculates the sum of episodes from all
previous seasons (e.g., if S01 has 13 episodes, S02E18 → S02E05
with offset=-13).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: add changelog for bangumi archive and episode offset features

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 09:13:49 +01:00
Estrella Pan
c5f4919e15 feat(rss): add connection status tracking and display
Track RSS feed reachability during refresh cycles. Each feed now stores
connection_status (healthy/error), last_checked_at, and last_error.
The RSS management page shows a green "Connected" tag for healthy feeds
and a red "Error" tag with tooltip for failed feeds.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 21:45:04 +01:00
Estrella Pan
5382aec8dc feat: add first-run setup wizard with guided configuration
Add a multi-step setup wizard that guides new users through initial
configuration on first run. The wizard covers account credentials,
download client connection (with test), RSS source, media paths,
and optional notification setup.

Backend: new /api/v1/setup/ endpoints with sentinel file mechanism.
Frontend: 7-step wizard with validation and i18n (en/zh-CN).

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-01-24 08:16:41 +01:00
Estrella Pan
3ff0a64e89 feat(webui): mobile-first responsive redesign with 3-tier breakpoints
Implement a comprehensive mobile-first UI redesign with touch-friendly
navigation, responsive data display, and proper device adaptation.

Key changes:
- Add 3-tier breakpoint system: mobile (<640px), tablet (640-1023px), desktop (1024px+)
- Create core mobile components: bottom-sheet, pull-refresh, swipe-container, data-list, adaptive-modal
- Redesign navigation: bottom nav with labels on mobile, mini sidebar on tablet
- Mobile-first layout with dvh units, safe area insets, and column-reverse flex
- Forms stack labels vertically on mobile, inputs go full-width
- Popups render as bottom sheets on mobile devices
- Bangumi grid uses CSS Grid with responsive minmax columns
- RSS page uses card-based data-list on mobile instead of NDataTable
- Config actions get safe area padding and full-width buttons on mobile/tablet
- Touch targets enforced at 44px minimum throughout
- Add sheet/overlay/swipe CSS transitions
- Topbar search visible on tablet (previously desktop-only)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-01-24 07:37:50 +01:00
Estrella Pan
2a3a53449c feat(webui): redesign LLM settings section
- Rename "Experimental Setting" to "LLM Settings" with cleaner labels
- Replace jarring yellow warning banner with subtle themed notice
- Only show config fields when LLM is enabled (slide-fade transition)
- Add gpt-4o and gpt-4o-mini to model options
- Use scoped CSS instead of UnoCSS utility classes for the section
- Update i18n labels for both en and zh-CN

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 21:26:06 +01:00
Estrella Pan
a98a162500 feat: fix search, poster serving, and add hover overlay UI for cards
- Fix search store exports to match component expectations (inputValue,
  bangumiList, onSearch) and transform data to SearchResult format
- Fix poster endpoint path check that incorrectly blocked all requests
- Add resolvePosterUrl utility to handle both external URLs and local paths
- Move tags into hover overlay on homepage cards and calendar cards
- Show title and tags on poster hover with dark semi-transparent styling
- Add downloader API, store, and page
- Update backend to async patterns and uv migration changes
- Remove .claude/settings.local.json from tracking

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 21:20:12 +01:00
EstrellaXD
2a757e8f2c feat: add calendar view with Bangumi.tv schedule integration
Add weekly broadcast schedule page showing subscribed anime grouped by
day-of-week. Backend fetches air_weekday from Bangumi.tv calendar API
and matches titles. Frontend displays responsive grid (desktop) and
vertical list (mobile). Edit popup moved to parent layout to fix
KeepAlive conflicts, and restyled with purple theme.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 17:51:19 +01:00
EstrellaXD
29e4c16b40 fix(webui): improve passkey UI and error handling
- Add secondary button type to ab-button with proper styling
- Fix small button sizing (min-width instead of fixed width)
- Add btn-content wrapper for icon+text alignment in buttons
- Add config-passkey panel to settings page
- Improve WebAuthn error messages with DOMException handling
- Prevent duplicate error messages from axios interceptor
- Fix Vite proxy to preserve Origin header for WebAuthn

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 15:49:42 +01:00
EstrellaXD
41397bd676 Merge branch 'feature/passkey-login' into feature/ui-redesign
# Conflicts:
#	webui/src/components/ab-bangumi-card.vue
#	webui/src/components/ab-container.vue
#	webui/src/components/ab-fold-panel.vue
#	webui/src/components/ab-search-bar.vue
#	webui/src/components/basic/ab-search.vue
#	webui/src/components/basic/ab-tag.vue
#	webui/src/components/layout/ab-topbar.vue
#	webui/src/pages/index.vue
#	webui/src/pages/index/bangumi.vue
#	webui/src/pages/index/config.vue
#	webui/src/pages/index/player.vue
#	webui/src/pages/login.vue
#	webui/types/dts/auto-imports.d.ts
#	webui/vite.config.ts
2026-01-23 15:08:16 +01:00
EstrellaXD
d2cfd9b150 feat: add WebAuthn passkey authentication support
- Add passkey login as alternative authentication method
- Support multiple passkeys per user with custom names
- Backend: WebAuthn service, auth strategy pattern, API endpoints
- Frontend: passkey management UI in settings, login option
- Fix: convert downloader check from sync requests to async httpx
  to prevent blocking the event loop when downloader unavailable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 14:57:00 +01:00
EstrellaXD
72679cca59 feat(webui): complete UI redesign with design system, dark mode, and accessibility
Implement a comprehensive UI overhaul using CSS custom properties for theming,
scoped SCSS for all components and pages, dark/light mode toggle with flash
prevention, page transitions, ARIA accessibility attributes, and responsive
layout fixes. Fix VueUse auto-import configuration and dev proxy target.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 14:54:26 +01:00
Rewrite0
a2eb8d3537 fix: type error 2024-09-23 16:04:31 +08:00
Rewrite0
fcdcde07ed feat: update deps 2024-09-23 15:49:52 +08:00
Rewrite0
fa3d5a158a feat: add image component with adjustable aspect ratio 2024-09-23 11:55:50 +08:00
Rewrite0
ae43989bc8 feat: 移动端响应式布局 2024-05-29 15:25:10 +08:00
EstrellaXD
004b1cefeb fix: error in build webui 2024-04-10 15:58:53 +08:00
Rewrite0
c95fe89d5d refactor: 整理unocss,重构useApi,完善通知i18n,调整了一些代码写法,调整了一些样式,清理了一些无用依赖和代码 2024-03-07 15:58:33 +08:00
Rewrite0
abd946b0f2 feat: add qb iframe page 2023-10-24 13:26:46 +08:00
EstrellaXD
155496f93a webui: change delete/disable button style. 2023-10-12 16:34:05 +08:00
100gle
94a32b3af3 feat(openai): support azure openai 2023-10-08 16:15:16 +08:00
Rewrite0
7113335b18 refactor: Move transition group style 2023-10-06 07:31:04 +00:00
Rewrite0
c403e266ea fix: fix openAI settings form & file rename 2023-10-06 05:12:10 +00:00
Rewrite0
edf697e68a feat: lint & format 2023-10-06 04:32:33 +00:00
100gle
2751bcabb2 refactor: flatten openai configuration options 2023-10-01 13:00:05 +08:00