Queue, Favorites, Providers, Now playing
This commit is contained in:
@@ -184,20 +184,22 @@ struct MAMediaItem: Codable, Identifiable, Hashable {
|
||||
let album: MAAlbum?
|
||||
let metadata: MediaItemMetadata?
|
||||
let duration: Int?
|
||||
let favorite: Bool
|
||||
|
||||
var id: String { uri }
|
||||
var imageUrl: String? { metadata?.thumbImage?.path }
|
||||
var imageProvider: String? { metadata?.thumbImage?.provider }
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uri, name, duration, artists, album, metadata
|
||||
case uri, name, duration, artists, album, metadata, favorite
|
||||
case mediaType = "media_type"
|
||||
case image // Direct image field from search results
|
||||
}
|
||||
|
||||
init(uri: String, name: String, mediaType: MediaType? = nil, artists: [MAArtist]? = nil, album: MAAlbum? = nil, imageUrl: String? = nil, duration: Int? = nil) {
|
||||
init(uri: String, name: String, mediaType: MediaType? = nil, artists: [MAArtist]? = nil, album: MAAlbum? = nil, imageUrl: String? = nil, duration: Int? = nil, favorite: Bool = false) {
|
||||
self.uri = uri; self.name = name; self.mediaType = mediaType
|
||||
self.artists = artists; self.album = album; self.duration = duration
|
||||
self.favorite = favorite
|
||||
self.metadata = imageUrl.map { MediaItemMetadata(images: [MediaItemImage(type: "thumb", path: $0, provider: nil, remotelyAccessible: nil)], cacheChecksum: nil) }
|
||||
}
|
||||
|
||||
@@ -205,6 +207,7 @@ struct MAMediaItem: Codable, Identifiable, Hashable {
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uri = try c.decode(String.self, forKey: .uri)
|
||||
name = try c.decode(String.self, forKey: .name)
|
||||
favorite = (try? c.decode(Bool.self, forKey: .favorite)) ?? false
|
||||
|
||||
// Media type is critical - decode it first
|
||||
let mediaTypeString = try? c.decodeIfPresent(String.self, forKey: .mediaType)
|
||||
@@ -248,6 +251,7 @@ struct MAMediaItem: Codable, Identifiable, Hashable {
|
||||
try c.encodeIfPresent(album, forKey: .album)
|
||||
try c.encodeIfPresent(duration, forKey: .duration)
|
||||
try c.encodeIfPresent(metadata, forKey: .metadata)
|
||||
try c.encode(favorite, forKey: .favorite)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,28 +273,31 @@ struct MAArtist: Codable, Identifiable, Hashable {
|
||||
let metadata: MediaItemMetadata?
|
||||
let sortName: String?
|
||||
let musicbrainzId: String?
|
||||
let favorite: Bool
|
||||
|
||||
var id: String { uri }
|
||||
var imageUrl: String? { metadata?.thumbImage?.path }
|
||||
var imageProvider: String? { metadata?.thumbImage?.provider }
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uri, name, metadata
|
||||
case uri, name, metadata, favorite
|
||||
case sortName = "sort_name"
|
||||
case musicbrainzId = "musicbrainz_id"
|
||||
case image // Direct image field
|
||||
}
|
||||
|
||||
init(uri: String, name: String, imageUrl: String? = nil, imageProvider: String? = nil, sortName: String? = nil, musicbrainzId: String? = nil) {
|
||||
init(uri: String, name: String, imageUrl: String? = nil, imageProvider: String? = nil, sortName: String? = nil, musicbrainzId: String? = nil, favorite: Bool = false) {
|
||||
self.uri = uri; self.name = name
|
||||
self.metadata = imageUrl.map { MediaItemMetadata(images: [MediaItemImage(type: "thumb", path: $0, provider: imageProvider, remotelyAccessible: nil)], cacheChecksum: nil) }
|
||||
self.sortName = sortName; self.musicbrainzId = musicbrainzId
|
||||
self.favorite = favorite
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uri = try c.decode(String.self, forKey: .uri)
|
||||
name = try c.decode(String.self, forKey: .name)
|
||||
favorite = (try? c.decode(Bool.self, forKey: .favorite)) ?? false
|
||||
sortName = try? c.decodeIfPresent(String.self, forKey: .sortName)
|
||||
musicbrainzId = try? c.decodeIfPresent(String.self, forKey: .musicbrainzId)
|
||||
|
||||
@@ -314,6 +321,7 @@ struct MAArtist: Codable, Identifiable, Hashable {
|
||||
try c.encodeIfPresent(sortName, forKey: .sortName)
|
||||
try c.encodeIfPresent(musicbrainzId, forKey: .musicbrainzId)
|
||||
try c.encodeIfPresent(metadata, forKey: .metadata)
|
||||
try c.encode(favorite, forKey: .favorite)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,18 +331,20 @@ struct MAAlbum: Codable, Identifiable, Hashable {
|
||||
let artists: [MAArtist]?
|
||||
let metadata: MediaItemMetadata?
|
||||
let year: Int?
|
||||
let favorite: Bool
|
||||
|
||||
var id: String { uri }
|
||||
var imageUrl: String? { metadata?.thumbImage?.path }
|
||||
var imageProvider: String? { metadata?.thumbImage?.provider }
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case uri, name, artists, metadata, year
|
||||
case uri, name, artists, metadata, year, favorite
|
||||
case image // Direct image field
|
||||
}
|
||||
|
||||
init(uri: String, name: String, artists: [MAArtist]? = nil, imageUrl: String? = nil, imageProvider: String? = nil, year: Int? = nil) {
|
||||
init(uri: String, name: String, artists: [MAArtist]? = nil, imageUrl: String? = nil, imageProvider: String? = nil, year: Int? = nil, favorite: Bool = false) {
|
||||
self.uri = uri; self.name = name; self.artists = artists; self.year = year
|
||||
self.favorite = favorite
|
||||
self.metadata = imageUrl.map { MediaItemMetadata(images: [MediaItemImage(type: "thumb", path: $0, provider: imageProvider, remotelyAccessible: nil)], cacheChecksum: nil) }
|
||||
}
|
||||
|
||||
@@ -342,6 +352,7 @@ struct MAAlbum: Codable, Identifiable, Hashable {
|
||||
let c = try decoder.container(keyedBy: CodingKeys.self)
|
||||
uri = try c.decode(String.self, forKey: .uri)
|
||||
name = try c.decode(String.self, forKey: .name)
|
||||
favorite = (try? c.decode(Bool.self, forKey: .favorite)) ?? false
|
||||
artists = try? c.decodeIfPresent([MAArtist].self, forKey: .artists)
|
||||
year = try? c.decodeIfPresent(Int.self, forKey: .year)
|
||||
|
||||
@@ -365,6 +376,7 @@ struct MAAlbum: Codable, Identifiable, Hashable {
|
||||
try c.encodeIfPresent(artists, forKey: .artists)
|
||||
try c.encodeIfPresent(year, forKey: .year)
|
||||
try c.encodeIfPresent(metadata, forKey: .metadata)
|
||||
try c.encode(favorite, forKey: .favorite)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,11 +419,17 @@ struct MAPlayerQueue: Codable {
|
||||
let queueId: String
|
||||
let currentItem: MAQueueItem?
|
||||
let currentIndex: Int?
|
||||
/// Seconds elapsed in current track (at the time of last update).
|
||||
let elapsedTime: Double?
|
||||
/// Unix timestamp when `elapsedTime` was last set by the server.
|
||||
let elapsedTimeLastUpdated: Double?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case queueId = "queue_id"
|
||||
case currentItem = "current_item"
|
||||
case currentIndex = "current_index"
|
||||
case elapsedTime = "elapsed_time"
|
||||
case elapsedTimeLastUpdated = "elapsed_time_last_updated"
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
@@ -419,6 +437,8 @@ struct MAPlayerQueue: Codable {
|
||||
queueId = try c.decode(String.self, forKey: .queueId)
|
||||
currentItem = try? c.decodeIfPresent(MAQueueItem.self, forKey: .currentItem)
|
||||
currentIndex = try? c.decodeIfPresent(Int.self, forKey: .currentIndex)
|
||||
elapsedTime = try? c.decodeIfPresent(Double.self, forKey: .elapsedTime)
|
||||
elapsedTimeLastUpdated = try? c.decodeIfPresent(Double.self, forKey: .elapsedTimeLastUpdated)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user