Skip to content

Commit

Permalink
Merge pull request #1068 from wakmusic/1067-connect-api-artist-detail
Browse files Browse the repository at this point in the history
  • Loading branch information
KangTaeHoon authored Aug 11, 2024
2 parents fefca20 + d44ce97 commit 8e16f33
Show file tree
Hide file tree
Showing 33 changed files with 302 additions and 68 deletions.
6 changes: 6 additions & 0 deletions Projects/App/Sources/Application/AppComponent+Artist.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ public extension AppComponent {
ArtistDetailComponent(parent: self)
}

var fetchArtistDetailUseCase: any FetchArtistDetailUseCase {
shared {
FetchArtistDetailUseCaseImpl(artistRepository: artistRepository)
}
}

var fetchArtistSongListUseCase: any FetchArtistSongListUseCase {
shared {
FetchArtistSongListUseCaseImpl(artistRepository: artistRepository)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import Foundation
import RxSwift

public protocol RemoteArtistDataSource {
func fetchArtistList() -> Single<[ArtistListEntity]>
func fetchArtistList() -> Single<[ArtistEntity]>
func fetchArtistDetail(id: String) -> Single<ArtistEntity>
func fetchArtistSongList(id: String, sort: ArtistSongSortType, page: Int) -> Single<[ArtistSongListEntity]>
func fetchArtistSubscriptionStatus(id: String) -> Single<ArtistSubscriptionStatusEntity>
func subscriptionArtist(id: String, on: Bool) -> Completable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

public struct ArtistListEntity: Equatable {
public struct ArtistEntity: Equatable {
public init(
id: String,
krName: String,
Expand All @@ -12,7 +12,7 @@ public struct ArtistListEntity: Equatable {
roundImage: String,
squareImage: String,
graduated: Bool,
playlist: ArtistListEntity.Playlist,
playlist: ArtistEntity.Playlist,
isHiddenItem: Bool
) {
self.id = id
Expand All @@ -38,12 +38,12 @@ public struct ArtistListEntity: Equatable {
public let personalColor: String
public let roundImage, squareImage: String
public let graduated: Bool
public let playlist: ArtistListEntity.Playlist
public let playlist: ArtistEntity.Playlist
public var isHiddenItem: Bool = false
}

public extension ArtistListEntity {
struct Playlist: Decodable {
public extension ArtistEntity {
struct Playlist {
public let latest, popular, oldest: String

public init(latest: String, popular: String, oldest: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import Foundation
import RxSwift

public protocol ArtistRepository {
func fetchArtistList() -> Single<[ArtistListEntity]>
func fetchArtistList() -> Single<[ArtistEntity]>
func fetchArtistDetail(id: String) -> Single<ArtistEntity>
func fetchArtistSongList(id: String, sort: ArtistSongSortType, page: Int) -> Single<[ArtistSongListEntity]>
func fetchArtistSubscriptionStatus(id: String) -> Single<ArtistSubscriptionStatusEntity>
func subscriptionArtist(id: String, on: Bool) -> Completable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Foundation
import RxSwift

public protocol FetchArtistDetailUseCase {
func execute(id: String) -> Single<ArtistEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import Foundation
import RxSwift

public protocol FetchArtistListUseCase {
func execute() -> Single<[ArtistListEntity]>
func execute() -> Single<[ArtistEntity]>
}
7 changes: 6 additions & 1 deletion Projects/Domains/ArtistDomain/Sources/API/ArtistAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Moya

public enum ArtistAPI {
case fetchArtistList
case fetchArtistDetail(id: String)
case fetchArtistSongList(id: String, sort: ArtistSongSortType, page: Int)
case fetchSubscriptionStatus(id: String)
case subscriptionArtist(id: String, on: Bool)
Expand All @@ -20,6 +21,8 @@ extension ArtistAPI: WMAPI {
switch self {
case .fetchArtistList:
return "/list"
case let .fetchArtistDetail(id):
return "/\(id)"
case let .fetchArtistSongList(id, _, _):
return "/\(id)/songs"
case let .fetchSubscriptionStatus(id):
Expand All @@ -32,6 +35,7 @@ extension ArtistAPI: WMAPI {
public var method: Moya.Method {
switch self {
case .fetchArtistList,
.fetchArtistDetail,
.fetchArtistSongList,
.fetchSubscriptionStatus:
return .get
Expand All @@ -43,6 +47,7 @@ extension ArtistAPI: WMAPI {
public var task: Moya.Task {
switch self {
case .fetchArtistList,
.fetchArtistDetail,
.fetchSubscriptionStatus,
.subscriptionArtist:
return .requestPlain
Expand All @@ -59,7 +64,7 @@ extension ArtistAPI: WMAPI {

public var jwtTokenType: JwtTokenType {
switch self {
case .fetchArtistList, .fetchArtistSongList:
case .fetchArtistList, .fetchArtistDetail, .fetchArtistSongList:
return .none
case .fetchSubscriptionStatus, .subscriptionArtist:
return .accessToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ import Foundation
import RxSwift

public final class RemoteArtistDataSourceImpl: BaseRemoteDataSource<ArtistAPI>, RemoteArtistDataSource {
public func fetchArtistList() -> Single<[ArtistListEntity]> {
public func fetchArtistList() -> Single<[ArtistEntity]> {
request(.fetchArtistList)
.map([ArtistListResponseDTO].self)
.map { $0.map { $0.toDomain() } }
}

public func fetchArtistDetail(id: String) -> Single<ArtistEntity> {
request(.fetchArtistDetail(id: id))
.map(ArtistDetailResponseDTO.self)
.map { $0.toDomain() }
}

public func fetchArtistSongList(id: String, sort: ArtistSongSortType, page: Int) -> Single<[ArtistSongListEntity]> {
request(.fetchArtistSongList(id: id, sort: sort, page: page))
.map([ArtistSongListResponseDTO].self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ public final class ArtistRepositoryImpl: ArtistRepository {
self.remoteArtistDataSource = remoteArtistDataSource
}

public func fetchArtistList() -> Single<[ArtistListEntity]> {
public func fetchArtistList() -> Single<[ArtistEntity]> {
remoteArtistDataSource.fetchArtistList()
}

public func fetchArtistDetail(id: String) -> Single<ArtistEntity> {
remoteArtistDataSource.fetchArtistDetail(id: id)
}

public func fetchArtistSongList(id: String, sort: ArtistSongSortType, page: Int) -> Single<[ArtistSongListEntity]> {
remoteArtistDataSource.fetchArtistSongList(id: id, sort: sort, page: page)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import ArtistDomainInterface
import Foundation

public struct ArtistDetailResponseDTO: Decodable, Equatable {
let id: String
let name: ArtistDetailResponseDTO.Name
let group: ArtistDetailResponseDTO.Group
let info: ArtistDetailResponseDTO.Info
let imageURL: ArtistDetailResponseDTO.ImageURL
let graduated: Bool

public static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.id == rhs.id
}

private enum CodingKeys: String, CodingKey {
case id
case name
case group
case info
case imageURL = "imageUrl"
case graduated
}
}

public extension ArtistDetailResponseDTO {
struct Name: Decodable {
let krName: String
let enName: String

private enum CodingKeys: String, CodingKey {
case krName = "krShort"
case enName = "en"
}
}

struct Group: Decodable {
let name: String
}

struct Info: Decodable {
let title: ArtistDetailResponseDTO.Info.Title
let description: String
let color: ArtistDetailResponseDTO.Info.Color
let playlist: ArtistDetailResponseDTO.Info.Playlist
}

struct ImageURL: Decodable {
let round: String
let square: String
}
}

public extension ArtistDetailResponseDTO.Info {
struct Title: Decodable {
let short: String
}

struct Color: Decodable {
let background: [[String]]
}

struct Playlist: Decodable {
let latest, popular, oldest: String
}
}

public extension ArtistDetailResponseDTO {
func toDomain() -> ArtistEntity {
ArtistEntity(
id: id,
krName: name.krName,
enName: name.enName,
groupName: group.name,
title: info.title.short,
description: info.description,
personalColor: info.color.background.flatMap { $0 }.first ?? "ffffff",
roundImage: imageURL.round,
squareImage: imageURL.square,
graduated: graduated,
playlist: ArtistEntity.Playlist(
latest: info.playlist.latest,
popular: info.playlist.popular,
oldest: info.playlist.oldest
),
isHiddenItem: false
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ public extension ArtistListResponseDTO.Info {
}

public extension ArtistListResponseDTO {
func toDomain() -> ArtistListEntity {
ArtistListEntity(
func toDomain() -> ArtistEntity {
ArtistEntity(
id: id,
krName: name.krName,
enName: name.enName,
Expand All @@ -78,7 +78,7 @@ public extension ArtistListResponseDTO {
roundImage: imageURL.round,
squareImage: imageURL.square,
graduated: graduated,
playlist: ArtistListEntity.Playlist(
playlist: ArtistEntity.Playlist(
latest: info.playlist.latest,
popular: info.playlist.popular,
oldest: info.playlist.oldest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import ArtistDomainInterface
import Foundation
import RxSwift

public struct FetchArtistDetailUseCaseImpl: FetchArtistDetailUseCase {
private let artistRepository: any ArtistRepository

public init(
artistRepository: ArtistRepository
) {
self.artistRepository = artistRepository
}

public func execute(id: String) -> Single<ArtistEntity> {
artistRepository.fetchArtistDetail(id: id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public struct FetchArtistListUseCaseImpl: FetchArtistListUseCase {
self.artistRepository = artistRepository
}

public func execute() -> Single<[ArtistListEntity]> {
public func execute() -> Single<[ArtistEntity]> {
artistRepository.fetchArtistList()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import RxSwift

public final class FetchArtistListUseCaseSpy: FetchArtistListUseCase {
public private(set) var callCount = 0
public var handler: (() -> Single<[ArtistListEntity]>) = { .never() }
public func execute() -> Single<[ArtistListEntity]> {
public var handler: (() -> Single<[ArtistEntity]>) = { .never() }
public func execute() -> Single<[ArtistEntity]> {
callCount += 1
return handler()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ import Foundation
import UIKit

public protocol ArtistDetailFactory {
func makeView(model: ArtistListEntity) -> UIViewController
func makeView(artistID: String) -> UIViewController
}
11 changes: 11 additions & 0 deletions Projects/Features/ArtistFeature/Resources/Artist.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,21 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dJE-xf-aMp">
<rect key="frame" x="0.0" y="323.66666666666669" width="393" height="528.33333333333326"/>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Eh4-JW-fWf" customClass="NVActivityIndicatorView" customModule="NVActivityIndicatorView">
<rect key="frame" x="181.66666666666666" y="411" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="5ny-iY-pKj"/>
<constraint firstAttribute="height" constant="30" id="vmF-Ia-1N0"/>
</constraints>
</view>
</subviews>
<viewLayoutGuide key="safeArea" id="xjg-5g-cse"/>
<color key="backgroundColor" name="gray100"/>
<constraints>
<constraint firstItem="Eh4-JW-fWf" firstAttribute="centerX" secondItem="pXR-lz-QGP" secondAttribute="centerX" id="5ia-qa-4Me"/>
<constraint firstItem="0qp-BF-xDH" firstAttribute="height" secondItem="pXR-lz-QGP" secondAttribute="height" multiplier="200:812" id="809-1f-hUH"/>
<constraint firstItem="xjg-5g-cse" firstAttribute="trailing" secondItem="PRy-Jh-l65" secondAttribute="trailing" id="9pW-NX-azx"/>
<constraint firstItem="Eh4-JW-fWf" firstAttribute="centerY" secondItem="pXR-lz-QGP" secondAttribute="centerY" id="EKI-wV-4kA"/>
<constraint firstItem="PRy-Jh-l65" firstAttribute="top" secondItem="xjg-5g-cse" secondAttribute="top" id="Gzy-bg-SOD"/>
<constraint firstItem="0qp-BF-xDH" firstAttribute="top" secondItem="pXR-lz-QGP" secondAttribute="top" id="LjD-rI-hoM"/>
<constraint firstItem="0qp-BF-xDH" firstAttribute="leading" secondItem="xjg-5g-cse" secondAttribute="leading" id="Lzn-n5-SvB"/>
Expand All @@ -373,6 +382,7 @@
</constraints>
</view>
<connections>
<outlet property="activityIndicator" destination="Eh4-JW-fWf" id="gpS-WL-Zem"/>
<outlet property="backButton" destination="2VE-qp-fkm" id="10e-xz-U9r"/>
<outlet property="contentView" destination="dJE-xf-aMp" id="xKa-Jn-VHb"/>
<outlet property="gradationView" destination="0qp-BF-xDH" id="eIc-iF-Iuh"/>
Expand Down Expand Up @@ -548,6 +558,7 @@
<connections>
<outlet property="activityIndidator" destination="DKc-qh-4Cf" id="uq2-Qu-Xfa"/>
<outlet property="songCartOnView" destination="0md-99-Zae" id="Rpk-qA-g16"/>
<outlet property="songCartOnViewHeightConstraint" destination="icd-GC-lhw" id="Zul-3O-BKU"/>
<outlet property="tableView" destination="MPq-Ds-wcF" id="xt0-Bw-pl3"/>
</connections>
</viewController>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ import UIKit

public protocol ArtistDetailDependency: Dependency {
var artistMusicComponent: ArtistMusicComponent { get }
var fetchArtistDetailUseCase: any FetchArtistDetailUseCase { get }
var fetchArtistSubscriptionStatusUseCase: any FetchArtistSubscriptionStatusUseCase { get }
var subscriptionArtistUseCase: any SubscriptionArtistUseCase { get }
var textPopUpFactory: any TextPopUpFactory { get }
var signInFactory: any SignInFactory { get }
}

public final class ArtistDetailComponent: Component<ArtistDetailDependency>, ArtistDetailFactory {
public func makeView(model: ArtistListEntity) -> UIViewController {
public func makeView(artistID: String) -> UIViewController {
return ArtistDetailViewController.viewController(
viewModel: .init(
model: model,
artistID: artistID,
fetchArtistDetailUseCase: dependency.fetchArtistDetailUseCase,
fetchArtistSubscriptionStatusUseCase: dependency.fetchArtistSubscriptionStatusUseCase,
subscriptionArtistUseCase: dependency.subscriptionArtistUseCase
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public protocol ArtistMusicDependency: Dependency {
}

public final class ArtistMusicComponent: Component<ArtistMusicDependency> {
public func makeView(model: ArtistListEntity?) -> ArtistMusicViewController {
public func makeView(model: ArtistEntity?) -> ArtistMusicViewController {
return ArtistMusicViewController.viewController(
model: model,
artistMusicContentComponent: dependency.artistMusicContentComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public protocol ArtistMusicContentDependency: Dependency {
public final class ArtistMusicContentComponent: Component<ArtistMusicContentDependency> {
public func makeView(
type: ArtistSongSortType,
model: ArtistListEntity?
model: ArtistEntity?
) -> ArtistMusicContentViewController {
return ArtistMusicContentViewController.viewController(
viewModel: .init(
Expand Down
Loading

0 comments on commit 8e16f33

Please sign in to comment.