Add album cover stacks to Artists and Album Artists views - #1563
Open
alchemyyy wants to merge 6 commits into
Open
Add album cover stacks to Artists and Album Artists views#1563alchemyyy wants to merge 6 commits into
alchemyyy wants to merge 6 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
alchemyyy
force-pushed
the
development
branch
from
January 16, 2026 16:02
e56cc00 to
a953813
Compare
alchemyyy
force-pushed
the
development
branch
from
January 16, 2026 16:10
a953813 to
d4ccca7
Compare
Author
|
I expect this to be pretty "raw" and in need of some work. The styling options stuff was more or less me messing around with possibilities. I didn't look too deeply into the Subsonic API for a way to run placeholder detections. Running image hashing "dynamically" by creating a single request for the size of placeholder the page would be requesting was one way I thought of doing it, but I'm not sure if retrieving the placeholder like I am with Navidrome is even guaranteed. |
Owner
|
From my testing, the artist grid works well, but the artist grid carousel is blank. |
alchemyyy
force-pushed
the
development
branch
from
January 27, 2026 02:19
cf8c691 to
4b15b22
Compare
alchemyyy
force-pushed
the
development
branch
from
January 27, 2026 17:32
25dc288 to
55fc1fe
Compare
alchemyyy
force-pushed
the
development
branch
from
February 16, 2026 17:40
cf09784 to
526a4ab
Compare
disk-backed image cache with rate-limited fetching via feishin-img:// protocol
All image URLs returned by getImageUrl() in the Jellyfin and Subsonic
controllers are wrapped into a feishin-img:// scheme, following the
existing feishin:// protocol pattern used for fonts. The main process
intercepts these requests, checks a disk cache, and only fetches from
the server on a miss. This is transparent to every existing image
consumer because the wrapping happens at the URL generation layer.
The disk cache stores images as flat files under {userData}/image-cache/,
organized into 2-character hex prefix subdirectories derived from a
SHA-256 hash of the original URL. An in-memory index tracks content
type, size, and last-accessed timestamp per entry, persisted to
index.json periodically and at shutdown. Eviction is LRU when total size
exceeds the configured limit.
Outbound fetches are governed by a token bucket rate limiter keyed per
server base URL, combined with a concurrency semaphore. Duplicate
requests for the same URL while a fetch is in-flight share the same
promise. A separate renderer-side concurrency limiter throttles the HEAD
requests used by the cover art stacking validator.
User-configurable settings:
- Image cache enabled: toggle on/off (default on)
- Disk cache size in MB (default 1000)
- Rate limit burst: tokens available before throttling (default 10)
- Rate limit refill rate: tokens per second (default 5)
- Max concurrent requests per server (default 6)
New files:
src/main/features/image-cache.ts
src/renderer/utils/image-url.ts
src/renderer/utils/rate-limited-fetch.ts
Contributor
|
Came here to suggest exactly this, looking forward to it! |
# Conflicts: # src/main/index.ts # src/renderer/store/settings.store.ts
# Conflicts: # src/main/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes:
getCoverArtValidatorendpoint to Navidrome and Jellyfin controllers (Subsonic stub returns true for all)useCoverArtValidatorhook creates a closure that captures server-specific placeholder detection stateuseArtistAlbumStackhook fetches artist albums and filters out placeholder coversSettings:
toggle to enable/disable artist album cover stack
toggle to prefer artist cover (shows artist image if available, falls back to stack)
stack size setting (1-10 albums)
style selector (spun or staggered)
fitment selector (underfit, fit, overfit) with overfit size option
style-specific settings
all sub-settings hidden when main stack toggle is disabled
style-specific settings are shown only when that style is selected
Placeholder detection approach:
Why the closure pattern:
The validator fetches server-specific state (the placeholder timestamp) once when the page mounts, captures it in a closure, and that closure lives for the duration of the page. When the user navigates away the component unmounts and the closure dies with it.