Remove the username requirement check that was blocking passkey login without
entering a username. The backend already supports discoverable credentials mode.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When multiple bangumi subscriptions share the same save_path (e.g., split-cour
anime with S01E1-12 and S01E13-24), the renamer's match_by_save_path() query
returned multiple rows causing "Multiple rows were found" errors.
Changes:
- Add qb_hash field to Torrent model for direct hash-to-bangumi linking
- Add database migration v6 for qb_hash column with index
- Add tags parameter to add_torrents() in all downloader clients
- Tag new torrents with ab:{bangumi_id} for offset lookup during rename
- Implement multi-tier lookup in renamer: qb_hash -> tags -> torrent_name -> save_path
- Fix auth tests by mocking DEV_AUTH_BYPASS for proper 401 testing
The renamer now reliably finds the correct bangumi and its offsets even when
multiple subscriptions download to the same directory.
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>
FastAPI's merged_lifespan mechanism triggers lifespan events for each
nested router layer. Since program_router is included in v1, which is
included in app, the startup handler was being called 3 times.
Added _startup_done flag to ensure Program.startup() only executes once.
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>
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>
- Add config-search-provider.vue component for managing search sources
- Support CRUD operations for custom search providers
- Default providers (mikan, nyaa, dmhy) cannot be deleted
- URL template validation ensures %s placeholder is present
- Add backend API endpoints GET/PUT /search/provider/config
- Add i18n translations for zh-CN and en
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The BangumiRule type uses episode_offset but components were using offset,
causing TypeScript errors.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- 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>
- Fix axios interceptor error when response.data is undefined by adding
optional chaining (?.msg_en, ?.msg_zh)
- Fix XML parsing crash in backend by catching ParseError exceptions
- Remove brotli (br) from Accept-Encoding header to fix mikan RSS fetch
issues (httpx doesn't auto-decompress brotli)
- Fix search card click event not triggering confirmation modal by
changing from native 'click' to custom 'select' event with typed payload
- Add NMessageProvider to App.vue to fix useMessage() outside setup error
- Replace structuredClone with JSON.parse/stringify in confirm modal
to handle Vue reactive Proxy objects
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add browser-like headers and full Chrome User-Agent to avoid Cloudflare blocking
- Use appropriate Accept headers for torrent files (application/x-bittorrent)
- Increase timeouts (connect: 5s→10s, read: 10s→30s) for slow responses
- Filter out None values from failed torrent fetches before sending to qBittorrent
- Add try-catch around add_torrents to prevent request crashes
- Improve logging from DEBUG to WARNING level for better visibility
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace dropdown search results with full-screen modal
- Add 4-tier filter chips: subtitle group, resolution, subtitle type, season
- Auto-extract filter options from search results
- Add confirmation modal before subscribing
- Support toggle close (click search input, Escape, or X button)
- Responsive grid layout: 1-4 columns based on viewport
- SSE streaming with fade-in card animations
- Add i18n translations for search filters and confirmation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Handles httpx.ReadError and other network exceptions when adding torrents
to qBittorrent by retrying up to 3 times with a 2-second delay.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add animated gradient background with floating blobs
- Use glassmorphism card with backdrop blur
- Add brand logo with theme-aware switching (light/dark)
- Improve form layout with input icons and better spacing
- Make login button full-width for better UX
- Add loading state for login button
- Improve passkey button styling with dashed border
- Respect prefers-reduced-motion for animations
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Make the "unknown" day column span 2 grid columns and display
items in a grid layout for better use of space.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Allow filtering logs by level (INFO, WARNING, ERROR, DEBUG) with
color-coded filter chips. Multiple levels can be selected simultaneously.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When migrating from older versions, new columns may have NULL values.
This adds a generic mechanism that scans all table models and fills
NULL values based on field defaults defined in SQLModel, improving
data consistency for upgraded databases.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevents startup from hanging indefinitely when downloader is
unreachable (e.g., due to proxy configuration). After 10 retries
(~5 min), program continues with an error log instead of blocking.
Fixes#955 (comment)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add size="small" to Resume, Pause, and Delete buttons in the
torrent action bar for consistent button heights.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When save_path ends with a season-only folder (Season 1, S01, 第1季),
display "Anime Name / Season 1" instead of just "Season 1"
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Increase dialog width from 380px to 460px to fit all content
- Unify button heights across ab-button and ab-button-multi components
- small: 32px, normal: 36px, big: 44px
- Restructure ab-rule form layout with consistent gap spacing
- Fix Episode Offset row to keep input and button on same line (mobile)
- Add proper z-index layering for ab-bottom-sheet (backdrop: 100, container: 101, panel: 102)
- Add scoped styles for ab-setting dynamic-tags wrapper
- Add action button separator line in edit dialog
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add _is_duplicate() helper to check by (title_raw, group_name)
- Fix add_all() to skip existing records and deduplicate within batch
- Improve add() to use same deduplication logic
feat(ui): calendar page grouping and accessibility improvements
- Calendar page now groups bangumi by title+season (same as main page)
- Add rule selection popup for grouped bangumi with multiple rules
- Add skeleton loading animation on bangumi list page
- Fix popup z-index layering with CSS variable system
- Improve accessibility: 44px touch targets, focus-visible states, aria-labels
- Add i18n translations for rule selection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Hide page title on mobile for cleaner layout
- Change group badge color to purple (primary color)
- Fix badge positioning at card corners with fit-content wrapper
- Increase grid padding to prevent badge clipping
- Center grid items for better alignment
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* 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>
- Fix DetachedInstanceError in bangumi cache by expunging objects from
session before caching, preventing lazy loading errors when cached
objects are accessed from different request contexts
- Add database migration v3 to create passkey table for WebAuthn support,
fixing "no such table: passkey" error for users upgrading from older
versions
Closes#956
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>
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>
Cover RSS engine, downloader, renamer, auth, notifications, search,
config, API endpoints, and end-to-end integration flows. When all
210 tests pass, the program's key behavioral contracts are verified.
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>
- Fix 'dict' object has no attribute 'files' in renamer by using dict
access for qBittorrent API responses and fetching file lists via
separate torrents/files endpoint
- Replace version-file-based migration with schema_version table to
reliably track and apply database migrations on every startup
- Add air_weekday column migration as versioned migration entry
- Add torrents_files method to QbDownloader and Aria2Downloader
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>
- Upgrade VitePress from 1.0.0-rc.4 to 1.6.4 (stable)
- Update all dependencies (vue 3.5, typescript 5.6, @vue/tsconfig 0.5)
- Remove defunct Documate AI integration and google-analytics plugin
- Add Google Analytics via head config instead
- Translate all 25+ documentation pages from Chinese to English
- Add comprehensive REST API reference (docs/api/index.md)
- Add v3.2 changelog to sidebar navigation (fixes dead link)
- Update version string from v3.1 to v3.2
- Fix homepage changelog link to point to v3.2
- Update all WebUI screenshots with current v3.2 UI
- Add new screenshots: calendar view, bangumi poster wall
- Remove obsolete files: documate.json, deploy/windows.md, deploy/unix.md
- Update CSS variables for VitePress 1.6.x compatibility
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>