github ZL154/AchievementBadges_for_Jellyfin v2.3.0

2 hours ago

v2.3.0 — Friends & Foundations

Achievement Badges gains a better social layer — hover a friend to see how they are doing, share your own improved card — on top of a long run of reliability fixes, several of which matter to anyone on the published v2.2.0 build.

Fixes for anyone on v2.2.0

These were fixed on main but never released, and both affect the published build today.

  • Empty twin profiles could swallow unlocked badges (#59/#60). GetOrCreateProfile now normalises the user id before touching the store, so a compact-GUID caller (the friends and messaging paths) can no longer create an empty profile beside the live one that later folds over it. Opening the friends panel was enough to trigger it.
  • The injected UI never mounted under gzip (#46). The client bootstrap now injects into compressed responses instead of skipping them. Every browser asks for gzip, so on v2.2.0 the sidebar, widget, item ribbon and toasts silently failed to load. This also explains the symptoms behind #37 and #36.

Added — friends and profiles

  • Friend profile card in the drawer (#76). Hovering a friend's name or avatar opens a summary with their rank tier, completion, score, best streak and equipped showcase; clicking pins a larger card that survives the pointer leaving, closes on Escape or an outside click, and is reachable by keyboard. It is backed by a public-summary endpoint that is privacy-gated to expose nothing the leaderboard does not — anyone opted out of being listed is equally invisible here.
  • Three shareable profile-card skins. Console (default), Metro, and Aurora Spine, each rendered server-side with the card owner's rank colour as the single accent. Every user picks their own skin; a card opened without an explicit style falls back to the owner's choice.
  • Per-user popover style. Choose between the detailed card and a compact card, independently of the shareable-card skin.

Added — completion tracking

  • Library completion now runs (#80, closes the first half of #79). The five library-completion badges are computed during the watch-history scan, so they can finally unlock through normal use instead of sitting at zero on every install.
  • Artist discography completion (#81, #24). Played tracks over total tracks per artist, exposed both as a badge for completing any artist and as a parameterised metric for a specific one, mirroring the existing music-genre metrics.

Added — Tracearr integration (#77/#84/#85)

  • A client for Tracearr's public v2 history API that credits genuine first watches the library scan cannot prove on its own, paging the history correctly and reading the accounts array.
  • A standalone sync button made idempotent by a ledger: the first sync adopts existing plays rather than crediting them, so pressing it twice credits nothing the second time. Configured admin-side with a Tracearr URL and token; nothing is required on the Tracearr side.

Added — notifications and layout

  • Per-user toast position across five placements, applied live.
  • Unlock toasts moved off the subtitle line, and the floating friends button hides while the video player is on screen.
  • Drawer avatar hover polish, and a batch-of-ten toast preview retained from v2.2.0.
  • Admin-set default achievements UI style, optionally locked (#43). Choose whether users start on Classic or Revamp and optionally make it the only choice so the page matches your Jellyfin theme; a user's own pick is remembered and returns if the lock is lifted.

Reliability

  • Watch-time carry now survives a session break, a restart, and a media-file replacement or quality upgrade — entries are keyed by media identity (#89) so an *arr upgrade mid-viewing no longer strands banked minutes — with a configurable retention window (#87). The scan clears the carry of exactly what it credits (#91/#92), so a later partial rewatch cannot reach the completion gate on minutes already counted.
  • Counter resilience. Rebuilt counters are floored and dated snapshots kept so a scan never loses progress; the score bank is floored on rebuild so deleted media cannot zero a balance; backfill is serialised per user to prevent interleaved resets; and what the rebuild cannot reconstruct is preserved on reset.
  • Failed loads are surfaced instead of drawn as empty or loading; dynamic JSON endpoints send Cache-Control: no-store.
  • Streak quests read the live watch streak rather than the all-time best, and milestone cosmetics are announced instead of granted in silence.
  • Outbound webhooks allow custom request headers.

Fixed

  • The pinned friend popover rendered underneath its own dim/blur backdrop, so clicks landed on the backdrop and closed it and the card's buttons were unreachable. It now stacks above the backdrop.

Internationalisation

  • All new interface strings are translated across English, French, Spanish, German, Italian, Portuguese, Chinese and Japanese, and the admin user-picker strings were completed in the seven non-English locales for full key parity.

Dependencies

  • actions/checkout 7, actions/cache 6, actions/setup-dotnet 5.4, Microsoft.CodeAnalysis.NetAnalyzers 10.0.302, and the oss-fuzz base-builder image digest.

Verification

  • 200/200 automated tests pass on .NET 9 / Jellyfin 10.11.x with zero build warnings.
  • Both browser bundles pass JavaScript syntax validation; all eight translation files parse and are at full key parity.
  • Deployed and smoke-tested against a healthy Jellyfin 10.11.x instance, including the friend popover hover, pin and outside-click close, and each shareable-card skin.

Credits

  • Sincere thanks to @camarigor for the friend profiles, Tracearr integration, the library and artist completion wiring, the watch-carry reliability work, and the profile data-loss and gzip injection fixes.

Upgrade

Drop-in upgrade from v2.2.x / v2.1.x / v2.0.x. Existing profiles deserialize with safe defaults; no manual migration or schema reset is required. The release ZIP is Sigstore-signed and carries GitHub SLSA build provenance.

Don't miss a new AchievementBadges_for_Jellyfin release

NewReleases is sending notifications on new releases.