iOS 1.0 RC 2: Plex streams under upload caps, shuffle and album radio stations, Recently Added list, photo covers, crossfade

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-11-06 08:40:37 -08:00
1 parent c0e33b5e3e
commit 2fb8040388
17 files changed
+412 -74

No files matched your search

+23 -12
View File
@@ -141,18 +141,6 @@ final class PlexClient: @unchecked Sendable {
return (out, total)
}
/// Every track in the library, in pages, shuffled.
func allTracksShuffled() async throws -> [Track] {
let size = 2000
var (out, total) = try await tracksPage(start: 0, size: size)
while out.count < total {
let (page, _) = try await tracksPage(start: out.count, size: size)
if page.isEmpty { break }
out += page
}
return out.shuffled()
}
func randomTracks(_ count: Int) async throws -> [Track] {
let each = count / max(sources.count, 1) + 1
return Array(try await pool { s in try await s.randomTracks(each).map { $0.tagged(s.server.id) } }.shuffled().prefix(count))
@@ -265,6 +253,7 @@ final class PlexClient: @unchecked Sendable {
// ---- URLs -----------------------------------------------------------------------
func artUrl(_ thumb: String?, px: Int) -> URL? {
if let thumb, thumb.hasPrefix(StemPlaylists.localPrefix) { return StemPlaylists.localArt(thumb) }
guard let thumb, !thumb.isEmpty, let r = route(thumb) else { return nil }
let (s, k) = r
return s.artUrl(k, px: px)
@@ -276,6 +265,26 @@ final class PlexClient: @unchecked Sendable {
return s.partUrl(k)
}
/// [track]'s file, set up for playback on its server (see PlexServer.streamUrl).
func streamUrl(_ track: Track) async -> URL? {
guard let part = track.partKey, let r = route(part) else { return nil }
let (s, k) = r
let rk = route(track.ratingKey)?.1 ?? track.ratingKey
return await s.streamUrl(rk, partKey: k)
}
/// Blocking form of [streamUrl] for worker threads.
func streamUrlNow(_ track: Track) -> URL? {
let box = UrlBox()
let sem = DispatchSemaphore(value: 0)
Task {
box.url = await streamUrl(track)
sem.signal()
}
sem.wait()
return box.url
}
// ---- sign-in helpers --------------------------------------------------------------
/// A Plex client for plex.tv calls and for a server that isn't saved yet.
@@ -333,3 +342,5 @@ final class PlexClient: @unchecked Sendable {
func jellyfin(_ s: MediaServer) -> JellyfinClient { JellyfinClient(http: http, settings: settings, server: s) }
}
private final class UrlBox: @unchecked Sendable { var url: URL? }