v5.5.1
Improvements
- Trakt Device Code authorization - the previous flow opened
https://trakt.tv/oauth/authorizewithredirect_uri=urn:ietf:wg:oauth:2.0:oob. Trakt retired out-of-band redirects, so approving the request sent the browser to aurn:address it cannot resolve; instead of showing a code, the browser offered to hand the address to an external application and the connection could never be completed. Settings now shows a short activation code next to a link tohttps://trakt.tv/activate, the server polls/oauth/device/tokenuntil you approve, and watched history synchronizes immediately afterwards - Trakt application credentials no longer lock the integration UI -
TRAKT_CLIENT_IDandTRAKT_CLIENT_SECRETidentify the application rather than a user session, so they no longer mark Trakt as environment controlled; onlyTRAKT_ENABLED,TRAKT_ACCESS_TOKEN, andTRAKT_REFRESH_TOKENdo. The built-in Trakt application needs no configuration, while self-hosters using their own application must set the client ID and its secret, since Trakt requires a secret for both the device and refresh grants - Tracking provider selector redesign - the None / Trakt / Simkl control now reports each provider's own state (Active, Signed in, Not connected, Needs Client Secret / Needs Client ID) beside provider logos, with hover, keyboard focus, disabled, and in-progress styling and a HeroUI variant matching the rest of the settings page. Both providers can hold a connection at once while only the selected one contributes watched status, so the labels now distinguish the active provider from a retained connection
Bug Fixes
- Trakt sessions dropped after the first token rotation - refresh requests omitted the client secret Trakt requires, and a rotated refresh token was not always persisted, so a single-use token could be spent without being replaced. Refreshes now send the secret, store the rotated pair, serialize concurrent refreshes, and skip the exchange when another request already renewed the session. A refresh rejected with
invalid_grantclears the stored tokens and resets the provider so the UI asks for a reconnect instead of retrying a dead session - Periodic Trakt sync skipped regular users - the background loop iterated
get_users(), which returns a projection carrying only account metadata, sotrakt_enabledandtrakt_access_tokenwere never present and no regular user was selected for a sync. Managed users were unaffected - Poster stuck on a finished movie instead of returning to the screensaver - the screensaver loop was never stopped when playback began, which killed the browser polling that reported
PLAYINGback to the server; the poster manager then stayed latched onSTOPPED, the 5-minute transition timer never armed, andcurrent_movie.jsonwas never cleared. Playback state is now driven server-side byPlaybackMonitor, and stored playback state past the movie's end time (plus a grace period) is discarded - Default-poster transition timer could only fire once - the expired
threading.Timerhandle was left assigned, and a new timer refuses to arm while one is present, so any later stop that was not preceded by a cancel never scheduled a transition
Full Changelog: v5.5.0...v5.5.1