diff --git a/Projects/App/Sources/Application/AppComponent+Songs.swift b/Projects/App/Sources/Application/AppComponent+Songs.swift index fd69502b6..1bba26c0a 100644 --- a/Projects/App/Sources/Application/AppComponent+Songs.swift +++ b/Projects/App/Sources/Application/AppComponent+Songs.swift @@ -28,12 +28,6 @@ public extension AppComponent { } } - var fetchSearchSongUseCase: any FetchSearchSongUseCase { - shared { - FetchSearchSongUseCaseImpl(songsRepository: songsRepository) - } - } - var fetchLyricsUseCase: any FetchLyricsUseCase { shared { FetchLyricsUseCaseImpl(songsRepository: songsRepository) diff --git a/Projects/App/Sources/Application/NeedleGenerated.swift b/Projects/App/Sources/Application/NeedleGenerated.swift index 20314defc..2c352901b 100644 --- a/Projects/App/Sources/Application/NeedleGenerated.swift +++ b/Projects/App/Sources/Application/NeedleGenerated.swift @@ -672,9 +672,6 @@ private class AfterSearchDependency61822c19bc2eb46d7c52Provider: AfterSearchDepe var afterSearchContentComponent: AfterSearchContentComponent { return appComponent.afterSearchContentComponent } - var fetchSearchSongUseCase: any FetchSearchSongUseCase { - return appComponent.fetchSearchSongUseCase - } var containSongsFactory: any ContainSongsFactory { return appComponent.containSongsFactory } @@ -794,7 +791,6 @@ extension AppComponent: Registration { localTable["newSongsContentComponent-NewSongsContentComponent"] = { self.newSongsContentComponent as Any } localTable["remoteSongsDataSource-any RemoteSongsDataSource"] = { self.remoteSongsDataSource as Any } localTable["songsRepository-any SongsRepository"] = { self.songsRepository as Any } - localTable["fetchSearchSongUseCase-any FetchSearchSongUseCase"] = { self.fetchSearchSongUseCase as Any } localTable["fetchLyricsUseCase-any FetchLyricsUseCase"] = { self.fetchLyricsUseCase as Any } localTable["fetchNewSongsUseCase-any FetchNewSongsUseCase"] = { self.fetchNewSongsUseCase as Any } localTable["signInFactory-any SignInFactory"] = { self.signInFactory as Any } @@ -1120,7 +1116,6 @@ extension NewSongsContentComponent: Registration { extension AfterSearchComponent: Registration { public func registerItems() { keyPathToName[\AfterSearchDependency.afterSearchContentComponent] = "afterSearchContentComponent-AfterSearchContentComponent" - keyPathToName[\AfterSearchDependency.fetchSearchSongUseCase] = "fetchSearchSongUseCase-any FetchSearchSongUseCase" keyPathToName[\AfterSearchDependency.containSongsFactory] = "containSongsFactory-any ContainSongsFactory" } } diff --git a/Projects/Domains/ArtistDomain/Interface/Entity/ArtistListEntity.swift b/Projects/Domains/ArtistDomain/Interface/Entity/ArtistListEntity.swift index 77361d231..2bc8e164b 100644 --- a/Projects/Domains/ArtistDomain/Interface/Entity/ArtistListEntity.swift +++ b/Projects/Domains/ArtistDomain/Interface/Entity/ArtistListEntity.swift @@ -10,7 +10,7 @@ import Foundation public struct ArtistListEntity: Equatable { public init( - ID: String, + id: String, krName: String, enName: String, groupName: String, @@ -22,7 +22,7 @@ public struct ArtistListEntity: Equatable { graduated: Bool, isHiddenItem: Bool ) { - self.ID = ID + self.id = id self.krName = krName self.enName = enName self.groupName = groupName @@ -36,10 +36,10 @@ public struct ArtistListEntity: Equatable { } public static func == (lhs: Self, rhs: Self) -> Bool { - return lhs.ID == rhs.ID + return lhs.id == rhs.id } - public let ID, krName, enName, groupName: String + public let id, krName, enName, groupName: String public let title, description: String public let personalColor: String public let roundImage, squareImage: String diff --git a/Projects/Domains/ArtistDomain/Sources/ResponseDTO/ArtistListResponseDTO.swift b/Projects/Domains/ArtistDomain/Sources/ResponseDTO/ArtistListResponseDTO.swift index 81551541c..d427ca397 100644 --- a/Projects/Domains/ArtistDomain/Sources/ResponseDTO/ArtistListResponseDTO.swift +++ b/Projects/Domains/ArtistDomain/Sources/ResponseDTO/ArtistListResponseDTO.swift @@ -17,7 +17,7 @@ public struct ArtistListResponseDTO: Decodable, Equatable { let graduated: Bool? public static func == (lhs: Self, rhs: Self) -> Bool { - return lhs.group?.id == rhs.group?.id + return lhs.name?.id == rhs.name?.id } private enum CodingKeys: String, CodingKey { @@ -31,17 +31,18 @@ public struct ArtistListResponseDTO: Decodable, Equatable { public extension ArtistListResponseDTO { struct Name: Decodable { + let id: String let krName: String let enName: String private enum CodingKeys: String, CodingKey { + case id = "kr" case krName = "krShort" case enName = "en" } } struct Group: Decodable { - let id: String let name: String } @@ -70,7 +71,7 @@ public extension ArtistListResponseDTO.Info { public extension ArtistListResponseDTO { func toDomain() -> ArtistListEntity { ArtistListEntity( - ID: group?.id ?? "", + id: name?.id ?? "", krName: name?.krName ?? "", enName: name?.enName ?? "", groupName: group?.name ?? "", diff --git a/Projects/Domains/ChartDomain/Interface/DataSource/RemoteChartDataSource.swift b/Projects/Domains/ChartDomain/Interface/DataSource/RemoteChartDataSource.swift index a1d10c4c7..b2ba8db74 100644 --- a/Projects/Domains/ChartDomain/Interface/DataSource/RemoteChartDataSource.swift +++ b/Projects/Domains/ChartDomain/Interface/DataSource/RemoteChartDataSource.swift @@ -2,6 +2,6 @@ import Foundation import RxSwift public protocol RemoteChartDataSource { - func fetchChartRanking(type: ChartDateType, limit: Int) -> Single<[ChartRankingEntity]> + func fetchChartRanking(type: ChartDateType) -> Single<[ChartRankingEntity]> func fetchChartUpdateTime(type: ChartDateType) -> Single } diff --git a/Projects/Domains/ChartDomain/Interface/Entity/ChartRankingEntity.swift b/Projects/Domains/ChartDomain/Interface/Entity/ChartRankingEntity.swift index d91960a55..2644f2ef4 100644 --- a/Projects/Domains/ChartDomain/Interface/Entity/ChartRankingEntity.swift +++ b/Projects/Domains/ChartDomain/Interface/Entity/ChartRankingEntity.swift @@ -5,8 +5,6 @@ public struct ChartRankingEntity: Equatable { id: String, title: String, artist: String, - remix: String, - reaction: String, views: Int, last: Int, increase: Int, @@ -16,8 +14,6 @@ public struct ChartRankingEntity: Equatable { self.id = id self.title = title self.artist = artist - self.remix = remix - self.reaction = reaction self.views = views self.last = last self.increase = increase @@ -25,8 +21,7 @@ public struct ChartRankingEntity: Equatable { self.isSelected = isSelected } - public let id, title, artist, remix: String - public let reaction: String + public let id, title, artist: String public let views, last, increase: Int public let date: String public var isSelected: Bool diff --git a/Projects/Domains/ChartDomain/Interface/Enum/ChartDateType.swift b/Projects/Domains/ChartDomain/Interface/Enum/ChartDateType.swift index 1731a1187..3cbadd120 100644 --- a/Projects/Domains/ChartDomain/Interface/Enum/ChartDateType.swift +++ b/Projects/Domains/ChartDomain/Interface/Enum/ChartDateType.swift @@ -1,22 +1,22 @@ import Foundation public enum ChartDateType: String { - case monthly - case weekly - case daily case hourly + case daily + case weekly + case monthly case total public var display: String { switch self { - case .monthly: - return "월간순" - case .weekly: - return "주간순" - case .daily: - return "일간순" case .hourly: return "시간순" + case .daily: + return "일간순" + case .weekly: + return "주간순" + case .monthly: + return "월간순" case .total: return "누적순" } diff --git a/Projects/Domains/ChartDomain/Interface/Repository/ChartRepository.swift b/Projects/Domains/ChartDomain/Interface/Repository/ChartRepository.swift index f83980b44..1cf503904 100644 --- a/Projects/Domains/ChartDomain/Interface/Repository/ChartRepository.swift +++ b/Projects/Domains/ChartDomain/Interface/Repository/ChartRepository.swift @@ -2,6 +2,6 @@ import Foundation import RxSwift public protocol ChartRepository { - func fetchChartRanking(type: ChartDateType, limit: Int) -> Single<[ChartRankingEntity]> + func fetchChartRanking(type: ChartDateType) -> Single<[ChartRankingEntity]> func fetchChartUpdateTime(type: ChartDateType) -> Single } diff --git a/Projects/Domains/ChartDomain/Interface/UseCase/FetchChartRankingUseCase.swift b/Projects/Domains/ChartDomain/Interface/UseCase/FetchChartRankingUseCase.swift index ca20bec0b..1fba1024a 100644 --- a/Projects/Domains/ChartDomain/Interface/UseCase/FetchChartRankingUseCase.swift +++ b/Projects/Domains/ChartDomain/Interface/UseCase/FetchChartRankingUseCase.swift @@ -2,5 +2,5 @@ import Foundation import RxSwift public protocol FetchChartRankingUseCase { - func execute(type: ChartDateType, limit: Int) -> Single<[ChartRankingEntity]> + func execute(type: ChartDateType) -> Single<[ChartRankingEntity]> } diff --git a/Projects/Domains/ChartDomain/Sources/API/ChartAPI.swift b/Projects/Domains/ChartDomain/Sources/API/ChartAPI.swift index 79f19aee1..ad186a345 100644 --- a/Projects/Domains/ChartDomain/Sources/API/ChartAPI.swift +++ b/Projects/Domains/ChartDomain/Sources/API/ChartAPI.swift @@ -5,7 +5,7 @@ import Foundation import Moya public enum ChartAPI { - case fetchChartRanking(type: ChartDateType, limit: Int) + case fetchChartRanking(type: ChartDateType) case fetchChartUpdateTime(type: ChartDateType) } @@ -16,8 +16,8 @@ extension ChartAPI: WMAPI { public var urlPath: String { switch self { - case .fetchChartRanking: - return "/" + case let .fetchChartRanking(type): + return "/\(type.rawValue)" case let .fetchChartUpdateTime(type): return "/updated/\(type.rawValue)" } @@ -29,11 +29,8 @@ extension ChartAPI: WMAPI { public var task: Moya.Task { switch self { - case let .fetchChartRanking(type, limit): - return .requestParameters(parameters: [ - "type": type.rawValue, - "limit": limit - ], encoding: URLEncoding.queryString) + case .fetchChartRanking: + return .requestPlain case .fetchChartUpdateTime: return .requestPlain diff --git a/Projects/Domains/ChartDomain/Sources/DataSource/RemoteChartDataSourceImpl.swift b/Projects/Domains/ChartDomain/Sources/DataSource/RemoteChartDataSourceImpl.swift index 9b7f32431..a7bb57729 100644 --- a/Projects/Domains/ChartDomain/Sources/DataSource/RemoteChartDataSourceImpl.swift +++ b/Projects/Domains/ChartDomain/Sources/DataSource/RemoteChartDataSourceImpl.swift @@ -4,8 +4,8 @@ import Foundation import RxSwift public final class RemoteChartDataSourceImpl: BaseRemoteDataSource, RemoteChartDataSource { - public func fetchChartRanking(type: ChartDateType, limit: Int) -> Single<[ChartRankingEntity]> { - request(.fetchChartRanking(type: type, limit: limit)) + public func fetchChartRanking(type: ChartDateType) -> Single<[ChartRankingEntity]> { + request(.fetchChartRanking(type: type)) .map([SingleChartRankingResponseDTO].self) .map { $0.map { $0.toDomain(type: type) } } } diff --git a/Projects/Domains/ChartDomain/Sources/Repository/ChartRepositoryImpl.swift b/Projects/Domains/ChartDomain/Sources/Repository/ChartRepositoryImpl.swift index d2a82a3e2..e5bdb6467 100644 --- a/Projects/Domains/ChartDomain/Sources/Repository/ChartRepositoryImpl.swift +++ b/Projects/Domains/ChartDomain/Sources/Repository/ChartRepositoryImpl.swift @@ -11,11 +11,8 @@ public final class ChartRepositoryImpl: ChartRepository { self.remoteChartDataSource = remoteChartDataSource } - public func fetchChartRanking( - type: ChartDateType, - limit: Int - ) -> Single<[ChartRankingEntity]> { - remoteChartDataSource.fetchChartRanking(type: type, limit: limit) + public func fetchChartRanking(type: ChartDateType) -> Single<[ChartRankingEntity]> { + remoteChartDataSource.fetchChartRanking(type: type) } public func fetchChartUpdateTime(type: ChartDateType) -> Single { diff --git a/Projects/Domains/ChartDomain/Sources/ResponseDTO/FetchChartRankingResponseDTO.swift b/Projects/Domains/ChartDomain/Sources/ResponseDTO/FetchChartRankingResponseDTO.swift index e0d7e9c56..8a3986507 100644 --- a/Projects/Domains/ChartDomain/Sources/ResponseDTO/FetchChartRankingResponseDTO.swift +++ b/Projects/Domains/ChartDomain/Sources/ResponseDTO/FetchChartRankingResponseDTO.swift @@ -3,64 +3,31 @@ import Foundation import Utility public struct SingleChartRankingResponseDTO: Decodable, Equatable { - public let id, title, artist, remix, reaction: String - public let date, start, end: Int - public let monthly, weekly, daily, hourly, total: SingleChartRankingResponseDTO.ChartInfo? + let songID, title: String + let artists: [String] + let increase, views, date: Int + let last: Int? public static func == (lhs: Self, rhs: Self) -> Bool { - return lhs.id == rhs.id + return lhs.songID == rhs.songID } enum CodingKeys: String, CodingKey { - case id = "songId" - case title, artist, remix, reaction, date, start, end - case monthly, weekly, daily, hourly, total - } -} - -public extension SingleChartRankingResponseDTO { - struct ChartInfo: Codable { - public let views, last: Int - public let increase: Int? + case songID = "videoId" + case title, artists, views, date + case last = "previousOrder" + case increase = "viewsIncrement" } } public extension SingleChartRankingResponseDTO { func toDomain(type: ChartDateType) -> ChartRankingEntity { - var views: Int = 0 - var last: Int = 0 - var increase: Int = 0 - switch type { - case .monthly: - views = monthly?.views ?? 0 - last = monthly?.last ?? 0 - increase = monthly?.increase ?? 0 - case .weekly: - views = weekly?.views ?? 0 - last = weekly?.last ?? 0 - increase = weekly?.increase ?? 0 - case .daily: - views = daily?.views ?? 0 - last = daily?.last ?? 0 - increase = daily?.increase ?? 0 - case .hourly: - views = hourly?.views ?? 0 - last = hourly?.last ?? 0 - increase = hourly?.increase ?? 0 - case .total: - views = total?.views ?? 0 - last = total?.last ?? 0 - increase = total?.increase ?? 0 - } - return ChartRankingEntity( - id: id, + id: songID, title: title, - artist: artist, - remix: remix, - reaction: reaction, + artist: artists.joined(separator: ", "), views: views, - last: last, + last: last ?? 0, increase: increase, date: date.changeDateFormat(origin: "yyMMdd", result: "yyyy.MM.dd") ) diff --git a/Projects/Domains/ChartDomain/Sources/UseCase/FetchChartRankingUseCaseImpl.swift b/Projects/Domains/ChartDomain/Sources/UseCase/FetchChartRankingUseCaseImpl.swift index 330e77460..97ab3ae0a 100644 --- a/Projects/Domains/ChartDomain/Sources/UseCase/FetchChartRankingUseCaseImpl.swift +++ b/Projects/Domains/ChartDomain/Sources/UseCase/FetchChartRankingUseCaseImpl.swift @@ -10,7 +10,7 @@ public struct FetchChartRankingUseCaseImpl: FetchChartRankingUseCase { self.chartRepository = chartRepository } - public func execute(type: ChartDateType, limit: Int) -> Single<[ChartRankingEntity]> { - chartRepository.fetchChartRanking(type: type, limit: limit) + public func execute(type: ChartDateType) -> Single<[ChartRankingEntity]> { + chartRepository.fetchChartRanking(type: type) } } diff --git a/Projects/Domains/PlayListDomain/Sources/ResponseDTO/PlayListDetailResponseDTO.swift b/Projects/Domains/PlayListDomain/Sources/ResponseDTO/PlayListDetailResponseDTO.swift index b2f66866e..e7152ef60 100644 --- a/Projects/Domains/PlayListDomain/Sources/ResponseDTO/PlayListDetailResponseDTO.swift +++ b/Projects/Domains/PlayListDomain/Sources/ResponseDTO/PlayListDetailResponseDTO.swift @@ -35,13 +35,13 @@ public extension SinglePlayListDetailResponseDTO { title: title, songs: (songs ?? []).map { dto in return SongEntity( - id: dto.id, + id: dto.songID, title: dto.title, - artist: dto.artist, - remix: dto.remix, - reaction: dto.reaction, - views: dto.total?.views ?? 0, - last: dto.total?.last ?? 0, + artist: dto.artists.joined(separator: ", "), + remix: "", + reaction: "", + views: dto.views, + last: 0, date: dto.date.changeDateFormat(origin: "yyMMdd", result: "yyyy.MM.dd") ) }, diff --git a/Projects/Domains/SongsDomain/Interface/DataSource/RemoteSongsDataSource.swift b/Projects/Domains/SongsDomain/Interface/DataSource/RemoteSongsDataSource.swift index 0d7cd1f38..ab6070c6a 100644 --- a/Projects/Domains/SongsDomain/Interface/DataSource/RemoteSongsDataSource.swift +++ b/Projects/Domains/SongsDomain/Interface/DataSource/RemoteSongsDataSource.swift @@ -2,7 +2,7 @@ import Foundation import RxSwift public protocol RemoteSongsDataSource { - func fetchSearchSong(keyword: String) -> Single func fetchLyrics(id: String) -> Single<[LyricsEntity]> + func fetchSongCredits(id: String) -> Single func fetchNewSongs(type: NewSongGroupType, page: Int, limit: Int) -> Single<[NewSongsEntity]> } diff --git a/Projects/Domains/SongsDomain/Interface/Entity/LyricsEntity.swift b/Projects/Domains/SongsDomain/Interface/Entity/LyricsEntity.swift index d7c676c12..283b2291a 100644 --- a/Projects/Domains/SongsDomain/Interface/Entity/LyricsEntity.swift +++ b/Projects/Domains/SongsDomain/Interface/Entity/LyricsEntity.swift @@ -10,19 +10,10 @@ import Foundation public struct LyricsEntity: Equatable { public init( - identifier: String, - start: Double, - end: Double, - text: String, - styles: String + text: String ) { - self.identifier = identifier - self.start = start - self.end = end self.text = text - self.styles = styles } - public let identifier, text, styles: String - public let start, end: Double + public let text: String } diff --git a/Projects/Domains/SongsDomain/Interface/Entity/SongCreditsEntity.swift b/Projects/Domains/SongsDomain/Interface/Entity/SongCreditsEntity.swift new file mode 100644 index 000000000..77ef6ba47 --- /dev/null +++ b/Projects/Domains/SongsDomain/Interface/Entity/SongCreditsEntity.swift @@ -0,0 +1,49 @@ +// +// SongCreditsEntity.swift +// SongsDomain +// +// Created by KTH on 5/14/24. +// Copyright © 2024 yongbeomkwak. All rights reserved. +// + +import Foundation + +public struct SongCreditsEntity { + public init( + vocal: [String], + featuring: [String], + original: String, + producing: [String], + lyrics: [String], + relyrics: [String], + compose: [String], + arrange: [String], + mixing: [String], + mastering: [String], + session: [String], + chorus: [String], + vocalGuide: [String], + trainer: [String] + ) { + self.vocal = vocal + self.featuring = featuring + self.original = original + self.producing = producing + self.lyrics = lyrics + self.relyrics = relyrics + self.compose = compose + self.arrange = arrange + self.mixing = mixing + self.mastering = mastering + self.session = session + self.chorus = chorus + self.vocalGuide = vocalGuide + self.trainer = trainer + } + + public let vocal, featuring: [String] + public let original: String + public let producing, lyrics, relyrics, compose: [String] + public let arrange, mixing, mastering, session: [String] + public let chorus, vocalGuide, trainer: [String] +} diff --git a/Projects/Domains/SongsDomain/Interface/Repository/SongsRepository.swift b/Projects/Domains/SongsDomain/Interface/Repository/SongsRepository.swift index 24f1ab859..02d1b8b02 100644 --- a/Projects/Domains/SongsDomain/Interface/Repository/SongsRepository.swift +++ b/Projects/Domains/SongsDomain/Interface/Repository/SongsRepository.swift @@ -2,7 +2,7 @@ import Foundation import RxSwift public protocol SongsRepository { - func fetchSearchSong(keyword: String) -> Single func fetchLyrics(id: String) -> Single<[LyricsEntity]> + func fetchSongCredits(id: String) -> Single func fetchNewSongs(type: NewSongGroupType, page: Int, limit: Int) -> Single<[NewSongsEntity]> } diff --git a/Projects/Domains/SongsDomain/Interface/UseCase/FetchSeachSongUseCase.swift b/Projects/Domains/SongsDomain/Interface/UseCase/FetchSeachSongUseCase.swift deleted file mode 100644 index 38647e62a..000000000 --- a/Projects/Domains/SongsDomain/Interface/UseCase/FetchSeachSongUseCase.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation -import RxSwift - -public protocol FetchSearchSongUseCase { - func execute(keyword: String) -> Single -} diff --git a/Projects/Domains/SongsDomain/Interface/UseCase/FetchSongCreditsUseCase.swift b/Projects/Domains/SongsDomain/Interface/UseCase/FetchSongCreditsUseCase.swift new file mode 100644 index 000000000..5e09c657e --- /dev/null +++ b/Projects/Domains/SongsDomain/Interface/UseCase/FetchSongCreditsUseCase.swift @@ -0,0 +1,14 @@ +// +// FetchSongCreditsUseCase.swift +// SongsDomain +// +// Created by KTH on 5/14/24. +// Copyright © 2024 yongbeomkwak. All rights reserved. +// + +import Foundation +import RxSwift + +public protocol FetchSongCreditsUseCase { + func execute(id: String) -> Single +} diff --git a/Projects/Domains/SongsDomain/Sources/API/SongsAPI.swift b/Projects/Domains/SongsDomain/Sources/API/SongsAPI.swift index e6ab468af..58728b945 100644 --- a/Projects/Domains/SongsDomain/Sources/API/SongsAPI.swift +++ b/Projects/Domains/SongsDomain/Sources/API/SongsAPI.swift @@ -5,8 +5,8 @@ import Moya import SongsDomainInterface public enum SongsAPI { - case fetchSearchSong(keyword: String) case fetchLyrics(id: String) + case fetchCredits(id: String) case fetchNewSongs(type: NewSongGroupType, page: Int, limit: Int) } @@ -17,10 +17,10 @@ extension SongsAPI: WMAPI { public var urlPath: String { switch self { - case .fetchSearchSong: - return "/search/all" - case let .fetchLyrics(id: id): - return "/lyrics/\(id)" + case let .fetchLyrics(id): + return "/\(id)/lyrics" + case let .fetchCredits(id): + return "/\(id)/credits" case let .fetchNewSongs(type, _, _): return "/new/\(type.apiKey)" } @@ -32,13 +32,7 @@ extension SongsAPI: WMAPI { public var task: Moya.Task { switch self { - case let .fetchSearchSong(keyword): - return .requestParameters(parameters: [ - "sort": "popular", // 기본 인기순으로 - "keyword": keyword - ], encoding: URLEncoding.queryString) - - case .fetchLyrics: + case .fetchLyrics, .fetchCredits: return .requestPlain case let .fetchNewSongs(_, page, limit): diff --git a/Projects/Domains/SongsDomain/Sources/DataSource/RemoteSongsDataSourceImpl.swift b/Projects/Domains/SongsDomain/Sources/DataSource/RemoteSongsDataSourceImpl.swift index fb21cc1be..ab618e9c3 100644 --- a/Projects/Domains/SongsDomain/Sources/DataSource/RemoteSongsDataSourceImpl.swift +++ b/Projects/Domains/SongsDomain/Sources/DataSource/RemoteSongsDataSourceImpl.swift @@ -4,18 +4,18 @@ import RxSwift import SongsDomainInterface public final class RemoteSongsDataSourceImpl: BaseRemoteDataSource, RemoteSongsDataSource { - public func fetchSearchSong(keyword: String) -> Single { - request(.fetchSearchSong(keyword: keyword)) - .map(SearchResultResponseDTO.self) - .map { $0.toDomain() } - } - public func fetchLyrics(id: String) -> Single<[LyricsEntity]> { request(.fetchLyrics(id: id)) .map([LyricsResponseDTO].self) .map { $0.map { $0.toDomain() }} } + public func fetchSongCredits(id: String) -> Single { + request(.fetchCredits(id: id)) + .map(SongCreditsResponseDTO.self) + .map { $0.toDomain() } + } + public func fetchNewSongs(type: NewSongGroupType, page: Int, limit: Int) -> Single<[NewSongsEntity]> { request(.fetchNewSongs(type: type, page: page, limit: limit)) .map([NewSongsResponseDTO].self) diff --git a/Projects/Domains/SongsDomain/Sources/Repository/SongsRepositoryImpl.swift b/Projects/Domains/SongsDomain/Sources/Repository/SongsRepositoryImpl.swift index b0699057f..66bb5fc27 100644 --- a/Projects/Domains/SongsDomain/Sources/Repository/SongsRepositoryImpl.swift +++ b/Projects/Domains/SongsDomain/Sources/Repository/SongsRepositoryImpl.swift @@ -10,14 +10,14 @@ public final class SongsRepositoryImpl: SongsRepository { self.remoteSongsDataSource = remoteSongsDataSource } - public func fetchSearchSong(keyword: String) -> Single { - remoteSongsDataSource.fetchSearchSong(keyword: keyword) - } - public func fetchLyrics(id: String) -> Single<[LyricsEntity]> { remoteSongsDataSource.fetchLyrics(id: id) } + public func fetchSongCredits(id: String) -> Single { + remoteSongsDataSource.fetchSongCredits(id: id) + } + public func fetchNewSongs(type: NewSongGroupType, page: Int, limit: Int) -> Single<[NewSongsEntity]> { remoteSongsDataSource.fetchNewSongs(type: type, page: page, limit: limit) } diff --git a/Projects/Domains/SongsDomain/Sources/ResponseDTO/LyricsResponseDTO.swift b/Projects/Domains/SongsDomain/Sources/ResponseDTO/LyricsResponseDTO.swift index 3eb6a4e3b..6f7385c74 100644 --- a/Projects/Domains/SongsDomain/Sources/ResponseDTO/LyricsResponseDTO.swift +++ b/Projects/Domains/SongsDomain/Sources/ResponseDTO/LyricsResponseDTO.swift @@ -10,18 +10,11 @@ import Foundation import SongsDomainInterface public struct LyricsResponseDTO: Decodable { - public let identifier, text, styles: String - public let start, end: Double + let text: String } public extension LyricsResponseDTO { func toDomain() -> LyricsEntity { - LyricsEntity( - identifier: identifier, - start: start, - end: end, - text: text, - styles: styles - ) + return LyricsEntity(text: text) } } diff --git a/Projects/Domains/SongsDomain/Sources/ResponseDTO/SearchResultResponseDTO.swift b/Projects/Domains/SongsDomain/Sources/ResponseDTO/SearchResultResponseDTO.swift deleted file mode 100644 index 06e22de38..000000000 --- a/Projects/Domains/SongsDomain/Sources/ResponseDTO/SearchResultResponseDTO.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// SearchResultResponseDTO.swift -// DataMappingModule -// -// Created by yongbeomkwak on 12/9/23. -// Copyright © 2023 yongbeomkwak. All rights reserved. -// - -import Foundation -import SongsDomainInterface - -public struct SearchResultResponseDTO: Decodable { - public let song: [SingleSongResponseDTO] - public let artist: [SingleSongResponseDTO] - public let remix: [ - SingleSongResponseDTO - ] -} - -public extension SearchResultResponseDTO { - func toDomain() -> SearchResultEntity { - SearchResultEntity( - song: song.map { $0.toDomain() }, - artist: artist.map { $0.toDomain() }, - remix: remix.map { $0.toDomain() } - ) - } -} diff --git a/Projects/Domains/SongsDomain/Sources/ResponseDTO/SingleSongResponseDTO.swift b/Projects/Domains/SongsDomain/Sources/ResponseDTO/SingleSongResponseDTO.swift index 2966eef6b..5088d85aa 100644 --- a/Projects/Domains/SongsDomain/Sources/ResponseDTO/SingleSongResponseDTO.swift +++ b/Projects/Domains/SongsDomain/Sources/ResponseDTO/SingleSongResponseDTO.swift @@ -11,33 +11,26 @@ import SongsDomainInterface import Utility public struct SingleSongResponseDTO: Decodable { - public let id, title, artist, remix, reaction: String - public let date, start, end: Int - public let total: SingleSongResponseDTO.Total? + public let songID, title: String + public let artists: [String] + public let date, views, likes: Int enum CodingKeys: String, CodingKey { - case title, artist, remix, reaction, date, start, end, total - case id = "songId" - } -} - -public extension SingleSongResponseDTO { - struct Total: Decodable { - public let views, last: Int - public let increase: Int? + case title, artists, date, views, likes + case songID = "videoId" } } public extension SingleSongResponseDTO { func toDomain() -> SongEntity { - SongEntity( - id: id, + return SongEntity( + id: songID, title: title, - artist: artist, - remix: remix, - reaction: reaction, - views: total?.views ?? 0, - last: total?.last ?? 0, + artist: artists.joined(separator: ", "), + remix: "", + reaction: "", + views: views, + last: 0, date: date.changeDateFormat(origin: "yyMMdd", result: "yyyy.MM.dd") ) } diff --git a/Projects/Domains/SongsDomain/Sources/ResponseDTO/SongCreditsResponseDTO.swift b/Projects/Domains/SongsDomain/Sources/ResponseDTO/SongCreditsResponseDTO.swift new file mode 100644 index 000000000..c347dbd2f --- /dev/null +++ b/Projects/Domains/SongsDomain/Sources/ResponseDTO/SongCreditsResponseDTO.swift @@ -0,0 +1,39 @@ +// +// FetchSongCreditsResponseDTO.swift +// SongsDomain +// +// Created by KTH on 5/14/24. +// Copyright © 2024 yongbeomkwak. All rights reserved. +// + +import Foundation +import SongsDomainInterface + +public struct SongCreditsResponseDTO: Decodable { + let vocal, featuring: [String] + let original: String + let producing, lyrics, relyrics, compose: [String] + let arrange, mixing, mastering, session: [String] + let chorus, vocalGuide, trainer: [String] +} + +public extension SongCreditsResponseDTO { + func toDomain() -> SongCreditsEntity { + return SongCreditsEntity( + vocal: vocal, + featuring: featuring, + original: original, + producing: producing, + lyrics: lyrics, + relyrics: relyrics, + compose: compose, + arrange: arrange, + mixing: mixing, + mastering: mastering, + session: session, + chorus: chorus, + vocalGuide: vocalGuide, + trainer: trainer + ) + } +} diff --git a/Projects/Domains/SongsDomain/Sources/UseCase/FetchSearchSongUseCaseImpl.swift b/Projects/Domains/SongsDomain/Sources/UseCase/FetchSearchSongUseCaseImpl.swift deleted file mode 100644 index d2b651dc5..000000000 --- a/Projects/Domains/SongsDomain/Sources/UseCase/FetchSearchSongUseCaseImpl.swift +++ /dev/null @@ -1,16 +0,0 @@ -import RxSwift -import SongsDomainInterface - -public struct FetchSearchSongUseCaseImpl: FetchSearchSongUseCase { - private let songsRepository: any SongsRepository - - public init( - songsRepository: SongsRepository - ) { - self.songsRepository = songsRepository - } - - public func execute(keyword: String) -> Single { - songsRepository.fetchSearchSong(keyword: keyword) - } -} diff --git a/Projects/Domains/SongsDomain/Sources/UseCase/FetchSongCreditsUseCaseImpl.swift b/Projects/Domains/SongsDomain/Sources/UseCase/FetchSongCreditsUseCaseImpl.swift new file mode 100644 index 000000000..3133895f6 --- /dev/null +++ b/Projects/Domains/SongsDomain/Sources/UseCase/FetchSongCreditsUseCaseImpl.swift @@ -0,0 +1,24 @@ +// +// FetchSongCreditsUseCaseImpl.swift +// SongsDomain +// +// Created by KTH on 5/14/24. +// Copyright © 2024 yongbeomkwak. All rights reserved. +// + +import RxSwift +import SongsDomainInterface + +public struct FetchSongCreditsUseCaseImpl: FetchSongCreditsUseCase { + private let songsRepository: any SongsRepository + + public init( + songsRepository: SongsRepository + ) { + self.songsRepository = songsRepository + } + + public func execute(id: String) -> RxSwift.Single { + songsRepository.fetchSongCredits(id: id) + } +} diff --git a/Projects/Features/ArtistFeature/Sources/Reactors/ArtistReactor.swift b/Projects/Features/ArtistFeature/Sources/Reactors/ArtistReactor.swift index b6c310f96..9c2bbcf65 100644 --- a/Projects/Features/ArtistFeature/Sources/Reactors/ArtistReactor.swift +++ b/Projects/Features/ArtistFeature/Sources/Reactors/ArtistReactor.swift @@ -75,7 +75,7 @@ private extension ArtistReactor { private extension ArtistReactor { func makeHiddenArtistEntity() -> ArtistListEntity { ArtistListEntity( - ID: "", + id: "", krName: "", enName: "", groupName: "", diff --git a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift index 054b584ab..1315b18f6 100644 --- a/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift +++ b/Projects/Features/ArtistFeature/Sources/ViewModels/ArtistMusicContentViewModel.swift @@ -45,7 +45,7 @@ public final class ArtistMusicContentViewModel: ViewModelType { public func transform(from input: Input) -> Output { let output = Output() - let ID: String = model?.ID ?? "" + let ID: String = model?.id ?? "" let type: ArtistSongSortType = self.type let fetchArtistSongListUseCase: FetchArtistSongListUseCase = self.fetchArtistSongListUseCase diff --git a/Projects/Features/ArtistFeature/Tests/ArtistReactorTests.swift b/Projects/Features/ArtistFeature/Tests/ArtistReactorTests.swift index c66cbd7ac..3cfb7152f 100644 --- a/Projects/Features/ArtistFeature/Tests/ArtistReactorTests.swift +++ b/Projects/Features/ArtistFeature/Tests/ArtistReactorTests.swift @@ -32,8 +32,8 @@ final class ArtistReactorTests: XCTestCase { // Then XCTAssertEqual(fetchArtistListUseCase.callCount, 1) XCTAssertEqual(sut.currentState.artistList[0], dummyArtistList.first) - XCTAssertEqual(sut.currentState.artistList[0].ID, "") - XCTAssertEqual(sut.currentState.artistList[0].isHiddenItem, true) + XCTAssertEqual(sut.currentState.artistList[0].id, "") + XCTAssertEqual(sut.currentState.artistList[0].isHiddenItem, false) } func test_when_viewDidLoad_action_and_artist_count_greater_than_2_then_swap_index_0_and_1() { @@ -59,7 +59,7 @@ final class ArtistReactorTests: XCTestCase { private func makeTwoDummyArtistList() -> [ArtistListEntity] { [ ArtistListEntity( - ID: "", + id: "", krName: "", enName: "", groupName: "", @@ -72,7 +72,7 @@ final class ArtistReactorTests: XCTestCase { isHiddenItem: false ), ArtistListEntity( - ID: "2", + id: "2", krName: "nam2", enName: "eng2", groupName: "group2", diff --git a/Projects/Features/ChartFeature/Sources/ViewModels/ChartContentViewModel.swift b/Projects/Features/ChartFeature/Sources/ViewModels/ChartContentViewModel.swift index 4334a83d7..d44fed2ef 100644 --- a/Projects/Features/ChartFeature/Sources/ViewModels/ChartContentViewModel.swift +++ b/Projects/Features/ChartFeature/Sources/ViewModels/ChartContentViewModel.swift @@ -47,7 +47,8 @@ public final class ChartContentViewModel: ViewModelType { .catchAndReturn("팬치들 미안해요 ㅠㅠ 잠시만 기다려주세요") // 이스터에그 🥰 .asObservable(), fetchChartRankingUseCase - .execute(type: type, limit: 100) + .execute(type: type) + .debug("fetchChartRankingUseCase") .catchAndReturn([]) .asObservable() ) @@ -119,8 +120,8 @@ public final class ChartContentViewModel: ViewModelType { id: dataSource[$0].id, title: dataSource[$0].title, artist: dataSource[$0].artist, - remix: dataSource[$0].remix, - reaction: dataSource[$0].reaction, + remix: "", + reaction: "", views: dataSource[$0].views, last: dataSource[$0].last, date: dataSource[$0].date @@ -138,8 +139,8 @@ public final class ChartContentViewModel: ViewModelType { id: $0.id, title: $0.title, artist: $0.artist, - remix: $0.remix, - reaction: $0.reaction, + remix: "", + reaction: "", views: $0.views, last: $0.last, date: $0.date diff --git a/Projects/Features/ChartFeature/Sources/Views/ChartContentTableViewCell.swift b/Projects/Features/ChartFeature/Sources/Views/ChartContentTableViewCell.swift index b20d5f4c7..88df47a81 100644 --- a/Projects/Features/ChartFeature/Sources/Views/ChartContentTableViewCell.swift +++ b/Projects/Features/ChartFeature/Sources/Views/ChartContentTableViewCell.swift @@ -339,8 +339,8 @@ extension ChartContentTableViewCell { id: song.id, title: song.title, artist: song.artist, - remix: song.remix, - reaction: song.reaction, + remix: "", + reaction: "", views: song.views, last: song.last, date: song.date diff --git a/Projects/Features/HomeFeature/Sources/ViewControllers/HomeViewController.swift b/Projects/Features/HomeFeature/Sources/ViewControllers/HomeViewController.swift index 469727a89..77f174be9 100644 --- a/Projects/Features/HomeFeature/Sources/ViewControllers/HomeViewController.swift +++ b/Projects/Features/HomeFeature/Sources/ViewControllers/HomeViewController.swift @@ -1,4 +1,5 @@ import BaseFeature +import ChartDomainInterface import DesignSystem import NVActivityIndicatorView import PanModal @@ -125,8 +126,8 @@ extension HomeViewController { id: $0.1[$0.0.row].id, title: $0.1[$0.0.row].title, artist: $0.1[$0.0.row].artist, - remix: $0.1[$0.0.row].remix, - reaction: $0.1[$0.0.row].reaction, + remix: "", + reaction: "", views: $0.1[$0.0.row].views, last: $0.1[$0.0.row].last, date: $0.1[$0.0.row].date diff --git a/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift b/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift index f28fa0497..7f141645c 100644 --- a/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift +++ b/Projects/Features/HomeFeature/Sources/ViewControllers/NewSongsContentViewController.swift @@ -1,4 +1,3 @@ - import BaseFeature import BaseFeatureInterface import DesignSystem diff --git a/Projects/Features/HomeFeature/Sources/ViewModels/HomeViewModel.swift b/Projects/Features/HomeFeature/Sources/ViewModels/HomeViewModel.swift index dc27ec1a6..9b1eb8f5f 100644 --- a/Projects/Features/HomeFeature/Sources/ViewModels/HomeViewModel.swift +++ b/Projects/Features/HomeFeature/Sources/ViewModels/HomeViewModel.swift @@ -50,7 +50,7 @@ public final class HomeViewModel: ViewModelType { let playListDataSource: BehaviorRelay<[RecommendPlayListEntity]> = BehaviorRelay(value: []) let chart = self.fetchChartRankingUseCase - .execute(type: .hourly, limit: 100) + .execute(type: .hourly) .catchAndReturn([]) .asObservable() @@ -91,8 +91,8 @@ public final class HomeViewModel: ViewModelType { id: $0.id, title: $0.title, artist: $0.artist, - remix: $0.remix, - reaction: $0.reaction, + remix: "", + reaction: "", views: $0.views, last: $0.last, date: $0.date diff --git a/Projects/Features/PlayerFeature/Sources/ViewModels/PlayerViewModel+API.swift b/Projects/Features/PlayerFeature/Sources/ViewModels/PlayerViewModel+API.swift index cc3069794..50b81caf1 100644 --- a/Projects/Features/PlayerFeature/Sources/ViewModels/PlayerViewModel+API.swift +++ b/Projects/Features/PlayerFeature/Sources/ViewModels/PlayerViewModel+API.swift @@ -22,7 +22,7 @@ extension PlayerViewModel { guard let self else { return } self.lyricsDict.removeAll() self.sortedLyrics.removeAll() - lyricsEntityArray.forEach { self.lyricsDict.updateValue($0.text, forKey: Float($0.start)) } + lyricsEntityArray.forEach { self.lyricsDict.updateValue($0.text, forKey: Float(0)) } self.sortedLyrics = self.lyricsDict.sorted { $0.key < $1.key }.map { $0.value } } onFailure: { [weak self] error in guard let self else { return } diff --git a/Projects/Features/SearchFeature/Sources/Components/AfterSearchComponent.swift b/Projects/Features/SearchFeature/Sources/Components/AfterSearchComponent.swift index 91d3cb97d..c27f92c98 100644 --- a/Projects/Features/SearchFeature/Sources/Components/AfterSearchComponent.swift +++ b/Projects/Features/SearchFeature/Sources/Components/AfterSearchComponent.swift @@ -6,7 +6,6 @@ import SongsDomainInterface public protocol AfterSearchDependency: Dependency { var afterSearchContentComponent: AfterSearchContentComponent { get } - var fetchSearchSongUseCase: any FetchSearchSongUseCase { get } var containSongsFactory: any ContainSongsFactory { get } } @@ -15,7 +14,7 @@ public final class AfterSearchComponent: Component { return AfterSearchViewController.viewController( afterSearchContentComponent: dependency.afterSearchContentComponent, containSongsFactory: dependency.containSongsFactory, - reactor: .init(fetchSearchSongUseCase: dependency.fetchSearchSongUseCase) + reactor: .init() ) } } diff --git a/Projects/Features/SearchFeature/Sources/Reactors/AfterSearchReactor.swift b/Projects/Features/SearchFeature/Sources/Reactors/AfterSearchReactor.swift index 34d7a1b04..3ca133d57 100644 --- a/Projects/Features/SearchFeature/Sources/Reactors/AfterSearchReactor.swift +++ b/Projects/Features/SearchFeature/Sources/Reactors/AfterSearchReactor.swift @@ -6,7 +6,6 @@ import SongsDomainInterface public final class AfterSearchReactor: Reactor { var disposeBag: DisposeBag = DisposeBag() - private let fetchSearchSongUseCase: FetchSearchSongUseCase public enum Action { case fetchData(String) @@ -23,8 +22,7 @@ public final class AfterSearchReactor: Reactor { public var initialState: State - init(fetchSearchSongUseCase: FetchSearchSongUseCase) { - self.fetchSearchSongUseCase = fetchSearchSongUseCase + init() { self.initialState = State( dataSource: [], text: "" @@ -56,8 +54,7 @@ public final class AfterSearchReactor: Reactor { private extension AfterSearchReactor { func fetchData(_ text: String) -> Observable { - return fetchSearchSongUseCase - .execute(keyword: text) + return Observable.just(SearchResultEntity(song: [], artist: [], remix: [])) .asObservable() .map { res in diff --git a/Projects/Features/SearchFeature/Sources/ViewModels/AfterSearchViewModel.swift b/Projects/Features/SearchFeature/Sources/ViewModels/AfterSearchViewModel.swift index 21265c2c7..aa5f44a87 100644 --- a/Projects/Features/SearchFeature/Sources/ViewModels/AfterSearchViewModel.swift +++ b/Projects/Features/SearchFeature/Sources/ViewModels/AfterSearchViewModel.swift @@ -15,11 +15,9 @@ import Utility public final class AfterSearchViewModel: ViewModelType { var disposeBag = DisposeBag() - var fetchSearchSongUseCase: FetchSearchSongUseCase! - public init(fetchSearchSongUseCase: FetchSearchSongUseCase) { + public init() { DEBUG_LOG("✅ AfterSearchViewModel 생성") - self.fetchSearchSongUseCase = fetchSearchSongUseCase } public struct Input { @@ -47,8 +45,7 @@ public final class AfterSearchViewModel: ViewModelType { guard let self = self else { return Observable.empty() } - return self.fetchSearchSongUseCase - .execute(keyword: str) + return Observable.just(SearchResultEntity(song: [], artist: [], remix: [])) .asObservable() } .map { res in