-
v0.2.1 Stable
released this
2026-04-07 20:46:52 +00:00 | 357 commits to main since this release0.2.1
A theme + persistence + ricer-friendliness release. The whole stylesheet system was rebuilt around a runtime preprocessor with
@palette/${name}vars, every bundled theme was rewritten end-to-end, and 12 theme variants ship instead of 6. Lots of UI state now survives a restart, and Hyprland ricers get an explicit opt-out for the in-code window management.This release does not ship a fresh Windows installer — the previous v0.2.0 installer remains the latest installable binary. Run from source to get 0.2.1, or wait for the next release.
Changes since v0.2.0
Theming System
@palette/${name}preprocessor — themes start with a/* @palette */header block listing color slots, the body uses${name}placeholders that the app substitutes at load time. Edit the 17-slot palette block at the top of any theme to recolor the entire app — no hunting through hex literals.- All 6 bundled themes rewritten with comprehensive Fusion-style QSS covering every widget the app uses, every state (hover, focus, disabled, checked), every control variant
- Two corner-radius variants per theme —
*-rounded.qss(4px radius, default Fusion-style look) and*-square.qss(every border-radius stripped except radio buttons, which stay circular) - Native Fusion sizing — themed widgets shrunk to match Qt+Fusion defaults, toolbar row height is now ~23px instead of 30px, matching what
no-custom.qssrenders - Bundled themes — catppuccin-mocha, nord, gruvbox, solarized-dark, tokyo-night, everforest. 12 files total (6 themes × 2 variants)
QSS-Targetable Surfaces
Many things hardcoded in Python paint code can now be overridden from a
custom.qsswithout touching the source:- InfoPanel tag category colors —
qproperty-tagArtistColor,tagCharacterColor,tagCopyrightColor,tagSpeciesColor,tagMetaColor,tagLoreColor - ThumbnailWidget selection paint —
qproperty-selectionColor,multiSelectColor,hoverColor,idleColor(in addition to existingsavedColorandbookmarkedColor) - VideoPlayer letterbox color —
qproperty-letterboxColor. mpv paints the area around the video frame in this color instead of hardcoded black. Defaults toQPalette.Windowso KDE color schemes, qt6ct, Windows dark/light mode, and any system Qt theme automatically produce a matching letterbox - Popout overlay bars — translucent background for the floating top toolbar and bottom controls bar via the
overlay_bgpalette slot - Library count label states —
QLabel[libraryCountState="..."]attribute selector distinguishes "N files" / "no items match" / "directory unreachable" with QSS-controlled colors instead of inline red
Hyprland Integration
- Two opt-out env vars for users with their own windowrules:
BOORU_VIEWER_NO_HYPR_RULES=1— disables every in-code hyprctl dispatch except the popout's keep_aspect_ratio lockBOORU_VIEWER_NO_POPOUT_ASPECT_LOCK=1— independently disables the popout's aspect ratio enforcement
- Popout overlays themed — top toolbar and bottom controls bar now look themed instead of hardcoded translucent black, respect the
@paletteoverlay_bgslot - Popout video letterbox tracks the theme's bg color via the new
qproperty-letterboxColor - Wayland app_id set via
setDesktopFileName("booru-viewer")so compositors can target windows by class —windowrule = float, class:^(booru-viewer)$— instead of by the volatile window title
State Persistence
- Main window — geometry, floating mode, tiled mode (Hyprland)
- Splitter sizes — main splitter (grid vs preview), right splitter (preview vs dl_progress vs info panel)
- Info panel visibility
- Cache spinbox auto-derived dialog min height (no more clipping when dragging the settings dialog small)
- Popout window position, dimensions, and F11 fullscreen state restored via Hyprland floating cache prime
UX
- Live debounced search in bookmarks and library tabs — type to filter, press Enter to commit immediately. 150ms debounce on bookmarks (cheap SQLite), 250ms on library (filesystem scan)
- Search button removed from bookmarks toolbar (live search + Enter)
- Score field +/- buttons removed from main search bar — type the value directly
- Embedded preview video controls moved out of the overlay style and into the panel layout, sitting under the media instead of floating on top of it. Popout still uses the floating overlay
- Next-mode loop wraps to the start of the bookmarks/library list at the end of the last item instead of stopping
- Splitter handle margins — 4px breathing margin on either side so toolbar buttons don't sit flush against the splitter line
Performance
- Page-load thumbnails pre-fetch bookmarks + cache state into set lookups instead of N synchronous SQLite queries per page
- Animated PNG/WebP conversion off-loaded to a worker thread via
asyncio.to_threadso it doesn't block the asyncio event loop during downloads
Fixes
- Open in Browser/Default App on the bookmarks tab now opens the bookmark's actual source post (was opening unrelated cached files)
- Cache settings spinboxes can no longer be vertically clipped at the dialog's minimum size; spinboxes use Python-side
setMinimumHeight()to propagate floors up the layout chain - Settings dialog uses side-by-side
+/-buttons instead of QSpinBox's default vertical arrows for clearer interaction - Bookmarks tab BL Tag refreshes correctly when navigating bookmarked posts (was caching stale tags from the first selection)
- Popout F11 → windowed restores its previous windowed position and dimensions
- Popout flicker on F11 transitions eliminated via
no_animsetprop + deferred fit + dedupe of mpvvideo-paramsevents - Bookmark + saved indicator dots in the thumbnail grid: bookmark star on left, saved dot on right, both vertically aligned in a fixed-size box
- Selection border on thumbnail cells redrawn pen-aware: square geometry (no rounded corner artifacts), even line width on all sides, no off-by-one anti-aliasing seams
- Toolbar buttons in narrow slots no longer clip text (Bookmark/Unbookmark, Save/Unsave, BL Tag, BL Post, Popout, + Folder, Refresh) — all bumped to fit "Unbookmark" comfortably under the bundled themes' button padding
- Toolbar rows on bookmarks/library/preview panels now sit at a uniform 23px height matching the inputs/combos in the same row
- Score and Page spinbox heights forced to 23px via
setFixedHeightto work around QSpinBox reserving vertical space for arrow buttons even whensetButtonSymbols(NoButtons)is set - Library Open in Default App uses the actual file path instead of routing through
cached_path_for(which would return a hash path that doesn't exist for library files)
Cleanup
- Deleted unused
booru_viewer/gui/theme.py(222 lines of legacy stylesheet template that was never imported) - Deleted
GREEN/DARK_GREEN/DIM_GREEN/BG/BG_LIGHTetc constants frombooru_viewer/core/config.py(onlytheme.pyused them) - Removed dead missing-indicator code (
set_missing,_missing_color,missingColorQt Property, the unreachableif not filepath.exists()branch inlibrary.refresh) - Removed dead score
+/-buttons code path
28 files changed, ~8400 insertions / ~1200 deletions across 13 commits.
Downloads