2554 Commits

Author SHA1 Message Date
Will Miao
75298a402f chore(release): bump version to v1.1.3 v1.1.3 2026-06-17 17:52:56 +08:00
Will Miao
92b5efd414 fix: guard posix_fadvise on non-Linux platforms to prevent AttributeError on Windows (#988) 2026-06-17 17:22:10 +08:00
Will Miao
33ee392b7b feat(settings): redesign Card Overlay Blur range slider to match settings UI style 2026-06-17 15:24:14 +08:00
Will Miao
5237f8b7dc chore: remove keyboard navigation UI elements and related code
- Delete static/css/components/keyboard-nav.css entirely
- Remove @import of keyboard-nav.css from style.css
- Remove keyboard-nav-hint divs from controls.html and recipes.html
- Clean up all keyboard.* translation keys from 10 locale files

The actual keyboard scrolling handlers (PageUp/PageDown in infiniteScroll.js
and VirtualScroller.js) are kept as they provide core scroll functionality.
2026-06-17 15:07:34 +08:00
Will Miao
5107313fd1 revert: restore &logo=github parameter to release-date badge
This reverts commit 95bbc669efb1aa0c23b94be6f0a5e7a188f1c019.

The real issue was shields.io GitHub API token pool exhaustion (intermittent),
not the &logo=github parameter. All 3 badges (Discord, Release, Release Date)
were affected at various times due to the same root cause: shields.io
temporarily unable to query GitHub API.
2026-06-17 11:24:40 +08:00
Will Miao
95bbc66919 fix: remove broken logo parameter from release-date badge URL 2026-06-17 11:21:26 +08:00
Will Miao
e268e59419 chore: stop tracking .docs/ and add to .gitignore
.docs/ is now excluded from git tracking so working/research notes
can live there without being committed.
2026-06-17 11:20:19 +08:00
willmiao
547e1f9498 docs: auto-update supporters list in README 2026-06-17 01:57:52 +00:00
Will Miao
bf32d8b6fd chore(release): bump version to v1.1.2 v1.1.2 2026-06-17 09:57:37 +08:00
Will Miao
8299881024 refactor(sidebar): remove pin/unpin and global hide, use per-page hide only
- Remove pin/unpin and auto-hide hover mechanism (isPinned, isHovering,
  hoverTimeout, showSidebar/hideSidebar, updateAutoHideState, etc.)
- Remove global show_folder_sidebar setting (SettingsManager,
  PageControls, recipes, backend default)
- Simplify sidebar visibility to a single per-page toggle:
  · Dedicated chevron-left button in header to hide sidebar
  · Edge indicator (chevron-right) to restore when hidden
  · No dropdown, no hover area, no pin button
- Add _migrateOldSettings() to convert old sidebarPinned and
  show_folder_sidebar states to per-page sidebarDisabled
- Fix sidebar flicker on page load: CSS defaults to off-screen,
  JS explicitly sets .visible or .hidden-by-setting
- Remove obsolete CSS classes: auto-hide, hover-active, collapsed
- Remove i18n keys: pinSidebar, unpinSidebar, moreOptions
- Update test mocks for the new initialize() interface
2026-06-17 09:49:24 +08:00
Will Miao
da02268196 fix(css): add top margin to stat-cards container for consistent spacing 2026-06-17 08:24:03 +08:00
Will Miao
8c4b9a1e70 fix(metadata-sync): persist not-found flags to SQLite cache on deleted-provider path
When a model is already classified as civitai_deleted=True via
.metadata.json but re-enters the failure block through the
civarchive/sqlite provider path (not the default provider),
needs_save was never set to True because civitai_api_not_found
and sqlite_attempted were both False. The flags were never
persisted to SQLite, causing the model to be re-fetched on
every restart.

Also demoted duplicate INFO/ERROR logging in fetch_and_update_model
to DEBUG (the use case already logs at WARNING), and added
exc_info=True to the fetch_all_civitai error handler.
2026-06-17 08:22:24 +08:00
Will Miao
0906c484e9 fix: actually halt bulk operations on cancel — frontend AbortController + backend guards (#986) 2026-06-17 07:20:32 +08:00
Will Miao
4199c30fec fix(metadata-sync): downgrade "Model not found" to INFO and replace model_name with file+sha256 in log 2026-06-17 00:06:43 +08:00
Will Miao
4a8084cdbc feat(save-image): support %NodeTitle.WidgetName% placeholders and fix %seed% None fallback (#314) 2026-06-16 23:48:44 +08:00
Will Miao
6263e6848c fix: move posix_fadvise(DONTNEED) after read loop so it actually evicts pages (#985) 2026-06-16 23:12:02 +08:00
Will Miao
58c266ad07 fix(scanner): respect lazy hash for checkpoints, add posix_fadvise, cancel on shutdown (#985) 2026-06-16 23:00:23 +08:00
Will Miao
2939813e1a feat(metadata-fetch): add result summary modal with i18n, fix contrast and counting bugs (#38) 2026-06-16 22:38:50 +08:00
Will Miao
a9e5ee7e79 fix: follow-up nits for AVIF/JXL brotli support
- Fix JXL container ftyp size check (==20 → >=16) to accept
  wider range of valid JXL files
- Add brotli decompression size limit (2 MB) to prevent OOM
- Add trailing newline to requirements.txt
- Add unit tests for new ISOBMFF/brotli extraction paths:
  JXL/AVIF happy paths, missing brob, corrupt payload,
  non-ISOBMFF fallthrough, write-skip on AVIF/JXL,
  JSON dict/list fields, and oversized decompression
2026-06-16 16:27:56 +08:00
Will Miao
a17b0e9901 Merge pull request #982 from koloved/main
Add AVIF and JXL image support with brotli metadata decompression
2026-06-16 16:24:30 +08:00
s.ivanov
8f23d966bf Update requirements.txt 2026-06-16 07:27:32 +02:00
Will Miao
7a76fc72d0 fix(rate-limit): continue to next provider on CivArchive 429 to prevent bulk refresh from freezing (#983)
When CivArchive returns HTTP 429 with a large retry_after, the bulk
metadata refresh would block for hours because:

1. FallbackMetadataProvider raised RateLimitError instead of continuing
   to the next provider (e.g., SQLite archive was never reached).

2. _RateLimitRetryHelper retried long-rate-limit 429s 3 times — all
   futile since the hourly cap hasn't reset.

3. The batch loop had no awareness of persistent rate-limiting,
   causing 192+ models to each hammer the same rate-limited endpoint.

Changes:
- FallbackMetadataProvider: all 6 methods now continue to next provider
  on RateLimitError instead of raising (model_metadata_provider.py)
- fetch_and_update_model: deleted-model path also continues on
  RateLimitError so sqlite provider gets a chance (metadata_sync_service.py)
- _RateLimitRetryHelper: when retry_after >= 120s, only 1 attempt is
  made — retries are futile for hour-scale rate limits
- BulkMetadataRefreshUseCase: tracks consecutive rate-limit failures
  and aborts early after 3 (bulk_metadata_refresh_use_case.py)

Tests: updated test_fallback_respects_retry_limit for new continue
behavior; added tests for large/small retry_after thresholds.
2026-06-16 13:08:34 +08:00
Will Miao
518a4dd5ee chore: add reasonix.toml and .codegraph/ to .gitignore 2026-06-16 13:05:11 +08:00
s.ivanov
2b6d4e5d8b Add AVIF and JXL image support with brotli metadata decompression 2026-06-15 09:28:49 +02:00
Will Miao
1f4edbeb9d chore(release): bump version to v1.1.1 v1.1.1 2026-06-14 23:49:44 +08:00
Will Miao
a256558a0e fix(downloads): delete history entries on retry and add dedup for bug #980
- retry_from_history() and retry_all_failed() now DELETE the original
  history entry after re-queuing it. Previously the old entry stayed
  in history causing exponential growth on repeated retry→cancel→retry
  cycles.
- Add deduplicate() called once on singleton creation to clean up
  existing duplicate queue/history entries left by the bug:
  1. In-status dedup (keep highest id per model+version+status)
  2. Cross-status dedup (prefer completed > failed > canceled)
  3. Queue dedup (keep highest rowid per model+version)
  4. Orphan queue cleanup (source='retry' entries obsoleted by
     terminal history entries)
2026-06-14 22:52:44 +08:00
Will Miao
818b9113f0 fix(preview): add Cache-Control header to FileResponse for browser caching (#975)
Chrome does not cache 206 Partial Content responses for <video> elements
without an explicit Cache-Control header. When VirtualScroller recycles
cards and creates new <video> elements with the same URL, Chrome
re-downloads the full video (several MB each) instead of using the cache.

Verified via Chrome DevTools: same .mp4 URL appears 2-3 times in network
trace as separate requests with no cache hit, each returning 206. With
Cache-Control: max-age=86400, the browser will reuse the cached response
for 24 hours across scroll cycles.

Video preview files are ~3.5MB while image previews are ~50-100KB (due
to WebP optimization), making caching especially impactful for videos.
2026-06-14 17:36:59 +08:00
Will Miao
6a4fd020dc fix(api): return JSON error responses for all /api/* routes — prevent JSON.parse crashes on 404/500 2026-06-14 13:13:01 +08:00
Will Miao
7a23040452 fix(save-image): sanitize invalid filename chars from %pprompt%, %nprompt%, %model% patterns (#978) 2026-06-14 09:33:12 +08:00
Will Miao
138024aefe fix(preview): revert to FileResponse as default for all platforms (#975)
The previous commit (a19ddc14) restored Linux sendfile but kept the
manual streaming path for Windows via sys.platform guard. A Windows
user reports performance is still worse than v1.0.5.

Switch back to web.FileResponse for all files on all platforms as the
default. The IOCP crash is an edge case (fast scrolling through many
video previews) that affects few users, while the Python chunked I/O
performance penalty affects everyone.

_stream_file() is kept as an unused fallback for a future compat
setting toggle.
2026-06-13 21:43:44 +08:00
Will Miao
a19ddc14f6 perf(preview): restore Linux sendfile, add cache headers, increase chunk size (#975)
- Restrict manual video streaming to Windows only (sys.platform == 'win32');
  Linux/macOS now uses kernel sendfile (zero-copy DMA) via aiohttp FileResponse
- Add Cache-Control: public, max-age=86400 to streaming responses so browsers
  cache video previews across scroll cycles
- Increase chunk size from 256KB to 1MB to reduce async iteration overhead on
  Windows where streaming is still required
2026-06-13 20:06:58 +08:00
Will Miao
7001ced694 fix(rate-limit): respect server retry_after instead of capping at 30s 2026-06-13 18:01:13 +08:00
pixelpaws
a5c861646c Merge pull request #974 from itkitteh/fix/socks-proxy-support
fix: support SOCKS proxies for outbound requests
2026-06-13 14:15:02 +08:00
Artem Yakimenko
3e0bb73793 fix: support SOCKS proxies for outbound requests
The proxy settings allow selecting a SOCKS proxy type, but the SOCKS
URL was passed to aiohttp's per-request `proxy=` argument, which only
supports http(s) proxies. With a SOCKS proxy this opens a plain TCP
connection to the proxy port and sends an HTTP request; the SOCKS
server replies with its handshake bytes (e.g. b"\x05\xff") and aiohttp
fails with "Bad status line ... Expected HTTP/, RTSP/ or ICE/".

Route SOCKS proxy types through an aiohttp-socks ProxyConnector on the
session instead, leaving the `proxy=` kwarg for http(s) proxies only.
trust_env now keys off whether an app-level proxy is active. Adds
aiohttp-socks to requirements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 14:05:15 +10:00
Will Miao
ac51f6a2f6 feat(settings): add adjustable card overlay blur setting (#973) 2026-06-13 09:43:49 +08:00
Will Miao
bef222c77d perf(recipe): precompute image_id_map for O(1) CivitAI image existence checks
Build a civitai_image_id → recipe_id mapping once during cache
initialization instead of scanning all recipes on every
check_image_exists and import_from_url call.

- RecipeCache gains an image_id_map field populated by
  _build_image_id_map() during cache init
- check_image_exists and import_from_url duplicate detection
  now use the precomputed map (O(k) / O(1) vs O(n))
- Map is persisted in SQLite cache_metadata for fast startup
- Incrementally updated on add/remove/bulk_remove paths
- Fix: conn.close() before cache_metadata query (dead connection)
2026-06-13 08:32:03 +08:00
Will Miao
7cd6a53447 fix(downloads): accept optional completed_at in complete_download to preserve original timestamps 2026-06-13 07:06:59 +08:00
willmiao
6850b35770 docs: auto-update supporters list in README 2026-06-12 15:38:33 +00:00
Will Miao
237a015cde chore(release): bump version to v1.1.0 v1.1.0 2026-06-12 23:38:16 +08:00
Will Miao
1ae2778baa feat(sidebar): add per-page hide toggle with more options dropdown
- Add ``` button in sidebar header with dropdown menu
- Add "Hide sidebar on this page" option with per-page localStorage state
- Show edge indicator (14px chevron) on left when hidden per-page
- Show brief toast notification when hiding
- Fix container margin not resetting when sidebar is per-page hidden
- Add i18n translations for all 10 locales
2026-06-12 18:27:54 +08:00
Will Miao
84fcdb5f20 fix(recipe): compute folder field on save to prevent reimported recipes disappearing from subfolder grid 2026-06-12 16:49:57 +08:00
Will Miao
8a0b368b44 feat(downloads): add persistent download queue/history with REST API 2026-06-12 15:00:21 +08:00
Will Miao
3990535505 fix(i18n): align bulk reimport label with single context menu, drop 'Metadata' for clarity 2026-06-12 10:19:33 +08:00
Will Miao
3e961a9860 fix(stats): load embeddings from saved stats on startup
_load_stats() was missing the embeddings section, so on every restart
the embeddings usage tracking hash would start from an empty dict.
This caused all previously saved embedding usage data to appear reset.

Added the missing load path for the 'embeddings' key, parallel to the
existing checkpoints and loras loading logic.
2026-06-12 08:57:25 +08:00
Will Miao
d6669f1d04 fix(ui): stabilize node selector ordering by type then ID 2026-06-12 08:47:11 +08:00
Will Miao
519bafebc8 fix(i18n): add missing embedding translation keys, sync locales, clean up dead replaceMode branch 2026-06-11 23:03:14 +08:00
Will Miao
d87863b423 feat(embedding): send embedding to workflow + fix copy button format
- Fix copy button on embedding cards to copy 'embedding:folder/name' format
- Add send-embedding-to-workflow for Prompt (LoraManager), Text (LoraManager),
  and CLIPTextEncode nodes, appending embedding code to text content
- Extend workflow registry to register text-capable nodes by comfyClass
  (not generic widget name 'text') to avoid false matches
- Add mode parameter to update_node_widget API/event for append support
- Fix single/bulk context menus: single shows plain 'Send to Workflow',
  bulk collapses submenu into direct action for embeddings (append-only)
2026-06-11 22:41:42 +08:00
Will Miao
84e9fe2dfb fix(import): defer git import to module-level to prevent startup crash when git executable missing (#971) 2026-06-11 21:47:55 +08:00
Will Miao
46cbcf94c8 fix(recipe): reimport data loss, local file support, and scroll bugs
- Add local file reimport support via _do_reimport_from_local
- Validate source_path BEFORE deleting old recipe (prevent data loss)
- Move delete_recipe after save_recipe (safe ordering)
- Preserve folder location, NSFW level, and carry over user edits
- Remove old timestamp preservation (use current time)
- Add scrollTop reset in resetAndReloadWithVirtualScroll
- Only reload on successful bulk reimport (avoid empty grid)
- Disable preserveScroll for both single and bulk reimport
2026-06-11 21:31:30 +08:00
Will Miao
05f3018495 refactor(stats): move lora_manager_stats.json from loras root to settings_dir/stats/
- Change _get_stats_file_path() to use get_settings_dir()/stats/ instead of
  first loras root directory
- Add _migrate_from_old_location() to copy existing stats from loras root
  to new location on first access, then clean up old file
- Add 'stats' to update protection skip lists (clean, extract, tracking)
  to prevent data loss during ZIP/git upgrades in portable mode
- Add usage_stats entry to backup targets and restore resolver so stats
  are included in automatic snapshots
2026-06-11 18:03:29 +08:00