Queue mgmt, Podcast support, Favorites section.

This commit is contained in:
2026-04-08 10:26:50 +02:00
parent f55b7e478b
commit d7e7bef83f
14 changed files with 1177 additions and 60 deletions
@@ -22,6 +22,7 @@ final class MALibraryManager {
private(set) var albumArtists: [MAArtist] = []
private(set) var albums: [MAAlbum] = []
private(set) var playlists: [MAPlaylist] = []
private(set) var podcasts: [MAPodcast] = []
// Pagination
private var artistsOffset = 0
@@ -37,6 +38,7 @@ final class MALibraryManager {
private(set) var isLoadingAlbumArtists = false
private(set) var isLoadingAlbums = false
private(set) var isLoadingPlaylists = false
private(set) var isLoadingPodcasts = false
/// URIs currently marked as favorites source of truth for UI.
/// Populated from decoded model data, then mutated optimistically on toggle.
@@ -47,6 +49,7 @@ final class MALibraryManager {
private(set) var lastAlbumArtistsRefresh: Date?
private(set) var lastAlbumsRefresh: Date?
private(set) var lastPlaylistsRefresh: Date?
private(set) var lastPodcastsRefresh: Date?
// MARK: - Disk Cache
@@ -109,17 +112,23 @@ final class MALibraryManager {
playlists = cached
logger.info("Loaded \(cached.count) playlists from disk cache")
}
if let cached: [MAPodcast] = load("podcasts.json") {
podcasts = cached
logger.info("Loaded \(cached.count) podcasts from disk cache")
}
// Seed favorite URIs from cached data
for artist in artists where artist.favorite { favoriteURIs.insert(artist.uri) }
for artist in albumArtists where artist.favorite { favoriteURIs.insert(artist.uri) }
for album in albums where album.favorite { favoriteURIs.insert(album.uri) }
for podcast in podcasts where podcast.favorite { favoriteURIs.insert(podcast.uri) }
let ud = UserDefaults.standard
lastArtistsRefresh = ud.object(forKey: "lib.lastArtistsRefresh") as? Date
lastAlbumArtistsRefresh = ud.object(forKey: "lib.lastAlbumArtistsRefresh") as? Date
lastAlbumsRefresh = ud.object(forKey: "lib.lastAlbumsRefresh") as? Date
lastPlaylistsRefresh = ud.object(forKey: "lib.lastPlaylistsRefresh") as? Date
lastPodcastsRefresh = ud.object(forKey: "lib.lastPodcastsRefresh") as? Date
}
private func save<T: Encodable>(_ value: T, _ filename: String) {
@@ -338,6 +347,32 @@ final class MALibraryManager {
logger.info("Loaded \(loaded.count) playlists")
}
// MARK: - Podcasts
func loadPodcasts(refresh: Bool = false) async throws {
guard !isLoadingPodcasts else { return }
guard let service else { throw MAWebSocketClient.ClientError.notConnected }
isLoadingPodcasts = true
defer { isLoadingPodcasts = false }
logger.info("Loading podcasts")
let loaded = try await service.getPodcasts()
podcasts = loaded
for podcast in loaded where podcast.favorite { favoriteURIs.insert(podcast.uri) }
save(podcasts, "podcasts.json")
lastPodcastsRefresh = markRefreshed("lib.lastPodcastsRefresh")
logger.info("Loaded \(loaded.count) podcasts")
}
func getPodcastEpisodes(podcastUri: String) async throws -> [MAMediaItem] {
guard let service else { throw MAWebSocketClient.ClientError.notConnected }
logger.info("Loading episodes for podcast \(podcastUri)")
return try await service.getPodcastEpisodes(podcastUri: podcastUri)
}
// MARK: - Artist Albums & Tracks (not cached fetched on demand)
func getArtistAlbums(artistUri: String) async throws -> [MAAlbum] {