Skip to content

fix(navidrome): preserve case-sensitivity of coverArtId and prioritize local disk cache - #113

Open
omixin wants to merge 1 commit into
PixelPlayerHQ:mainfrom
omixin:fix/navidrome-artwork-cache
Open

fix(navidrome): preserve case-sensitivity of coverArtId and prioritize local disk cache#113
omixin wants to merge 1 commit into
PixelPlayerHQ:mainfrom
omixin:fix/navidrome-artwork-cache

Conversation

@omixin

@omixin omixin commented Aug 29, 2026

Copy link
Copy Markdown

Preserve Case-Sensitivity: Extracted coverArtId using uri.schemeSpecificPart rather than uri.host, preventing Android framework's Uri.getHost() from forcefully lowercasing case-sensitive Base64 IDs (which caused HTTP 404 / empty responses from Navidrome).

Cold Start Cache Priority: Checked local disk cache (cachedFile.exists()) before verifying online login status so cached album art loads instantly on cold app startup and offline.

Persistent Storage: Saved cached artwork in persistent filesDir/album_art/ rather than volatile cacheDir.
Tested and verified working on Android with Navidrome server integration.

@greptile-apps

greptile-apps Bot commented Aug 29, 2026

Copy link
Copy Markdown

Greptile Summary

This PR preserves case-sensitive Navidrome cover-art identifiers, checks disk cache before network authentication, and moves artwork into persistent application storage.

  • Extracts coverArtId from the URI scheme-specific part rather than the lowercased host.
  • Allows disk-cached covers to load before login state is available.
  • Stores Navidrome covers under filesDir/album_art.

Confidence Score: 3/5

The PR should not merge until cached Navidrome artwork remains subject to an appropriate session or account boundary; persistent-cache cleanup should also be added.

Cached artwork is returned before login validation from an account-agnostic directory that survives logout, and those persistent files are excluded from existing album-art cleanup.

Files Needing Attention: app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt

Security Review

The cache-first path bypasses the previous login boundary, allowing artwork retained from an authenticated session to be returned after logout; cache entries are neither cleared on logout nor scoped by account or server.

Important Files Changed

Filename Overview
app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt Corrects case-sensitive ID parsing and enables persistent offline caching, but cache hits bypass logout state and the new persistent files have no eviction lifecycle.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Request[Navidrome cover request] --> Key[Build account-agnostic cache key]
    Key --> Exists{Persistent file exists?}
    Exists -->|Yes| Return[Return cached artwork]
    Exists -->|No| Login{Logged in?}
    Login -->|No| Stop[Return null]
    Login -->|Yes| Download[Download and persist artwork]
Loading

Fix all with Greploop Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
### Issue 1
app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt:71-81
**Cache bypasses the login boundary**

When a cover remains cached after Navidrome logout, `fetch()` returns the persistent, account-agnostic file before checking `repository.isLoggedIn`, causing artwork from the previous authenticated session to remain visible and allowing an account with the same cover identifier to receive stale artwork. **How this was verified:** The cache-return branch precedes the login check, while logout does not clear this directory and the cache key contains no account or server identity.

### Issue 2
app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt:161-164
**Persistent covers lack eviction**

Each distinct Navidrome cover now creates a `navidrome_cover_*` file under persistent `filesDir/album_art`, but existing cache maintenance only processes `song_art_*` files, so artwork storage grows with the browsed library and is not reclaimed by the application's cache cleanup.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "fix(navidrome): preserve case-sensitivit..." | Re-trigger Greptile

Comment on lines 71 to 81
@@ -80,6 +80,12 @@ class NavidromeCoilFetcher(
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Cache bypasses the login boundary

When a cover remains cached after Navidrome logout, fetch() returns the persistent, account-agnostic file before checking repository.isLoggedIn, causing artwork from the previous authenticated session to remain visible and allowing an account with the same cover identifier to receive stale artwork. How this was verified: The cache-return branch precedes the login check, while logout does not clear this directory and the cache key contains no account or server identity.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt
Line: 71-81

Comment:
**Cache bypasses the login boundary**

When a cover remains cached after Navidrome logout, `fetch()` returns the persistent, account-agnostic file before checking `repository.isLoggedIn`, causing artwork from the previous authenticated session to remain visible and allowing an account with the same cover identifier to receive stale artwork. **How this was verified:** The cache-return branch precedes the login check, while logout does not clear this directory and the cache key contains no account or server identity.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Comment on lines +161 to +164
val cache = cacheDir ?: File(options.context.filesDir, "album_art").also {
if (!it.exists()) it.mkdirs()
cacheDir = it
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Persistent covers lack eviction

Each distinct Navidrome cover now creates a navidrome_cover_* file under persistent filesDir/album_art, but existing cache maintenance only processes song_art_* files, so artwork storage grows with the browsed library and is not reclaimed by the application's cache cleanup.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/src/main/java/com/lostf1sh/pixelplayeross/data/image/NavidromeCoilFetcher.kt
Line: 161-164

Comment:
**Persistent covers lack eviction**

Each distinct Navidrome cover now creates a `navidrome_cover_*` file under persistent `filesDir/album_art`, but existing cache maintenance only processes `song_art_*` files, so artwork storage grows with the browsed library and is not reclaimed by the application's cache cleanup.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant