diff --git a/Sources/API/YouTubePlayer+QueueingAPI.swift b/Sources/API/YouTubePlayer+QueueingAPI.swift index 191ce2a..2552117 100644 --- a/Sources/API/YouTubePlayer+QueueingAPI.swift +++ b/Sources/API/YouTubePlayer+QueueingAPI.swift @@ -76,7 +76,7 @@ private extension YouTubePlayer { struct LoadPlaylistParameter: Encodable { /// The list - let list: String + let list: Source.PlaylistID /// The ListType let listType: Configuration.ListType @@ -108,17 +108,17 @@ private extension YouTubePlayer { startSeconds: startSeconds, endSeconds: endSeconds ) - case .playlist(let id, let index, let startSeconds), - .channel(let id, let index, let startSeconds): + case .playlist(let id, let index, let startSeconds): return LoadPlaylistParameter( list: id, - listType: { - if case .playlist = source { - return .playlist - } else { - return .userUploads - } - }(), + listType: .playlist, + index: index, + startSeconds: startSeconds + ) + case .channel(let id, let index, let startSeconds): + return LoadPlaylistParameter( + list: .init(id), + listType: .userUploads, index: index, startSeconds: startSeconds ) diff --git a/Sources/Extensions/Dictionary+json.swift b/Sources/Extensions/Dictionary+json.swift index 03af934..3428770 100644 --- a/Sources/Extensions/Dictionary+json.swift +++ b/Sources/Extensions/Dictionary+json.swift @@ -7,7 +7,7 @@ extension Dictionary { /// Make JSON String /// - Parameter options: The JSONSerialization WritingOptions. Default value `.init()` func jsonData( - options: JSONSerialization.WritingOptions = .init() + options: JSONSerialization.WritingOptions = [.withoutEscapingSlashes] ) throws -> Data { try JSONSerialization.data( withJSONObject: self, @@ -24,7 +24,7 @@ extension Dictionary { /// Make JSON String /// - Parameter options: The JSONSerialization WritingOptions. Default value `.init()` func jsonString( - options: JSONSerialization.WritingOptions = .init() + options: JSONSerialization.WritingOptions = [.withoutEscapingSlashes] ) throws -> String { .init( decoding: try JSONSerialization.data( diff --git a/Sources/Extensions/Encodable+json.swift b/Sources/Extensions/Encodable+json.swift index ceae66b..8e22c22 100644 --- a/Sources/Extensions/Encodable+json.swift +++ b/Sources/Extensions/Encodable+json.swift @@ -44,8 +44,12 @@ extension Encodable { /// - encoder: The JSONEncoder. Default value `.init()` /// - options: The JSONSerialization WritingOptions. Default value `.init()` func jsonString( - encoder: JSONEncoder = .init(), - options: JSONSerialization.WritingOptions = .init() + encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.outputFormatting = [.withoutEscapingSlashes] + return encoder + }(), + options: JSONSerialization.WritingOptions = [.withoutEscapingSlashes] ) throws -> String { try self .json(encoder: encoder) diff --git a/Sources/Models/YouTubePlayer+Source+PlaylistID.swift b/Sources/Models/YouTubePlayer+Source+PlaylistID.swift new file mode 100644 index 0000000..e40908f --- /dev/null +++ b/Sources/Models/YouTubePlayer+Source+PlaylistID.swift @@ -0,0 +1,111 @@ +import Foundation + +// MARK: - YouTubePlayer+Source+PlaylistID + +public extension YouTubePlayer.Source { + + /// A playlist identifier. + enum PlaylistID: Hashable { + /// Playlist identifier. + case playlist(String) + /// An array of video identifiers. + case videos([String]) + } + +} + +// MARK: - PlaylistID+init(playlist:) + +public extension YouTubePlayer.Source.PlaylistID { + + /// Creates a new instance of `YouTubePlayer.Source.PlaylistID` + /// - Parameter playlist: The playlist identifier + init( + _ playlist: String + ) { + if case let videoIds = playlist.components(separatedBy: ","), videoIds.count > 1 { + self.init(videoIds) + } else { + self = .playlist(playlist) + } + } + +} + +// MARK: - PlaylistID+init(videos:) + +public extension YouTubePlayer.Source.PlaylistID { + + /// Creates a new instance of `YouTubePlayer.Source.PlaylistID` + /// - Parameter videos: An array of video identifiers + init( + _ videos: [String] + ) { + self = .videos(videos) + } + +} + +// MARK: - ExpressibleByStringLiteral + +extension YouTubePlayer.Source.PlaylistID: ExpressibleByStringLiteral { + + /// Creates a new instance of `YouTubePlayer.Source.PlaylistID` + /// - Parameter playlist: The playlist identifier + public init( + stringLiteral playlist: String + ) { + self.init(playlist) + } + +} + +// MARK: - ExpressibleByArrayLiteral + +extension YouTubePlayer.Source.PlaylistID: ExpressibleByArrayLiteral { + + /// Creates a new instance of `YouTubePlayer.Source.PlaylistID` + /// - Parameter videos: An array of video identifiers + public init( + arrayLiteral videos: String... + ) { + self.init(videos) + } + +} + +// MARK: - Encodable + +extension YouTubePlayer.Source.PlaylistID: Encodable { + + /// Encode + /// - Parameter encoder: The encoder + public func encode( + to encoder: Encoder + ) throws { + var container = encoder.singleValueContainer() + switch self { + case .playlist(let playlist): + try container.encode(playlist) + case .videos(let videos): + try container.encode(videos) + } + } + +} + +// MARK: - Identifiable + +extension YouTubePlayer.Source.PlaylistID: Identifiable { + + /// The identifier. + public var id: String { + switch self { + case .playlist(let playlist): + return playlist + case .videos(let videos): + return videos.joined(separator: ",") + } + } + +} diff --git a/Sources/Models/YouTubePlayer+Source.swift b/Sources/Models/YouTubePlayer+Source.swift index 2d3cbf8..c600264 100644 --- a/Sources/Models/YouTubePlayer+Source.swift +++ b/Sources/Models/YouTubePlayer+Source.swift @@ -14,7 +14,7 @@ public extension YouTubePlayer { ) /// Playlist case playlist( - id: String, + id: PlaylistID, index: Int? = nil, startSeconds: Int? = nil ) @@ -36,9 +36,10 @@ extension YouTubePlayer.Source: Identifiable { public var id: String { switch self { case .video(let id, _, _), - .playlist(let id, _, _), .channel(let id, _, _): return id + case .playlist(let playlistID, _, _): + return playlistID.id } } @@ -79,7 +80,7 @@ public extension YouTubePlayer.Source { if let playlistId = urlComponents?.queryItems?["list"] { // Return playlist source return .playlist( - id: playlistId + id: .init(playlistId) ) } // Check if video id is available diff --git a/Sources/Options/YouTubePlayer+Options.swift b/Sources/Options/YouTubePlayer+Options.swift index 38ce51f..830d9b6 100644 --- a/Sources/Options/YouTubePlayer+Options.swift +++ b/Sources/Options/YouTubePlayer+Options.swift @@ -90,7 +90,14 @@ extension YouTubePlayer.Options { // Set playlist id playerConfigurationJSON[ YouTubePlayer.Configuration.CodingKeys.list.rawValue - ] = id + ] = { + switch id { + case .playlist(let playlist): + return playlist + case .videos(let videos): + return videos + } + }() case .channel(let name, _, _): // Set user uploads playerConfigurationJSON[