diff --git a/BlackCandy/Store/PlayerReducer.swift b/BlackCandy/Store/PlayerReducer.swift index e45c308..ae00f6a 100644 --- a/BlackCandy/Store/PlayerReducer.swift +++ b/BlackCandy/Store/PlayerReducer.swift @@ -63,12 +63,16 @@ struct PlayerReducer: Reducer { case moveSongsResponse(TaskResult) case getCurrentPlaylist case currentPlaylistResponse(TaskResult<[Song]>) - case playAll(String, Int) - case playAllResponse(TaskResult<[Song]>) - case playSong(Int) + case playAlbum(Int) + case playAlbumBeginWith(Int, Int) + case playPlaylist(Int) + case playPlaylistBeginWith(Int, Int) + case playSongsResponse(TaskResult<[Song]>) + case playSongsBeginWithResponse(TaskResult<[Song]>, Int) + case playNow(Int) case playNext(Int) case playLast(Int) - case playSongResponse(TaskResult) + case playNowResponse(TaskResult) case playNextResponse(TaskResult) case playLastResponse(TaskResult) } @@ -285,37 +289,72 @@ struct PlayerReducer: Reducer { return .none - case let .playAll(resourceType, resourceId): + case let .playAlbum(albumId): return .run { send in await send( - .playAllResponse( + .playSongsResponse( TaskResult { - switch resourceType { - case "album": - return try await apiClient.replaceCurrentPlaylistWithAlbumSongs(resourceId) - case "playlist": - return try await apiClient.replaceCurrentPlaylistWithPlaylistSongs(resourceId) - default: - throw APIClient.APIError.invalidRequest - } + try await apiClient.replaceCurrentPlaylistWithAlbumSongs(albumId) + } + ) + ) + } + + case let .playAlbumBeginWith(albumId, songId): + return .run { send in + await send( + .playSongsBeginWithResponse( + TaskResult { try await apiClient.replaceCurrentPlaylistWithAlbumSongs(albumId) }, + songId + ) + ) + } + + case let .playPlaylist(playlistId): + return .run { send in + await send( + .playSongsResponse( + TaskResult { + try await apiClient.replaceCurrentPlaylistWithPlaylistSongs(playlistId) } ) ) } - case let .playAllResponse(.success(songs)): + case let .playPlaylistBeginWith(playlistId, songId): + return .run { send in + await send( + .playSongsBeginWithResponse( + TaskResult { try await apiClient.replaceCurrentPlaylistWithPlaylistSongs(playlistId) }, + songId + ) + ) + } + + case let .playSongsResponse(.success(songs)): state.playlist.update(songs: songs) state.currentSong = songs.first return self.playOn(state: &state, index: 0) - case let .playSong(songId): + case let .playSongsBeginWithResponse(.success(songs), songId): + state.playlist.update(songs: songs) + + if let songIndex = state.playlist.index(by: songId) { + state.currentSong = state.playlist.find(byIndex: songIndex) + return self.playOn(state: &state, index: songIndex) + } else { + state.currentSong = songs.first + return self.playOn(state: &state, index: 0) + } + + case let .playNow(songId): if let songIndex = state.playlist.index(by: songId) { return self.playOn(state: &state, index: songIndex) } else { return .run { [currentSong = state.currentSong] send in await send( - .playSongResponse( + .playNowResponse( TaskResult { try await apiClient.addSongToCurrentPlaylist(songId, currentSong, nil) } ) ) @@ -340,7 +379,7 @@ struct PlayerReducer: Reducer { ) } - case let .playSongResponse(.success(song)): + case let .playNowResponse(.success(song)): let insertIndex = state.insertSongNextToCurrent(song: song) return self.playOn(state: &state, index: insertIndex) @@ -359,8 +398,9 @@ struct PlayerReducer: Reducer { case let .deleteSongsResponse(.failure(error)), let .moveSongsResponse(.failure(error)), let .currentPlaylistResponse(.failure(error)), - let .playAllResponse(.failure(error)), - let .playSongResponse(.failure(error)), + let .playSongsResponse(.failure(error)), + let .playSongsBeginWithResponse(.failure(error), _), + let .playNowResponse(.failure(error)), let .playNextResponse(.failure(error)), let .playLastResponse(.failure(error)), let .toggleFavoriteResponse(.failure(error)): diff --git a/BlackCandy/Turbo/TurboScriptMessageHandler.swift b/BlackCandy/Turbo/TurboScriptMessageHandler.swift index ece32f7..e5759d6 100644 --- a/BlackCandy/Turbo/TurboScriptMessageHandler.swift +++ b/BlackCandy/Turbo/TurboScriptMessageHandler.swift @@ -17,29 +17,51 @@ class TurboScriptMessageHandler: NSObject, WKScriptMessageHandler { let actionName = body["name"] as? String else { return } switch actionName { - case "playAll": - guard let resourceType = body["resourceType"] as? String, - let resourceId = body["resourceId"] as? Int else { return } + case "playAlbum": + guard let albumId = body["albumId"] as? Int else { return } + store.send(.player(.playAlbum(albumId))) - store.send(.player(.playAll(resourceType, resourceId))) - case "playSong": + case "playAlbumBeginWith": + guard + let albumId = body["albumId"] as? Int, + let songId = body["songId"] as? Int else { return } + + store.send(.player(.playAlbumBeginWith(albumId, songId))) + + case "playPlaylist": + guard let playlistId = body["playlistId"] as? Int else { return } + store.send(.player(.playPlaylist(playlistId))) + + case "playPlaylistBeginWith": + guard + let playlistId = body["playlistId"] as? Int, + let songId = body["songId"] as? Int else { return } + + store.send(.player(.playPlaylistBeginWith(playlistId, songId))) + + case "playNow": guard let songId = body["songId"] as? Int else { return } - store.send(.player(.playSong(songId))) + store.send(.player(.playNow(songId))) + case "playNext": guard let songId = body["songId"] as? Int else { return } store.send(.player(.playNext(songId))) + case "playLast": guard let songId = body["songId"] as? Int else { return } store.send(.player(.playLast(songId))) + case "showFlashMessage": guard let message = body["message"] as? String else { return } flashMessageClient.showMessage(message) + case "updateTheme": guard let theme = body["theme"] as? String, let currentTheme = AppReducer.State.Theme(rawValue: theme) else { return } store.send(.updateTheme(currentTheme)) + default: return } diff --git a/BlackCandyTests/Store/PlayerReducerTests.swift b/BlackCandyTests/Store/PlayerReducerTests.swift index 5b65846..310341a 100644 --- a/BlackCandyTests/Store/PlayerReducerTests.swift +++ b/BlackCandyTests/Store/PlayerReducerTests.swift @@ -534,9 +534,9 @@ final class PlayerReducerTests: XCTestCase { store.exhaustivity = .off - await store.send(.playAll("album", 1)) + await store.send(.playAlbum(1)) - await store.receive(.playAllResponse(.success(songs))) { + await store.receive(.playSongsResponse(.success(songs))) { $0.playlist.orderedSongs = songs $0.currentSong = songs.first } @@ -555,9 +555,9 @@ final class PlayerReducerTests: XCTestCase { store.exhaustivity = .off - await store.send(.playAll("playlist", 1)) + await store.send(.playPlaylist(1)) - await store.receive(.playAllResponse(.success(songs))) { + await store.receive(.playSongsResponse(.success(songs))) { $0.playlist.orderedSongs = songs $0.currentSong = songs.first } @@ -574,7 +574,7 @@ final class PlayerReducerTests: XCTestCase { reducer: { PlayerReducer() } ) - await store.send(.playSong(1)) { + await store.send(.playNow(1)) { $0.currentSong = songs.first } } @@ -598,9 +598,9 @@ final class PlayerReducerTests: XCTestCase { store.exhaustivity = .off - await store.send(.playSong(2)) + await store.send(.playNow(2)) - await store.receive(.playSongResponse(.success(playingSong))) { + await store.receive(.playNowResponse(.success(playingSong))) { $0.playlist.orderedSongs = [song, playingSong] $0.currentSong = playingSong } @@ -621,9 +621,9 @@ final class PlayerReducerTests: XCTestCase { store.exhaustivity = .off - await store.send(.playSong(1)) + await store.send(.playNow(1)) - await store.receive(.playSongResponse(.success(song))) { + await store.receive(.playNowResponse(.success(song))) { $0.playlist.orderedSongs = [song] $0.currentSong = song }