Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Camera 관련 비즈니스 로직 부분 리팩토링 해요 #718

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import UIKit

protocol CameraDisplayNavigatorProtocol: BaseNavigator {
func toHome()
func toCamera()
func showErrorAlert()
}

final class CameraDisplayNavigator: CameraDisplayNavigatorProtocol {
Expand All @@ -24,9 +26,31 @@ final class CameraDisplayNavigator: CameraDisplayNavigatorProtocol {
self.navigationController = navigationController
}

func showErrorAlert() {
let confirmHandler: BBAlertActionHandler = { [weak self] alert in
self?.toCamera()
alert?.close()
}
let cancelHandler: BBAlertActionHandler = { [weak self] alert in
self?.toHome()
alert?.close()
}

BBAlert.style(
.uploadFailed,
primaryAction: confirmHandler,
secondaryAction: cancelHandler
).show()
}

func toCamera() {
navigationController.popViewController(animated: true)
}


//MARK: - Configure
func toHome() {
let vc = MainViewControllerWrapper().viewController
navigationController.setViewControllers([vc], animated: true)
navigationController.setViewControllers([vc], animated: false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,49 @@ import UIKit

import DesignSystem
import Core
import Domain



protocol CameraNavigatorProtocol: BaseNavigator {
func showErrorAlert(_ type: UploadLocation)
func showErrorToast(_ description: String)
func toCamera(_ type: UploadLocation)
func toHome()
}


final class CameraNavigator: CameraNavigatorProtocol {
final class CameraNavigator: CameraNavigatorProtocol {
var navigationController: UINavigationController

init(navigationController: UINavigationController) {
self.navigationController = navigationController
}

func showErrorAlert(_ type: UploadLocation) {
let confirmHandler: BBAlertActionHandler = makeConfirmHandler(for: type)
let cancelHandler: BBAlertActionHandler = { [weak self] alert in
self?.toHome()
alert?.close()
}

BBAlert.style(
.uploadFailed,
primaryAction: confirmHandler,
secondaryAction: cancelHandler
).show()
}

func toCamera(_ type: UploadLocation) {
let vc = CameraViewControllerWrapper(cameraType: type).viewController
navigationController.pushViewController(vc, animated: true)
}

func toHome() {
let vc = MainViewControllerWrapper().viewController
navigationController.setViewControllers([vc], animated: false)
}

func showErrorToast(_ descrption: String) {
let config = BBToastConfiguration(direction: .top(yOffset: 75))
let viewConfig = BBToastViewConfiguration(minWidth: 100)
Expand All @@ -36,3 +65,21 @@ final class CameraNavigator: CameraNavigatorProtocol {
}


private extension CameraNavigator {
func makeConfirmHandler(for type: UploadLocation) -> BBAlertActionHandler {
switch type {
case .survival, .mission:
return { [weak self] alert in
self?.toCamera(type)
alert?.close()
}
case .profile, .realEmoji:
return { alert in
alert?.close()
}
default:
return nil
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ public final class CameraDisplayViewReactor: Reactor {
.just(.setError(false)),
.just(.setLoading(true))
)
}.catch { _ in
return .just(.setError(true))
}.catchError(with: self) { owner, _ in
owner.cameraDisplayNavigator.showErrorAlert()
return .empty()
}

case let .fetchDisplayImage(description):
Expand Down Expand Up @@ -149,6 +150,9 @@ public final class CameraDisplayViewReactor: Reactor {
.flatMap { _ in Observable<Mutation>.empty() }
)
}
}.catchError(with: self) { owner, _ in
owner.cameraDisplayNavigator.showErrorAlert()
return .empty()
}
case .hideDisplayEditCell:
return .concat(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ public final class CameraViewReactor: Reactor {
case setProfilePresignedResponse(CreateMemberPresignedEntity?)
case setProfileMemberResponse(MembersProfileEntity?)
case setRealEmojiImageURLResponse(CameraRealEmojiPreSignedEntity?)
case setRealEmojiImageCreateResponse(CameraCreateRealEmojiEntity?)
case setRealEmojiItems([CameraRealEmojiImageItemEntity?])
case setRealEmojiSection([EmojiSectionItem])
case setErrorAlert(Bool)
case setRealEmojiType(Emojis)
case setImageData(Data)
case setUpdateEmojiImage(URL)
}

public struct State {
Expand All @@ -70,13 +68,11 @@ public final class CameraViewReactor: Reactor {
@Pulse var missionEntity: MissonTodayContentEntity?
@Pulse var memberPresignedEntity: CreateMemberPresignedEntity?
@Pulse var realEmojiURLEntity: CameraRealEmojiPreSignedEntity?
@Pulse var realEmojiCreateEntity: CameraCreateRealEmojiEntity?
@Pulse var realEmojiEntity: [CameraRealEmojiImageItemEntity?]
@Pulse var realEmojiSection: [EmojiSectionModel]
@Pulse var zoomScale: CGFloat
@Pulse var pinchZoomScale: CGFloat
@Pulse var imageData: Data?
var updateEmojiImage: URL?
var emojiType: Emojis = .emoji(forIndex: 1)
@Pulse var cameraType: UploadLocation = .survival
var accountImage: Data?
Expand Down Expand Up @@ -154,8 +150,6 @@ public final class CameraViewReactor: Reactor {
newState.profileMemberEntity = entity
case let .setRealEmojiImageURLResponse(entity):
newState.realEmojiURLEntity = entity
case let .setRealEmojiImageCreateResponse(entity):
newState.realEmojiCreateEntity = entity
case let .setRealEmojiItems(items):
newState.realEmojiEntity = items
case let .setRealEmojiSection(section):
Expand All @@ -165,8 +159,6 @@ public final class CameraViewReactor: Reactor {
newState.isError = isError
case let .setRealEmojiType(emojiType):
newState.emojiType = emojiType
case let .setUpdateEmojiImage(realEmoji):
newState.updateEmojiImage = realEmoji
case let .setZoomScale(zoomScale):
newState.zoomScale = zoomScale
case let .setPinchZoomScale(pinchZoomScale):
Expand Down Expand Up @@ -304,12 +296,14 @@ extension CameraViewReactor {
.just(.setProfileMemberResponse(entity)),
.just(.setLoading(true))
)
}.catch { [weak self] error in
self?.cameraNavigator.showErrorToast(error.localizedDescription)
}.catchError(with: self) { owner, _ in
let type = owner.currentState.cameraType
owner.cameraNavigator.showErrorAlert(type)
return .empty()
}
}.catch { [weak self] error in
self?.cameraNavigator.showErrorToast(error.localizedDescription)
}.catchError(with: self) { owner, _ in
let type = owner.currentState.cameraType
owner.cameraNavigator.showErrorAlert(type)
return .empty()
}
case .realEmoji:
Expand All @@ -320,84 +314,52 @@ extension CameraViewReactor {
let realEmojiImage = "\(imageData.hashValue).jpg"
let body = CreatePresignedURLRequest(imageName: realEmojiImage)
if currentState.realEmojiEntity[currentState.emojiType.rawValue - 1] == nil {
return .concat(
.just(.setLoading(false)),
fetchRealEmojiPreSignedUseCase.execute(memberId: memberId, body: body)
.withUnretained(self)
.subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .background))
.flatMap { owner, entity -> Observable<CameraViewReactor.Mutation> in
guard let remoteURL = entity?.imageURL else { return .just(.setErrorAlert(true))}

return owner.uploadImageUseCase.execute(remoteURL, image: imageData)
.subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .background))
.flatMap { isSuccess -> Observable<CameraViewReactor.Mutation> in
let originalURL = owner.configureProfileOriginalS3URL(url: remoteURL, with: .realEmoji)
let body = CreateEmojiImageRequest(type: owner.currentState.emojiType.emojiString, imageUrl: originalURL)
if isSuccess {
return owner.fetchRealEmojiCreateUseCase.execute(memberId: memberId, body: body)
.subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .background))
.flatMap { realEmojiEntity -> Observable<CameraViewReactor.Mutation> in
guard let createRealEmojiEntity = realEmojiEntity else { return .just(.setErrorAlert(true))}
owner.provider.realEmojiGlobalState.createRealEmojiImage(indexPath: owner.currentState.emojiType.rawValue - 1, image: createRealEmojiEntity.realEmojiImageURL, emojiType: createRealEmojiEntity.realEmojiType)
return owner.fetchRealEmojiListUseCase.execute(memberId: memberId)
.asObservable()
.flatMap { reloadEntity -> Observable<CameraViewReactor.Mutation> in
return .concat(
.just(.setRealEmojiImageURLResponse(entity)),
.just(.setRealEmojiItems(reloadEntity)),
.just(.setRealEmojiImageCreateResponse(realEmojiEntity)),
.just(.setErrorAlert(false)),
.just(.setLoading(true))
)
}

}
} else {
return .just(.setErrorAlert(true))
}

return fetchRealEmojiPreSignedUseCase.execute(memberId: memberId, body: body, imageData: imageData)
.withUnretained(self)
.flatMap { owner, remoteURL -> Observable<Mutation> in
let originalURL = owner.configureProfileOriginalS3URL(url: remoteURL.imageURL, with: .realEmoji)
let body = CreateEmojiImageRequest(type: owner.currentState.emojiType.emojiString, imageUrl: originalURL)
return owner.fetchRealEmojiCreateUseCase.execute(memberId: memberId, body: body)
.flatMap { entity -> Observable<Mutation> in
guard let entity else {
return .empty()
}

}

)
owner.provider.realEmojiGlobalState.createRealEmojiImage(indexPath: owner.currentState.emojiType.rawValue - 1, image: entity.realEmojiImageURL, emojiType: entity.realEmojiType)
return .empty()
}
}.catchError(with: self) { owner, _ in
let type = owner.currentState.cameraType
owner.cameraNavigator.showErrorAlert(type)
return .empty()
}
} else {
let realEmojiImage = "\(imageData.hashValue).jpg"
let body = CreatePresignedURLRequest(imageName: realEmojiImage)
return .concat(
.just(.setLoading(false)),
fetchRealEmojiPreSignedUseCase.execute(memberId: memberId, body: body)
.withUnretained(self)
.subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .background))
.flatMap { owner, entity -> Observable<CameraViewReactor.Mutation> in
guard let remoteURL = entity?.imageURL else { return .just(.setErrorAlert(true))}
let originalURL = owner.configureProfileOriginalS3URL(url: remoteURL, with: .realEmoji)

return owner.uploadImageUseCase.execute(remoteURL, image: imageData)
.subscribe(on: ConcurrentDispatchQueueScheduler.init(qos: .background))
.asObservable()
.flatMap { isSuccess -> Observable<CameraViewReactor.Mutation> in
if isSuccess {
let body = UpdateRealEmojiImageRequest(imageUrl: originalURL)
return owner.fetchRealEmojiUpdateUseCase.execute(memberId: memberId, realEmojiId: owner.currentState.realEmojiEntity[owner.currentState.emojiType.rawValue - 1]?.realEmojiId ?? "", body: body)
.flatMap { updateRealEmojiEntity -> Observable<CameraViewReactor.Mutation> in
guard let updateEntity = updateRealEmojiEntity else { return .just(.setErrorAlert(true))}
owner.provider.realEmojiGlobalState.updateRealEmojiImage(indexPath: owner.currentState.emojiType.rawValue - 1, image: updateEntity.realEmojiImageURL)
return .concat(
.just(.setUpdateEmojiImage(updateEntity.realEmojiImageURL)),
.just(.setLoading(true)),
.just(.setErrorAlert(false))
)
}
} else {
return .empty()
}
}

}

)

return fetchRealEmojiPreSignedUseCase.execute(memberId: memberId, body: body, imageData: imageData)
.withUnretained(self)
.flatMap { owner, remoteURL -> Observable<Mutation> in
let originalURL = owner.configureProfileOriginalS3URL(url: remoteURL.imageURL, with: .realEmoji)
let body = UpdateRealEmojiImageRequest(imageUrl: originalURL)
let realEmojiId = owner.currentState.realEmojiEntity[owner.currentState.emojiType.rawValue - 1]?.realEmojiId ?? ""
return owner.fetchRealEmojiUpdateUseCase.execute(memberId: memberId, realEmojiId: realEmojiId, body: body)
.flatMap { entity -> Observable<Mutation> in
guard let entity else {
return .empty()
}
owner.provider.realEmojiGlobalState.updateRealEmojiImage(indexPath: owner.currentState.emojiType.rawValue - 1, image: entity.realEmojiImageURL)

return .empty()
}.catchError(with: self) { owner, _ in
let type = owner.currentState.cameraType
owner.cameraNavigator.showErrorAlert(type)
return .empty()
}
}.catchError(with: self) { owner, _ in
let type = owner.currentState.cameraType
owner.cameraNavigator.showErrorAlert(type)
return .empty()
}
}
}
}
Expand Down
Loading
Loading