Skip to content

Commit d8ff82e

Browse files
cacuscacussozercan
andauthored
Queue Enhancement Features (#97)
Co-authored-by: Sertac Ozercan <sozercan@gmail.com>
1 parent 1a192e0 commit d8ff82e

25 files changed

+3767
-179
lines changed

App/AppDelegate.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
3232

3333
// Register for system sleep/wake notifications
3434
self.registerForSleepWakeNotifications()
35+
36+
// Restore saved queue if available
37+
self.playerService?.restoreQueueFromPersistence()
38+
}
39+
40+
func applicationWillTerminate(_: Notification) {
41+
// Save queue for persistence on next launch
42+
self.playerService?.saveQueueForPersistence()
43+
DiagnosticsLogger.player.info("Application will terminate - saved queue for persistence")
3544
}
3645

3746
/// Registers for system sleep and wake notifications to handle playback appropriately.

App/KasetApp.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ struct KasetApp: App {
7676
_notificationService = State(initialValue: NotificationService(playerService: player))
7777
_accountService = State(initialValue: account)
7878

79+
// Wire up PlayerService to AppDelegate immediately (not in onAppear)
80+
// This ensures playerService is available for lifecycle events like queue restoration
81+
self.appDelegate.playerService = player
82+
7983
if UITestConfig.isUITestMode {
8084
DiagnosticsLogger.ui.info("App launched in UI Test mode")
8185
}

Core/Models/QueueDisplayMode.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Foundation
2+
3+
// MARK: - QueueDisplayMode
4+
5+
/// Display mode for the playback queue panel.
6+
enum QueueDisplayMode: String, Codable, CaseIterable, Sendable {
7+
case popup
8+
case sidepanel
9+
10+
var displayName: String {
11+
switch self {
12+
case .popup: "Popup"
13+
case .sidepanel: "Side Panel"
14+
}
15+
}
16+
17+
var description: String {
18+
switch self {
19+
case .popup: "Compact overlay view"
20+
case .sidepanel: "Full-width panel with reordering"
21+
}
22+
}
23+
}

Core/Models/Song.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import CoreTransferable
12
import Foundation
23

34
// MARK: - Song
@@ -140,3 +141,11 @@ extension Song {
140141
hasher.combine(self.videoId)
141142
}
142143
}
144+
145+
// MARK: Transferable
146+
147+
extension Song: Transferable {
148+
static var transferRepresentation: some TransferRepresentation {
149+
CodableRepresentation(for: Song.self, contentType: .data)
150+
}
151+
}

Core/Services/Player/PlayerService+Library.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,25 @@ extension PlayerService {
146146
}
147147

148148
self.logger.info("Updated track metadata - inLibrary: \(self.currentTrackInLibrary), hasTokens: \(self.currentTrackFeedbackTokens != nil)")
149+
150+
// Also update the corresponding song in the queue with enriched metadata
151+
// This ensures the queue displays complete info without separate API calls
152+
if let queueIndex = self.queue.firstIndex(where: { $0.videoId == videoId }) {
153+
// Only update if the queue entry is missing metadata
154+
let currentQueueSong = self.queue[queueIndex]
155+
let needsUpdate = currentQueueSong.artists.isEmpty ||
156+
currentQueueSong.artists.allSatisfy { $0.name.isEmpty || $0.name == "Unknown Artist" } ||
157+
currentQueueSong.title.isEmpty ||
158+
currentQueueSong.title == "Loading..." ||
159+
currentQueueSong.thumbnailURL == nil
160+
161+
if needsUpdate {
162+
self.queue[queueIndex] = songData
163+
self.logger.debug("Enriched queue entry at index \(queueIndex): '\(songData.title)' with artists: \(songData.artistsDisplay)")
164+
// Save the enriched queue to persistence
165+
self.saveQueueForPersistence()
166+
}
167+
}
149168
}
150169
} catch {
151170
self.logger.warning("Failed to fetch song metadata: \(error.localizedDescription)")

0 commit comments

Comments
 (0)