Commit Graph
27 Commits
Author SHA1 Message Date
edde746 69fadc220d chore: clean up code comments 2026-08-10 20:28:41 +02:00
edde746 eaa1736c4e feat(mdblist): sync watched history, scrobbles and ratings with MDBList
Connects MDBList through its OAuth device-code grant, registered as a
Device Code app so no client secret or redirect URI ships in the binary
and TV, mobile and desktop all use the same flow.

MDBList omits `verification_uri_complete`, but its device page seeds the
code field from a `user_code` query parameter and the sign-in redirect
preserves the query string, so the activation link is built locally and
the dialog's open button lands on a filled-in form instead of an empty
one. A server-supplied complete URL still wins if one ever appears.

Poll state is read from the response body rather than the status code:
`authorization_pending` and `slow_down` both arrive as HTTP 400, and a
missing grant answers 404 `device_not_found`.

Writes go out as real-time `/scrobble/*` reports plus `/sync/watched`
for the marks that never pass through the player, with ratings on
`/sync/ratings`. Matching uses IMDb and TMDb only — MDBList's id block
has no `tvdb` field, so a TVDB-only item is skipped rather than written
under an empty id block.
2026-08-05 12:03:05 +02:00
edde746 05fd622968 feat(emby): add Emby as a MediaBrowser backend alongside Jellyfin
Emby is Jellyfin's upstream ancestor and speaks a near-identical MediaBrowser
API, so the existing Jellyfin stack is parameterised by a `MediaBrowserDialect`
rather than forked. `JellyfinClient`, its auth service, endpoint discovery, LAN
discovery, and the add/edit connection screens all take the dialect and keep one
implementation; `MediaBackend.emby` and `ConnectionKind.emby` carry it through
the neutral models, the Drift `kind` discriminator, downloads, and caches.

Every divergence below was measured against a live Emby 4.9.5 server, not
inferred from documentation, and each is documented at its capability getter.
Jellyfin's request strings stay byte-identical so nothing about its behaviour
changes.

Routes and auth
- Emby only accepts the pre-10.9 user-scoped item routes (`/Users/{id}/Items/…`,
  `/Users/{id}/PlayedItems/…`, `/Users/{id}/FavoriteItems/…`); the unprefixed
  forms Jellyfin 10.11 added return 404.
- The API is also served under a legacy `/emby` prefix, and both dialects accept
  the token as `X-Emby-Token` or `api_key=`.
- Emby answers only its own LAN discovery datagram ("who is EmbyServer?") and
  ignores Jellyfin's; its default HTTPS port is 8920.
- No `/QuickConnect` route exists, so Quick Connect stays Jellyfin-only.

Row fields Emby withholds
- `ProductionYear`, `OfficialRating`, `PremiereDate` and `DateCreated` are absent
  from list rows unless named in `Fields`, which would otherwise strip the year
  and age-rating badge from every card in the app.
- `UserData.LastPlayedDate` never appears on a list row under `Fields=UserData`,
  `EnableUserData=true` or the user-scoped `Ids=` form — only on the single-item
  detail route, or when the Emby-specific `UserDataLastPlayedDate` token is
  requested. Without it every recency-ordered surface silently degrades to
  library-add time, and `JellyfinApiCache.applyWatchState` stamps
  `DateTime.now()` on watched rows, so an offline watch-state pull would rewrite
  the cached play time of everything it walked.

Continue Watching and Next Up
- Emby computes Next Up per series only: the library-wide `/Shows/NextUp` query
  returns nothing under every parameter combination tried. The shelf is
  therefore reconstructed from a played-episode recency scan plus one
  `/Shows/NextUp?SeriesId=` per distinct series, bounded by a shared wall clock
  that covers the scan as well — per-request timeouts cannot bound the pass
  because `MediaServerHttpClient` times the connect and receive phases
  independently. Rows are stamped with their series' newest play from the same
  response that ordered them, so no per-series enrichment request is needed.
- `/Shows/NextUp` ignores `NextUpDateCutoff`, and no server-side played-date
  filter exists to delegate to (`MinDatePlayed` and `MinDateLastPlayed` are
  ignored; `MinDateLastSaved`, `MinDateCreated` and `MinPremiereDate` filter
  unrelated dates), so the 365-day window is applied to the scanned dates.
- The resume route returns items with no saved position, including plain next
  episodes, so the Emby resume leg reads from `/Items?Filters=IsResumable`.
- Emby is ahead of Jellyfin in one place: `/Users/{id}/Items/{id}/HideFromResume`
  makes Continue Watching removal a real capability.

Everything else
- `/Sessions/Playing` and `/Sessions/Playing/Progress` reject a body with no
  `PlaySessionId` (HTTP 400), so playback reporting always sends one.
- Passing any `MediaTypes` value to the playlist query returns an empty list.
- There is no aggregate `/Items/Filters` route; the four filter facets are
  reassembled from `/Genres`, `/OfficialRatings`, `/Studios` and `/Tags`.
- Metadata writes take name-pair lists (`Genres: [{'Name': 'Action'}]`); the
  plain string array is accepted and then silently discarded.
- Custom artwork uploads must be base64 text, not raw bytes — which was broken
  for Jellyfin too and is fixed for both.
- Trickplay, media segments and lyrics 404 on Emby, so scrub previews are absent
  and intro/credit markers fall back to chapter names.

Verified against a local Emby 4.9.5 and a Jellyfin 10.11.11 control server:
onboarding, browse, detail, playable stream URLs serving real bytes, subtitle
sidecars, watch-state write and restore, hubs, cross-server aggregation and
search across both backends simultaneously.
2026-08-05 06:09:26 +02:00
edde746 3509f4b989 docs: vendor the Microsoft Store badge as a PNG
GitHub sized the hotlinked SVG from its 161x44 intrinsic box rather than the
img height attribute, so the badge rendered short beside the other three.

rsvg-convert at exactly 4x intrinsic keeps the aspect ratio bit-identical and
the rounded corners transparent, matching the neighbouring badge assets. All
four now render 60px tall, and the README no longer hotlinks any image.
2026-07-31 22:52:07 +02:00
edde746 f30e2c621a docs: refresh readme features and download channels
The features section last changed substantively in 2c54baca3 (2026-05-17),
before the music and Explore subsystems shipped, so two whole feature areas
were missing and several availability notes had drifted.

Adds Music and Explore & Requests sections, and corrects claims that no
longer hold: the locale count (14 -> 21), the EPG guide is not Plex-only,
downloads include music and are unavailable on tvOS, Picture-in-Picture
excludes the TV platforms, and shaders and ambient lighting need the mpv
backend. Footnotes move from numeric to named so adding one no longer
renumbers the rest.

Windows now points at the Microsoft Store listing instead of the direct
installer and portable archives. The App Store and Play badges carry
campaign tokens so README traffic is attributable in each store's own
reporting.

The prerequisite Flutter version matches the pinned toolchain (3.44.0), and
the Maestro end-to-end suite gets the pointer it never had.
2026-07-31 21:18:53 +02:00
edde746 f94b8c6586 feat(settings): Services hub, Seerr sign-in, and all-locale strings 2026-07-10 07:09:29 +02:00
edde746 8d14a14781 docs: update readme showcase 2026-05-18 06:16:26 +02:00
edde746 31d2d9dc98 feat: jellyfin 2026-05-01 01:20:36 +02:00
edde746 19a0128363 feat(playback): add ArtCNN shader presets
close #924
2026-04-26 20:29:38 +02:00
edde746 1582fdbd5b feat: mal/anilist/simkl progress sync
close #914
2026-04-24 08:29:49 +02:00
edde746 4667b104d2 docs: refresh readme features 2026-04-20 13:52:19 +02:00
edde746 ff2928b18f feat: trakt integration
close #617
2026-04-19 11:31:27 +02:00
edde746 7784cb7511 fix: TMDB icon gradient 2026-03-09 16:24:59 +01:00
edde746 8eda892b68 feat: themed splash screen with status messages 2026-02-26 11:55:45 +01:00
edde746 03907db6c4 feat: external player support
close #388
2026-02-11 14:59:52 +01:00
edde746 a5a72147c7 feat: show ratings
close #410
2026-02-08 16:03:23 +01:00
edde746 873936c28d add amazon app store
close #219
2026-02-03 15:07:05 +01:00
edde746 77eef1ada7 feat: built-in shaders
close #341
2026-01-29 07:22:21 +01:00
edde746 688ad291bd refactor: hero section design improvements 2025-12-20 04:59:03 +01:00
edde746 2644c3ca55 update screenshots 2025-12-19 14:01:37 +01:00
edde746 0d0388f7a8 fix: change android subtitle font
close #131
2025-11-25 22:44:59 +01:00
edde746 eb8968c428 feat(android): dark mode icon 2025-11-05 19:33:44 +01:00
edde746 7efa96be74 fix: missing subtitles on android 2025-11-04 08:48:04 +01:00
edde746 bae7b70feb docs: mobile store links 2025-11-02 07:21:41 +01:00
edde746 5c418395b1 chore: bump version
also update screenshots
2025-10-31 05:17:30 +01:00
edde746 8d086d282c chore: update screenshots 2025-10-29 11:01:20 +01:00
edde746 a6effe208b squash 2025-10-22 12:45:29 +02:00