Skip to content

External Resource - #1523

Closed
Hirobreak wants to merge 29 commits into
TortugaPower:developfrom
Hirobreak:external-resource
Closed

Hirobreak wants to merge 29 commits into
TortugaPower:developfrom
Hirobreak:external-resource

Conversation

@Hirobreak

Copy link
Copy Markdown
Contributor

Purpose

  • Allow for a new subscription tier to stream files from external resources (Jellyfin, Audiobookshelf)

Related tasks

  • Based on the rework of uuids for library items

Approach

  • New table External Resource which allows for the id, provider name and more metadata related to the source to be stored in the database

Screenshots

IMG_8741

@GianniCarlo GianniCarlo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI feedback:

Comment thread Shared/Services/ConcurrentSync/AsyncOperation.swift
Comment thread Shared/Services/ConcurrentSync/ConcurrenceService.swift
Comment thread Shared/CoreData/BookPlayer.xcdatamodeld/Audiobook Player 12.xcdatamodel/contents Outdated
Comment thread BookPlayer/Import/ImportManager.swift
Comment thread BookPlayer/Profile/Login/ExternalSyncInfoView.swift
Comment thread BookPlayer/Profile/Profile/Views/SubscriptionPillView.swift Outdated
Comment thread Shared/CoreData/Lightweight-Models/SimpleExternalResource.swift Outdated
@Hirobreak
Hirobreak force-pushed the external-resource branch 2 times, most recently from 3c6c771 to 77e7c44 Compare May 13, 2026 21:27
@Hirobreak
Hirobreak force-pushed the external-resource branch from 03d0720 to a2001b7 Compare June 15, 2026 19:57
@Hirobreak
Hirobreak force-pushed the external-resource branch from 6121610 to 948be81 Compare July 7, 2026 19:20
@GianniCarlo

Copy link
Copy Markdown
Collaborator

Thanks @Hirobreak for this work! develop moved ~70 commits since this branch's base and the fork has maintainer edits disabled, so we've rebased it ourselves and continued in #1586 — your commits are preserved as the feature commit's author there. Closing this one in favor of #1586.

GianniCarlo added a commit that referenced this pull request Sep 6, 2026
The #1523 squash-rebase resurrected two files that develop had
deliberately deleted in the connection-flow and integrations reworks:
JellyfinConnectionFormViewModel and JellyfinLibraryGridView (with its
MockJellyfinLibraryViewModel). Both were git-tracked but never
pbxproj-registered, so they never compiled — dead on arrival, including
every conformance edit this branch faithfully made to the grid file's
mock along the way.

A three-signal sweep of all 33 PR-added Swift files (develop deletion
history x pbxproj registration x external type references) found exactly
these two.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YNhXd8EkXcrjBVYLHm5ZSp
GianniCarlo pushed a commit that referenced this pull request Sep 9, 2026
… onto develop)

Squash of Hirobreak's PR #1523 (29 commits) replayed onto current develop —
the original branch is from a fork with maintainer edits disabled and had
diverged 70 commits from its July base, so per-commit rebase was not viable.

Conflict-resolution decisions:
- The integration services the PR moved into Shared/ (Jellyfin + ABS
  connection services, IntegrationError) were grafted onto develop's newer
  store-based rewrites at their new homes — develop's implementations win,
  with the PR's deltas re-applied: public framework surface, the
  manualConnection/useConnection pin for the sync engine, deviceIdentifier,
  and the new fetchItem/updateItemProgress/updateItemsFromJellyfin endpoints
  (routed through develop's send()/validateAuthenticatedResponse so the
  session-expiry re-auth mapping applies to them too).
- Server-GUID capture (the cross-device hostId identity) now happens on ALL
  sign-in paths: Jellyfin password AND Quick Connect (getPublicSystemInfo.id),
  ABS password login (server.id), always preserving a previously captured id.
- The browser-SSO stack develop added (WebAuthenticating, OIDC flow, PKCE) is
  guarded iOS-only — it cannot compile for watchOS and the watch never signs
  in by itself. Its window lookup goes through a dynamic sharedApplication
  read because BookPlayerKit compiles extension-safe.
- The app-layer helper closure the moved services depend on
  (IntegrationConnectionStore, IntegrationConnectionPayload,
  IntegrationHTTPClient, WebAuthenticating, PKCE) moved to
  Shared/Integrations with framework-target membership (both Kits).
- The PR's SPM version bumps (jellyfin-sdk 0.6, Kingfisher 8) were dropped in
  favor of develop's existing pins — nothing in the PR requires them.
- Localizations union-merged; develop's wording wins on duplicated keys.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YNhXd8EkXcrjBVYLHm5ZSp
GianniCarlo added a commit that referenced this pull request Sep 9, 2026
…contract

Review findings from comparing the rebased #1523 against the Android
implementation (shipped in android 1.1.3):

- New IntegrationHostResolver in Shared/Integrations — the single resolution
  choke point, mirroring Android's ExternalServiceUtils.serverForResource:
  stable server GUID match (case-insensitive; Jellyfin reports lowercase hex,
  ABS uppercase UUIDs) → canonical URL key → nil. The previous per-call-site
  lookups compared serverId case-sensitively against raw url.absoluteString
  and then fell back to connections.first — the guess-a-server behavior the
  Android rework eliminated, which cross-device streams the wrong file or
  writes progress to the wrong server when provider ids collide.
- Applied at every consumer: PlaybackService stream-URL building,
  SyncService.downloadRemoteFiles, ItemDetailsView host display,
  ExternalUpdateProgressOperation (progress pushes to an unresolvable host
  are now DISCARDED, never sent to the active connection), and
  ItemListViewModel (batch metadata refresh now groups resources by their
  resolved server; the remote-resume check pins the resource's own server).
- hostId writes go through the new stableHostId helper
  (serverId ?? url.canonicalDedupKey) at all six import sites — raw
  absoluteString fallbacks break cross-device matching on trailing-slash/
  port/case URL variants.
- PlayableChapter's Codable now excludes externalUrl/externalHeaders: the
  headers carry the media server's live Authorization token, and encoded
  PlayableItems travel through the WatchConnectivity application context,
  which is persisted to disk on both devices. Both values are per-device and
  re-resolved locally at load time.
- The error alert's Media Servers shortcut now also appears when NO source
  resolves (no local file, no cloud copy) — previously it was gated on
  externalUrl != nil, hiding it in exactly the connect-your-server case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YNhXd8EkXcrjBVYLHm5ZSp
GianniCarlo added a commit that referenced this pull request Sep 9, 2026
The #1523 squash-rebase resurrected two files that develop had
deliberately deleted in the connection-flow and integrations reworks:
JellyfinConnectionFormViewModel and JellyfinLibraryGridView (with its
MockJellyfinLibraryViewModel). Both were git-tracked but never
pbxproj-registered, so they never compiled — dead on arrival, including
every conformance edit this branch faithfully made to the grid file's
mock along the way.

A three-signal sweep of all 33 PR-added Swift files (develop deletion
history x pbxproj registration x external type references) found exactly
these two.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YNhXd8EkXcrjBVYLHm5ZSp
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.

2 participants