Fixes for everything you flagged
💾 Badges RESET AGAIN root cause + recovery chain
v1.7.2 quarantined a bad primary file and refused to save. Problem: in-session play progress was then never persisted anywhere, so every Jellyfin restart looked like a fresh reset. This was happening to you on v1.7.4.
New: Load() walks a 3-stage recovery chain:
- Primary
badges.json badges.json.bak(rolling backup, written before every successful Save since v1.7.3)badges.json.recovery(in-session state written while quarantined)
Only if ALL three fail does the plugin quarantine and give up. Users with a flaky primary but a healthy .bak silently recover and carry on.
Save() while quarantined now writes to .recovery instead of skipping. So even in the worst case — primary + bak both unreadable — your play progress this session still persists to disk and gets picked up on next restart.
Admins can see load status (LastLoadSummary) via the /test endpoint.
👥 Friends button visibility
- Hides on
/dashboardand/pluginshash paths (admin screens have their own crowded UI). - Hides during media playback — detected via a playing
<video>element orbody.playingVideo. - Reappears automatically when you leave either state. Polled every 500ms +
hashchangelistener. - Drawer closes cleanly if it was open when you started playback.
🌍 Admin page translation finally works
waitForApiClient(2500ms)before querying user prefs. Jellyfin'sApiClientcan be late-mount on admin iframe loads — previously we readuserId='', skipped the prefs fetch, and fell back to browser language (usually English even for French users).- Optimistic first paint: loads translations from
localStorageimmediately, then upgrades to server-authoritative language once ApiClient mounts. - Same
textContentguard as standalone.js: admin containers with rendered content (badge catalog, custom badges list, audit log) no longer get wiped when translations apply.
MD5: 6517B33B00010C7AE6987B2E098FB5E9