Queue, Favorites, Providers, Now playing

This commit is contained in:
2026-04-06 11:46:04 +02:00
parent e7e9a59e70
commit 56199db301
12 changed files with 462 additions and 58 deletions
+26 -6
View File
@@ -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)
}
}