Skip to content

Commit

Permalink
fix/#223 충돌 해결
Browse files Browse the repository at this point in the history
  • Loading branch information
youz2me committed Jul 18, 2024
1 parent 2818853 commit 364730c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@

import UIKit

import RxSwift
import RxCocoa

class ProfileSetupViewController: BaseViewController {
private let rootView = ProfileSetupView()
private let viewModel: ProfileSetupViewModel
private let disposeBag = DisposeBag()

init(viewModel: ProfileSetupViewModel) {
self.viewModel = viewModel
Expand All @@ -30,78 +26,57 @@ class ProfileSetupViewController: BaseViewController {

override func viewDidLoad() {
super.viewDidLoad()

setupNavigationBarTitle(with: "프로필 설정")
setupNavigationBarBackButton()
setupBindings()
}

override func setupAction() {
rootView.confirmButton.addTarget(self, action: #selector(confirmButtonTapped), for: .touchUpInside)
rootView.skipButton.addTarget(self, action: #selector(skipButtonTapped), for: .touchUpInside)
rootView.cameraButton.addTarget(self, action: #selector(cameraButtonTapped), for: .touchUpInside)
}

private func setupBindings() {
viewModel.profileImage
.bind(to: rootView.profileImageView.rx.image)
.disposed(by: disposeBag)

viewModel.isConfirmButtonEnabled
.bind(to: rootView.confirmButton.rx.isEnabled)
.disposed(by: disposeBag)

viewModel.isConfirmButtonEnabled
.map { $0 ? 1.0 : 0.5 }
.bind(to: rootView.confirmButton.rx.alpha)
.disposed(by: disposeBag)

rootView.confirmButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.viewModel.uploadProfileImage()
})
.disposed(by: disposeBag)

rootView.skipButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.navigateToWelcome()
})
.disposed(by: disposeBag)

rootView.cameraButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.showImagePicker()
})
.disposed(by: disposeBag)
viewModel.profileImage.bind { [weak self] image in
self?.rootView.profileImageView.image = image
}

viewModel.uploadSuccess
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] in
self?.navigateToWelcome()
})
.disposed(by: disposeBag)
viewModel.isConfirmButtonEnabled.bind { [weak self] isEnabled in
self?.rootView.confirmButton.isEnabled = isEnabled
self?.rootView.confirmButton.alpha = isEnabled ? 1.0 : 0.5
}
}

private func showImagePicker() {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = true
present(imagePicker, animated: true)
}
@objc private func confirmButtonTapped() {
viewModel.uploadProfileImage { [weak self] success in
if success {
DispatchQueue.main.async {
let welcomeVC = WelcomeViewController(
viewModel: WelcomeViewModel(nickname: self?.viewModel.nickname ?? "")
)
welcomeVC.modalPresentationStyle = .fullScreen
self?.present(welcomeVC, animated: true, completion: nil)
}
}
}
}

private func navigateToWelcome() {
let welcomeVM = WelcomeViewModel(nickname: viewModel.nickname)
let welcomeVC = WelcomeViewController(viewModel: welcomeVM)
@objc private func skipButtonTapped() {
let welcomeVC = WelcomeViewController(
viewModel: WelcomeViewModel(nickname: viewModel.nickname)
)
welcomeVC.modalPresentationStyle = .fullScreen
present(welcomeVC, animated: true, completion: nil)
}
}

extension ProfileSetupViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let editedImage = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {
let croppedImage = cropToCircle(image: editedImage)
viewModel.updateProfileImage(croppedImage)
}
dismiss(animated: true)
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
@objc private func cameraButtonTapped() {
let imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = true
present(imagePicker, animated: true)
}

private func cropToCircle(image: UIImage) -> UIImage {
Expand All @@ -117,4 +92,20 @@ extension ProfileSetupViewController: UIImagePickerControllerDelegate, UINavigat
return circleImage
}
}

extension ProfileSetupViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]
) {
if let editedImage = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {
let croppedImage = cropToCircle(image: editedImage)
viewModel.updateProfileImage(croppedImage)
}
dismiss(animated: true)
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,13 @@

import UIKit

import RxSwift
import RxCocoa
import Moya

class ProfileSetupViewModel {
// Inputs
let updateProfileImageTrigger = PublishSubject<Void>()

// Outputs
let profileImage = BehaviorRelay<UIImage?>(value: UIImage.imgProfile)
let isConfirmButtonEnabled = BehaviorRelay<Bool>(value: false)
let serverResponse = PublishSubject<String?>()
let uploadSuccess = PublishSubject<Void>()

let profileImage = ObservablePattern<UIImage?>(UIImage.imgProfile)
let isConfirmButtonEnabled = ObservablePattern<Bool>(false)
let nickname: String
private let disposeBag = DisposeBag()
private let provider = MoyaProvider<ProfileTargetType>()
let serverResponse = ObservablePattern<String?>(nil)

private let authService: AuthServiceType

init(nickname: String, authService: AuthServiceType = AuthService()) {
self.nickname = nickname
Expand All @@ -51,65 +41,18 @@ class ProfileSetupViewModel {
let fileName = "profile_image.jpg"
let mimeType = "image/jpeg"

updateProfileImageTrigger
.withLatestFrom(profileImage)
.flatMapLatest { [weak self] image -> Observable<Result<ResponseBodyDTO<EmptyModel>, Error>> in
guard let self = self, let image = image else { return .empty() }
return self.uploadProfileImage(image: image)
}
.subscribe(onNext: { [weak self] result in
switch result {
case .success(let response):
if response.success {
self?.serverResponse.onNext("프로필 이미지가 성공적으로 업로드되었습니다.")
self?.uploadSuccess.onNext(())
} else {
self?.serverResponse.onNext(response.error?.message ?? "알 수 없는 오류가 발생했습니다.")
}
case .failure(let error):
self?.serverResponse.onNext("네트워크 오류: \(error.localizedDescription)")
}
})
.disposed(by: disposeBag)
}

func updateProfileImage(_ image: UIImage?) {
profileImage.accept(image)
isConfirmButtonEnabled.accept(image != nil)
}

func uploadProfileImage() {
updateProfileImageTrigger.onNext(())
}

private func uploadProfileImage(image: UIImage) -> Observable<Result<ResponseBodyDTO<EmptyModel>, Error>> {
return Observable.create { [weak self] observer in
guard let self = self,
let imageData = image.jpegData(compressionQuality: 0.8) else {
observer.onNext(.failure(NSError(domain: "Image conversion failed", code: 0, userInfo: nil)))
observer.onCompleted()
return Disposables.create()
}

let fileName = "profile_image.jpg"
let mimeType = "image/jpeg"

self.provider.request(.updateProfileImage(image: imageData, fileName: fileName, mimeType: mimeType)) { result in
switch result {
case .success(let response):
do {
let decodedResponse = try JSONDecoder().decode(ResponseBodyDTO<EmptyModel>.self, from: response.data)
observer.onNext(.success(decodedResponse))
} catch {
observer.onNext(.failure(error))
}
case .failure(let error):
observer.onNext(.failure(error))
}
observer.onCompleted()
authService.performRequest(.updateProfileImage(image: imageData, fileName: fileName, mimeType: mimeType)) { [weak self] (result: Result<EmptyModel, NetworkError>) in
print("네트워크 요청 완료")
switch result {
case .success:
self?.serverResponse.value = "프로필 이미지가 성공적으로 업로드되었습니다."
print("프로필 이미지 업로드 성공")
completion(true)
case .failure(let error):
self?.serverResponse.value = error.message
print("프로필 이미지 업로드 실패: \(error.message)")
completion(false)
}

return Disposables.create()
}
}
}

0 comments on commit 364730c

Please sign in to comment.