Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ extension PlayerService {
if !preservesQueueContext {
self.cancelDeferredQueueWork()
}
self.sourcePlaylistId = nil
self.logger.debug("Stopping playback")
self.isStoppingPlayback = true
self.shouldResumeAfterInterruption = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ extension PlayerService {
func play(videoId: String, intent: MusicPlaybackIntent) async {
guard self.acceptsMusicPlaybackIntent(intent) else { return }
self.logger.debug("play() called with videoId: \(videoId)")
self.sourcePlaylistId = nil
let acceptsPlaybackRequest = SingletonPlayerWebView.shared.acceptsPlaybackRequest(
videoId: videoId,
strategy: .standard
Expand Down Expand Up @@ -164,6 +165,7 @@ extension PlayerService {
/// Plays a song.
func play(song: Song) async {
let intent = self.beginMusicPlaybackIntent()
self.sourcePlaylistId = nil
await self.play(
song: song,
webLoadStrategy: .standard,
Expand All @@ -182,6 +184,7 @@ extension PlayerService {
episode: ArtistEpisode? = nil
) async {
let intent = self.beginMusicPlaybackIntent()
self.sourcePlaylistId = nil
await self.play(
song: song,
webLoadStrategy: webLoadStrategy,
Expand Down
2 changes: 2 additions & 0 deletions Sources/Kaset/Services/Player/PlayerService+Queue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ extension PlayerService {
func playWithRadio(song: Song, intent: MusicPlaybackIntent) async {
guard self.acceptsMusicPlaybackIntent(intent) else { return }
self.logger.info("Playing with radio: \(song.title)")
self.sourcePlaylistId = nil
self.clearForwardSkipNavigationStack()
self.recordQueueStateForUndo()
self.prepareForNewPlaybackContext()
Expand Down Expand Up @@ -137,6 +138,7 @@ extension PlayerService {
guard self.acceptsMusicPlaybackIntent(intent) else { return }
self.logger.info("Playing mix playlist: \(playlistId), startVideoId: \(startVideoId ?? "nil (random)")")
let continuationRequiresAuth = self.authService?.hasPersonalAccount == true
self.sourcePlaylistId = nil
self.clearForwardSkipNavigationStack()

guard let client = self.ytMusicClient else {
Expand Down
6 changes: 6 additions & 0 deletions Sources/Kaset/Services/Player/PlayerService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ final class PlayerService: NSObject, PlayerServiceProtocol {
}
}

/// The playlist ID the current track was played from, if any.
/// Set when playback starts from a playlist/album and cleared when a non-playlist
/// source (radio, mix, standalone track, or stop) takes over. The sidebar reads
/// this to highlight the originating pinned playlist row.
var sourcePlaylistId: String?

@ObservationIgnored private var durationObservation: (videoId: String, duration: TimeInterval)?
@ObservationIgnored var isApplyingPlaybackStateObservation = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum PlaylistPlaybackActions {
playerService: PlayerService
) -> Task<Void, Never> {
let intent = playerService.beginMusicPlaybackIntent()
playerService.sourcePlaylistId = playlist.id
return Task { @MainActor in
do {
let response = try await client.getPlaylist(id: playlist.id)
Expand Down
3 changes: 3 additions & 0 deletions Sources/Kaset/Services/Protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ protocol PlayerServiceProtocol: AnyObject, Sendable {
/// Currently playing track.
var currentTrack: Song? { get }

/// The playlist ID the current track was played from, if any.
var sourcePlaylistId: String? { get }

/// Whether playback is active.
var isPlaying: Bool { get }

Expand Down
1 change: 1 addition & 0 deletions Sources/Kaset/Views/PlaylistDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ struct PlaylistDetailView: View {
fallbackArtist: String?, fallbackAlbum: Album?
) {
let intent = self.playerService.beginMusicPlaybackIntent()
self.playerService.sourcePlaylistId = self.viewModel.playlistDetail?.id
Task { @MainActor in
let willDeferLoad = self.viewModel.hasMore
let loadGeneration = await self.playerService.playQueue(
Expand Down
3 changes: 2 additions & 1 deletion Sources/Kaset/Views/SharedViews/KasetSidebarRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ struct KasetSidebarRow: View {
let title: String
let systemImage: String
let isSelected: Bool
var isNowPlayingSource: Bool = false
let action: () -> Void

var body: some View {
Button(action: self.action) {
Label {
Text(self.title)
.lineLimit(1)
.foregroundStyle(.primary)
.foregroundStyle(self.isNowPlayingSource ? PackageResourceLookup.brandAccent : .primary)
} icon: {
Image(systemName: self.systemImage)
.foregroundStyle(PackageResourceLookup.brandAccent)
Expand Down
3 changes: 2 additions & 1 deletion Sources/Kaset/Views/Sidebar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ struct Sidebar: View {
KasetSidebarRow(
title: item.title,
systemImage: item.systemImage,
isSelected: self.currentSidebarSelection == .pinned(item)
isSelected: self.currentSidebarSelection == .pinned(item),
isNowPlayingSource: self.playerService.sourcePlaylistId == item.contentId
) {
self.selectPinnedItem(item)
}
Expand Down
1 change: 1 addition & 0 deletions Tests/KasetTests/Helpers/MockPlayerService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Foundation
final class MockPlayerService: PlayerServiceProtocol {
var state: PlayerService.PlaybackState = .idle
var currentTrack: Song?
var sourcePlaylistId: String?
var progress: TimeInterval = 0
var duration: TimeInterval = 0
var volume: Double = 1
Expand Down
Loading