From 128e198c901bf39d05d718a77ac962d963a7e271 Mon Sep 17 00:00:00 2001 From: zaehorang Date: Thu, 27 Jun 2024 11:45:51 +0900 Subject: [PATCH 1/5] chore: [#114] Delete description --- .../xcshareddata/xcschemes/MinGenie.xcscheme | 2 +- .../MinGenie/Playback/NowPlayingView.swift | 25 +++---------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/MinGenie/MinGenie.xcodeproj/xcshareddata/xcschemes/MinGenie.xcscheme b/MinGenie/MinGenie.xcodeproj/xcshareddata/xcschemes/MinGenie.xcscheme index f7c47ad..83d9905 100644 --- a/MinGenie/MinGenie.xcodeproj/xcshareddata/xcschemes/MinGenie.xcscheme +++ b/MinGenie/MinGenie.xcodeproj/xcshareddata/xcschemes/MinGenie.xcscheme @@ -1,7 +1,7 @@ + version = "1.8"> some View { ScrollViewReader { proxy in @@ -116,6 +100,7 @@ struct NowPlayingView: View { } .background(Color.BG.main) .listStyle(.plain) + ///비활성화되어있을 때 곡이 넘어가도, 켜면 바로 그 곡으로 스크롤되도록! .onAppear { if let entry = playbackQueue.currentEntry, let newIndex = playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { @@ -250,7 +235,6 @@ struct NowPlayingView: View { private func imageContainer(for artwork: Artwork?) -> some View { VStack { - // Spacer() if let artwork = artwork { ZStack { ArtworkImage(artwork, width: 244, height: 244) @@ -269,7 +253,6 @@ struct NowPlayingView: View { .cornerRadius(16) .shadow(radius: 4) } - // Spacer() } } } From a82db356940a59c559f4684def21f09420cd2253 Mon Sep 17 00:00:00 2001 From: zaehorang Date: Thu, 27 Jun 2024 15:56:21 +0900 Subject: [PATCH 2/5] refactor: [#114] Store current playing music index in MusicPlayerModel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 현재 재생 중인 음악의 인덱스를 @AppStorage에서 음악 재생 모델의 프로퍼티로 저장하는 방식으로 수정 --- .../MinGenie/Playback/MusicPlayerModel.swift | 1 + .../MinGenie/Playback/NowPlayingView.swift | 41 ++++++++----------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift index b8e7288..544585b 100644 --- a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift +++ b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift @@ -10,6 +10,7 @@ final class MusicPlayerModel: ObservableObject { // MARK: - Properties @Published var isPlaying = false @Published var playbackQueue = ApplicationMusicPlayer.shared.queue + @Published var currentMusicIndex: Int = 0 var playbackStateObserver: AnyCancellable? diff --git a/MinGenie/MinGenie/Playback/NowPlayingView.swift b/MinGenie/MinGenie/Playback/NowPlayingView.swift index 7e563a8..3d0b75b 100644 --- a/MinGenie/MinGenie/Playback/NowPlayingView.swift +++ b/MinGenie/MinGenie/Playback/NowPlayingView.swift @@ -1,8 +1,6 @@ import MusicKit import SwiftUI -/// ✏️ 현재 재생 View입니다 (수정중) ✏️ - struct NowPlayingView: View { ///Music Player관련 @@ -13,11 +11,6 @@ struct NowPlayingView: View { @Environment(\.presentationMode) var presentation @GestureState private var dragOffset: CGFloat = 0 - ///Carousel 인덱스 관련 - @AppStorage("currentIndex") private var currentIndex: Int = 0 - - @State var idx = -1 - var body: some View { /// 전체 View 구성 NavigationView { @@ -56,18 +49,18 @@ struct NowPlayingView: View { .onAppear { /// onAppear시, entries에서의 index와 캐러셀의 index를 일치시켜줘요! if let savedEntryIndex = playbackQueue.entries.firstIndex(where: { $0.id == playbackQueue.currentEntry?.id }) { - currentIndex = savedEntryIndex + musicPlayer.currentMusicIndex = savedEntryIndex } /// entries에 아무것도 안담겨 있으면 index 0으로 초기화해요! else { - currentIndex = 0 + musicPlayer.currentMusicIndex = 0 } } /// fullScreen일때, 현재재생곡이 넘어가면 캐러셀이 전환되는 부분입니다! .onChange(of: playbackQueue.currentEntry) { _, entry in /// 또 전수검사 해줘요.. if let entry = entry, let newIndex = playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { - currentIndex = newIndex + musicPlayer.currentMusicIndex = newIndex } } } @@ -93,7 +86,7 @@ struct NowPlayingView: View { .listRowBackground(Color.BG.main) .onTapGesture { playbackQueue.currentEntry = playbackQueue.entries[index] - currentIndex = index + musicPlayer.currentMusicIndex = index if !musicPlayer.isPlaying { pausePlay() } } } @@ -104,18 +97,18 @@ struct NowPlayingView: View { ///비활성화되어있을 때 곡이 넘어가도, 켜면 바로 그 곡으로 스크롤되도록! .onAppear { if let entry = playbackQueue.currentEntry, let newIndex = playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { - currentIndex = newIndex + musicPlayer.currentMusicIndex = newIndex withAnimation { - proxy.scrollTo(currentIndex, anchor: .top) + proxy.scrollTo(musicPlayer.currentMusicIndex, anchor: .top) } } } ///현재재생곡이 넘어가면 list가 스크롤되는 부분입니다! .onChange(of: playbackQueue.currentEntry) { _, entry in if let entry = entry, let newIndex = playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { - currentIndex = newIndex + musicPlayer.currentMusicIndex = newIndex withAnimation { - proxy.scrollTo(currentIndex, anchor: .top) + proxy.scrollTo(musicPlayer.currentMusicIndex, anchor: .top) } } } @@ -136,19 +129,19 @@ struct NowPlayingView: View { VStack { ZStack { if playbackQueue.entries.count > 0 { - let startIndex = max(currentIndex - 2, 0) - let endIndex = min(currentIndex + 2, playbackQueue.entries.count - 1) + let startIndex = max(musicPlayer.currentMusicIndex - 2, 0) + let endIndex = min(musicPlayer.currentMusicIndex + 2, playbackQueue.entries.count - 1) if startIndex <= endIndex { ForEach(startIndex...endIndex, id: \.self) { index in imageContainer(for: playbackQueue.entries[index].artwork) - .scaleEffect(1.0 - CGFloat(abs(index - currentIndex)) * 0.1) - .zIndex(1.0 - Double(abs(index - currentIndex))) - .offset(x: CGFloat(index - currentIndex) * 50 * (1 - CGFloat(abs(index - currentIndex)) * 0.1) + dragOffset, y: 0) + .scaleEffect(1.0 - CGFloat(abs(index - musicPlayer.currentMusicIndex)) * 0.1) + .zIndex(1.0 - Double(abs(index - musicPlayer.currentMusicIndex))) + .offset(x: CGFloat(index - musicPlayer.currentMusicIndex) * 50 * (1 - CGFloat(abs(index - musicPlayer.currentMusicIndex)) * 0.1) + dragOffset, y: 0) .padding(.top, -20) - if index == currentIndex { + if index == musicPlayer.currentMusicIndex { VStack(spacing: 0) { Text(playbackQueue.entries[index].title) .font(.system(size: 20, weight: .bold)) @@ -184,15 +177,15 @@ struct NowPlayingView: View { let threshold: CGFloat = 50 if value.translation.width > threshold { withAnimation { - currentIndex = max(0, currentIndex - 1) + musicPlayer.currentMusicIndex = max(0, musicPlayer.currentMusicIndex - 1) } } else if value.translation.width < -threshold { withAnimation { - currentIndex = min(playbackQueue.entries.count - 1, currentIndex + 1) + musicPlayer.currentMusicIndex = min(playbackQueue.entries.count - 1, musicPlayer.currentMusicIndex + 1) } } /// 캐러셀 넘기면 currentEntry를 갈아치워요! - playbackQueue.currentEntry = playbackQueue.entries[currentIndex] + playbackQueue.currentEntry = playbackQueue.entries[musicPlayer.currentMusicIndex] } ) } From d9d075ef06ea9ce6f835871968e22734bd144764 Mon Sep 17 00:00:00 2001 From: zaehorang Date: Fri, 28 Jun 2024 00:21:35 +0900 Subject: [PATCH 3/5] Refactor: Change MusicPlayerModel injection to @EnvironmentObject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MusicPlayerModel을 @ObservedObject에서 @EnvironmentObject로 변경 - 최상단 뷰에서 PlayerModel 인스턴스를 주입하여 환경 기반 의존성 주입 구현 - MusicPlayerModel을 필요로 하는 모든 뷰를 @EnvironmentObject로 수정 --- MinGenie/MinGenie/ContentView.swift | 10 +++---- MinGenie/MinGenie/MinGenieApp.swift | 4 ++- .../Playback/Cells/NowQueueItemCell.swift | 4 --- .../MinGenie/Playback/MiniPlayerView.swift | 10 +++---- .../MinGenie/Playback/MusicPlayerModel.swift | 3 --- .../MinGenie/Playback/NowPlayingView.swift | 26 +++++++++---------- 6 files changed, 23 insertions(+), 34 deletions(-) diff --git a/MinGenie/MinGenie/ContentView.swift b/MinGenie/MinGenie/ContentView.swift index 3328ffa..55d3b52 100644 --- a/MinGenie/MinGenie/ContentView.swift +++ b/MinGenie/MinGenie/ContentView.swift @@ -11,9 +11,9 @@ import SwiftUI struct ContentView: View { @Environment(\.scenePhase) var phase + @EnvironmentObject var musicPlayer: MusicPlayerModel @StateObject var shakeDetectionModel = ShakeDetectionModel() - @StateObject var musicPlayerModel = MusicPlayerModel.shared @AppStorage("Onboarding") var hasSeenOnboarding = false @AppStorage("BackgroundInfo") var hasSeenBackgroundInfoView = false @@ -23,16 +23,16 @@ struct ContentView: View { ZStack(alignment: .bottom) { HomeView() .modelContainer(for: StoredTrackID.self) - .environmentObject(musicPlayerModel) + .environmentObject(musicPlayer) .onChange(of: phase) { _, newValue in - if newValue == .background && musicPlayerModel.isPlaying { + if newValue == .background && musicPlayer.isPlaying { shakeDetectionModel.startDetection() } else { shakeDetectionModel.stopDetection() } } .onChange(of: shakeDetectionModel.shakeDetected) { _, newValue in - if newValue && musicPlayerModel.isPlaying { + if newValue && musicPlayer.isPlaying { print("🎧 Music Change") AudioServicesPlaySystemSound(kSystemSoundID_Vibrate) //진동 주기 @@ -40,7 +40,7 @@ struct ContentView: View { // 노래 교체가 끝나면 다시 시작 shakeDetectionModel.stopDetection() Task { - await musicPlayerModel.updatePlaylistAfterShaking() + await musicPlayer.updatePlaylistAfterShaking() if phase == .background { shakeDetectionModel.startDetection() } diff --git a/MinGenie/MinGenie/MinGenieApp.swift b/MinGenie/MinGenie/MinGenieApp.swift index c3e4c4c..6c8a586 100644 --- a/MinGenie/MinGenie/MinGenieApp.swift +++ b/MinGenie/MinGenie/MinGenieApp.swift @@ -10,10 +10,12 @@ import SwiftUI @main struct MinGenieApp: App { - + @StateObject var musicPlayerModel = MusicPlayerModel() + var body: some Scene { WindowGroup { ContentView() + .environmentObject(musicPlayerModel) } } } diff --git a/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift b/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift index 5246257..7f06aa2 100644 --- a/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift +++ b/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift @@ -27,19 +27,15 @@ struct NowQueueItemCell: View { // MARK: - View var body: some View { HStack { - if let itemArtwork = artwork { imageContainer(for: itemArtwork) .frame(width: artworkSize, height: artworkSize) } else { - Image("FlowishGray") .resizable() .frame(width: artworkSize, height: artworkSize) } - - VStack(alignment: .leading) { Text(title) .font(.system(size: 17, weight: .semibold)) diff --git a/MinGenie/MinGenie/Playback/MiniPlayerView.swift b/MinGenie/MinGenie/Playback/MiniPlayerView.swift index 047ecaf..3c2e8a0 100644 --- a/MinGenie/MinGenie/Playback/MiniPlayerView.swift +++ b/MinGenie/MinGenie/Playback/MiniPlayerView.swift @@ -4,15 +4,11 @@ import SwiftUI /// ✏️ 하단에 띄워 둘 미니플레이어 View입니다 (완성) ✏️ struct MiniPlayerView: View { - - /// musicPlayer 관련 변수 - @ObservedObject private var playbackQueue = ApplicationMusicPlayer.shared.queue - @ObservedObject private var musicPlayer = MusicPlayerModel.shared + @EnvironmentObject var musicPlayer: MusicPlayerModel /// fullscreen전환 관련 변수 @State private var isShowingNowPlaying = false - // MARK: - View var body: some View { content @@ -25,13 +21,13 @@ struct MiniPlayerView: View { .shadow(radius: 20) ) .fullScreenCover(isPresented: $isShowingNowPlaying) { - NowPlayingView(playbackQueue: playbackQueue) + NowPlayingView() } } @ViewBuilder private var content: some View { - if let currentPlayerEntry = playbackQueue.currentEntry { + if let currentPlayerEntry = musicPlayer.playbackQueue.currentEntry { HStack { VStack(alignment: .leading){ Button(action: handleTap) { diff --git a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift index 544585b..1642975 100644 --- a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift +++ b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift @@ -3,9 +3,6 @@ import MusicKit import SwiftUI final class MusicPlayerModel: ObservableObject { - static let shared = MusicPlayerModel() - - private init() {} // MARK: - Properties @Published var isPlaying = false diff --git a/MinGenie/MinGenie/Playback/NowPlayingView.swift b/MinGenie/MinGenie/Playback/NowPlayingView.swift index 3d0b75b..ff5835b 100644 --- a/MinGenie/MinGenie/Playback/NowPlayingView.swift +++ b/MinGenie/MinGenie/Playback/NowPlayingView.swift @@ -2,10 +2,7 @@ import MusicKit import SwiftUI struct NowPlayingView: View { - - ///Music Player관련 - @ObservedObject var playbackQueue: ApplicationMusicPlayer.Queue - @ObservedObject private var musicPlayer = MusicPlayerModel.shared + @EnvironmentObject var musicPlayer: MusicPlayerModel ///FullScreen Dismiss 관련 @Environment(\.presentationMode) var presentation @@ -16,7 +13,7 @@ struct NowPlayingView: View { NavigationView { VStack(spacing: 0) { - DismissButton { FullScreenDismiss() } + DismissButton { fullScreenDismiss() } .padding(.bottom, 10) HStack { Text("Flowish") @@ -42,13 +39,13 @@ struct NowPlayingView: View { .gesture( DragGesture().onEnded { value in if value.translation.height > 150 { - FullScreenDismiss() + fullScreenDismiss() } } ) .onAppear { /// onAppear시, entries에서의 index와 캐러셀의 index를 일치시켜줘요! - if let savedEntryIndex = playbackQueue.entries.firstIndex(where: { $0.id == playbackQueue.currentEntry?.id }) { + if let savedEntryIndex = musicPlayer.playbackQueue.entries.firstIndex(where: { $0.id == musicPlayer.playbackQueue.currentEntry?.id }) { musicPlayer.currentMusicIndex = savedEntryIndex } /// entries에 아무것도 안담겨 있으면 index 0으로 초기화해요! @@ -57,9 +54,9 @@ struct NowPlayingView: View { } } /// fullScreen일때, 현재재생곡이 넘어가면 캐러셀이 전환되는 부분입니다! - .onChange(of: playbackQueue.currentEntry) { _, entry in + .onChange(of: musicPlayer.playbackQueue.currentEntry) { _, entry in /// 또 전수검사 해줘요.. - if let entry = entry, let newIndex = playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { + if let entry = entry, let newIndex = musicPlayer.playbackQueue.entries.firstIndex(where: { $0.id == entry.id }) { musicPlayer.currentMusicIndex = newIndex } } @@ -69,12 +66,12 @@ struct NowPlayingView: View { private var QueueView: some View { ZStack { Color.BG.main.ignoresSafeArea(.all) - Queuelist(for: playbackQueue) + QueueList(for: musicPlayer.playbackQueue) } } @ViewBuilder - private func Queuelist(for playbackQueue: ApplicationMusicPlayer.Queue) -> some View { + private func QueueList(for playbackQueue: ApplicationMusicPlayer.Queue) -> some View { ScrollViewReader { proxy in List { ForEach(playbackQueue.entries.indices, id: \.self) { index in @@ -117,10 +114,11 @@ struct NowPlayingView: View { @ViewBuilder private var CarouselView: some View { - Carousellist(for: playbackQueue) + CarouselList(for: musicPlayer.playbackQueue) } - private func Carousellist(for playbackQueue: ApplicationMusicPlayer.Queue) -> some View { + @ViewBuilder + private func CarouselList(for playbackQueue: ApplicationMusicPlayer.Queue) -> some View { NavigationStack { ZStack { @@ -204,7 +202,7 @@ struct NowPlayingView: View { musicPlayer.togglePlaybackStatus() } - private func FullScreenDismiss() { + private func fullScreenDismiss() { presentation.wrappedValue.dismiss() } From 633049d2bf93037fd14efca1b5b4e42c897714eb Mon Sep 17 00:00:00 2001 From: zaehorang Date: Sun, 7 Jul 2024 20:36:33 +0900 Subject: [PATCH 4/5] fix: Update `isPlaying` on main thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 뷰와 관련된 published 프로퍼티의 값 변경을 메인 스레드에서 하도록 수정 --- MinGenie/MinGenie/Playback/MusicPlayerModel.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift index 1642975..25de7e5 100644 --- a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift +++ b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift @@ -248,7 +248,9 @@ final class MusicPlayerModel: ObservableObject { } private func handlePlaybackStateDidChange() { - isPlaying = (musicPlayer.state.playbackStatus == .playing) + DispatchQueue.main.async { + self.isPlaying = (self.musicPlayer.state.playbackStatus == .playing) + } } } From 8cd7f780f44d7fec0e0d9416425d82eca6a859d3 Mon Sep 17 00:00:00 2001 From: zaehorang Date: Mon, 8 Jul 2024 01:40:02 +0900 Subject: [PATCH 5/5] fix: [#114] Display artwork in view by resolving cache issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 플레이어 뷰에서 아트워크 이미지가 보이지 않는 이슈 해결 - queue에 음악을 넣으면서 관련 track을 배열에 따로 저장한 뒤, 해당 값의 아트워크에 접근하여 뷰에 보여줌 --- .../Playback/Cells/NowQueueItemCell.swift | 6 ++--- .../MinGenie/Playback/MusicPlayerModel.swift | 26 ++++++++++++++++--- .../MinGenie/Playback/NowPlayingView.swift | 4 +-- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift b/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift index 7f06aa2..d3f6775 100644 --- a/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift +++ b/MinGenie/MinGenie/Playback/Cells/NowQueueItemCell.swift @@ -4,9 +4,9 @@ import SwiftUI /// A view that displays information about a music item. struct NowQueueItemCell: View { // MARK: - Properties - private var artworkSize: CGFloat = 51 - private var artworkCornerRadius: CGFloat = 11 - private var subtitleVerticalOffset: CGFloat = -8 + private let artworkSize: CGFloat = 51 + private let artworkCornerRadius: CGFloat = 11 + private let subtitleVerticalOffset: CGFloat = -8 let artwork: Artwork? let title: String diff --git a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift index 25de7e5..4d48b59 100644 --- a/MinGenie/MinGenie/Playback/MusicPlayerModel.swift +++ b/MinGenie/MinGenie/Playback/MusicPlayerModel.swift @@ -8,6 +8,8 @@ final class MusicPlayerModel: ObservableObject { @Published var isPlaying = false @Published var playbackQueue = ApplicationMusicPlayer.shared.queue @Published var currentMusicIndex: Int = 0 + // Track 캐싱을 위한 배열 + @Published var queueTracks: [Track] = [] var playbackStateObserver: AnyCancellable? @@ -151,8 +153,9 @@ final class MusicPlayerModel: ObservableObject { /// - Returns: 필터링된 트랙 배열 private func filterInstrumentalTracks(from tracks: MusicItemCollection) -> [Track] { return tracks.filter { track in - // 대, 소문자 구분 없이 제외 - return track.title.range(of: "(instrumental)", options: .caseInsensitive) == nil + // 대, 소문자 구분 없이 'instrumental' 및 'inst.'를 제외 + let lowercasedTitle = track.title.lowercased() + return !lowercasedTitle.contains("instrumental") && !lowercasedTitle.contains("inst.") } } @@ -160,6 +163,8 @@ final class MusicPlayerModel: ObservableObject { /// - Parameter song: 관련된 노래를 찾을 때 사용할 노래 func playMusicWithRecommendedList(_ song: Song) { let track = fromSongToTrack(song) + queueTracks.removeAll() + saveTracks(for: [track]) // 개별 곡 재생 play(track, in: nil, with: nil) @@ -168,18 +173,21 @@ final class MusicPlayerModel: ObservableObject { Task { let recommendedList = try await getRelatedSongs(song) if let recommendedList { + saveTracks(for: recommendedList) try await ApplicationMusicPlayer.shared.queue.insert(recommendedList, position: .tail) } } } - /// 🐯 앨범 전체 재생하고 그 뒤에 추천 플레이리스트 붙여주기 /// - Parameter tracks: 사용자가 선택한 전체 재생할 앨범에 담긴 트랙 /// - Parameter album: 관련된 노래를 찾을 때 사용할 앨범 func playAlbumWithRecommendedList(_ tracks: MusicItemCollection, album: Album) { // ⁉️호랑: 이후에 DetailedAlbumModel에서 진행중인 로직을 여기다가 합칠 지 고민해보기 -> 현재는 앨범을 통해 트랙 배열을 받고 해당 메서드에 파라미터로 사용하는 로직 + queueTracks.removeAll() + saveTracks(for: tracks) + // 앨범 재생 play(tracks[0], in: tracks, with: nil) @@ -187,6 +195,7 @@ final class MusicPlayerModel: ObservableObject { Task { let recommendedList = try await getRelatedSongs(album) if let recommendedList { + saveTracks(for: recommendedList) try await ApplicationMusicPlayer.shared.queue.insert(recommendedList, position: .tail) } } @@ -254,3 +263,14 @@ final class MusicPlayerModel: ObservableObject { } } + + +extension MusicPlayerModel { + /// queue에 음악을 넣기 전에 따로 배열에 저장을 해주는 메서드 + private func saveTracks(for tracks: MusicItemCollection) { + DispatchQueue.main.async { + self.queueTracks += tracks + } + } +} + diff --git a/MinGenie/MinGenie/Playback/NowPlayingView.swift b/MinGenie/MinGenie/Playback/NowPlayingView.swift index ff5835b..c18acac 100644 --- a/MinGenie/MinGenie/Playback/NowPlayingView.swift +++ b/MinGenie/MinGenie/Playback/NowPlayingView.swift @@ -76,7 +76,7 @@ struct NowPlayingView: View { List { ForEach(playbackQueue.entries.indices, id: \.self) { index in NowQueueItemCell( - artwork: playbackQueue.entries[index].artwork, + artwork: musicPlayer.queueTracks[index].artwork, title: playbackQueue.entries[index].title, subtitle: playbackQueue.entries[index].subtitle ) @@ -133,7 +133,7 @@ struct NowPlayingView: View { if startIndex <= endIndex { ForEach(startIndex...endIndex, id: \.self) { index in - imageContainer(for: playbackQueue.entries[index].artwork) + imageContainer(for: musicPlayer.queueTracks[index].artwork) .scaleEffect(1.0 - CGFloat(abs(index - musicPlayer.currentMusicIndex)) * 0.1) .zIndex(1.0 - Double(abs(index - musicPlayer.currentMusicIndex))) .offset(x: CGFloat(index - musicPlayer.currentMusicIndex) * 50 * (1 - CGFloat(abs(index - musicPlayer.currentMusicIndex)) * 0.1) + dragOffset, y: 0)