Skip to content

Commit

Permalink
Merge pull request #1136 from wakmusic/1135-add-credit-profile-image
Browse files Browse the repository at this point in the history
πŸ”€ :: (#1135) ν¬λ ˆλ”§ μž‘μ—…μž ν”„λ‘œν•„ 이미지 지원
  • Loading branch information
baekteun authored Aug 14, 2024
2 parents 5066395 + ffadfd2 commit b0ca385
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 15 deletions.
6 changes: 6 additions & 0 deletions Projects/App/Sources/Application/AppComponent+Credit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public extension AppComponent {
}
}

var fetchCreditProfileImageURLUseCase: any FetchCreditProfileImageURLUseCase {
shared {
FetchCreditProfileImageURLUseCaseImpl(creditRepository: creditRepository)
}
}

var songCreditFactory: any SongCreditFactory {
SongCreditComponent(parent: self)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public protocol RemoteCreditDataSource {
page: Int,
limit: Int
) -> Single<[SongEntity]>

func fetchCreditProfileImageURL(name: String) -> Single<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public protocol CreditRepository {
page: Int,
limit: Int
) -> Single<[SongEntity]>

func fetchCreditProfileImageURL(name: String) -> Single<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import RxSwift

public protocol FetchCreditProfileImageURLUseCase {
func execute(name: String) -> Single<String>
}
10 changes: 8 additions & 2 deletions Projects/Domains/CreditDomain/Sources/API/CreditAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum CreditAPI {
page: Int,
limit: Int
)
case fetchProfileImageURL(name: String)
}

extension CreditAPI: WMAPI {
Expand All @@ -23,12 +24,14 @@ extension CreditAPI: WMAPI {
switch self {
case let .fetchCreditSongList(name, _, _, _):
return "/\(name)/songs"
case let .fetchProfileImageURL(name):
return "/\(name)"
}
}

public var method: Moya.Method {
switch self {
case .fetchCreditSongList:
case .fetchCreditSongList, .fetchProfileImageURL:
return .get
}
}
Expand All @@ -41,12 +44,15 @@ extension CreditAPI: WMAPI {
"page": page,
"limit": limit
], encoding: URLEncoding.queryString)

case .fetchProfileImageURL:
return .requestPlain
}
}

public var jwtTokenType: JwtTokenType {
switch self {
case .fetchCreditSongList:
case .fetchCreditSongList, .fetchProfileImageURL:
return .none
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ public final class RemoteCreditDataSourceImpl: BaseRemoteDataSource<CreditAPI>,
.map([FetchCreditSongListResponseDTO].self)
.map { $0.toDomain() }
}

public func fetchCreditProfileImageURL(name: String) -> Single<String> {
request(.fetchProfileImageURL(name: name))
.map(FetchCreditProfileImageURLResponseDTO.self)
.map(\.profileURL)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ public final class CreditRepositoryImpl: CreditRepository {
) -> Single<[SongEntity]> {
remoteCreditDataSource.fetchCreditSongList(name: name, order: order, page: page, limit: limit)
}

public func fetchCreditProfileImageURL(name: String) -> Single<String> {
remoteCreditDataSource.fetchCreditProfileImageURL(name: name)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

struct FetchCreditProfileImageURLResponseDTO: Decodable {
let profileURL: String

enum CodingKeys: String, CodingKey {
case profileURL = "profileUrl"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import CreditDomainInterface
import RxSwift

public final class FetchCreditProfileImageURLUseCaseImpl: FetchCreditProfileImageURLUseCase {
private let creditRepository: any CreditRepository

public init(
creditRepository: any CreditRepository
) {
self.creditRepository = creditRepository
}

public func execute(name: String) -> Single<String> {
creditRepository.fetchCreditProfileImageURL(name: name)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import CreditDomainInterface
import RxSwift
import SongsDomainInterface

public final class FetchCreditProfileImageURLUseCaseSpy: FetchCreditProfileImageURLUseCase {
public var callCount = 0
public var handler: (String) -> Single<String> = { _ in fatalError() }

public init() {}

public func execute(
name: String
) -> Single<String> {
callCount += 1
return handler(name)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
let creditSongListTabFactory = FakeCreditSongListTabFactory()
let reactor = CreditSongListReactor(workerName: "CLTH")
let reactor = CreditSongListReactor(
workerName: "CLTH",
fetchCreditProfileImageURLUseCase: FetchCreditProfileImageURLUseCaseSpy()
)
let viewController = CreditSongListViewController(
reactor: reactor,
creditSongListTabFactory: creditSongListTabFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import CreditDomainInterface
import CreditSongListFeatureInterface
import NeedleFoundation
import UIKit

public protocol CreditSongListDependency: Dependency {
var creditSongListTabFactory: any CreditSongListTabFactory { get }
var fetchCreditProfileImageURLUseCase: any FetchCreditProfileImageURLUseCase { get }
}

public final class CreditSongListComponent: Component<CreditSongListDependency>, CreditSongListFactory {
public func makeViewController(workerName: String) -> UIViewController {
let reactor = CreditSongListReactor(workerName: workerName)
let reactor = CreditSongListReactor(
workerName: workerName,
fetchCreditProfileImageURLUseCase: dependency.fetchCreditProfileImageURLUseCase
)
let viewController = CreditSongListViewController(
reactor: reactor,
creditSongListTabFactory: dependency.creditSongListTabFactory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,59 @@
import CreditDomainInterface
import ReactorKit

final class CreditSongListReactor: Reactor {
enum Action {}
enum Mutation {}
enum Action {
case viewDidLoad
}

enum Mutation {
case updateProfileImageURL(String?)
}

struct State {
var workerName: String
var profileImageURL: String?
}

let initialState: State
internal let workerName: String
private let fetchCreditProfileImageURLUseCase: FetchCreditProfileImageURLUseCase

init(workerName: String) {
init(
workerName: String,
fetchCreditProfileImageURLUseCase: FetchCreditProfileImageURLUseCase
) {
self.initialState = .init(
workerName: workerName
)
self.workerName = workerName
self.fetchCreditProfileImageURLUseCase = fetchCreditProfileImageURLUseCase
}

func mutate(action: Action) -> Observable<Mutation> {
.empty()
switch action {
case .viewDidLoad:
return viewDidLoad()
}
}

func reduce(state: State, mutation: Mutation) -> State {
state
var newState = state

switch mutation {
case let .updateProfileImageURL(url):
newState.profileImageURL = url
}

return newState
}
}

private extension CreditSongListReactor {
func viewDidLoad() -> Observable<Mutation> {
fetchCreditProfileImageURLUseCase
.execute(name: workerName)
.map { Mutation.updateProfileImageURL($0) }
.asObservable()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ final class CreditSongListViewController: BaseReactorViewController<CreditSongLi
override func configureNavigation() {}

override func bindAction(reactor: CreditSongListReactor) {
self.rx.methodInvoked(#selector(viewDidLoad))
.map { _ in Reactor.Action.viewDidLoad }
.bind(to: reactor.action)
.disposed(by: disposeBag)

dismissButton.rx.tap
.bind(with: self) { owner, _ in
owner.navigationController?.popViewController(animated: true)
Expand All @@ -115,6 +120,12 @@ final class CreditSongListViewController: BaseReactorViewController<CreditSongLi
}
.disposed(by: disposeBag)

sharedState.map(\.profileImageURL)
.bind(with: creditProfileView) { view, url in
view.updateProfileImageURL(url: url)
}
.disposed(by: disposeBag)

CreditSongListScopedState.shared.creditSongTabItemScrolledObservable
.observe(on: MainScheduler.asyncInstance)
.bind(with: self) { owner, scrollView in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import DesignSystem
import Kingfisher
import Then
import UIKit
import Utility

protocol CreditProfileViewStateProtocol {
func updateProfileImageURL(url: String?)
}

final class CreditProfileView: UIStackView {
private let creditProfileContainer = UIView().then {
private let creditProfileImageViewContainer = UIImageView().then {
$0.backgroundColor = DesignSystemAsset.BlueGrayColor.blueGray200.color
$0.layer.cornerRadius = 8
$0.clipsToBounds = true
}

private let creditProfileImageView = UIImageView().then {
private let creditProfilePlaceholderImageView = UIImageView().then {
$0.image = DesignSystemAsset.Logo.placeHolderLarge.image
$0.contentMode = .scaleAspectFill
}
Expand Down Expand Up @@ -48,19 +53,30 @@ final class CreditProfileView: UIStackView {
}
}

extension CreditProfileView: CreditProfileViewStateProtocol {
func updateProfileImageURL(url: String?) {
if let url {
creditProfilePlaceholderImageView.isHidden = true
creditProfileImageViewContainer.kf.setImage(
with: URL(string: url)
)
}
}
}

private extension CreditProfileView {
func addView() {
self.addArrangedSubviews(creditProfileContainer, creditNameContainer)
creditProfileContainer.addSubview(creditProfileImageView)
self.addArrangedSubviews(creditProfileImageViewContainer, creditNameContainer)
creditProfileImageViewContainer.addSubview(creditProfilePlaceholderImageView)
creditNameContainer.addSubview(creditNameLabel)
}

func setLayout() {
creditProfileContainer.snp.makeConstraints {
creditProfileImageViewContainer.snp.makeConstraints {
$0.size.equalTo(140)
}

creditProfileImageView.snp.makeConstraints {
creditProfilePlaceholderImageView.snp.makeConstraints {
$0.center.equalToSuperview()
$0.size.equalTo(80)
}
Expand Down

0 comments on commit b0ca385

Please sign in to comment.