diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/NottodoModalViewController.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewControllers/NottodoModalViewController.swift similarity index 70% rename from iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/NottodoModalViewController.swift rename to iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewControllers/NottodoModalViewController.swift index 6df688f8..70b926f6 100644 --- a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/NottodoModalViewController.swift +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewControllers/NottodoModalViewController.swift @@ -9,6 +9,7 @@ import UIKit import SnapKit import KakaoSDKUser import SafariServices +import Combine enum ViewType { case quit @@ -20,8 +21,12 @@ final class NottodoModalViewController: UIViewController { // MARK: - Properties - private weak var coordinator: MypageCoordinator? - + private let viewWillAppearSubject = PassthroughSubject() + private let modalViewControllerDismiss = PassthroughSubject() + private let safariDismiss = PassthroughSubject() + private let safariPresent = PassthroughSubject() + private var viewModel: any ModalViewModel + private var viewType: ViewType? = .quit { didSet { setUI() @@ -38,8 +43,8 @@ final class NottodoModalViewController: UIViewController { // MARK: - init - init(coordinator: MypageCoordinator) { - self.coordinator = coordinator + init(viewModel: some ModalViewModel) { + self.viewModel = viewModel super.init(nibName: nil, bundle: nil) } @@ -49,12 +54,19 @@ final class NottodoModalViewController: UIViewController { // MARK: - Life Cycle + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + viewWillAppearSubject.send(()) + } + override func viewDidLoad() { super.viewDidLoad() - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.AccountInfo.appearWithdrawalModal) + setUI() setLayout() setDelegate() + setBindings() } override func touchesBegan(_ touches: Set, with event: UIEvent?) { @@ -63,7 +75,7 @@ final class NottodoModalViewController: UIViewController { let location = touch.location(in: self.view) if !modalView.frame.contains(location) { - coordinator?.dismiss() + modalViewControllerDismiss.send(()) } } } @@ -96,6 +108,15 @@ extension NottodoModalViewController { withdrawView.delegate = self safariViewController.delegate = self } + + private func setBindings() { + let input = ModalViewModelInput(viewWillAppearSubject: viewWillAppearSubject, + modalDismiss: modalViewControllerDismiss, + safariDismiss: safariDismiss, + safariPresent: safariPresent) + + _ = viewModel.transform(input: input) + } } extension NottodoModalViewController: ModalDelegate { @@ -103,7 +124,7 @@ extension NottodoModalViewController: ModalDelegate { switch viewType { case .quitSurvey: self.present(safariViewController, animated: true) { - self.withdrawal() + self.safariPresent.send(()) } case .quit: viewType = .quitSurvey @@ -114,34 +135,13 @@ extension NottodoModalViewController: ModalDelegate { } func modalDismiss() { - coordinator?.dismiss() // 탈퇴 alert 취소 - } -} - -extension NottodoModalViewController { - func withdrawal() { - if !KeychainUtil.getBool(DefaultKeys.isAppleLogin) { - kakaoWithdrawal() - } - AuthService.shared.withdrawalAuth { _ in - AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.AccountInfo.completeWithdrawal) - } - } - - func kakaoWithdrawal() { - UserApi.shared.unlink {(error) in - if let error = error { - print(error) - } else { - print("unlink() success.") - } - } + modalViewControllerDismiss.send(()) } } extension NottodoModalViewController: SFSafariViewControllerDelegate { func safariViewControllerDidFinish(_ controller: SFSafariViewController) { controller.delegate = nil - coordinator?.connectAuthCoordinator(type: .quitSurvey) + safariDismiss.send(.quitSurvey) } } diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModel.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModel.swift new file mode 100644 index 00000000..967acfea --- /dev/null +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModel.swift @@ -0,0 +1,22 @@ +// +// ModalViewModel.swift +// iOS-NOTTODO +// +// Created by JEONGEUN KIM on 3/21/24. +// + +import Foundation +import Combine + +protocol ModalViewModelPresentable {} + +protocol ModalViewModel: ViewModel where Input == ModalViewModelInput, Output == ModalViewModelOutput {} + +struct ModalViewModelInput { + let viewWillAppearSubject: PassthroughSubject + let modalDismiss: PassthroughSubject + let safariDismiss: PassthroughSubject + let safariPresent: PassthroughSubject +} + +struct ModalViewModelOutput {} diff --git a/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModelImpl.swift b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModelImpl.swift new file mode 100644 index 00000000..f7dff969 --- /dev/null +++ b/iOS-NOTTODO/iOS-NOTTODO/Presentation/Common/Modal/ViewModel/ModalViewModelImpl.swift @@ -0,0 +1,59 @@ +// +// ModalViewModelImpl.swift +// iOS-NOTTODO +// +// Created by JEONGEUN KIM on 3/21/24. +// + +import Foundation +import Combine + +final class ModalViewModelImpl: ModalViewModel { + + private weak var coordinator: MypageCoordinator? + private var manager: MyPageManger + private var cancelBag = Set() + + init(coordinator: MypageCoordinator, manager: MyPageManger) { + self.coordinator = coordinator + self.manager = manager + } + + func transform(input: ModalViewModelInput) -> ModalViewModelOutput { + + input.viewWillAppearSubject + .sink { _ in + AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.AccountInfo.appearWithdrawalModal) + } + .store(in: &cancelBag) + + input.modalDismiss + .sink { [weak self] _ in + self?.coordinator?.dismiss() + } + .store(in: &cancelBag) + + input.safariDismiss + .sink { [weak self] type in + self?.coordinator?.connectAuthCoordinator(type: type) + } + .store(in: &cancelBag) + + input.safariPresent + .sink { [weak self] _ in + self?.withdrawal() + } + .store(in: &cancelBag) + return Output() + } + + func withdrawal() { + manager.withdrawl() + .sink(receiveCompletion: { event in + print("completion: \(event)") + }, receiveValue: { _ in + AmplitudeAnalyticsService.shared.send(event: AnalyticsEvent.AccountInfo.completeWithdrawal) + }) + .store(in: &cancelBag) + } +}