From fa80b69822fa600be5bd176e131fbf54a2d41c06 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Sun, 6 Oct 2024 10:48:14 +0900 Subject: [PATCH 01/11] =?UTF-8?q?[IDLE-409]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C=20=EB=B0=8F=20Coordi?= =?UTF-8?q?nator=ED=83=80=EC=9E=85=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RemoteNotification/FCMService.swift | 1 - .../CommonUI/TabBar/IdleTabBarProto.swift | 170 ------------------ .../AccountDeregisterCoordinator.swift | 2 +- .../Auth/Sources/AuthCoordinator.swift | 2 +- .../CenterAccountRegisterCoordinator.swift | 2 +- .../CenterSetupNewPasswordCoordinator.swift | 2 +- .../WorkerAccountRegisterCoordinator.swift | 2 +- .../ExampleApp/Sources/ViewController.swift | 4 - .../DefaultLoadingVC.swift | 0 .../Sources/Coordinator/BaseCoordinator.swift | 20 +-- .../Sources/Coordinator/Coordinator.swift | 16 ++ .../Sources/DeepLink/DeepLinkExecutable.swift | 2 +- .../MakeCenterProfilePageCoordinator.swift | 2 +- .../WaitCertificatePageCoordinator.swift | 2 +- .../PostApplicantPageCoordinator.swift | 2 +- .../PostBoardPageViewModel.swift | 6 +- .../CreatePostCoordinator.swift | 2 +- .../PostDetailForWorkerCoodinator.swift | 2 +- .../ExampleApp/Sources/SceneDelegate.swift | 2 - .../Sources/Application/AppCoordinator.swift | 2 +- .../CenterProfileCoordinator.swift | 2 +- .../WorkerMyProfileCoordinator.swift | 2 +- .../WorkerProfileCoordinator.swift | 2 +- .../ScreenCoordinating/Coordinator.swift | 101 ----------- .../CoordinatorWrapper.swift | 39 ---- .../Interface/Auth/AuthCoordinatable.swift | 25 --- .../Interface/Auth/CanterLoginFlowable.swift | 14 -- .../Auth/CenterAuthCoordinatable.swift | 15 -- .../Auth/WorkerAuthCoordinatable.swift | 14 -- .../Main/CenterMainCoordinatable.swift | 12 -- .../CenterProfileRegisterCoordinatable.swift | 17 -- .../Center/CenterPostBoardCoordinatable.swift | 15 -- .../RecruitmentManagementCoordinatable.swift | 17 -- ...RegisterRecruitmentPostCoordinatable.swift | 16 -- .../WorkerRecruitmentBoardCoordinatable.swift | 21 --- .../Interface/Root/RootCoorinatable.swift | 17 -- .../Setting/CenterSettingCoordinatable.swift | 16 -- .../Deregister/DeregisterCoordinatable.swift | 27 --- .../WorkerSettingScreenCoordinatable.swift | 16 -- .../CoordinatingNotifications.swift | 13 -- .../RecruitmentPostNotifications.swift | 13 -- 41 files changed, 41 insertions(+), 616 deletions(-) delete mode 100644 project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift rename project/Projects/Presentation/Feature/Base/Sources/BaseVC/{Loading => LoadingVC}/DefaultLoadingVC.swift (100%) create mode 100644 project/Projects/Presentation/Feature/Base/Sources/Coordinator/Coordinator.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Coordinator.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/CoordinatorWrapper.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/AuthCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CanterLoginFlowable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CenterAuthCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/WorkerAuthCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Main/CenterMainCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Profile/CenterProfileRegisterCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/CenterPostBoardCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RecruitmentManagementCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RegisterRecruitmentPostCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Worker/WorkerRecruitmentBoardCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Root/RootCoorinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/CenterSettingCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/Deregister/DeregisterCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/WorkerSettingScreenCoordinatable.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/CoordinatingNotifications.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/RecruitmentPostNotifications.swift diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index a1a3a021..238d572d 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -7,7 +7,6 @@ import Foundation import BaseFeature -import PresentationCore import Domain import Core diff --git a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift b/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift deleted file mode 100644 index 99c407c2..00000000 --- a/project/Projects/Presentation/DSKit/Sources/CommonUI/TabBar/IdleTabBarProto.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// IdleTabBarProto.swift -// PresentationCore -// -// Created by choijunios on 7/25/24. -// - -import UIKit -import RxSwift -import RxCocoa -import PresentationCore - -public class IdleTabBarProto: UIViewController { - - // Coordinator - public weak var coordinator: ParentCoordinator? - - // 탭바구성 - public private(set) var viewControllers: [UIViewController] = [] - private var tabBarItems: [IdleTabBarItemProto] = [] - - // View - var tabBarItemStack: UIView! - - // 탭바 아이템 - private var tabBarItemViews: [IdleTabBarItemViewable] = [] - - private var currentIndex: Int = -1 - - public var selectedIndex: Int { - get { - currentIndex - } - set { - moveTo(index: newValue) - currentIndex = newValue - } - } - - private let disposeBag = DisposeBag() - - public init() { - - super.init(nibName: nil, bundle: nil) - - setAppearance() - } - - public required init?(coder: NSCoder) { fatalError() } - - /// 생성시 한번만 호출해야 합니다. - public func setViewControllers(info: [TabBarInfo]) { - - viewControllers = [] - tabBarItems = [] - - info.forEach { - viewControllers.append($0.viewController) - tabBarItems.append($0.tabBarItem) - } - - // 뷰컨트롤러들 추가 - viewControllers - .forEach { - self.addChild($0) - $0.didMove(toParent: self) - } - - setTabBarItems() - } - - private func setTabBarItems() { - - tabBarItemViews = tabBarItems.map { item in - TextButtonType1(labelText: item.name) - } - - let tabBarItemStack = HStack( - tabBarItemViews, - alignment: .fill, - distribution: .fillEqually - ) - - self.tabBarItemStack = tabBarItemStack - - view.addSubview(tabBarItemStack) - tabBarItemStack.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - tabBarItemStack.topAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor), - tabBarItemStack.leadingAnchor.constraint(equalTo: view.leadingAnchor), - tabBarItemStack.trailingAnchor.constraint(equalTo: view.trailingAnchor), - tabBarItemStack.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) - ]) - - setTabBarItemObservable() - } - - private func setTabBarItemObservable() { - - let observers = tabBarItemViews.enumerated().map { (index, element) in - element.eventPublisher.map { _ in index } - } - - Observable - .merge(observers) - .asDriver(onErrorJustReturn: 0) - .drive(onNext: { [weak self] index in - self?.selectedIndex = index - }) - .disposed(by: disposeBag) - } - - private func moveTo(index: Int) { - - if currentIndex == index { return } - - if currentIndex != -1 { - let prevVC = viewControllers[currentIndex] - prevVC.view.removeFromSuperview() - } - - let currentVC = viewControllers[index] - view.addSubview(currentVC.view) - currentVC.view.translatesAutoresizingMaskIntoConstraints = false - - let currentView = currentVC.view! - - NSLayoutConstraint.activate([ - currentView.topAnchor.constraint(equalTo: view.topAnchor), - currentView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - currentView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - currentView.bottomAnchor.constraint(equalTo: tabBarItemStack.topAnchor) - ]) - } - - // MARK: ViewController 세팅 - private func setAppearance() { - - view.backgroundColor = .white - view.layoutMargins = .init(top: 0, left: 0, bottom: 56, right: 0) - } -} - -// 임시적 세팅 -extension TextButtonType1: IdleTabBarItemViewable { } - -// 임시적 세팅 -public protocol IdleTabBarItemViewable: UIView { - var eventPublisher: Observable { get } -} - - -public struct IdleTabBarItemProto { - let name: String - - public init(name: String) { - self.name = name - } -} - -public struct TabBarInfo { - let viewController: UIViewController - let tabBarItem: IdleTabBarItemProto - - public init(viewController: UIViewController, tabBarItem: IdleTabBarItemProto) { - self.viewController = viewController - self.tabBarItem = tabBarItem - } -} diff --git a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AccountDeregisterCoordinator.swift b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AccountDeregisterCoordinator.swift index f936467c..c78965d7 100644 --- a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AccountDeregisterCoordinator.swift +++ b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AccountDeregisterCoordinator.swift @@ -13,7 +13,7 @@ public enum AccountDeregisterCoordinatorDestination { case accountAuthFlow } -public class AccountDeregisterCoordinator: Coordinator2 { +public class AccountDeregisterCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/Auth/Sources/AuthCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/AuthCoordinator.swift index 869aea32..13b8492e 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/AuthCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/AuthCoordinator.swift @@ -15,7 +15,7 @@ public enum AuthCoordinatorDestination { case loginPage } -public class AuthCoordinator: Coordinator2 { +public class AuthCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterCoordinator.swift index e0d04596..8c3cdd82 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterCoordinator.swift @@ -41,7 +41,7 @@ public enum CenterAccountRegisterCoordinatorDestination { case centerMainPage } -public class CenterAccountRegisterCoordinator: Coordinator2 { +public class CenterAccountRegisterCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Center/SetNewPassword/CenterSetupNewPasswordCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Center/SetNewPassword/CenterSetupNewPasswordCoordinator.swift index ef7977c7..c62d846c 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Center/SetNewPassword/CenterSetupNewPasswordCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Center/SetNewPassword/CenterSetupNewPasswordCoordinator.swift @@ -19,7 +19,7 @@ enum SetNewPasswordStage: Int { case finish } -public class CenterSetupNewPasswordCoordinator: Coordinator2 { +public class CenterSetupNewPasswordCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Worker/WorkerAccountRegisterCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Worker/WorkerAccountRegisterCoordinator.swift index 4c7fdda4..d7462861 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Worker/WorkerAccountRegisterCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Worker/WorkerAccountRegisterCoordinator.swift @@ -38,7 +38,7 @@ public enum WorkerAccountRegisterCoordinatorDestination { case workerMainPage } -public class WorkerAccountRegisterCoordinator: Coordinator2 { +public class WorkerAccountRegisterCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/Base/ExampleApp/Sources/ViewController.swift b/project/Projects/Presentation/Feature/Base/ExampleApp/Sources/ViewController.swift index c04d8514..25750709 100644 --- a/project/Projects/Presentation/Feature/Base/ExampleApp/Sources/ViewController.swift +++ b/project/Projects/Presentation/Feature/Base/ExampleApp/Sources/ViewController.swift @@ -30,10 +30,6 @@ class ViewController: BaseViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - - self.viewModel? - .snackBar - .onNext(.init(titleText: "테스트테스트테스트")) } } diff --git a/project/Projects/Presentation/Feature/Base/Sources/BaseVC/Loading/DefaultLoadingVC.swift b/project/Projects/Presentation/Feature/Base/Sources/BaseVC/LoadingVC/DefaultLoadingVC.swift similarity index 100% rename from project/Projects/Presentation/Feature/Base/Sources/BaseVC/Loading/DefaultLoadingVC.swift rename to project/Projects/Presentation/Feature/Base/Sources/BaseVC/LoadingVC/DefaultLoadingVC.swift diff --git a/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift index 83a6b190..9715519b 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift @@ -7,35 +7,25 @@ import Foundation - -public protocol Coordinator2: AnyObject { - - var onFinish: (() -> ())? { get set } - - /// Coordinator를 시작한다. - func start() -} - - /// 자식 코디네이터를 가질 수 있는 코디네이터 -open class BaseCoordinator: Coordinator2 { +open class BaseCoordinator: Coordinator { public var onFinish: (() -> ())? - var children: [Coordinator2] = [] + var children: [Coordinator] = [] - public init(children: [Coordinator2] = []) { + public init(children: [Coordinator] = []) { self.children = children } open func start() { } - public func addChild(_ coordinator: Coordinator2) { + public func addChild(_ coordinator: Coordinator) { children.append(coordinator) } - public func removeChild(_ coordinator: Coordinator2) { + public func removeChild(_ coordinator: Coordinator) { children.removeAll { $0 === coordinator} } } diff --git a/project/Projects/Presentation/Feature/Base/Sources/Coordinator/Coordinator.swift b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/Coordinator.swift new file mode 100644 index 00000000..ee393269 --- /dev/null +++ b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/Coordinator.swift @@ -0,0 +1,16 @@ +// +// Coordinator.swift +// BaseFeature +// +// Created by choijunios on 10/6/24. +// + +import Foundation + +public protocol Coordinator: AnyObject { + + var onFinish: (() -> ())? { get set } + + /// Coordinator를 시작한다. + func start() +} diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift index 17ee5ec5..db8b2036 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift @@ -18,7 +18,7 @@ public protocol DeepLinkTreeNode { public protocol DeepLinkExecutable: DeepLinkTreeNode { @discardableResult - func execute(with coordinator: Coordinator2, userInfo: [String: String]?) -> Coordinator2? + func execute(with coordinator: Coordinator, userInfo: [String: String]?) -> Coordinator? } extension DeepLinkExecutable { diff --git a/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/MakeProfile/MakeCenterProfilePageCoordinator.swift b/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/MakeProfile/MakeCenterProfilePageCoordinator.swift index 028ea837..03ef67f1 100644 --- a/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/MakeProfile/MakeCenterProfilePageCoordinator.swift +++ b/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/MakeProfile/MakeCenterProfilePageCoordinator.swift @@ -15,7 +15,7 @@ public enum MakeCenterProfilePageCoordinatorDestination { case authFlow } -public class MakeCenterProfilePageCoordinator: Coordinator2 { +public class MakeCenterProfilePageCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/WaitCertificatePage/WaitCertificatePageCoordinator.swift b/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/WaitCertificatePage/WaitCertificatePageCoordinator.swift index 0ed2b0f7..cacda336 100644 --- a/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/WaitCertificatePage/WaitCertificatePageCoordinator.swift +++ b/project/Projects/Presentation/Feature/CenterCetificatePage/Sources/WaitCertificatePage/WaitCertificatePageCoordinator.swift @@ -15,7 +15,7 @@ public enum WaitCertificatePageCoordinatorDestination { case makeProfileFlow } -public class WaitCertificatePageCoordinator: Coordinator2 { +public class WaitCertificatePageCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostApplicantPage/PostApplicantPageCoordinator.swift b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostApplicantPage/PostApplicantPageCoordinator.swift index 07dcb58c..ecbf6226 100644 --- a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostApplicantPage/PostApplicantPageCoordinator.swift +++ b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostApplicantPage/PostApplicantPageCoordinator.swift @@ -14,7 +14,7 @@ enum PostApplicantPageCoordinatorDestination { case applicantDetail(id: String) } -class PostApplicantPageCoordinator: Coordinator2 { +class PostApplicantPageCoordinator: Coordinator { var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostBoardPage/PostBoardPageViewModel.swift b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostBoardPage/PostBoardPageViewModel.swift index 04f5038e..159e74f0 100644 --- a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostBoardPage/PostBoardPageViewModel.swift +++ b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostBoardPage/PostBoardPageViewModel.swift @@ -1,6 +1,6 @@ // // CenterRecruitmentPostBoardVM.swift -// CenterFeature +// CenterMainPageFeature // // Created by choijunios on 8/13/24. // @@ -263,3 +263,7 @@ class CenterEmployCardVM: CenterEmployCardViewModelable { .disposed(by: disposeBag) } } + +extension Notification.Name { + static let removePostRequestFromCell: Notification.Name = .init("removePostRequestFromCell") +} diff --git a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostRegisterPage/CreatePostCoordinator.swift b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostRegisterPage/CreatePostCoordinator.swift index 51294f6e..49dbacfa 100644 --- a/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostRegisterPage/CreatePostCoordinator.swift +++ b/project/Projects/Presentation/Feature/CenterMainPage/Sources/PostRegisterPage/CreatePostCoordinator.swift @@ -11,7 +11,7 @@ import Domain import BaseFeature import Core -public class CreatePostCoordinator: Coordinator2 { +public class CreatePostCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/PostDetailForWorker/Sources/RecruitmentPost/PostDetailForWorkerCoodinator.swift b/project/Projects/Presentation/Feature/PostDetailForWorker/Sources/RecruitmentPost/PostDetailForWorkerCoodinator.swift index 168156bc..06294ffc 100644 --- a/project/Projects/Presentation/Feature/PostDetailForWorker/Sources/RecruitmentPost/PostDetailForWorkerCoodinator.swift +++ b/project/Projects/Presentation/Feature/PostDetailForWorker/Sources/RecruitmentPost/PostDetailForWorkerCoodinator.swift @@ -14,7 +14,7 @@ public enum PostDetailForWorkerCoodinatorDestination { case centerProfile(mode: ProfileMode) } -public class PostDetailForWorkerCoodinator: Coordinator2 { +public class PostDetailForWorkerCoodinator: Coordinator { public var startFlow: ((PostDetailForWorkerCoodinatorDestination) -> ())! diff --git a/project/Projects/Presentation/Feature/Root/ExampleApp/Sources/SceneDelegate.swift b/project/Projects/Presentation/Feature/Root/ExampleApp/Sources/SceneDelegate.swift index 6c0a2ac2..3339b518 100644 --- a/project/Projects/Presentation/Feature/Root/ExampleApp/Sources/SceneDelegate.swift +++ b/project/Projects/Presentation/Feature/Root/ExampleApp/Sources/SceneDelegate.swift @@ -12,8 +12,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - var coordinator: DeRegisterCoordinator! - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } diff --git a/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift b/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift index c314fe9f..da4a0986 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift @@ -36,7 +36,7 @@ public class AppCoordinator: BaseCoordinator { extension AppCoordinator { - func executeChild(_ coordinator: Coordinator2) { + func executeChild(_ coordinator: Coordinator) { coordinator.onFinish = { [weak self, weak coordinator] in if let coordinator { self?.removeChild(coordinator) diff --git a/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileCoordinator.swift b/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileCoordinator.swift index 309a8c2b..8e36c070 100644 --- a/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileCoordinator.swift +++ b/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileCoordinator.swift @@ -11,7 +11,7 @@ import BaseFeature import Domain /// 내센터, 다른 센터를 모두 불러올 수 있습니다. -public class CenterProfileCoordinator: Coordinator2 { +public class CenterProfileCoordinator: Coordinator { public var onFinish: (() -> ())? diff --git a/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerMyProfileCoordinator.swift b/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerMyProfileCoordinator.swift index a9e6f4e1..4cd31864 100644 --- a/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerMyProfileCoordinator.swift +++ b/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerMyProfileCoordinator.swift @@ -8,7 +8,7 @@ import Foundation import BaseFeature -public class WorkerMyProfileCoordinator: Coordinator2 { +public class WorkerMyProfileCoordinator: Coordinator { public var onFinish: (() -> ())? let router: Router diff --git a/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerProfileCoordinator.swift b/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerProfileCoordinator.swift index 1cc1940b..5ccb1031 100644 --- a/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerProfileCoordinator.swift +++ b/project/Projects/Presentation/Feature/UserProfile/Sources/WorkerProfile/WorkerProfileCoordinator.swift @@ -10,7 +10,7 @@ import BaseFeature import Domain import Core -public class WorkerProfileCoordinator: Coordinator2 { +public class WorkerProfileCoordinator: Coordinator { public var onFinish: (() -> ())? let router: Router diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Coordinator.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Coordinator.swift deleted file mode 100644 index 8909325f..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Coordinator.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// Coordinator.swift -// PresentationCore -// -// Created by 최준영 on 6/21/24. -// - -import UIKit -import Core - -// MARK: Coordinator -public protocol Coordinator: AnyObject { - - var parent: ParentCoordinator? { get set } - var navigationController: UINavigationController { get } - - func start() - func popViewController(animated: Bool) -} - -public extension Coordinator { - - func popViewController(animated: Bool = true) { - navigationController.popViewController(animated: animated) - } -} - -// MARK: ParentCoordinator -public protocol ParentCoordinator: Coordinator { - - var childCoordinators: [Coordinator] { get set } - - func addChildCoordinator(_ coordinator: Coordinator) - func removeChildCoordinator(_ coordinator: Coordinator) - - func clearChildren() -} - -public extension ParentCoordinator { - - func addChildCoordinator(_ coordinator: Coordinator) { - childCoordinators.append(coordinator) - coordinator.parent = self - } - - func removeChildCoordinator(_ coordinator: Coordinator) { - childCoordinators = childCoordinators.filter { $0 !== coordinator } - } - - func clearChildren() { - - printIfDebug(self, childCoordinators, navigationController.viewControllers) - - let lastCoordinator = childCoordinators.popLast() - - var middleViewControllers: [UIViewController?] = [] - - childCoordinators.reversed().forEach { coordinator in - - if coordinator is ChildCoordinator { - - let child = coordinator as! ChildCoordinator - - if let middleViewController = child.viewControllerRef { - - middleViewControllers.append(middleViewController) - } - - self.removeChildCoordinator(child) - } - } - - navigationController.viewControllers = navigationController.viewControllers.filter({ viewController in - !middleViewControllers.contains(where: { $0 === viewController }) - }) - - if lastCoordinator is ParentCoordinator { - - (lastCoordinator as! ParentCoordinator).clearChildren() - - } else { - - if let lastCoordinator { - - self.removeChildCoordinator(lastCoordinator) - lastCoordinator.popViewController() - } - } - - print("종료", self, childCoordinators, navigationController.viewControllers) - } -} - -// MARK: ChildCoordinator -public protocol ChildCoordinator: Coordinator { - - var viewControllerRef: UIViewController? { get } - - func coordinatorDidFinish() -} - diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/CoordinatorWrapper.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/CoordinatorWrapper.swift deleted file mode 100644 index cd607f79..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/CoordinatorWrapper.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// CoordinatorWrapper.swift -// PresentationCore -// -// Created by choijunios on 8/29/24. -// - -import UIKit - - -public class CoordinatorWrapper: ChildCoordinator { - - public weak var viewControllerRef: UIViewController? - public weak var parent: ParentCoordinator? - - public let navigationController: UINavigationController - - let animated: Bool - - public init( - nav: UINavigationController, - vc: UIViewController, - animated: Bool = true - ) { - self.navigationController = nav - self.viewControllerRef = vc - self.animated = animated - } - - public func start() { - navigationController.pushViewController(viewControllerRef!, animated: animated) - } - - public func coordinatorDidFinish() { - popViewController() - parent?.removeChildCoordinator(self) - } -} - diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/AuthCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/AuthCoordinatable.swift deleted file mode 100644 index 75894939..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/AuthCoordinatable.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// AuthCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 7/1/24. -// - -import Foundation - -public enum AuthType { - - case worker - case center -} - -public protocol AuthCoordinatable: ParentCoordinator { - - func authFinished() - func showCompleteScreen(ro: AnonymousCompleteVCRenderObject) - func registerAsWorker() - func registerAsCenter() - func startCenterLoginFlow() -} - - diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CanterLoginFlowable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CanterLoginFlowable.swift deleted file mode 100644 index 31f371a6..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CanterLoginFlowable.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// CanterLoginFlowable.swift -// PresentationCore -// -// Created by choijunios on 8/27/24. -// - -import Foundation - -public protocol CanterLoginFlowable: ParentCoordinator { - func login() - func setNewPassword() - func authFinished() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CenterAuthCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CenterAuthCoordinatable.swift deleted file mode 100644 index bfe5bda2..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/CenterAuthCoordinatable.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// CenterAuthCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 7/1/24. -// - -import Foundation - -public protocol CanterLoginCoordinatable: ParentCoordinator { - - func login() - func setNewPassword() - func authFinished() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/WorkerAuthCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/WorkerAuthCoordinatable.swift deleted file mode 100644 index 96c39c08..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Auth/WorkerAuthCoordinatable.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// WorkerAuthCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 7/1/24. -// - -import Foundation - -public protocol WorkerAuthCoordinatable: ParentCoordinator { - - func register() - func authFinished() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Main/CenterMainCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Main/CenterMainCoordinatable.swift deleted file mode 100644 index 7fdb10a3..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Main/CenterMainCoordinatable.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// CenterMainCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 7/27/24. -// - -import Foundation - -public protocol CenterMainCoordinatable: ParentCoordinator { - -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Profile/CenterProfileRegisterCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Profile/CenterProfileRegisterCoordinatable.swift deleted file mode 100644 index 55a7ebb2..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Profile/CenterProfileRegisterCoordinatable.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// CenterProfileRegisterCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 7/27/24. -// - -import Foundation -import Domain - - -public protocol CenterProfileRegisterCoordinatable: ParentCoordinator { - - func registerFinished() - func showPreviewScreen(stateObject: CenterProfileRegisterState) - func showCompleteScreen() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/CenterPostBoardCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/CenterPostBoardCoordinatable.swift deleted file mode 100644 index ea8a3374..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/CenterPostBoardCoordinatable.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// CenterPostBoardCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/13/24. -// - -import Foundation - -public protocol CenterPostBoardTabCoordinatable: ParentCoordinator { - - func showApplicantScreen() - func postDetailScreen() - func showPostEditScreen() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RecruitmentManagementCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RecruitmentManagementCoordinatable.swift deleted file mode 100644 index f975524f..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RecruitmentManagementCoordinatable.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// RecruitmentManagementCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/13/24. -// - -import Domain - - -public protocol RecruitmentManagementCoordinatable: ParentCoordinator { - - func showCheckingApplicantScreen(postId: String) - func showPostDetailScreenForCenter(postId: String, postState: PostState) - func showEditScreen(postId: String) - func showRegisterPostScrean() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RegisterRecruitmentPostCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RegisterRecruitmentPostCoordinatable.swift deleted file mode 100644 index 9cf386f9..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Center/RegisterRecruitmentPostCoordinatable.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// RegisterRecruitmentPostCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/5/24. -// - -import Foundation - -public protocol RegisterRecruitmentPostCoordinatable: ParentCoordinator { - - func showOverViewScreen() - func showEditPostScreen() - func showRegisterCompleteScreen() - func registerFinished() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Worker/WorkerRecruitmentBoardCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Worker/WorkerRecruitmentBoardCoordinatable.swift deleted file mode 100644 index f54ffff6..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/RecruitmentPost/Worker/WorkerRecruitmentBoardCoordinatable.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// WorkerRecruitmentBoardCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/15/24. -// - -import Foundation -import Domain - - -public protocol WorkerRecruitmentBoardCoordinatable: ParentCoordinator { - /// 요양보호사가 볼 수 있는 공고 상세정보를 표시합니다. - func showPostDetail(postInfo: RecruitmentPostInfo) - - /// 센터 프로필을 표시합니다. - func showCenterProfile(centerId: String) - - /// 요양보호사의 프로필을 표시합니다. - func showWorkerProfile() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Root/RootCoorinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Root/RootCoorinatable.swift deleted file mode 100644 index effd5d48..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Root/RootCoorinatable.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// asd.swift -// PresentationCore -// -// Created by choijunios on 8/25/24. -// - -import Foundation - -public protocol RootCoorinatable: ParentCoordinator { - func auth() - func centerAuth() - func workerMain() - func centerMain() - func makeCenterProfile() - func popToRoot() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/CenterSettingCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/CenterSettingCoordinatable.swift deleted file mode 100644 index f982d60a..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/CenterSettingCoordinatable.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// CenterSettingCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/25/24. -// - -import Foundation - -public protocol CenterSettingCoordinatable: ParentCoordinator { - /// 시설 관리자 계정을 지우는 작업을 시작합니다. - func startRemoveCenterAccountFlow() - - /// 현재 센터 프로필을 표시합니다. - func showMyCenterProfile() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/Deregister/DeregisterCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/Deregister/DeregisterCoordinatable.swift deleted file mode 100644 index 17089d71..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/Deregister/DeregisterCoordinatable.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// asd.swift -// PresentationCore -// -// Created by choijunios on 8/25/24. -// - -import Foundation - - -public protocol DeregisterCoordinatable: ParentCoordinator { - - /// 공통: 탈퇴 이유를 선택합니다. - func showSelectReasonScreen() - - /// 공통: 탈퇴를 취소합니다. - func cancelDeregister() - - /// 센터관리자: 마지막으로 비밀번호를 입력합니다. - func showFinalPasswordScreen(reasons: [String]) - - /// 요양보호사: 마지막으로 전화번호를 입력합니다. - func showFinalPhoneAuthScreen(reasons: [String]) - - /// 최초화면으로 돌아갑니다. - func popToRoot() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/WorkerSettingScreenCoordinatable.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/WorkerSettingScreenCoordinatable.swift deleted file mode 100644 index 5d3ef1a2..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Interface/Setting/WorkerSettingScreenCoordinatable.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// WorkerSettingScreenCoordinatable.swift -// PresentationCore -// -// Created by choijunios on 8/25/24. -// - -import Foundation - -public protocol WorkerSettingScreenCoordinatable: ParentCoordinator { - /// 요양보호사 계정을 지우는 작업을 시작합니다. - func startRemoveWorkerAccountFlow() - - /// 요양보호사 프로필을 열람합니다. - func showMyProfileScreen() -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/CoordinatingNotifications.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/CoordinatingNotifications.swift deleted file mode 100644 index a10550e3..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/CoordinatingNotifications.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// CoordinatingNotifications.swift -// PresentationCore -// -// Created by choijunios on 8/25/24. -// - -import Foundation - -public extension Notification.Name { - - static let popToInitialVC: Notification.Name = .init("popToInitialVC") -} diff --git a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/RecruitmentPostNotifications.swift b/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/RecruitmentPostNotifications.swift deleted file mode 100644 index b6e0d67e..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/ScreenCoordinating/Notification/RecruitmentPostNotifications.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// RecruitmentPost.swift -// PresentationCore -// -// Created by choijunios on 8/29/24. -// - -import Foundation - -public extension Notification.Name { - - static let removePostRequestFromCell: Notification.Name = .init("removePostRequestFromCell") -} From a3be3a908072609e74d8f50331b7bd7dec2c3b18 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 11:21:00 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[IDLE-409]=20NotificationTokenAPI?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Resources/GoogleService-Info.plist | 12 ++-- .../RemoteNotification/FCMService.swift | 8 +-- .../Data/DataSource/API/BaseAPI.swift | 3 + .../DataSource/API/NotificationTokenAPI.swift | 62 +++++++++++++++++++ .../{Cache => }/CacheRepository.swift | 0 ...DefaultAuthInputValidationRepository.swift | 0 .../{Auth => }/DefaultAuthRepository.swift | 0 .../DefaultRecruitmentPostRepository.swift | 0 .../DefaultUserInfoLocalRepository.swift | 0 .../DefaultUserProfileRepository.swift | 0 ... => DefaultNotificationTokenUseCase.swift} | 6 +- ...e.swift => NotificationTokenUseCase.swift} | 4 +- .../RemoteNotification.swift | 0 13 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 project/Projects/Data/DataSource/API/NotificationTokenAPI.swift rename project/Projects/Data/Repository/{Cache => }/CacheRepository.swift (100%) rename project/Projects/Data/Repository/{Auth => }/DefaultAuthInputValidationRepository.swift (100%) rename project/Projects/Data/Repository/{Auth => }/DefaultAuthRepository.swift (100%) rename project/Projects/Data/Repository/{RecruitmentPost => }/DefaultRecruitmentPostRepository.swift (100%) rename project/Projects/Data/Repository/{UserInfo => }/DefaultUserInfoLocalRepository.swift (100%) rename project/Projects/Data/Repository/{UserInfo => }/DefaultUserProfileRepository.swift (100%) rename project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/{DefaultNotificationTokenManage.swift => DefaultNotificationTokenUseCase.swift} (79%) rename project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/{NotificationTokenManage.swift => NotificationTokenUseCase.swift} (84%) rename project/Projects/Presentation/PresentationCore/Sources/{ => Extensions}/NotificationName+Extension/RemoteNotification.swift (100%) diff --git a/project/Projects/App/Resources/GoogleService-Info.plist b/project/Projects/App/Resources/GoogleService-Info.plist index e902d244..35260fe6 100644 --- a/project/Projects/App/Resources/GoogleService-Info.plist +++ b/project/Projects/App/Resources/GoogleService-Info.plist @@ -15,16 +15,16 @@ STORAGE_BUCKET swm-3idiots.appspot.com IS_ADS_ENABLED - + IS_ANALYTICS_ENABLED - + IS_APPINVITE_ENABLED - + IS_GCM_ENABLED - + IS_SIGNIN_ENABLED - + GOOGLE_APP_ID 1:740246202578:ios:d5e59f4f2116f92342250b - \ No newline at end of file + diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index 238d572d..a3c89140 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -36,11 +36,10 @@ class FCMService: NSObject { if let token = Messaging.messaging().fcmToken { - notificationTokenManageUseCase.setNotificationToken( - token: token) { result in + notificationTokenManageUseCase.setNotificationToken(token: token) { result in - print("FCMService 토큰 전송 \(result ? "완료" : "실패")") - } + print("FCMService 토큰 전송 \(result ? "완료" : "실패")") + } } } @@ -67,7 +66,6 @@ extension FCMService: MessagingDelegate { print("FCM토큰: \(fcmToken)") notificationTokenManageUseCase.setNotificationToken(token: fcmToken) { isSuccess in - print(isSuccess ? "토큰 전송 성공" : "토큰 전송 실패") } } diff --git a/project/Projects/Data/DataSource/API/BaseAPI.swift b/project/Projects/Data/DataSource/API/BaseAPI.swift index 6e0e2cb7..3c16127e 100644 --- a/project/Projects/Data/DataSource/API/BaseAPI.swift +++ b/project/Projects/Data/DataSource/API/BaseAPI.swift @@ -16,6 +16,7 @@ public enum APIType { case crawling_job_postings case external(url: String) case applys + case notificationToken } // MARK: BaseAPI @@ -43,6 +44,8 @@ public extension BaseAPI { baseStr += "/applys" case .external(let url): baseStr = url + case .notificationToken: + baseStr += "/fcm" } return URL(string: baseStr)! diff --git a/project/Projects/Data/DataSource/API/NotificationTokenAPI.swift b/project/Projects/Data/DataSource/API/NotificationTokenAPI.swift new file mode 100644 index 00000000..7be6452e --- /dev/null +++ b/project/Projects/Data/DataSource/API/NotificationTokenAPI.swift @@ -0,0 +1,62 @@ +// +// NotificationTokenAPI.swift +// DataSource +// +// Created by choijunios on 10/8/24. +// + +import Foundation +import Moya + +public enum NotificationTokenAPI { + case saveToken(deviceToken: String, userType: String) + case deleteToken(deviceToken: String) +} + +extension NotificationTokenAPI: BaseAPI { + + public var apiType: APIType { + .notificationToken + } + + public var path: String { + switch self { + case .saveToken(let deviceToken, let userType): + "token" + case .deleteToken(let deviceToken): + "token" + } + } + + public var method: Moya.Method { + switch self { + case .saveToken: + .post + case .deleteToken: + .delete + } + } + + var parameterEncoding: ParameterEncoding { + switch self { + default: + return JSONEncoding.default + } + } + + public var task: Moya.Task { + switch self { + case .saveToken(let deviceToken, let userType): + var bodyData: [String: String] = [ + "deviceToken": deviceToken, + "userType": userType + ] + return .requestParameters(parameters: bodyData, encoding: parameterEncoding) + case .deleteToken(let deviceToken): + var bodyData: [String: String] = [ + "deviceToken": deviceToken + ] + return .requestParameters(parameters: bodyData, encoding: parameterEncoding) + } + } +} diff --git a/project/Projects/Data/Repository/Cache/CacheRepository.swift b/project/Projects/Data/Repository/CacheRepository.swift similarity index 100% rename from project/Projects/Data/Repository/Cache/CacheRepository.swift rename to project/Projects/Data/Repository/CacheRepository.swift diff --git a/project/Projects/Data/Repository/Auth/DefaultAuthInputValidationRepository.swift b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift similarity index 100% rename from project/Projects/Data/Repository/Auth/DefaultAuthInputValidationRepository.swift rename to project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift diff --git a/project/Projects/Data/Repository/Auth/DefaultAuthRepository.swift b/project/Projects/Data/Repository/DefaultAuthRepository.swift similarity index 100% rename from project/Projects/Data/Repository/Auth/DefaultAuthRepository.swift rename to project/Projects/Data/Repository/DefaultAuthRepository.swift diff --git a/project/Projects/Data/Repository/RecruitmentPost/DefaultRecruitmentPostRepository.swift b/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift similarity index 100% rename from project/Projects/Data/Repository/RecruitmentPost/DefaultRecruitmentPostRepository.swift rename to project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift diff --git a/project/Projects/Data/Repository/UserInfo/DefaultUserInfoLocalRepository.swift b/project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift similarity index 100% rename from project/Projects/Data/Repository/UserInfo/DefaultUserInfoLocalRepository.swift rename to project/Projects/Data/Repository/DefaultUserInfoLocalRepository.swift diff --git a/project/Projects/Data/Repository/UserInfo/DefaultUserProfileRepository.swift b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift similarity index 100% rename from project/Projects/Data/Repository/UserInfo/DefaultUserProfileRepository.swift rename to project/Projects/Data/Repository/DefaultUserProfileRepository.swift diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenManage.swift b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift similarity index 79% rename from project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenManage.swift rename to project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift index 4fa9dc98..7be9b094 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenManage.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift @@ -1,5 +1,5 @@ // -// DefaultNotificationTokenManage.swift +// DefaultNotificationTokenUseCase.swift // ConcreteUseCase // // Created by choijunios on 9/26/24. @@ -7,7 +7,9 @@ import Foundation -public class DefaultNotificationTokenManage: NotificationTokenManage { +public class DefaultNotificationTokenUseCase: NotificationTokenUseCase { + + public init() { } diff --git a/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenManage.swift b/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift similarity index 84% rename from project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenManage.swift rename to project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift index 40b4c1ff..fe4ff08f 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenManage.swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift @@ -1,5 +1,5 @@ // -// NotificationTokenManage.swift +// NotificationTokenUseCase.swift // UseCaseInterface // // Created by choijunios on 9/26/24. @@ -7,7 +7,7 @@ import Foundation -public protocol NotificationTokenManage { +public protocol NotificationTokenUseCase { /// 유저와 매치되는 노티피케이션 토큰을 서버로 전송합니다. func setNotificationToken(token: String, completion: @escaping (Bool) -> ()) diff --git a/project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift b/project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift similarity index 100% rename from project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift rename to project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift From 2e989dc22a7bbde19d4b55a4faa4f0d065c40994 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 11:22:45 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[IDLE-409]=20NotificationTokenService?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/NotificationTokenService.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 project/Projects/Data/DataSource/Service/NotificationTokenService.swift diff --git a/project/Projects/Data/DataSource/Service/NotificationTokenService.swift b/project/Projects/Data/DataSource/Service/NotificationTokenService.swift new file mode 100644 index 00000000..cfc79624 --- /dev/null +++ b/project/Projects/Data/DataSource/Service/NotificationTokenService.swift @@ -0,0 +1,17 @@ +// +// NotificationTokenService.swift +// DataSource +// +// Created by choijunios on 10/8/24. +// + +import Foundation + +public class NotificationTokenService: BaseNetworkService { + + public init() { } + + public override init(keyValueStore: KeyValueStore) { + super.init(keyValueStore: keyValueStore) + } +} From 54ee843bba8cf0d02cf759f40c5f14bd5072d5b6 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 14:11:05 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[IDLE-409]=20DefaultNotificationTokenUseC?= =?UTF-8?q?ase=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RemoteNotification/FCMService.swift | 2 - ...=> NotificationTokenTransferService.swift} | 4 +- ...tNotificationTokenTransferRepository.swift | 44 +++++++++++++++ .../DefaultNotificationTokenUseCase.swift | 52 +++++++++++++++--- .../NotificationTokenRepository.swift | 21 +++++++ .../NotificationTokenTransferRepository.swift | 17 ++++++ .../RepositoryInterface/RepositoryBase.swift | 55 +++++++++++++++++++ .../UseCaseInterface/BaseUseCase.swift | 4 +- .../NotificationTokenUseCase.swift | 7 ++- 9 files changed, 191 insertions(+), 15 deletions(-) rename project/Projects/Data/DataSource/Service/{NotificationTokenService.swift => NotificationTokenTransferService.swift} (63%) create mode 100644 project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift create mode 100644 project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift create mode 100644 project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenTransferRepository.swift diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index a3c89140..813736d7 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -14,8 +14,6 @@ import FirebaseMessaging class FCMService: NSObject { - @Injected var notificationTokenManageUseCase: NotificationTokenManage - override public init() { super.init() Messaging.messaging().delegate = self diff --git a/project/Projects/Data/DataSource/Service/NotificationTokenService.swift b/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift similarity index 63% rename from project/Projects/Data/DataSource/Service/NotificationTokenService.swift rename to project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift index cfc79624..1bce1ab9 100644 --- a/project/Projects/Data/DataSource/Service/NotificationTokenService.swift +++ b/project/Projects/Data/DataSource/Service/NotificationTokenTransferService.swift @@ -1,5 +1,5 @@ // -// NotificationTokenService.swift +// NotificationTokenTransferService.swift // DataSource // // Created by choijunios on 10/8/24. @@ -7,7 +7,7 @@ import Foundation -public class NotificationTokenService: BaseNetworkService { +public class NotificationTokenTransferService: BaseNetworkService { public init() { } diff --git a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift new file mode 100644 index 00000000..fbd1ada0 --- /dev/null +++ b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift @@ -0,0 +1,44 @@ +// +// DefaultNotificationTokenTransferRepository.swift +// DataSource +// +// Created by choijunios on 10/8/24. +// + +import Foundation +import Domain + + +import RxSwift + +public class DefaultNotificationTokenTransferRepository: NotificationTokenTransferRepository { + + let transferService: NotificationTokenTransferService = .init() + + public init() { } + + public func sendToken(token: String, userType: UserType) -> Single> { + + let userTypeString = userType == .center ? "CENTER" : "CARER" + let dataTask = transferService + .request( + api: .saveToken(deviceToken: token, userType: userTypeString), + with: .withToken + ) + .mapToVoid() + + return convert(task: dataTask) + } + + public func deleteToken(token: String) -> Single> { + + let dataTask = transferService + .request( + api: .deleteToken(deviceToken: token), + with: .withToken + ) + .mapToVoid() + + return convert(task: dataTask) + } +} diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift index 7be9b094..f43b6c8d 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift @@ -6,22 +6,60 @@ // import Foundation +import Core + + +import RxSwift public class DefaultNotificationTokenUseCase: NotificationTokenUseCase { + // Repositories + @Injected var tokenTransferRepository: NotificationTokenTransferRepository + @Injected var tokenRepository: NotificationTokenRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository + let disposeBag = DisposeBag() - public init() { } + public init() { + // set deleage + self.tokenRepository.delegate = self + } - public func setNotificationToken(token: String, completion: @escaping (Bool) -> ()) { + public func setNotificationToken() -> Single> { + + guard let userType = userInfoLocalRepository.getUserType() else { + return .just(.failure(.clientException)) + } + + let notificationToken = tokenRepository.getToken() - //TODO: 구체적 스팩 산정 후 구현 - completion(true) + return tokenTransferRepository + .sendToken(token: notificationToken, userType: userType) } - public func deleteNotificationToken(completion: @escaping (Bool) -> ()) { + public func deleteNotificationToken() -> Single> { - //TODO: 구체적 스팩 산정 후 구현 - completion(true) + let notificationToken = tokenRepository.getToken() + + return tokenTransferRepository + .deleteToken(token: notificationToken) + } +} + +extension DefaultNotificationTokenUseCase: NotificationTokenRepositoryDelegate { + + public func notificationToken(freshToken: String) { + setNotificationToken() + .subscribe { result in + + switch result { + case .success: + printIfDebug("자동 리프래쉬 토큰 전송 성공") + case .failure(let error): + printIfDebug("자동 리프래쉬 토큰 전송 실패: \(error.localizedDescription)") + } + + } + .disposed(by: disposeBag) } } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift new file mode 100644 index 00000000..7912b7ee --- /dev/null +++ b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift @@ -0,0 +1,21 @@ +// +// NotificationTokenRepository.swift +// Domain +// +// Created by choijunios on 10/8/24. +// + +import Foundation + +public protocol NotificationTokenRepository: AnyObject { + + // delegate + var delegate: NotificationTokenRepositoryDelegate? { get set } + + func getToken() -> String +} + +public protocol NotificationTokenRepositoryDelegate { + + func notificationToken(freshToken: String) +} diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenTransferRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenTransferRepository.swift new file mode 100644 index 00000000..465aeadc --- /dev/null +++ b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenTransferRepository.swift @@ -0,0 +1,17 @@ +// +// NotificationTokenTransportRepository.swift +// Domain +// +// Created by choijunios on 10/8/24. +// + +import Foundation + + +import RxSwift + +public protocol NotificationTokenTransferRepository: RepositoryBase { + + func sendToken(token: String, userType: UserType) -> Single> + func deleteToken(token: String) -> Single> +} diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift b/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift index 65a2b474..a564b33e 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift @@ -7,4 +7,59 @@ import Foundation + +import RxSwift + public protocol RepositoryBase { } + +public extension RepositoryBase { + + /// Repository로 부터 전달받은 언어레벨의 에러를 도메인 특화 에러로 변경하고, error를 Result의 Failure로, 성공을 Success로 변경합니다. + func convert(task: Single) -> Single> { + Single.create { single in + let disposable = task + .subscribe { success in + single(.success(.success(success))) + } onFailure: { error in + single(.success(.failure(self.toDomainError(error: error)))) + } + return Disposables.create { disposable.dispose() } + } + } + + // MARK: InputValidationError + private func toDomainError(error: Error) -> DomainError { + + // 네트워크 에러 + if let httpError = error as? HTTPResponseException { + + if let code = httpError.rawCode { + + let domainError = DomainError(code: code) + + if domainError == .undefinedCode { + #if DEBUG + print("‼️ 정의되지 않은 에러코드가 발견되었습니다. 노션을 확인해주세요") + #endif + } + + return domainError + } + + #if DEBUG + print("InputValidationError변환실패 Error: \(httpError)") + #endif + } + + // 네트워크 에러보다 근본적인 에러 + if let underlyingError = error as? UnderLyingError { + + let domainError: DomainError = .undelyingError(error: underlyingError) + + return domainError + } + + return DomainError.undelyingError(error: .unHandledError) + } + +} diff --git a/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift b/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift index 52ba9da4..3ddb6f87 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift @@ -38,9 +38,9 @@ public extension BaseUseCase { let domainError = DomainError(code: code) if domainError == .undefinedCode { -#if DEBUG + #if DEBUG print("‼️ 정의되지 않은 에러코드가 발견되었습니다. 노션을 확인해주세요") -#endif + #endif } return domainError diff --git a/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift b/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift index fe4ff08f..31f9ec2b 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/NotificationTokenManage/NotificationTokenUseCase.swift @@ -7,11 +7,14 @@ import Foundation + +import RxSwift + public protocol NotificationTokenUseCase { /// 유저와 매치되는 노티피케이션 토큰을 서버로 전송합니다. - func setNotificationToken(token: String, completion: @escaping (Bool) -> ()) + func setNotificationToken() -> Single> /// 유저와 매치되는 노티피케이션 토큰을 서버로부터 제거합니다. - func deleteNotificationToken(completion: @escaping (Bool) -> ()) + func deleteNotificationToken() -> Single> } From 380bf90e35b6af034e9a6537a35e7a4c5c1531ef Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 15:40:26 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[IDLE-409]=20=EC=84=BC=ED=84=B0=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20/=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 앱에 접속할 때마다 로그인 된 타입으로 토큰을 서버에 전송합니다. --- .../Sources/DIAssembly/DataAssembly.swift | 11 +++ .../Sources/DIAssembly/DomainAssembly.swift | 31 ++----- .../Sources/DIAssembly/LoggerAssembly.swift | 1 - .../RemoteNotification/FCMService.swift | 86 ------------------- .../Projects/App/Sources/SceneDelegate.swift | 6 -- ...tNotificationTokenTransferRepository.swift | 1 + .../Auth/DefaultAuthUseCase.swift | 50 +++++++---- .../DefaultNotificationTokenUseCase.swift | 8 +- .../Setting/DefaultSettingUseCase.swift | 53 ++++++------ .../NotificationTokenRepository.swift | 4 +- .../Setting/SettingScreenUseCase .swift | 6 -- .../PasswordForDeregisterVM.swift | 4 - ...PhoneNumberValidationForDeregisterVM.swift | 4 - .../Center/SignIn/CenterLoginViewModel.swift | 4 - .../AuthInOutStreamManager+PhoneNumber.swift | 4 - .../SettingPage/CenterSettingViewModel.swift | 4 - .../FireBaseTokenRepository.swift | 38 ++++++++ .../RemoteNotificationHelper.swift | 28 ++++++ .../Setting/SettingPageViewModel.swift | 2 - .../RemoteNotification.swift | 14 --- 20 files changed, 156 insertions(+), 203 deletions(-) rename project/Projects/{Presentation/Feature/Base => App}/Sources/DIAssembly/DataAssembly.swift (80%) rename project/Projects/{Presentation/Feature/Base => App}/Sources/DIAssembly/DomainAssembly.swift (67%) delete mode 100644 project/Projects/App/Sources/RemoteNotification/FCMService.swift create mode 100644 project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift create mode 100644 project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift delete mode 100644 project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift diff --git a/project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DataAssembly.swift b/project/Projects/App/Sources/DIAssembly/DataAssembly.swift similarity index 80% rename from project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DataAssembly.swift rename to project/Projects/App/Sources/DIAssembly/DataAssembly.swift index 6bfcee48..5e13e8c9 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DataAssembly.swift +++ b/project/Projects/App/Sources/DIAssembly/DataAssembly.swift @@ -9,6 +9,7 @@ import Foundation import Domain import Repository import DataSource +import RootFeature import Swinject @@ -57,5 +58,15 @@ public struct DataAssembly: Assembly { container.register(RecruitmentPostRepository.self) { _ in return DefaultRecruitmentPostRepository() } + + // MARK: 토큰 전송 레포지토리 + container.register(NotificationTokenTransferRepository.self) { _ in + return DefaultNotificationTokenTransferRepository() + } + + // MARK: 토큰 획득 레포지토리 + container.register(NotificationTokenRepository.self) { _ in + return RootFeature.FCMTokenRepository() + } } } diff --git a/project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DomainAssembly.swift b/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift similarity index 67% rename from project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DomainAssembly.swift rename to project/Projects/App/Sources/DIAssembly/DomainAssembly.swift index 9e70eede..0115cb24 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/DIAssembly/DomainAssembly.swift +++ b/project/Projects/App/Sources/DIAssembly/DomainAssembly.swift @@ -17,22 +17,19 @@ public struct DomainAssembly: Assembly { public func assemble(container: Container) { // MARK: UseCase + container.register(NotificationTokenUseCase.self) { _ in + return DefaultNotificationTokenUseCase() + } + .inObjectScope(.container) + container.register(AuthInputValidationUseCase.self) { resolver in let repository = resolver.resolve(AuthInputValidationRepository.self)! return DefaultAuthInputValidationUseCase(repository: repository) } - container.register(AuthUseCase.self) { resolver in - let authRepository = resolver.resolve(AuthRepository.self)! - let userProfileRepository = resolver.resolve(UserProfileRepository.self)! - let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)! - - return DefaultAuthUseCase( - authRepository: authRepository, - userProfileRepository: userProfileRepository, - userInfoLocalRepository: userInfoLocalRepository - ) + container.register(AuthUseCase.self) { _ in + return DefaultAuthUseCase() } container.register(CenterProfileUseCase.self) { resolver in @@ -61,14 +58,8 @@ public struct DomainAssembly: Assembly { ) } - container.register(SettingScreenUseCase.self) { resolver in - let authRepository = resolver.resolve(AuthRepository.self)! - let userInfoLocalRepository = resolver.resolve(UserInfoLocalRepository.self)! - - return DefaultSettingUseCase( - authRepository: authRepository, - userInfoLocalRepository: userInfoLocalRepository - ) + container.register(SettingScreenUseCase.self) { _ in + return DefaultSettingUseCase() } container.register(CenterCertificateUseCase.self) { resolver in @@ -80,9 +71,5 @@ public struct DomainAssembly: Assembly { userInfoLocalRepository: userInfoLocalRepository ) } - - container.register(NotificationTokenManage.self) { resolver in - DefaultNotificationTokenManage() - } } } diff --git a/project/Projects/App/Sources/DIAssembly/LoggerAssembly.swift b/project/Projects/App/Sources/DIAssembly/LoggerAssembly.swift index 3ee4f9aa..2772a77b 100644 --- a/project/Projects/App/Sources/DIAssembly/LoggerAssembly.swift +++ b/project/Projects/App/Sources/DIAssembly/LoggerAssembly.swift @@ -8,7 +8,6 @@ import Foundation import RootFeature import AuthFeature -import CenterFeature import PresentationCore import CenterMainPageFeature diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift deleted file mode 100644 index 813736d7..00000000 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// FCMService.swift -// Idle-iOS -// -// Created by choijunios on 9/24/24. -// - -import Foundation -import BaseFeature -import Domain -import Core - -import FirebaseMessaging - -class FCMService: NSObject { - - override public init() { - super.init() - Messaging.messaging().delegate = self - - - // Notification설정 - subscribeNotification() - } - - func subscribeNotification() { - - NotificationCenter.default.addObserver( - forName: .requestTransportTokenToServer, - object: nil, - queue: nil) { [weak self] _ in - - guard let self else { return } - - if let token = Messaging.messaging().fcmToken { - - notificationTokenManageUseCase.setNotificationToken(token: token) { result in - - print("FCMService 토큰 전송 \(result ? "완료" : "실패")") - } - } - } - - NotificationCenter.default.addObserver( - forName: .requestDeleteTokenFromServer, - object: nil, - queue: nil) { [weak self] _ in - - guard let self else { return } - - notificationTokenManageUseCase.deleteNotificationToken(completion: { result in - print("FCMService 토큰 삭제 \(result ? "완료" : "실패")") - }) - } - } -} - -extension FCMService: MessagingDelegate { - - func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { - - if let fcmToken { - - print("FCM토큰: \(fcmToken)") - - notificationTokenManageUseCase.setNotificationToken(token: fcmToken) { isSuccess in - print(isSuccess ? "토큰 전송 성공" : "토큰 전송 실패") - } - } - } -} - - -extension FCMService: UNUserNotificationCenterDelegate { - - /// 앱이 포그라운드에 있는 경우, 노티페이케이션이 도착하기만 하면 호출된다. - public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { - - } - - /// 앱이 백그라운드에 있는 경우, 유저가 노티피케이션을 통해 액션을 선택한 경우 호출 - public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - - print(response.notification.request.content.userInfo) - } -} diff --git a/project/Projects/App/Sources/SceneDelegate.swift b/project/Projects/App/Sources/SceneDelegate.swift index 7474990c..95ea1ebf 100644 --- a/project/Projects/App/Sources/SceneDelegate.swift +++ b/project/Projects/App/Sources/SceneDelegate.swift @@ -23,9 +23,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { return coodinator }() - // FCMService - var fcmService: FCMService! - func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = scene as? UIWindowScene else { return } @@ -41,9 +38,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { DataAssembly(), DomainAssembly(), ]) - - // FCMService - fcmService = FCMService() // Start AppCoodinator appCoordinator.start() diff --git a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift index fbd1ada0..0377257e 100644 --- a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift +++ b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift @@ -7,6 +7,7 @@ import Foundation import Domain +import DataSource import RxSwift diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift index 23b77f4b..8a18312d 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift @@ -6,26 +6,29 @@ // import Foundation +import Core import RxSwift public class DefaultAuthUseCase: AuthUseCase { - let authRepository: AuthRepository - let userProfileRepository: UserProfileRepository - let userInfoLocalRepository: UserInfoLocalRepository + // UseCase + @Injected var notificationTokenUseCase: NotificationTokenUseCase - public init(authRepository: AuthRepository, userProfileRepository: UserProfileRepository, userInfoLocalRepository: UserInfoLocalRepository) { - self.authRepository = authRepository - self.userProfileRepository = userProfileRepository - self.userInfoLocalRepository = userInfoLocalRepository - } + // Repository + @Injected var authRepository: AuthRepository + @Injected var userProfileRepository: UserProfileRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository + + public init() { } // 센터 회원가입 실행 public func registerCenterAccount(registerState: CenterRegisterState) -> Single> { - let task = authRepository.requestRegisterCenterAccount( + // #1. 회원가입 실행 + authRepository + .requestRegisterCenterAccount( managerName: registerState.name, phoneNumber: registerState.phoneNumber, businessNumber: registerState.businessNumber, @@ -33,24 +36,31 @@ public class DefaultAuthUseCase: AuthUseCase { password: registerState.password ) .map { [userInfoLocalRepository] _ in + // #2. 유저정보 로컬에 저장 userInfoLocalRepository.updateUserType(.center) } - return convert(task: task) + .flatMap { [notificationTokenUseCase] _ in + // #3. 원격알림 토큰을 서버에 전송 + notificationTokenUseCase.setNotificationToken() + } } // 센터 로그인 실행 public func loginCenterAccount(id: String, password: String) -> Single> { - let task = authRepository.requestCenterLogin(id: id, password: password) + authRepository.requestCenterLogin(id: id, password: password) .map { [userInfoLocalRepository] vo in userInfoLocalRepository.updateUserType(.center) } - return convert(task: task) + .flatMap { [notificationTokenUseCase] _ in + // 원격알림 토큰을 서버에 전송 + notificationTokenUseCase.setNotificationToken() + } } // 요양 보호사 회원가입 실행, 성공한 경우 프로필 Fetch후 저장 public func registerWorkerAccount(registerState: WorkerRegisterState) -> Single> { - let task = authRepository + authRepository .requestRegisterWorkerAccount(registerState: registerState) .flatMap { [userProfileRepository] _ in userProfileRepository.getWorkerProfile(mode: .myProfile) @@ -59,14 +69,16 @@ public class DefaultAuthUseCase: AuthUseCase { userInfoLocalRepository.updateUserType(.worker) userInfoLocalRepository.updateCurrentWorkerData(vo: vo) } - - return convert(task: task) + .flatMap { [notificationTokenUseCase] _ in + // 원격알림 토큰을 서버에 전송 + notificationTokenUseCase.setNotificationToken() + } } // 요양 보호사 로그인 실행, 성공한 경우 프로필 Fetch후 저장 public func loginWorkerAccount(phoneNumber: String, authNumber: String) -> Single> { - let task = authRepository.requestWorkerLogin(phoneNumber: phoneNumber, authNumber: authNumber) + authRepository.requestWorkerLogin(phoneNumber: phoneNumber, authNumber: authNumber) .flatMap { [userProfileRepository] _ in userProfileRepository.getWorkerProfile(mode: .myProfile) } @@ -74,8 +86,10 @@ public class DefaultAuthUseCase: AuthUseCase { userInfoLocalRepository.updateUserType(.worker) userInfoLocalRepository.updateCurrentWorkerData(vo: vo) } - - return convert(task: task) + .flatMap { [notificationTokenUseCase] _ in + // 원격알림 토큰을 서버에 전송 + notificationTokenUseCase.setNotificationToken() + } } public func checkCenterJoinStatus() -> Single> { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift index f43b6c8d..592c811d 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/NotificationTokenManage/DefaultNotificationTokenUseCase.swift @@ -31,7 +31,9 @@ public class DefaultNotificationTokenUseCase: NotificationTokenUseCase { return .just(.failure(.clientException)) } - let notificationToken = tokenRepository.getToken() + guard let notificationToken = tokenRepository.getToken() else { + return .just(.failure(.resourceNotFound)) + } return tokenTransferRepository .sendToken(token: notificationToken, userType: userType) @@ -39,7 +41,9 @@ public class DefaultNotificationTokenUseCase: NotificationTokenUseCase { public func deleteNotificationToken() -> Single> { - let notificationToken = tokenRepository.getToken() + guard let notificationToken = tokenRepository.getToken() else { + return .just(.failure(.resourceNotFound)) + } return tokenTransferRepository .deleteToken(token: notificationToken) diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift index cc83fb4f..378fec20 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift @@ -7,19 +7,21 @@ import Foundation import UserNotifications +import Core import RxSwift public class DefaultSettingUseCase: SettingScreenUseCase { - let authRepository: AuthRepository - let userInfoLocalRepository: UserInfoLocalRepository + // UseCase + @Injected var notificationTokenUseCase: NotificationTokenUseCase - public init(authRepository: AuthRepository, userInfoLocalRepository: UserInfoLocalRepository) { - self.authRepository = authRepository - self.userInfoLocalRepository = userInfoLocalRepository - } + // Repository + @Injected var authRepository: AuthRepository + @Injected var userInfoLocalRepository: UserInfoLocalRepository + + public init() { } public func checkPushNotificationApproved() -> Single { Single.create { single in @@ -71,39 +73,42 @@ public class DefaultSettingUseCase: SettingScreenUseCase { } } - public func getPersonalDataUsageDescriptionUrl() -> URL { - // MARK: TODO - URL(string: "")! - } - - public func getApplicationPolicyUrl() -> URL { - // MARK: TODO - URL(string: "")! - } - // MARK: 회원탈퇴 & 로그아웃 // 센터 회원탈퇴 public func deregisterCenterAccount(reasons: [String], password: String) -> RxSwift.Single> { - let task = authRepository + authRepository .deregisterCenterAccount(reasons: reasons, password: password) .map { [weak self] _ in self?.removeAllLocalData() return () } - return convert(task: task) + .flatMap { [notificationTokenUseCase] _ in + notificationTokenUseCase + .deleteNotificationToken() + } } // 센터 로그아웃 public func signoutCenterAccount() -> RxSwift.Single> { - let task = authRepository - .signoutCenterAccount() - .map { [weak self] _ in - self?.removeAllLocalData() + notificationTokenUseCase + .deleteNotificationToken() + .flatMap{ [authRepository] result in - return () + switch result { + case .success: + let task = authRepository + .signoutCenterAccount() + .map { [weak self] ads in + self?.removeAllLocalData() + + return ads + } + return self.convert(task: task) + case .failure: + return Single.just(result) + } } - return convert(task: task) } // 요양보호사 회원탈퇴 diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift index 7912b7ee..ae183f86 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/RemoteNotification/NotificationTokenRepository.swift @@ -12,10 +12,10 @@ public protocol NotificationTokenRepository: AnyObject { // delegate var delegate: NotificationTokenRepositoryDelegate? { get set } - func getToken() -> String + func getToken() -> String? } -public protocol NotificationTokenRepositoryDelegate { +public protocol NotificationTokenRepositoryDelegate: AnyObject { func notificationToken(freshToken: String) } diff --git a/project/Projects/Domain/Sources/UseCaseInterface/Setting/SettingScreenUseCase .swift b/project/Projects/Domain/Sources/UseCaseInterface/Setting/SettingScreenUseCase .swift index 2e89c32b..8b34341e 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/Setting/SettingScreenUseCase .swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/Setting/SettingScreenUseCase .swift @@ -24,12 +24,6 @@ public protocol SettingScreenUseCase: BaseUseCase { /// 알림동의를 요청합니다. func requestNotificationPermission() -> Maybe - /// 개인정보 처리방침 웹 URL을 가져옵니다. - func getPersonalDataUsageDescriptionUrl() -> URL - - /// 어플리케이션 이용약관을 가져옵니다. - func getApplicationPolicyUrl() -> URL - // MARK: Worker /// 요양보호사 회원 탈퇴 diff --git a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPasswordPage/PasswordForDeregisterVM.swift b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPasswordPage/PasswordForDeregisterVM.swift index 96003d52..d6714978 100644 --- a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPasswordPage/PasswordForDeregisterVM.swift +++ b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPasswordPage/PasswordForDeregisterVM.swift @@ -45,10 +45,6 @@ public class PasswordForDeregisterVM: BaseViewModel { .observe(on: MainScheduler.asyncInstance) .unretained(self) .subscribe(onNext: { (obj, _) in - - // 회원탈퇴 성공 -> 원격알림 토큰 제거 - NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) - // RootCoordinator로 이동 obj.changeToAuthFlow?() }) diff --git a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPhoneNumberPage/PhoneNumberValidationForDeregisterVM.swift b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPhoneNumberPage/PhoneNumberValidationForDeregisterVM.swift index f6336889..1102e983 100644 --- a/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPhoneNumberPage/PhoneNumberValidationForDeregisterVM.swift +++ b/project/Projects/Presentation/Feature/AccountDeregister/Sources/AuthPhoneNumberPage/PhoneNumberValidationForDeregisterVM.swift @@ -76,10 +76,6 @@ class PhoneNumberValidationForDeregisterVM: BaseViewModel, PhoneNumberValidation .observe(on: MainScheduler.asyncInstance) .unretained(self) .subscribe(onNext: { (obj, _) in - - // 회원탈퇴 성공 -> 원격알림 토큰 제거 - NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) - // RootCoordinator로 이동 obj.changeToAuthFlow?() }) diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Center/SignIn/CenterLoginViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/Center/SignIn/CenterLoginViewModel.swift index 95e5991e..2e0a51e2 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Center/SignIn/CenterLoginViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Center/SignIn/CenterLoginViewModel.swift @@ -62,10 +62,6 @@ public class CenterLoginViewModel: BaseViewModel, ViewModelType { loginSuccess .unretained(self) .subscribe(onNext: { (obj, _) in - - // 원격 알림 토큰 저장요청 - NotificationCenter.default.post(name: .requestTransportTokenToServer, object: nil) - // 센터 메인화면으로 이동 obj.presentCenterMainPage() }) diff --git a/project/Projects/Presentation/Feature/Base/Sources/CommonView/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift b/project/Projects/Presentation/Feature/Base/Sources/CommonView/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift index 4d3a661b..c2d1058d 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/CommonView/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/CommonView/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift @@ -97,10 +97,6 @@ public extension AuthInOutStreamManager { output.loginSuccess = loginResult .compactMap { $0.value } .map { phoneNumber in - - // 원격 알림 토큰 전송 - NotificationCenter.default.post(name: .requestTransportTokenToServer, object: nil) - printIfDebug("✅ 요양보호사 로그인 성공") return () } diff --git a/project/Projects/Presentation/Feature/CenterMainPage/Sources/SettingPage/CenterSettingViewModel.swift b/project/Projects/Presentation/Feature/CenterMainPage/Sources/SettingPage/CenterSettingViewModel.swift index a2b66c10..80f1fe08 100644 --- a/project/Projects/Presentation/Feature/CenterMainPage/Sources/SettingPage/CenterSettingViewModel.swift +++ b/project/Projects/Presentation/Feature/CenterMainPage/Sources/SettingPage/CenterSettingViewModel.swift @@ -173,10 +173,6 @@ class CenterSettingViewModel: BaseViewModel, CenterSettingVMable { signOutSuccess .unretained(self) .subscribe(onNext: { (obj, _) in - - // 로그이아웃 성공 -> 원격알림 토큰 제거 - NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) - obj.changeToAuthFlow?() }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift new file mode 100644 index 00000000..b4d5de78 --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift @@ -0,0 +1,38 @@ +// +// FireBaseTokenRepository.swift +// RootFeature +// +// Created by choijunios on 10/8/24. +// + +import Foundation +import Domain + + +import FirebaseMessaging + +public class FCMTokenRepository: NSObject, NotificationTokenRepository { + + public weak var delegate: NotificationTokenRepositoryDelegate? + + public override init() { + super.init() + Messaging.messaging().delegate = self + } + + public func getToken() -> String? { + Messaging.messaging().fcmToken + } +} + +extension FCMTokenRepository: MessagingDelegate { + + // 새로운 토큰 수신 + public func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { + + if let fcmToken { + + delegate?.notificationToken(freshToken: fcmToken) + } + } +} diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift new file mode 100644 index 00000000..4332f2c5 --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift @@ -0,0 +1,28 @@ +// +// RemoteNotificationHelper.swift +// RootFeature +// +// Created by choijunios on 10/8/24. +// + +import Foundation +import UserNotifications + +class RemoteNotificationHelper: NSObject { + + +} + +extension RemoteNotificationHelper: UNUserNotificationCenterDelegate { + + /// 앱이 포그라운드에 있는 경우, 노티페이케이션이 도착하기만 하면 호출된다. + public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + + } + + /// 앱이 백그라운드에 있는 경우, 유저가 노티피케이션을 통해 액션을 선택한 경우 호출 + public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + + print(response.notification.request.content.userInfo) + } +} diff --git a/project/Projects/Presentation/Feature/WorkerMainPage/Sources/Setting/SettingPageViewModel.swift b/project/Projects/Presentation/Feature/WorkerMainPage/Sources/Setting/SettingPageViewModel.swift index 9d24c1a8..906294a7 100644 --- a/project/Projects/Presentation/Feature/WorkerMainPage/Sources/Setting/SettingPageViewModel.swift +++ b/project/Projects/Presentation/Feature/WorkerMainPage/Sources/Setting/SettingPageViewModel.swift @@ -133,8 +133,6 @@ class SettingPageViewModel: BaseViewModel { signOutSuccess .unretained(self) .subscribe(onNext: { (obj, _) in - // 로그이아웃 성공 -> 원격알림 토큰 제거 - NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) obj.changeToAuthFlow?() }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift b/project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift deleted file mode 100644 index a4f64697..00000000 --- a/project/Projects/Presentation/PresentationCore/Sources/Extensions/NotificationName+Extension/RemoteNotification.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// RemoteNotification.swift -// PresentationCore -// -// Created by choijunios on 9/26/24. -// - -import Foundation - -public extension Notification.Name { - - static let requestTransportTokenToServer: Self = .init("requestTransportTokenToServer") - static let requestDeleteTokenFromServer: Self = .init("requestDeleteTokenFromServer") -} From 0b2124ebd82d9e246d74240d26612c3c52126f15 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 15:40:51 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[IDLE-409]=20=EA=B3=84=EC=A0=95=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EC=A0=84=20FCM=EB=B6=80=ED=84=B0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Setting/DefaultSettingUseCase.swift | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift index 378fec20..5b435873 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift @@ -76,16 +76,24 @@ public class DefaultSettingUseCase: SettingScreenUseCase { // MARK: 회원탈퇴 & 로그아웃 // 센터 회원탈퇴 public func deregisterCenterAccount(reasons: [String], password: String) -> RxSwift.Single> { - authRepository - .deregisterCenterAccount(reasons: reasons, password: password) - .map { [weak self] _ in - self?.removeAllLocalData() + + notificationTokenUseCase + .deleteNotificationToken() + .flatMap{ [authRepository] result in - return () - } - .flatMap { [notificationTokenUseCase] _ in - notificationTokenUseCase - .deleteNotificationToken() + switch result { + case .success: + let task = authRepository + .deregisterCenterAccount(reasons: reasons, password: password) + .map { [weak self] _ in + self?.removeAllLocalData() + + return () + } + return self.convert(task: task) + case .failure: + return Single.just(result) + } } } From ad699b3b0f97d7cdb812b4513f11e9ecdda6e3c0 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Tue, 8 Oct 2024 16:38:19 +0900 Subject: [PATCH 07/11] =?UTF-8?q?[IDLE-409]=20Repository=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...DefaultAuthInputValidationRepository.swift | 33 +++-- .../Repository/DefaultAuthRepository.swift | 85 +++++++----- .../DefaultRecruitmentPostRepository.swift | 123 +++++++++++------- .../DefaultUserProfileRepository.swift | 106 +++++++++++---- .../Auth/AuthInputValidationRepository.swift | 8 +- .../Auth/AuthRepository.swift | 22 ++-- .../RecruitmentPostRepository.swift | 80 ++++++------ .../RepositoryInterface/RepositoryBase.swift | 2 +- .../UserInfo/UserProfileRepository.swift | 29 +++-- 9 files changed, 307 insertions(+), 181 deletions(-) diff --git a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift index 0cc4734b..103ba872 100644 --- a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift +++ b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift @@ -8,6 +8,7 @@ import Foundation import DataSource import Domain +import Core import RxSwift @@ -18,30 +19,40 @@ public class DefaultAuthInputValidationRepository: AuthInputValidationRepository public init() { } - public func requestPhoneNumberAuthentication(phoneNumber: String) -> Single { + public func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> { - networkService + let dataTask = networkService .request(api: .startPhoneNumberAuth(phoneNumber: phoneNumber), with: .plain) - .map { _ in return () } + .mapToVoid() + + return convertToDomain(task: dataTask) } - public func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single { + public func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> { + + let dataTask = networkService.request(api: .checkAuthNumber(phoneNumber: phoneNumber, authNumber: authNumber), with: .plain) + .mapToVoid() - networkService.request(api: .checkAuthNumber(phoneNumber: phoneNumber, authNumber: authNumber), with: .plain) - .map { _ in return () } + return convertToDomain(task: dataTask) } - public func requestBusinessNumberAuthentication(businessNumber: String) -> Single { + public func requestBusinessNumberAuthentication(businessNumber: String) -> Single> { - networkService.requestDecodable( + let dataTask = networkService.requestDecodable( api: .authenticateBusinessNumber(businessNumber: businessNumber), with: .plain ).map { (dto: BusinessInfoDTO) in dto.toEntity() } + + return convertToDomain(task: dataTask) } - public func requestCheckingIdDuplication(id: String) -> Single { - networkService.request(api: .checkIdDuplication(id: id), with: .plain) - .map { _ in return () } + public func requestCheckingIdDuplication(id: String) -> Single> { + + let dataTask = networkService + .request(api: .checkIdDuplication(id: id), with: .plain) + .mapToVoid() + + return convertToDomain(task: dataTask) } } diff --git a/project/Projects/Data/Repository/DefaultAuthRepository.swift b/project/Projects/Data/Repository/DefaultAuthRepository.swift index 8f1244d2..d0555602 100644 --- a/project/Projects/Data/Repository/DefaultAuthRepository.swift +++ b/project/Projects/Data/Repository/DefaultAuthRepository.swift @@ -28,7 +28,7 @@ public extension DefaultAuthRepository { businessNumber: String, id: String, password: String - ) -> Single { + ) -> Single> { let dto = CenterRegistrationDTO( identifier: id, @@ -40,26 +40,34 @@ public extension DefaultAuthRepository { let data = (try? JSONEncoder().encode(dto)) ?? Data() - return networkService.request(api: .registerCenterAccount(data: data), with: .plain) - .map { _ in return () } + let dataTask = networkService.request(api: .registerCenterAccount(data: data), with: .plain) + .mapToVoid() + + return convertToDomain(task: dataTask) } - func requestCenterLogin(id: String, password: String) -> Single { - return networkService.requestDecodable(api: .centerLogin(id: id, password: password), with: .plain) - .flatMap { [unowned self] in saveTokenToStore(token: $0) } + func requestCenterLogin(id: String, password: String) -> Single> { + let dataTask = networkService.requestDecodable(api: .centerLogin(id: id, password: password), with: .plain) + .flatMap { [unowned self] in + saveTokenToStore(token: $0) + } + + return convertToDomain(task: dataTask) } - func signoutCenterAccount() -> RxSwift.Single { - networkService + func signoutCenterAccount() -> Single> { + let dataTask = networkService .request(api: .signoutCenterAccount, with: .withToken) - .map { _ in } + .mapToVoid() + + return convertToDomain(task: dataTask) } - func deregisterCenterAccount(reasons: [String], password: String) -> RxSwift.Single { + func deregisterCenterAccount(reasons: [String], password: String) -> Single> { let reasonString = reasons.joined(separator: "|") - return networkService + let dataTask = networkService .request( api: .deregisterCenterAccount( reason: reasonString, @@ -67,25 +75,33 @@ public extension DefaultAuthRepository { ), with: .withToken ) - .map { _ in } + .mapToVoid() + + return convertToDomain(task: dataTask) } - func getCenterJoinStatus() -> RxSwift.Single { - networkService + func getCenterJoinStatus() -> Single> { + let dataTask = networkService .request(api: .centerJoinStatus, with: .withToken) .map(CenterJoinStatusInfoVO.self) + + return convertToDomain(task: dataTask) } - func requestCenterJoin() -> Single { - networkService + func requestCenterJoin() -> Single> { + let dataTask = networkService .request(api: .requestCenterJoin, with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } - func setNewPassword(phoneNumber: String, password: String) -> Single { - networkService + func setNewPassword(phoneNumber: String, password: String) -> Single> { + let dataTask = networkService .request(api: .makeNewPassword(phoneNumber: phoneNumber, newPassword: password), with: .plain) .mapToVoid() + + return convertToDomain(task: dataTask) } } @@ -93,7 +109,7 @@ public extension DefaultAuthRepository { public extension DefaultAuthRepository { /// 요양보호사의 경우 회원가입시 곧바로 토큰을 발급받습니다. - func requestRegisterWorkerAccount(registerState: WorkerRegisterState) -> Single { + func requestRegisterWorkerAccount(registerState: WorkerRegisterState) -> Single> { let dto = WorkerRegistrationDTO( carerName: registerState.name, birthYear: registerState.birthYear, @@ -105,32 +121,37 @@ public extension DefaultAuthRepository { let data = (try? JSONEncoder().encode(dto)) ?? Data() - return networkService.requestDecodable(api: .registerWorkerAccount(data: data), with: .plain) + let dataTask = networkService.requestDecodable(api: .registerWorkerAccount(data: data), with: .plain) .flatMap { [unowned self] in saveTokenToStore(token: $0) } + + return convertToDomain(task: dataTask) } - func requestWorkerLogin(phoneNumber: String, authNumber: String) -> Single { - return networkService.requestDecodable(api: .workerLogin(phoneNumber: phoneNumber, verificationNumber: authNumber), with: .plain) + func requestWorkerLogin(phoneNumber: String, authNumber: String) -> Single> { + let dataTask = networkService.requestDecodable(api: .workerLogin(phoneNumber: phoneNumber, verificationNumber: authNumber), with: .plain) .flatMap { [unowned self] in saveTokenToStore(token: $0) } + + return convertToDomain(task: dataTask) } - func signoutWorkerAccount() -> RxSwift.Single { - networkService + func signoutWorkerAccount() -> Single> { + let dataTask = networkService .request(api: .signoutWorkerAccount, with: .withToken) - .map { _ in } + .mapToVoid() + + return convertToDomain(task: dataTask) } - func deregisterWorkerAccount(reasons: [String]) -> RxSwift.Single { + func deregisterWorkerAccount(reasons: [String]) -> Single> { let reasonString = reasons.joined(separator: "|") - - return networkService + let dataTask = networkService .request( - api: .deregisterWorkerAccount( - reason: reasonString - ), + api: .deregisterWorkerAccount(reason: reasonString), with: .withToken ) - .map { _ in } + .mapToVoid() + + return convertToDomain(task: dataTask) } } diff --git a/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift b/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift index b0d5dca7..dbee1445 100644 --- a/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift +++ b/project/Projects/Data/Repository/DefaultRecruitmentPostRepository.swift @@ -13,8 +13,6 @@ import DataSource import Moya import RxSwift - - public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { private var recruitmentPostService: RecruitmentPostService = .init() @@ -29,132 +27,160 @@ public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { } } - // MARK: Center - public func registerPost(bundle: RegisterRecruitmentPostBundle) -> RxSwift.Single { + // MARK: Center + public func registerPost(bundle: RegisterRecruitmentPostBundle) -> RxSwift.Single> { let encodedData = try! JSONEncoder().encode(bundle.toDTO()) - - return recruitmentPostService.request(api: .registerPost(postData: encodedData), with: .withToken) + let dataTask = recruitmentPostService.request(api: .registerPost(postData: encodedData), with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } - public func getPostDetailForCenter(id: String) -> RxSwift.Single { + public func getPostDetailForCenter(id: String) -> RxSwift.Single> { - recruitmentPostService.request(api: .postDetail(id: id, userType: .center), with: .withToken) + let dataTask = recruitmentPostService.request(api: .postDetail(id: id, userType: .center), with: .withToken) .map(RecruitmentPostFetchDTO.self) .map { dto in dto.toEntity() } + + return convertToDomain(task: dataTask) } - public func editPostDetail(id: String, bundle: RegisterRecruitmentPostBundle) -> RxSwift.Single { + public func editPostDetail(id: String, bundle: RegisterRecruitmentPostBundle) -> RxSwift.Single> { let encodedData = try! JSONEncoder().encode(bundle.toDTO()) - - return recruitmentPostService.request( + let dataTask = recruitmentPostService.request( api: .editPost(id: id, postData: encodedData), with: .withToken ).map { _ in () } + + return convertToDomain(task: dataTask) } - public func getOngoingPosts() -> RxSwift.Single<[RecruitmentPostInfoForCenterVO]> { - return recruitmentPostService.request(api: .getOnGoingPosts, with: .withToken) + public func getOngoingPosts() -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .getOnGoingPosts, with: .withToken) .map(RecruitmentPostForCenterListDTO.self) .map({ $0.jobPostings.map { $0.toVO() } }) + + return convertToDomain(task: dataTask) } - public func getClosedPosts() -> RxSwift.Single<[RecruitmentPostInfoForCenterVO]> { - return recruitmentPostService.request(api: .getClosedPosts, with: .withToken) + public func getClosedPosts() -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .getClosedPosts, with: .withToken) .map(RecruitmentPostForCenterListDTO.self) .map({ $0.jobPostings.map { $0.toVO() } }) + + return convertToDomain(task: dataTask) } - public func getPostApplicantCount(id: String) -> RxSwift.Single { - recruitmentPostService.request(api: .getPostApplicantCount(id: id), with: .withToken) + public func getPostApplicantCount(id: String) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .getPostApplicantCount(id: id), with: .withToken) .map(PostApplicantCountDTO.self) .map { dto in dto.applicantCount } + + return convertToDomain(task: dataTask) } - public func getPostApplicantScreenData(id: String) -> RxSwift.Single { - recruitmentPostService.request(api: .getApplicantList(id: id), with: .withToken) + public func getPostApplicantScreenData(id: String) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .getApplicantList(id: id), with: .withToken) .map(PostApplicantScreenDTO.self) .map { dto in dto.toVO() } + + return convertToDomain(task: dataTask) } - public func closePost(id: String) -> RxSwift.Single { - recruitmentPostService.request(api: .closePost(id: id), with: .withToken) + public func closePost(id: String) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .closePost(id: id), with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } - public func removePost(id: String) -> RxSwift.Single { - recruitmentPostService.request(api: .removePost(id: id), with: .withToken) + public func removePost(id: String) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request(api: .removePost(id: id), with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } // MARK: Worker - public func getNativePostDetailForWorker(id: String) -> RxSwift.Single { - recruitmentPostService.request( + public func getNativePostDetailForWorker(id: String) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request( api: .postDetail(id: id, userType: .worker), with: .withToken ) .mapToEntity(NativeRecruitmentPostDetailDTO.self) + + return convertToDomain(task: dataTask) } - public func getWorknetPostDetailForWorker(id: String) -> RxSwift.Single { - crawlingPostService + public func getWorknetPostDetailForWorker(id: String) -> RxSwift.Single> { + let dataTask = crawlingPostService .request(api: .getDetail(postId: id), with: .withToken) .mapToEntity(WorknetRecruitmentPostDetailDTO.self) + + return convertToDomain(task: dataTask) } - - public func getNativePostListForWorker(nextPageId: String?, requestCnt: Int = 10) -> RxSwift.Single { - - recruitmentPostService.request( + public func getNativePostListForWorker(nextPageId: String?, requestCnt: Int = 10) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request( api: .getOnGoingNativePostListForWorker(nextPageId: nextPageId, requestCnt: String(requestCnt)), with: .withToken ) .mapToEntity(RecruitmentPostListForWorkerDTO.self) + + return convertToDomain(task: dataTask) } - public func getNativeFavoritePostListForWorker() -> RxSwift.Single<[RecruitmentPostForWorkerRepresentable]> { - recruitmentPostService.request( + public func getNativeFavoritePostListForWorker() -> RxSwift.Single> { + let dataTask = recruitmentPostService.request( api: .getNativeFavoritePost, with: .withToken ) .mapToEntity(FavoriteNativeRecruitmentPostListForWorkerDTO.self) + + return convertToDomain(task: dataTask) } - public func getWorknetFavoritePostListForWorker() -> RxSwift.Single<[RecruitmentPostForWorkerRepresentable]> { - crawlingPostService.request( + public func getWorknetFavoritePostListForWorker() -> RxSwift.Single> { + let dataTask = crawlingPostService.request( api: .getWorknetFavoritePost, with: .withToken ) .mapToEntity(FavoriteWorknetRecruitmentPostListForWorkerDTO.self) + + return convertToDomain(task: dataTask) } - public func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single { - recruitmentPostService.request( + public func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single> { + let dataTask = recruitmentPostService.request( api: .getAppliedPostListForWorker(nextPageId: nextPageId, requestCnt: String(requestCnt)), with: .withToken ) .mapToEntity(RecruitmentPostListForWorkerDTO.self) + + return convertToDomain(task: dataTask) } - public func getWorknetPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single { - crawlingPostService + public func getWorknetPostListForWorker(nextPageId: String?, requestCnt: Int) -> RxSwift.Single> { + let dataTask = crawlingPostService .request( api: .getPostList(nextPageId: nextPageId, requestCnt: requestCnt), with: .withToken ) .mapToEntity(RecruitmentPostListForWorkerDTO.self) + + return convertToDomain(task: dataTask) } - public func applyToPost(postId: String, method: ApplyType) -> Single { - applyService + public func applyToPost(postId: String, method: ApplyType) -> Single> { + let dataTask = applyService .request( api: .applys( jobPostingId: postId, @@ -163,21 +189,28 @@ public class DefaultRecruitmentPostRepository: RecruitmentPostRepository { with: .withToken ) .mapToVoid() + + return convertToDomain(task: dataTask) } - public func addFavoritePost(postId: String, type: PostOriginType) -> Single { - recruitmentPostService + public func addFavoritePost(postId: String, type: PostOriginType) -> Single> { + let dataTask = recruitmentPostService .request(api: .addFavoritePost(id: postId, jobPostingType: type), with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } - public func removeFavoritePost(postId: String) -> Single { - recruitmentPostService + public func removeFavoritePost(postId: String) -> Single> { + let dataTask = recruitmentPostService .request(api: .removeFavoritePost(id: postId), with: .withToken) .mapToVoid() + + return convertToDomain(task: dataTask) } } + // MARK: 공고등록 정보를 DTO로 변환하는 영역 extension RegisterRecruitmentPostBundle { diff --git a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift index 4e50fc2b..60735cf8 100644 --- a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift +++ b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift @@ -18,7 +18,6 @@ public class DefaultUserProfileRepository: UserProfileRepository { let externalRequestService: ExternalRequestService public init(_ keyValueStore: KeyValueStore? = nil) { - if let keyValueStore { self.userInformationService = .init(keyValueStore: keyValueStore) self.externalRequestService = .init(keyValueStore: keyValueStore) @@ -29,7 +28,7 @@ public class DefaultUserProfileRepository: UserProfileRepository { } /// 센터프로필(최초 센터정보)를 등록합니다. - public func registerCenterProfileForText(state: CenterProfileRegisterState) -> Single { + public func registerCenterProfileForText(state: CenterProfileRegisterState) -> Single> { let dto = RegisterCenterProfileDTO( centerName: state.centerName, @@ -41,12 +40,14 @@ public class DefaultUserProfileRepository: UserProfileRepository { ) let data = try! JSONEncoder().encode(dto) - return userInformationService + let dataTask = userInformationService .request(api: .registerCenterProfile(data: data), with: .withToken) .map { _ in () } + + return convertToDomain(task: dataTask) } - public func getCenterProfile(mode: ProfileMode) -> Single { + public func getCenterProfile(mode: ProfileMode) -> Single> { var api: UserInformationAPI! @@ -57,28 +58,34 @@ public class DefaultUserProfileRepository: UserProfileRepository { api = .getCenterProfile(id: id) } - return userInformationService + let dataTask = userInformationService .requestDecodable(api: api, with: .withToken) .map { (dto: CenterProfileDTO) in dto.toEntity() } + + return convertToDomain(task: dataTask) } - public func getCenterProfile(id: String) -> Single { - userInformationService + public func getCenterProfile(id: String) -> Single> { + let dataTask = userInformationService .requestDecodable(api: .getCenterProfile(id: id), with: .withToken) .map { (dto: CenterProfileDTO) in dto.toEntity() } + + return convertToDomain(task: dataTask) } - public func updateCenterProfileForText(phoneNumber: String, introduction: String?) -> Single { - userInformationService + public func updateCenterProfileForText(phoneNumber: String, introduction: String?) -> Single> { + let dataTask = userInformationService .request(api: .updateCenterProfile( officeNumber: phoneNumber, introduce: introduction ), with: .withToken) .map { _ in return () } + + return convertToDomain(task: dataTask) } /// 요양보호사 프로필 정보를 가져옵니다. - public func getWorkerProfile(mode: ProfileMode) -> RxSwift.Single { + public func getWorkerProfile(mode: ProfileMode) -> Single> { var api: UserInformationAPI! switch mode { @@ -88,13 +95,15 @@ public class DefaultUserProfileRepository: UserProfileRepository { api = .getOtherWorkerProfile(id: id) } - return userInformationService + let dataTask = userInformationService .requestDecodable(api: api, with: .withToken) .map { (dto: CarerProfileDTO) in dto.toVO() } + + return convertToDomain(task: dataTask) } /// 요양보호사 프로필 정보를 업데이트 합니다. - public func updateWorkerProfile(stateObject: WorkerProfileStateObject) -> RxSwift.Single { + public func updateWorkerProfile(stateObject: WorkerProfileStateObject) -> Single> { var availableValues: [String: Any] = [:] @@ -124,42 +133,87 @@ public class DefaultUserProfileRepository: UserProfileRepository { let encoded = try! JSONSerialization.data(withJSONObject: availableValues) - return userInformationService + let dataTask = userInformationService .request(api: .updateWorkerProfile(data: encoded), with: .withToken) .map { _ in return () } + + return convertToDomain(task: dataTask) } /// 이미지 업로드 - public func uploadImage(_ userType: UserType, imageInfo: ImageUploadInfo) -> Single { - getPreSignedUrl(userType, ext: imageInfo.ext) - .flatMap { [unowned self] dto in - self.uploadImageToPreSignedUrl(url: dto.uploadUrl, data: imageInfo.data) - .map { _ in (id: dto.imageId, ext: dto.imageFileExtension) } + public func uploadImage(_ userType: UserType, imageInfo: ImageUploadInfo) -> Single> { + + let getPreSignedUrlResult = getPreSignedUrl(userType, ext: imageInfo.ext) + + let getPreSignedUrlSuccess = getPreSignedUrlResult.compactMap { $0.value } + let getPreSignedUrlFailure = getPreSignedUrlResult.compactMap { $0.error } + + let uploadImageToPreSignedUrlResult = getPreSignedUrlSuccess + .asObservable() + .unretained(self) + .flatMap { (obj, dto) in + obj + .uploadImageToPreSignedUrl(url: dto.uploadUrl, data: imageInfo.data) + .map { result -> Result in + switch result { + case .success: + return .success(dto) + case .failure(let error): + return .failure(error) + } + } } - .flatMap { (id, ext) in - self.callbackToServerForUploadImageSuccess(userType, imageId: id, ext: ext) + + let uploadImageToPreSignedUrlSuccess = uploadImageToPreSignedUrlResult.compactMap { $0.value } + let uploadImageToPreSignedUrlFailure = uploadImageToPreSignedUrlResult.compactMap { $0.error } + + let callbackToServerForUploadImageResult = uploadImageToPreSignedUrlSuccess + .unretained(self) + .flatMap { (obj, dto) in + obj.callbackToServerForUploadImageSuccess( + userType, + imageId: dto.imageId, + ext: dto.imageFileExtension + ) } + + return Observable> + .merge( + callbackToServerForUploadImageResult, + Observable.merge( + getPreSignedUrlFailure.asObservable(), + uploadImageToPreSignedUrlFailure.asObservable() + ).map { error in Result.failure(error) } + ) + .asSingle() + } - private func getPreSignedUrl(_ userType: UserType, ext: String) -> Single { - userInformationService + private func getPreSignedUrl(_ userType: UserType, ext: String) -> Single> { + let dataTask = userInformationService .request(api: .getPreSignedUrl(userType: userType, imageExt: ext), with: .withToken) .map(ProfileImageUploadInfoDTO.self) + + return convertToDomain(task: dataTask) } - private func uploadImageToPreSignedUrl(url: String, data: Data) -> Single { - externalRequestService + private func uploadImageToPreSignedUrl(url: String, data: Data) -> Single> { + let dataTask = externalRequestService .request(api: .uploadImageToS3(url: url, data: data), with: .plain) .map { _ in () } + + return convertToDomain(task: dataTask) } - private func callbackToServerForUploadImageSuccess(_ userType: UserType, imageId: String, ext: String) -> Single { - userInformationService + private func callbackToServerForUploadImageSuccess(_ userType: UserType, imageId: String, ext: String) -> Single> { + let dataTask = userInformationService .request(api: .imageUploadSuccessCallback( userType: userType, imageId: imageId, imageExt: ext), with: .withToken ) .map { _ in () } + + return convertToDomain(task: dataTask) } } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift index 602c6b10..63751d43 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift @@ -12,8 +12,8 @@ import RxSwift public protocol AuthInputValidationRepository: RepositoryBase { - func requestPhoneNumberAuthentication(phoneNumber: String) -> Single - func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single - func requestBusinessNumberAuthentication(businessNumber: String) -> Single - func requestCheckingIdDuplication(id: String) -> Single + func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> + func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> + func requestBusinessNumberAuthentication(businessNumber: String) -> Single> + func requestCheckingIdDuplication(id: String) -> Single> } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthRepository.swift index d0cd139e..9f1a80c5 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthRepository.swift @@ -10,18 +10,18 @@ import RxSwift public protocol AuthRepository: RepositoryBase { // MARK: Center - func requestRegisterCenterAccount(managerName: String, phoneNumber: String, businessNumber: String, id: String, password: String) -> Single - func requestCenterLogin(id: String, password: String) -> Single - func signoutCenterAccount() -> Single - func deregisterCenterAccount(reasons: [String], password: String) -> Single - func getCenterJoinStatus() -> Single - func requestCenterJoin() -> Single - func setNewPassword(phoneNumber: String, password: String) -> Single + func requestRegisterCenterAccount(managerName: String, phoneNumber: String, businessNumber: String, id: String, password: String) -> Single> + func requestCenterLogin(id: String, password: String) -> Single> + func signoutCenterAccount() -> Single> + func deregisterCenterAccount(reasons: [String], password: String) -> Single> + func getCenterJoinStatus() -> Single> + func requestCenterJoin() -> Single> + func setNewPassword(phoneNumber: String, password: String) -> Single> // MARK: Worker - func requestRegisterWorkerAccount(registerState: WorkerRegisterState) -> Single - func requestWorkerLogin(phoneNumber: String, authNumber: String) -> Single - func signoutWorkerAccount() -> Single - func deregisterWorkerAccount(reasons: [String]) -> Single + func requestRegisterWorkerAccount(registerState: WorkerRegisterState) -> Single> + func requestWorkerLogin(phoneNumber: String, authNumber: String) -> Single> + func signoutWorkerAccount() -> Single> + func deregisterWorkerAccount(reasons: [String]) -> Single> } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift index 8f71678f..bec59e22 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/RecruitmentPost/RecruitmentPostRepository.swift @@ -14,65 +14,65 @@ public protocol RecruitmentPostRepository: RepositoryBase { // MARK: Center - post crud /// 공고를 등록합니다. - func registerPost(bundle: RegisterRecruitmentPostBundle) -> Single - + func registerPost(bundle: RegisterRecruitmentPostBundle) -> Single> + /// 센터측에서 등록한 공고의 상세내역을 확인합니다. - func getPostDetailForCenter(id: String) -> Single - + func getPostDetailForCenter(id: String) -> Single> + /// 센터가 등록한 공고의 상세정보를 수정합니다. - func editPostDetail(id: String, bundle: RegisterRecruitmentPostBundle) -> Single - + func editPostDetail(id: String, bundle: RegisterRecruitmentPostBundle) -> Single> + // MARK: Center - check posts /// 현재 진행중인 공고를 획득합니다. - func getOngoingPosts() -> Single<[RecruitmentPostInfoForCenterVO]> - - /// 현재 진행중인 공고를 획득합니다. - func getClosedPosts() -> Single<[RecruitmentPostInfoForCenterVO]> - + func getOngoingPosts() -> Single> + + /// 닫힌 공고를 획득합니다. + func getClosedPosts() -> Single> + /// 특정 공고의 지원자 수를 확인합니다. - func getPostApplicantCount(id: String) -> Single - + func getPostApplicantCount(id: String) -> Single> + /// 특정 공고의 지원자 리스트를 조회합니다. 요약된 공고정보가 포함되어 있습니다. - func getPostApplicantScreenData(id: String) -> Single - + func getPostApplicantScreenData(id: String) -> Single> + /// 공고를 종료합니다. - func closePost(id: String) -> Single - + func closePost(id: String) -> Single> + /// 공고를 삭제합니다. - func removePost(id: String) -> Single - + func removePost(id: String) -> Single> + // MARK: Worker /// 요양보호사 앱내 공고의 상세정보를 조회합니다. - func getNativePostDetailForWorker(id: String) -> Single - + func getNativePostDetailForWorker(id: String) -> Single> + /// 요양보호사 워크넷 공고의 상세정보를 조회합니다. - func getWorknetPostDetailForWorker(id: String) -> Single - + func getWorknetPostDetailForWorker(id: String) -> Single> + // MARK: Native post - + /// 요양보호사가 확인하는 케어밋 자체 공고정보를 가져옵니다. - func getNativePostListForWorker(nextPageId: String?, requestCnt: Int) -> Single - + func getNativePostListForWorker(nextPageId: String?, requestCnt: Int) -> Single> + /// 요양보호사가 즐겨찾는 케어밋 자체 공고정보를 가져옵니다. - func getNativeFavoritePostListForWorker() -> Single<[RecruitmentPostForWorkerRepresentable]> - + func getNativeFavoritePostListForWorker() -> Single> + /// 요양보호사가 즐겨찾는 워크넷 공고정보를 가져옵니다. - func getWorknetFavoritePostListForWorker() -> Single<[RecruitmentPostForWorkerRepresentable]> - + func getWorknetFavoritePostListForWorker() -> Single> + /// 요양보호사가 확인하는 케어밋 자체 공고정보를 가져옵니다. - func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> Single - + func getAppliedPostListForWorker(nextPageId: String?, requestCnt: Int) -> Single> + // MARK: Worknet Post - + /// 요양보호사가 확인하는 워크넷 공고정보를 가져옵니다. - func getWorknetPostListForWorker(nextPageId: String?, requestCnt: Int) -> Single - + func getWorknetPostListForWorker(nextPageId: String?, requestCnt: Int) -> Single> + /// 요양보호사가 인앱 공고에 지원합니다. - func applyToPost(postId: String, method: ApplyType) -> Single - + func applyToPost(postId: String, method: ApplyType) -> Single> + /// 요양보호사 즐겨찾기 공고 추가 - func addFavoritePost(postId: String, type: PostOriginType) -> Single - + func addFavoritePost(postId: String, type: PostOriginType) -> Single> + /// 요양보호사 즐겨찾기 공고 삭제 - func removeFavoritePost(postId: String) -> Single + func removeFavoritePost(postId: String) -> Single> } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift b/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift index a564b33e..5dfcd20d 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/RepositoryBase.swift @@ -15,7 +15,7 @@ public protocol RepositoryBase { } public extension RepositoryBase { /// Repository로 부터 전달받은 언어레벨의 에러를 도메인 특화 에러로 변경하고, error를 Result의 Failure로, 성공을 Success로 변경합니다. - func convert(task: Single) -> Single> { + func convertToDomain(task: Single) -> Single> { Single.create { single in let disposable = task .subscribe { success in diff --git a/project/Projects/Domain/Sources/RepositoryInterface/UserInfo/UserProfileRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/UserInfo/UserProfileRepository.swift index 6f0a6767..8e2b9d12 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/UserInfo/UserProfileRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/UserInfo/UserProfileRepository.swift @@ -11,15 +11,22 @@ import Foundation import RxSwift public protocol UserProfileRepository: RepositoryBase { - - func registerCenterProfileForText(state: CenterProfileRegisterState) -> Single - - func getCenterProfile(mode: ProfileMode) -> Single - func updateCenterProfileForText(phoneNumber: String, introduction: String?) -> Single - - // ImageUpload - func uploadImage(_ userType: UserType, imageInfo: ImageUploadInfo) -> Single - - func getWorkerProfile(mode: ProfileMode) -> Single - func updateWorkerProfile(stateObject: WorkerProfileStateObject) -> Single + + // 센터 프로필 등록 (텍스트 정보) + func registerCenterProfileForText(state: CenterProfileRegisterState) -> Single> + + // 센터 프로필 가져오기 + func getCenterProfile(mode: ProfileMode) -> Single> + + // 센터 프로필 업데이트 (텍스트 정보) + func updateCenterProfileForText(phoneNumber: String, introduction: String?) -> Single> + + // 이미지 업로드 + func uploadImage(_ userType: UserType, imageInfo: ImageUploadInfo) -> Single> + + // 요양보호사 프로필 가져오기 + func getWorkerProfile(mode: ProfileMode) -> Single> + + // 요양보호사 프로필 업데이트 + func updateWorkerProfile(stateObject: WorkerProfileStateObject) -> Single> } From 4a08be7968f3d503533e4ff43bf90779532a71fa Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Wed, 9 Oct 2024 10:34:53 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[IDLE-409]=20UseCase=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EB=B0=8F=20=EC=84=BC=ED=84=B0=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=88=98=EC=A0=95=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...DefaultAuthInputValidationRepository.swift | 8 +- ...tNotificationTokenTransferRepository.swift | 4 +- .../DefaultUserProfileRepository.swift | 3 + .../DefaultAuthInputValidationUseCase.swift | 20 +-- .../Auth/DefaultAuthUseCase.swift | 64 +++++++--- .../DefaultCenterCertificateUseCase.swift | 32 +++-- .../DefualtRecruitmentPostUseCase.swift | 102 ++++++++------- .../Setting/DefaultSettingUseCase.swift | 52 ++++---- .../DefaultCenterProfileUseCase.swift | 112 +++++++++++++---- .../DefaultWorkerProfileUseCase.swift | 60 ++++++--- .../Post/RecruitmentPostInfoForCenterVO.swift | 5 + .../Auth/AuthInputValidationRepository.swift | 4 +- .../Auth/AuthInputValidationUseCase.swift | 4 +- .../UseCaseInterface/BaseUseCase.swift | 51 -------- .../CenterAccountRegisterViewModel.swift | 22 ++-- .../View/AuthInOutStreamManager+Signin.swift | 11 +- .../Base/Sources/BaseVM/BaseViewModel.swift | 4 +- .../CenterProfileViewModel.swift | 117 +++++++++--------- 18 files changed, 389 insertions(+), 286 deletions(-) diff --git a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift index 103ba872..1f68a9e6 100644 --- a/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift +++ b/project/Projects/Data/Repository/DefaultAuthInputValidationRepository.swift @@ -19,19 +19,19 @@ public class DefaultAuthInputValidationRepository: AuthInputValidationRepository public init() { } - public func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> { + public func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> { let dataTask = networkService .request(api: .startPhoneNumberAuth(phoneNumber: phoneNumber), with: .plain) - .mapToVoid() + .map { _ in phoneNumber } return convertToDomain(task: dataTask) } - public func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> { + public func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> { let dataTask = networkService.request(api: .checkAuthNumber(phoneNumber: phoneNumber, authNumber: authNumber), with: .plain) - .mapToVoid() + .map { _ in phoneNumber } return convertToDomain(task: dataTask) } diff --git a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift index 0377257e..0815df2b 100644 --- a/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift +++ b/project/Projects/Data/Repository/DefaultNotificationTokenTransferRepository.swift @@ -28,7 +28,7 @@ public class DefaultNotificationTokenTransferRepository: NotificationTokenTransf ) .mapToVoid() - return convert(task: dataTask) + return convertToDomain(task: dataTask) } public func deleteToken(token: String) -> Single> { @@ -40,6 +40,6 @@ public class DefaultNotificationTokenTransferRepository: NotificationTokenTransf ) .mapToVoid() - return convert(task: dataTask) + return convertToDomain(task: dataTask) } } diff --git a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift index 60735cf8..bc395462 100644 --- a/project/Projects/Data/Repository/DefaultUserProfileRepository.swift +++ b/project/Projects/Data/Repository/DefaultUserProfileRepository.swift @@ -144,6 +144,8 @@ public class DefaultUserProfileRepository: UserProfileRepository { public func uploadImage(_ userType: UserType, imageInfo: ImageUploadInfo) -> Single> { let getPreSignedUrlResult = getPreSignedUrl(userType, ext: imageInfo.ext) + .asObservable() + .share() let getPreSignedUrlSuccess = getPreSignedUrlResult.compactMap { $0.value } let getPreSignedUrlFailure = getPreSignedUrlResult.compactMap { $0.error } @@ -163,6 +165,7 @@ public class DefaultUserProfileRepository: UserProfileRepository { } } } + .share() let uploadImageToPreSignedUrlSuccess = uploadImageToPreSignedUrlResult.compactMap { $0.value } let uploadImageToPreSignedUrlFailure = uploadImageToPreSignedUrlResult.compactMap { $0.error } diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift index 2dbb7d0c..5f047c93 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthInputValidationUseCase.swift @@ -26,10 +26,8 @@ public class DefaultAuthInputValidationUseCase: AuthInputValidationUseCase { // MARK: 전화번호 인증 public func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> { - convert(task: self.repository + repository .requestPhoneNumberAuthentication(phoneNumber: phoneNumber) - .map { _ in phoneNumber } - ) } public func checkPhoneNumberIsValid(phoneNumber: String) -> Bool { @@ -40,18 +38,14 @@ public class DefaultAuthInputValidationUseCase: AuthInputValidationUseCase { } public func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> { - convert(task: repository + repository .authenticateAuthNumber(phoneNumber: phoneNumber, authNumber: authNumber) - .map({ _ in phoneNumber }) - ) } // MARK: 사업자 번호 인증 - public func requestBusinessNumberAuthentication(businessNumber: String) -> Single> { - convert(task: repository + public func requestBusinessNumberAuthentication(businessNumber: String) -> Single> { + repository .requestBusinessNumberAuthentication(businessNumber: businessNumber) - .map({ vo in (businessNumber, vo) }) - ) } public func checkBusinessNumberIsValid(businessNumber: String) -> Bool { @@ -69,11 +63,9 @@ public class DefaultAuthInputValidationUseCase: AuthInputValidationUseCase { return predicate.evaluate(with: id) } - public func requestCheckingIdDuplication(id: String) -> Single> { - convert(task: repository + public func requestCheckingIdDuplication(id: String) -> Single> { + repository .requestCheckingIdDuplication(id: id) - .map({ _ in id }) - ) } public func checkPasswordIsValid(password: String) -> Bool { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift index 8a18312d..b3c9649b 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Auth/DefaultAuthUseCase.swift @@ -60,11 +60,23 @@ public class DefaultAuthUseCase: AuthUseCase { // 요양 보호사 회원가입 실행, 성공한 경우 프로필 Fetch후 저장 public func registerWorkerAccount(registerState: WorkerRegisterState) -> Single> { - authRepository - .requestRegisterWorkerAccount(registerState: registerState) + let registerResult = authRepository.requestRegisterWorkerAccount(registerState: registerState) + + let registerSuccess = registerResult.compactMap({ $0.value }) + let registerFailure = registerResult.compactMap({ $0.error }) + + let fetchProfileResult = registerSuccess + .asObservable() .flatMap { [userProfileRepository] _ in - userProfileRepository.getWorkerProfile(mode: .myProfile) + userProfileRepository + .getWorkerProfile(mode: .myProfile) } + .share() + + let fetchProfileSuccess = fetchProfileResult.compactMap { $0.value} + let fetchProfileFailure = fetchProfileResult.compactMap { $0.error} + + let saveAndNotificationResult = fetchProfileSuccess .map { [userInfoLocalRepository] vo in userInfoLocalRepository.updateUserType(.worker) userInfoLocalRepository.updateCurrentWorkerData(vo: vo) @@ -73,30 +85,54 @@ public class DefaultAuthUseCase: AuthUseCase { // 원격알림 토큰을 서버에 전송 notificationTokenUseCase.setNotificationToken() } + + return Observable.merge( + saveAndNotificationResult, + Observable + .merge(registerFailure.asObservable(), fetchProfileFailure.asObservable()) + .map { error -> Result in .failure(error) } + ).asSingle() } // 요양 보호사 로그인 실행, 성공한 경우 프로필 Fetch후 저장 public func loginWorkerAccount(phoneNumber: String, authNumber: String) -> Single> { - authRepository.requestWorkerLogin(phoneNumber: phoneNumber, authNumber: authNumber) + let loginResult = authRepository.requestWorkerLogin(phoneNumber: phoneNumber, authNumber: authNumber) + .asObservable() .flatMap { [userProfileRepository] _ in userProfileRepository.getWorkerProfile(mode: .myProfile) } - .map { [userInfoLocalRepository] vo in - userInfoLocalRepository.updateUserType(.worker) - userInfoLocalRepository.updateCurrentWorkerData(vo: vo) - } - .flatMap { [notificationTokenUseCase] _ in - // 원격알림 토큰을 서버에 전송 - notificationTokenUseCase.setNotificationToken() - } + .share() + + let loginSuccess = loginResult.compactMap { $0.value } + let loginFailure = loginResult.compactMap { $0.error } + + let tokenTransferResult = loginSuccess + .asObservable() + .map { [userInfoLocalRepository] vo in + userInfoLocalRepository.updateUserType(.worker) + userInfoLocalRepository.updateCurrentWorkerData(vo: vo) + } + .flatMap { [notificationTokenUseCase] _ in + // 원격알림 토큰을 서버에 전송 + notificationTokenUseCase.setNotificationToken() + } + + return Observable + .merge( + tokenTransferResult, + loginFailure.map({ error -> Result in + .failure(error) + }).asObservable() + ) + .asSingle() } public func checkCenterJoinStatus() -> Single> { - convert(task: authRepository.getCenterJoinStatus()) + authRepository.getCenterJoinStatus() } public func setNewPassword(phoneNumber: String, password: String) -> Single> { - convert(task: authRepository.setNewPassword(phoneNumber: phoneNumber, password: password)) + authRepository.setNewPassword(phoneNumber: phoneNumber, password: password) } } diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift index 02d8d557..b6853563 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/CenterCertificate/DefaultCenterCertificateUseCase.swift @@ -22,37 +22,35 @@ public class DefaultCenterCertificateUseCase: CenterCertificateUseCase { public func requestCenterCertificate() -> RxSwift.Single> { - convert(task: authRepository.requestCenterJoin()) + authRepository.requestCenterJoin() } public func getCenterJoinStatus() -> RxSwift.Single> { - convert(task: authRepository.getCenterJoinStatus()) + + authRepository.getCenterJoinStatus() } // 센터 로그아웃 public func signoutCenterAccount() -> RxSwift.Single> { - let task = authRepository + authRepository .signoutCenterAccount() - .map { [weak self] _ in - self?.removeAllLocalData() - - return () + .map { [weak self] result in + if case .success = result { + self?.userInfoLocalRepository.removeAllData() + } + return result } - return convert(task: task) } // 요양보호사 로그아웃 public func signoutWorkerAccount() -> RxSwift.Single> { - let task = authRepository + authRepository .signoutWorkerAccount() - .map { [weak self] _ in - self?.removeAllLocalData() - - return () + .map { [weak self] result in + if case .success = result { + self?.userInfoLocalRepository.removeAllData() + } + return result } - return convert(task: task) - } - private func removeAllLocalData() { - userInfoLocalRepository.removeAllData() } } diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift index e3634fe8..371f79c0 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/RecruitmentPost/DefualtRecruitmentPostUseCase.swift @@ -26,11 +26,7 @@ public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { inputs.applicationDetail.deadlineDate = oneMonthLater } - return convert( - task: repository.registerPost( - bundle: inputs - ) - ) + return repository.registerPost(bundle: inputs) } public func editRecruitmentPost(id: String, inputs: RegisterRecruitmentPostBundle) -> RxSwift.Single> { @@ -40,65 +36,68 @@ public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { inputs.applicationDetail.deadlineDate = oneMonthLater } - return convert( - task: repository.editPostDetail( - id: id, - bundle: inputs - ) - ) + return repository.editPostDetail(id: id, bundle: inputs) } public func getPostDetailForCenter(id: String) -> RxSwift.Single> { - convert(task: repository.getPostDetailForCenter(id: id)) + repository.getPostDetailForCenter(id: id) } public func getNativePostDetailForWorker(id: String) -> RxSwift.Single> { - convert(task: repository.getNativePostDetailForWorker(id: id)) + repository.getNativePostDetailForWorker(id: id) } public func getWorknetPostDetailForWorker(id: String) -> RxSwift.Single> { - convert(task: repository.getWorknetPostDetailForWorker(id: id)) + repository.getWorknetPostDetailForWorker(id: id) } - public func getOngoingPosts() -> RxSwift.Single> { - let task = repository + public func getOngoingPosts() -> Single> { + + repository .getOngoingPosts() - .map { postInfo in - postInfo.forEach { vo in vo.state = .onGoing } - return postInfo + .map { result -> Result<[RecruitmentPostInfoForCenterVO], DomainError> in + + if case .success(let postInfos) = result { + + return .success(postInfos.map { $0.setState(.onGoing) }) + } + return result } - return convert(task: task) } public func getClosedPosts() -> RxSwift.Single> { - let task = repository + + repository .getClosedPosts() - .map { postInfo in - postInfo.forEach { vo in vo.state = .closed } - return postInfo + .map { result -> Result<[RecruitmentPostInfoForCenterVO], DomainError> in + + if case .success(let postInfos) = result { + + return .success(postInfos.map { $0.setState(.closed) }) + } + return result } - return convert(task: task) } public func closePost(id: String) -> Single> { - convert(task: repository.closePost(id: id)) + repository.closePost(id: id) } public func removePost(id: String) -> Single> { - convert(task: repository.removePost(id: id)) + repository.removePost(id: id) } public func getPostApplicantCount(id: String) -> RxSwift.Single> { - convert(task: repository.getPostApplicantCount(id: id)) + repository.getPostApplicantCount(id: id) } public func getPostApplicantScreenData(id: String) -> RxSwift.Single> { - convert(task: repository.getPostApplicantScreenData(id: id)) + repository.getPostApplicantScreenData(id: id) } public func getPostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> Single> { - let stream: Single! + let stream: Single>! switch request { case .initial: @@ -121,26 +120,43 @@ public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { } } - return convert(task: stream) + return stream } public func getFavoritePostListForWorker() -> RxSwift.Single> { - let nativeList = repository.getNativeFavoritePostListForWorker() - let worknetList = repository.getWorknetFavoritePostListForWorker() + let fetchNativeListResult = repository.getNativeFavoritePostListForWorker() + let nativeSuccess = fetchNativeListResult.compactMap { $0.value } + let nativeFailure = fetchNativeListResult.compactMap { $0.error } + + let fetchWorknetListResult = repository + .getWorknetFavoritePostListForWorker() + .asObservable() + .share() + let worknetSuccess = fetchWorknetListResult.compactMap { $0.value } + let worknetFailure = fetchWorknetListResult.compactMap { $0.error } + + + let successZip = Observable + .zip(nativeSuccess.asObservable(), worknetSuccess.asObservable()) + .map { (native, worknet) -> Result<[RecruitmentPostForWorkerRepresentable], DomainError> in + .success(native + worknet) + } - let task = Single - .zip(nativeList, worknetList) - .map { (native, worknet) in - native + worknet + let failureMerge = Observable + .merge(nativeFailure.asObservable(), worknetFailure.asObservable()) + .map { error -> Result<[RecruitmentPostForWorkerRepresentable], DomainError> in + .failure(error) } - return convert(task: task) + return Observable + .merge(successZip, failureMerge) + .asSingle() } public func getAppliedPostListForWorker(request: PostPagingRequestForWorker, postCount: Int) -> RxSwift.Single> { - let stream: Single! + let stream: Single>! switch request { case .initial: @@ -161,18 +177,18 @@ public class DefaultRecruitmentPostUseCase: RecruitmentPostUseCase { } } - return convert(task: stream) + return stream } public func applyToPost(postId: String, method: ApplyType) -> RxSwift.Single> { - convert(task: repository.applyToPost(postId: postId, method: method)) + repository.applyToPost(postId: postId, method: method) } public func addFavoritePost(postId: String, type: PostOriginType) -> Single> { - convert(task: repository.addFavoritePost(postId: postId, type: type)) + repository.addFavoritePost(postId: postId, type: type) } public func removeFavoritePost(postId: String) -> Single> { - convert(task: repository.removeFavoritePost(postId: postId)) + repository.removeFavoritePost(postId: postId) } } diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift index 5b435873..f9304d03 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/Setting/DefaultSettingUseCase.swift @@ -83,16 +83,16 @@ public class DefaultSettingUseCase: SettingScreenUseCase { switch result { case .success: - let task = authRepository + authRepository .deregisterCenterAccount(reasons: reasons, password: password) - .map { [weak self] _ in - self?.removeAllLocalData() - - return () + .map { [weak self] result in + if case .success = result { + self?.removeAllLocalData() + } + return result } - return self.convert(task: task) case .failure: - return Single.just(result) + Single.just(result) } } } @@ -105,42 +105,42 @@ public class DefaultSettingUseCase: SettingScreenUseCase { switch result { case .success: - let task = authRepository + authRepository .signoutCenterAccount() - .map { [weak self] ads in - self?.removeAllLocalData() - - return ads + .map { [weak self] result in + if case .success = result { + self?.removeAllLocalData() + } + return result } - return self.convert(task: task) case .failure: - return Single.just(result) + Single.just(result) } } } // 요양보호사 회원탈퇴 public func deregisterWorkerAccount(reasons: [String]) -> RxSwift.Single> { - let task = authRepository + authRepository .deregisterWorkerAccount(reasons: reasons) - .map { [weak self] _ in - self?.removeAllLocalData() - - return () + .map { [weak self] result in + if case .success = result { + self?.removeAllLocalData() + } + return result } - return convert(task: task) } // 요양보호사 로그아웃 public func signoutWorkerAccount() -> RxSwift.Single> { - let task = authRepository + authRepository .signoutWorkerAccount() - .map { [weak self] _ in - self?.removeAllLocalData() - - return () + .map { [weak self] result in + if case .success = result { + self?.removeAllLocalData() + } + return result } - return convert(task: task) } private func removeAllLocalData() { diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift index bcbca84a..280a40fe 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultCenterProfileUseCase.swift @@ -31,21 +31,23 @@ public class DefaultCenterProfileUseCase: CenterProfileUseCase { } public func getFreshProfile(mode: ProfileMode) -> RxSwift.Single> { - convert(task: userProfileRepository.getCenterProfile(mode: mode)) + userProfileRepository.getCenterProfile(mode: mode) } public func updateProfile(phoneNumber: String?, introduction: String?, imageInfo: ImageUploadInfo?) -> Single> { - var updateTextTask: Single! - var updateImageTask: Single! + var updateTextTask: Observable>! + var updateImageTask: Observable>! if let phoneNumber { updateTextTask = userProfileRepository.updateCenterProfileForText( phoneNumber: phoneNumber, introduction: introduction ) + .asObservable() + .share() } else { - updateTextTask = .just(()) + updateTextTask = .just(.success(())) } if let imageInfo { @@ -53,30 +55,59 @@ public class DefaultCenterProfileUseCase: CenterProfileUseCase { .center, imageInfo: imageInfo ) + .asObservable() + .share() } else { - updateImageTask = .just(()) + updateImageTask = .just(.success(())) } - let task = Observable + let textSuccess = updateTextTask.compactMap { $0.value } + let textFailure = updateTextTask.compactMap { $0.error } + + let imageSuccess = updateImageTask.compactMap { $0.value } + let imageFailure = updateImageTask.compactMap { $0.error } + + let fetchProfileResult = Observable .zip( - updateTextTask.asObservable(), - updateImageTask.asObservable() + textSuccess.asObservable(), + imageSuccess.asObservable() ) .flatMap { [userProfileRepository] _ in // 등록성공후 내프로필 불러오기 userProfileRepository.getCenterProfile(mode: .myProfile) } - .map({ [userInfoLocalRepository] vo in - userInfoLocalRepository.updateCurrentCenterData(vo: vo) - }) - .asSingle() + .share() + + let task = fetchProfileResult + .map { [userInfoLocalRepository] result -> Result in + switch result { + case .success(let vo): + userInfoLocalRepository.updateCurrentCenterData(vo: vo) + return .success(()) + case .failure(let error): + return .failure(error) + } + } - return convert(task: task) + let failures = Observable + .merge( + textFailure.asObservable(), + imageFailure.asObservable() + ) + .map { error -> Result in + .failure(error) + } + + return Observable.merge( + task.asObservable(), + failures + ) + .asSingle() } public func registerCenterProfile(state: CenterProfileRegisterState) -> Single> { - var registerImageTask: Single! + var registerImageTask: Observable>! let imageInfo = state.imageInfo @@ -85,26 +116,57 @@ public class DefaultCenterProfileUseCase: CenterProfileUseCase { .center, imageInfo: imageInfo ) + .asObservable() + .share() } else { - registerImageTask = .just(()) + registerImageTask = .just(.success(())) } - let registerTextTask = userProfileRepository.registerCenterProfileForText(state: state) - - let task = Observable + let registerImageTaskSuccess = registerImageTask.compactMap { $0.value } + let registerImageTaskFailure = registerImageTask.compactMap { $0.error } + + let registerTextTask = userProfileRepository + .registerCenterProfileForText(state: state) + .asObservable() + .share() + let registerTextTaskSuccess = registerTextTask.compactMap { $0.value } + let registerTextTaskFailure = registerTextTask.compactMap { $0.error } + + let fetchProfileResult = Observable .zip( - registerTextTask.asObservable(), - registerImageTask.asObservable() + registerImageTaskSuccess.asObservable(), + registerTextTaskSuccess.asObservable() ) .flatMap { [userProfileRepository] _ in // 등록성공후 내프로필 불러오기 userProfileRepository.getCenterProfile(mode: .myProfile) } - .map({ [userInfoLocalRepository] vo in - userInfoLocalRepository.updateCurrentCenterData(vo: vo) - }) - .asSingle() + .share() + + let task = fetchProfileResult + .map { [userInfoLocalRepository] result -> Result in + switch result { + case .success(let vo): + userInfoLocalRepository.updateCurrentCenterData(vo: vo) + return .success(()) + case .failure(let error): + return .failure(error) + } + } + + let failures = Observable + .merge( + registerImageTaskFailure.asObservable(), + registerTextTaskFailure.asObservable() + ) + .map { error -> Result in + .failure(error) + } - return convert(task: task) + return Observable.merge( + task.asObservable(), + failures + ) + .asSingle() } } diff --git a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift index 2ecfd620..eb607214 100644 --- a/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift +++ b/project/Projects/Domain/Sources/ConcreteUseCase/UserInfo/DefaultWorkerProfileUseCase.swift @@ -31,40 +31,70 @@ public class DefaultWorkerProfileUseCase: WorkerProfileUseCase { } public func getFreshProfile(mode: ProfileMode) -> RxSwift.Single> { - convert(task: userProfileRepository.getWorkerProfile(mode: mode)) + userProfileRepository.getWorkerProfile(mode: mode) } public func updateProfile(stateObject: WorkerProfileStateObject, imageInfo: ImageUploadInfo?) -> Single> { - var updateTextTask: Single! - var updateImageTask: Single! + var updateTextTask: Observable>! + var updateImageTask: Observable>! - updateTextTask = userProfileRepository.updateWorkerProfile( - stateObject: stateObject - ) + updateTextTask = userProfileRepository.updateWorkerProfile(stateObject: stateObject) + .asObservable() + .share() if let imageInfo { updateImageTask = userProfileRepository.uploadImage( .worker, imageInfo: imageInfo ) + .asObservable() + .share() } else { - updateImageTask = .just(()) + updateImageTask = .just(.success(())) } - let task = Observable + let textSuccess = updateTextTask.compactMap { $0.value } + let textFailure = updateTextTask.compactMap { $0.error } + + let imageSuccess = updateImageTask.compactMap { $0.value } + let imageFailure = updateImageTask.compactMap { $0.error } + + let fetchProfileResult = Observable .zip( - updateTextTask.asObservable(), - updateImageTask.asObservable() + textSuccess.asObservable(), + imageSuccess.asObservable() ) .flatMap { [userProfileRepository] _ in + // 등록성공후 내프로필 불러오기 userProfileRepository.getWorkerProfile(mode: .myProfile) } - .map({ [userInfoLocalRepository] vo in - userInfoLocalRepository.updateCurrentWorkerData(vo: vo) - }) - .asSingle() + .share() + + let task = fetchProfileResult + .map { [userInfoLocalRepository] result -> Result in + switch result { + case .success(let vo): + userInfoLocalRepository.updateCurrentWorkerData(vo: vo) + return .success(()) + case .failure(let error): + return .failure(error) + } + } - return convert(task: task) + let failures = Observable + .merge( + textFailure.asObservable(), + imageFailure.asObservable() + ) + .map { error -> Result in + .failure(error) + } + + return Observable.merge( + task.asObservable(), + failures + ) + .asSingle() } } diff --git a/project/Projects/Domain/Sources/Entity/VO/Post/RecruitmentPostInfoForCenterVO.swift b/project/Projects/Domain/Sources/Entity/VO/Post/RecruitmentPostInfoForCenterVO.swift index d627cf5f..01b8cd34 100644 --- a/project/Projects/Domain/Sources/Entity/VO/Post/RecruitmentPostInfoForCenterVO.swift +++ b/project/Projects/Domain/Sources/Entity/VO/Post/RecruitmentPostInfoForCenterVO.swift @@ -40,4 +40,9 @@ public class RecruitmentPostInfoForCenterVO { self.applyDeadline = applyDeadline self.createdAt = createdAt } + + func setState(_ to: PostState) -> Self { + state = to + return self + } } diff --git a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift index 63751d43..e9884b45 100644 --- a/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift +++ b/project/Projects/Domain/Sources/RepositoryInterface/Auth/AuthInputValidationRepository.swift @@ -12,8 +12,8 @@ import RxSwift public protocol AuthInputValidationRepository: RepositoryBase { - func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> - func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> + func requestPhoneNumberAuthentication(phoneNumber: String) -> Single> + func authenticateAuthNumber(phoneNumber: String, authNumber: String) -> Single> func requestBusinessNumberAuthentication(businessNumber: String) -> Single> func requestCheckingIdDuplication(id: String) -> Single> } diff --git a/project/Projects/Domain/Sources/UseCaseInterface/Auth/AuthInputValidationUseCase.swift b/project/Projects/Domain/Sources/UseCaseInterface/Auth/AuthInputValidationUseCase.swift index 79774a35..3c8bcd47 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/Auth/AuthInputValidationUseCase.swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/Auth/AuthInputValidationUseCase.swift @@ -55,7 +55,7 @@ public protocol AuthInputValidationUseCase: BaseUseCase { /// - Observable // MARK: 사업자 번호 조회 - func requestBusinessNumberAuthentication(businessNumber: String) -> Single> + func requestBusinessNumberAuthentication(businessNumber: String) -> Single> // #5. /// 사업자 번호 유효성 로직 @@ -79,7 +79,7 @@ public protocol AuthInputValidationUseCase: BaseUseCase { /// - id : "idle1234" /// - returns: /// - Bool, true: 가능, flase: 증복 - func requestCheckingIdDuplication(id: String) -> Single> + func requestCheckingIdDuplication(id: String) -> Single> // #8. /// 아이디 유효성확인 로직 diff --git a/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift b/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift index 3ddb6f87..0d5c7793 100644 --- a/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift +++ b/project/Projects/Domain/Sources/UseCaseInterface/BaseUseCase.swift @@ -11,54 +11,3 @@ import Foundation import RxSwift public protocol BaseUseCase: AnyObject { } - -public extension BaseUseCase { - - /// Repository로 부터 전달받은 언어레벨의 에러를 도메인 특화 에러로 변경하고, error를 Result의 Failure로, 성공을 Success로 변경합니다. - func convert(task: Single) -> Single> { - Single.create { single in - let disposable = task - .subscribe { success in - single(.success(.success(success))) - } onFailure: { error in - single(.success(.failure(self.toDomainError(error: error)))) - } - return Disposables.create { disposable.dispose() } - } - } - - // MARK: InputValidationError - private func toDomainError(error: Error) -> DomainError { - - // 네트워크 에러 - if let httpError = error as? HTTPResponseException { - - if let code = httpError.rawCode { - - let domainError = DomainError(code: code) - - if domainError == .undefinedCode { - #if DEBUG - print("‼️ 정의되지 않은 에러코드가 발견되었습니다. 노션을 확인해주세요") - #endif - } - - return domainError - } - - #if DEBUG - print("InputValidationError변환실패 Error: \(httpError)") - #endif - } - - // 네트워크 에러보다 근본적인 에러 - if let underlyingError = error as? UnderLyingError { - - let domainError: DomainError = .undelyingError(error: underlyingError) - - return domainError - } - - return DomainError.undelyingError(error: .unHandledError) - } -} diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterViewModel.swift index 93664bfa..acc0288b 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/CenterAccountRegisterViewModel.swift @@ -228,19 +228,23 @@ extension CenterAccountRegisterViewModel { } .asDriver(onErrorJustReturn: false) - let businessNumberValidationResult = input + let requestingBusinessNumber = input .requestBusinessNumberValidation + .withLatestFrom(input.editingBusinessNumber) + .map { unformedNumber in + let formatted = AuthInOutStreamManager.formatBusinessNumber(businessNumber: unformedNumber) + return formatted + } + + let businessNumberValidationResult = requestingBusinessNumber .compactMap { $0 } - .flatMap { [weak self, input, inputValidationUseCase] _ in + .flatMap { [weak self, inputValidationUseCase] businessNumber in // 로딩 시작 self?.showLoading.onNext(()) - let businessNumber = input.editingBusinessNumber.value - let formatted = AuthInOutStreamManager.formatBusinessNumber(businessNumber: businessNumber) - printIfDebug("[CenterAccountRegisterViewModel] 사업자 번호 인증 요청: \(formatted)") return inputValidationUseCase - .requestBusinessNumberAuthentication(businessNumber: formatted) + .requestBusinessNumberAuthentication(businessNumber: businessNumber) } .share() @@ -251,9 +255,11 @@ extension CenterAccountRegisterViewModel { }) .disposed(by: disposeBag) - - output.businessNumberVO = businessNumberValidationResult + let businessNumberValidationSuccess = businessNumberValidationResult .compactMap { $0.value } + + output.businessNumberVO = Observable + .combineLatest(requestingBusinessNumber, businessNumberValidationSuccess) .map { [stateObject] (businessNumber, infoVO) in printIfDebug("✅ 사업자번호 검색 성공") // 🚀 상태추적 🚀 diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/View/AuthInOutStreamManager+Signin.swift b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/View/AuthInOutStreamManager+Signin.swift index c771e54b..9a71a863 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/View/AuthInOutStreamManager+Signin.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Center/AccountRegister/View/AuthInOutStreamManager+Signin.swift @@ -37,7 +37,7 @@ extension AuthInOutStreamManager { // 중복성 검사 let idDuplicationValidation = input .requestIdDuplicationValidation - .flatMap { [unowned useCase] id in + .flatMap { [useCase] id in printIfDebug("[CenterRegisterViewModel] 중복성 검사 대상 id: \(id)") @@ -46,16 +46,17 @@ extension AuthInOutStreamManager { print("✅ 디버그모드에서 아이디 중복검사 미실시") // ☑️ 상태추적 ☑️ stateTracker(id) - return Single.just(Result.success(id)) + return Single.just(Result.success(())) #endif return useCase.requestCheckingIdDuplication(id: id) } - output.idDuplicationValidation = idDuplicationValidation - .map { [stateTracker] result in + output.idDuplicationValidation = Observable + .combineLatest(idDuplicationValidation, input.requestIdDuplicationValidation) + .map { [stateTracker] (result, id) in switch result { - case .success(let id): + case .success: printIfDebug("[CenterRegisterViewModel] 중복체크 결과: ✅ 성공") // 🚀 상태추적 🚀 stateTracker(id) diff --git a/project/Projects/Presentation/Feature/Base/Sources/BaseVM/BaseViewModel.swift b/project/Projects/Presentation/Feature/Base/Sources/BaseVM/BaseViewModel.swift index 3f37155a..719b3e20 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/BaseVM/BaseViewModel.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/BaseVM/BaseViewModel.swift @@ -50,7 +50,7 @@ open class BaseViewModel { .asDriver(onErrorDriveWith: .never()) } - public func mapStartLoading(_ target: Observable) -> Observable { + public func mapStartLoading(_ target: T) -> Observable { target .throttle(.milliseconds(500), scheduler: MainScheduler.instance) @@ -62,7 +62,7 @@ open class BaseViewModel { } } - public func mapEndLoading(_ target: Observable) -> Observable { + public func mapEndLoading(_ target: T) -> Observable { target .map { [weak self] item in diff --git a/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileViewModel.swift b/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileViewModel.swift index 9c2ec2bb..06b181f2 100644 --- a/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileViewModel.swift +++ b/project/Projects/Presentation/Feature/UserProfile/Sources/CenterProfile/CenterProfileViewModel.swift @@ -33,7 +33,7 @@ protocol CenterProfileInputable { var editingFinishButtonPressed: PublishRelay { get } var editingPhoneNumber: BehaviorRelay { get } var editingInstruction: BehaviorRelay { get } - var selectedImage: PublishRelay { get } + var selectedImage: BehaviorRelay { get } var exitButtonClicked: PublishRelay { get } } @@ -73,7 +73,7 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { var editingFinishButtonPressed: PublishRelay = .init() var editingPhoneNumber: BehaviorRelay = .init(value: "") var editingInstruction: BehaviorRelay = .init(value: "") - var selectedImage: PublishRelay = .init() + var selectedImage: BehaviorRelay = .init(value: nil) var exitButtonClicked: RxRelay.PublishRelay = .init() // 기본 데이터 @@ -84,6 +84,8 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { var centerIntroduction: Driver? var displayingImage: Driver? + var originalPhonenumber: String = "" + // 수정 상태 여부 var isEditingMode: Driver? @@ -93,18 +95,6 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { // Image private let imageDownLoadScheduler = ConcurrentDispatchQueueScheduler(qos: .userInitiated) - func checkModification() -> (String?, String?, ImageUploadInfo?) { - - let phoneNumber = editingPhoneNumber.value - let instruction = editingInstruction.value - - return ( - phoneNumber == fetchedPhoneNumber ? nil : phoneNumber, - instruction == fetchedIntroduction ? nil : instruction, - editingImageInfo - ) - } - init(mode: ProfileMode) { self.mode = mode @@ -115,18 +105,18 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { super.init() // MARK: fetch from server - let profileRequestResult = readyToFetch + let profileRequestResult = mapEndLoading(mapStartLoading(readyToFetch) .unretained(self) .flatMap { (obj, _) in obj.profileUseCase.getProfile(mode: obj.mode) - } + }) .share() let profileRequestSuccess = profileRequestResult .compactMap { $0.value } .share() - let profileRequestFailure = profileRequestResult + let profileRequestFailureAlert = profileRequestResult .compactMap { $0.error } .map { error in DefaultAlertContentVO( @@ -156,64 +146,72 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { .map { [weak self] in let phoneNumber = $0.officeNumber self?.fetchedPhoneNumber = phoneNumber + self?.originalPhonenumber = phoneNumber return phoneNumber } .asDriver(onErrorJustReturn: "") - let fetchCenterImageInfo = profileRequestSuccess + let fetchCenterImageInfo = mapEndLoading(mapStartLoading(profileRequestSuccess) .compactMap { $0.profileImageInfo } .observe(on: imageDownLoadScheduler) .flatMap { [cacheRepository] downloadInfo in cacheRepository .getImage(imageInfo: downloadInfo) - }.map { image -> UIImage? in - image - } + }.map { image -> UIImage? in image }) // MARK: image validation - let imageValidationResult = selectedImage - .map { [unowned self] image -> UIImage? in - guard let imageInfo = self.validateSelectedImage(image: image) else { return nil } - printIfDebug("✅ 업로드 가능한 이미지 타입 \(imageInfo.ext)") - self.editingImageInfo = imageInfo - return image - } - .share() - - let imageValidationFailure = imageValidationResult - .filter { $0 == nil } - .map { _ in - DefaultAlertContentVO( - title: "이미지 선택 오류", - message: "지원하지 않는 이미지 형식입니다." - ) - } - let displayingImageDriver = Observable .merge( fetchCenterImageInfo, - imageValidationResult + selectedImage.compactMap { $0 } ) .asDriver(onErrorJustReturn: .init()) // 최신 값들 + 버튼이 눌릴 경우 변경 로직이 실행된다. - let editingRequestResult = mapEndLoading(mapStartLoading(editingFinishButtonPressed.asObservable()) - .map({ [unowned self] _ in - checkModification() - }) - .flatMap { [profileUseCase, editingPhoneNumber] (inputs) in - - let (phoneNumber, introduction, imageInfo) = inputs + let checkImageSelectionResult = mapStartLoading(editingFinishButtonPressed) + .withLatestFrom(selectedImage) + .share() + + let imageSelected = checkImageSelectionResult.compactMap { $0 } + let imageDoesntSelected = checkImageSelectionResult + .filter { $0 == nil } + .map { _ -> ImageUploadInfo? in nil } + + let imageEncodingResult = imageSelected + .observe(on: ConcurrentDispatchQueueScheduler(qos: .userInitiated)) + .map { image -> ImageUploadInfo? in + ImageUploadInfo.create(image: image) + } + .share() + + + let imageEcodingSuccess = imageEncodingResult.filter { $0 != nil } + let imageEcodingFailure = mapEndLoading(imageEncodingResult.filter { $0 == nil }) + + let imageEncodingFailureAlert = imageEcodingFailure.map { _ in + DefaultAlertContentVO( + title: "이미지 선택 오류", + message: "지원하지 않는 이미지 형식입니다." + ) + } + + let imageProcessingFinishWithSuccess = Observable.merge(imageEcodingSuccess, imageDoesntSelected) + + + let editingRequestResult = mapEndLoading(imageProcessingFinishWithSuccess + .unretained(self) + .flatMap { (obj, imageInfo) in + let (phoneNumber, introduction) = obj.checkTextInputModification() // 변경이 발생하지 않은 곳은 nil값이 전달된다. if let _ = phoneNumber { printIfDebug("✅ 전화번호 변경되었음") } if let _ = introduction { printIfDebug("✅ 센터소개 변경되었음") } if let _ = imageInfo { printIfDebug("✅ 센터 이미지 변경되었음") } - // 전화번호는 무조건 포함시켜야 함으로 아래와 같이 포함합니다. - return profileUseCase.updateProfile( - phoneNumber: phoneNumber ?? editingPhoneNumber.value, + // 전화번호는 무조건 포함시켜야 함으로 변경이 발생하지 않더라도 아래와 같이 포함합니다. + return obj.profileUseCase.updateProfile( + phoneNumber: phoneNumber ?? obj.originalPhonenumber, introduction: introduction, imageInfo: imageInfo ) @@ -233,7 +231,7 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { } .asDriver(onErrorJustReturn: ()) - let editingRequestFailure = editingRequestResult + let editingRequestFailureAlert = editingRequestResult .compactMap({ $0.error }) .map({ error in // 변경 실패 Alert @@ -272,9 +270,9 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { Observable .merge( - profileRequestFailure, - editingRequestFailure, - imageValidationFailure + profileRequestFailureAlert, + editingRequestFailureAlert, + imageEncodingFailureAlert ) .subscribe(self.alert) .disposed(by: disposeBag) @@ -296,7 +294,14 @@ class CenterProfileViewModel: BaseViewModel, CenterProfileViewModelable { self.editingValidation = editingValidation } - func validateSelectedImage(image: UIImage) -> ImageUploadInfo? { - .create(image: image) + func checkTextInputModification() -> (String?, String?) { + + let phoneNumber = editingPhoneNumber.value + let instruction = editingInstruction.value + + return ( + phoneNumber == fetchedPhoneNumber ? nil : phoneNumber, + instruction == fetchedIntroduction ? nil : instruction + ) } } From 99182cf2eaf17f80b823ff4c1791c6fec5a69eb8 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Wed, 9 Oct 2024 14:14:27 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[IDLE-409]=20=EC=84=BC=ED=84=B0=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EC=9E=90=ED=99=95=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=94=A5=EB=A7=81=ED=81=AC=20=EA=B0=9D=EC=B2=B4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DeepLink/DeepLinkExecutable.swift | 4 +-- .../DeepLinks/CenterMainPageDeepLink.swift | 33 +++++++++++++++++ .../DeepLinks/PostApplicantDeepLink.swift | 34 ++++++++++++++++++ project/graph.png | Bin 130166 -> 144283 bytes 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift create mode 100644 project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift index db8b2036..0bfbb652 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift @@ -11,7 +11,7 @@ public protocol DeepLinkTreeNode { var name: String { get } var children: [DeepLinkExecutable] { get } -// var isDestination: Bool { get set } + var isDestination: Bool { get set } func findChild(name: String) -> DeepLinkExecutable? } @@ -21,7 +21,7 @@ public protocol DeepLinkExecutable: DeepLinkTreeNode { func execute(with coordinator: Coordinator, userInfo: [String: String]?) -> Coordinator? } -extension DeepLinkExecutable { +public extension DeepLinkExecutable { func findChild(name: String) -> DeepLinkExecutable? { children.first(where: { $0.name == name }) diff --git a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift b/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift new file mode 100644 index 00000000..6352c7a7 --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift @@ -0,0 +1,33 @@ +// +// CenterMainPageDeepLink.swift +// RootFeature +// +// Created by choijunios on 10/9/24. +// + +import Foundation +import BaseFeature + +class CenterMainPageDeepLink: DeepLinkExecutable { + + var name: String = "CenterMainPage" + + var children: [DeepLinkExecutable] = [ + PostApplicantDeepLink() + ] + + var isDestination: Bool = false + + init() { } + + func execute(with coordinator: Coordinator, userInfo: [String : String]?) -> Coordinator? { + + guard let appCoordinator = coordinator as? AppCoordinator else { + return nil + } + + let mainPageCoordinator = appCoordinator.runCenterMainPageFlow() + + return mainPageCoordinator + } +} diff --git a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift b/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift new file mode 100644 index 00000000..9121f0f2 --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift @@ -0,0 +1,34 @@ +// +// PostApplicantDeepLink.swift +// RootFeature +// +// Created by choijunios on 10/9/24. +// + +import Foundation +import CenterMainPageFeature +import BaseFeature + +class PostApplicantDeepLink: DeepLinkExecutable { + + var name: String = "PostApplicantPage" + + var children: [DeepLinkExecutable] = [] + + var isDestination: Bool = false + + init() { } + + func execute(with coordinator: Coordinator, userInfo: [String : String]?) -> Coordinator? { + + guard let centerMainPageCoordinator = coordinator as? CenterMainPageCoordinator else { + return nil + } + + guard let postId = userInfo?["postId"] else { return nil } + + centerMainPageCoordinator.presentPostApplicantPage(postId: postId) + + return centerMainPageCoordinator + } +} diff --git a/project/graph.png b/project/graph.png index 4da4ae8d71839803a00789c90f4eaac9cbe891a8..53be928f6640e3b1aa983cd598e06ac2ab74c43d 100644 GIT binary patch literal 144283 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

EeyPPyHBp@c#@F~ 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 F1OT6E5l;XB literal 130166 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

o~acl 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 Date: Wed, 9 Oct 2024 17:28:53 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[IDLE-409]=20=EB=B0=B1=EA=B7=B8=EB=9D=BC?= =?UTF-8?q?=EC=9A=B4=EB=93=9C=20=EC=83=81=ED=83=9C=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EC=9E=90=20=ED=99=95=EC=9D=B8=20=EB=94=A5=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DeepLink/DeepLinkExecutable.swift | 31 ------------ .../Sources/DeepLink/DeeplinkExecutable.swift | 31 ++++++++++++ .../Feature/Base/Sources/Router/Router.swift | 18 +++---- .../Sources/Application/AppCoordinator.swift | 39 ++++++++++++++- .../Components/CenterMainPageDeeplink.swift} | 10 ++-- .../Components/PostApplicantDeeplink.swift} | 10 ++-- .../Deeplinks/Components/SplashDeeplink.swift | 33 ++++++++++++ .../Sources/Deeplinks/DeeplinkParser.swift | 50 +++++++++++++++++++ .../FireBaseTokenRepository.swift | 3 +- .../RemoteNotificationHelper.swift | 44 ++++++++++++++-- .../Splash/Sources/SplashCoordinator.swift | 7 +++ 11 files changed, 217 insertions(+), 59 deletions(-) delete mode 100644 project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift create mode 100644 project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift rename project/Projects/Presentation/Feature/Root/Sources/{DeepLinks/CenterMainPageDeepLink.swift => Deeplinks/Components/CenterMainPageDeeplink.swift} (63%) rename project/Projects/Presentation/Feature/Root/Sources/{DeepLinks/PostApplicantDeepLink.swift => Deeplinks/Components/PostApplicantDeeplink.swift} (62%) create mode 100644 project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift create mode 100644 project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift deleted file mode 100644 index 0bfbb652..00000000 --- a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeepLinkExecutable.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// DeepLinkExecutable.swift -// BaseFeature -// -// Created by choijunios on 10/2/24. -// - -import Foundation - -public protocol DeepLinkTreeNode { - - var name: String { get } - var children: [DeepLinkExecutable] { get } - var isDestination: Bool { get set } - - func findChild(name: String) -> DeepLinkExecutable? -} - -public protocol DeepLinkExecutable: DeepLinkTreeNode { - @discardableResult - func execute(with coordinator: Coordinator, userInfo: [String: String]?) -> Coordinator? -} - -public extension DeepLinkExecutable { - - func findChild(name: String) -> DeepLinkExecutable? { - children.first(where: { $0.name == name }) - } -} - - diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift new file mode 100644 index 00000000..a1676c6d --- /dev/null +++ b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift @@ -0,0 +1,31 @@ +// +// DeepLinkExecutable.swift +// BaseFeature +// +// Created by choijunios on 10/2/24. +// + +import Foundation + +public protocol DeeplinkTreeNode { + + var name: String { get } + var children: [DeeplinkExecutable] { get } + var isDestination: Bool { get set } + + func findChild(name: String) -> DeeplinkExecutable? +} + +public protocol DeeplinkExecutable: DeeplinkTreeNode { + @discardableResult + func execute(with coordinator: Coordinator, userInfo: [AnyHashable: Any]?) -> Coordinator? +} + +public extension DeeplinkExecutable { + + func findChild(name: String) -> DeeplinkExecutable? { + children.first(where: { $0.name == name }) + } +} + + diff --git a/project/Projects/Presentation/Feature/Base/Sources/Router/Router.swift b/project/Projects/Presentation/Feature/Base/Sources/Router/Router.swift index 2f954685..970b8854 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/Router/Router.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/Router/Router.swift @@ -190,25 +190,15 @@ public final class Router: NSObject, RouterProtocol { self.rootController = navigationController if let willReplacedModule = keyWindow.rootViewController { - + // 이미 키윈도우가 존재했던 경우 dismissCompletion실행 let pointer = willReplacedModule.getRawPointer completion[pointer]?() completion.removeValue(forKey: pointer) } - if !animated { - // 애니메이션이 없는 경우 - setRootModuleTo(module: module) - completion[module.getRawPointer] = dismissCompletion - return - } - - if let snapshot = keyWindow.snapshotView(afterScreenUpdates: true) { + if animated, let snapshot = keyWindow.snapshotView(afterScreenUpdates: true) { module.view.addSubview(snapshot) - keyWindow.rootViewController = navigationController - - completion[navigationController.getRawPointer] = dismissCompletion UIView.animate(withDuration: 0.35, animations: { snapshot.layer.opacity = 0 @@ -216,6 +206,10 @@ public final class Router: NSObject, RouterProtocol { snapshot.removeFromSuperview() }) } + + keyWindow.rootViewController = navigationController + keyWindow.makeKeyAndVisible() + completion[navigationController.getRawPointer] = dismissCompletion } public func setRootModuleTo(module: Module, popCompletion: RoutingCompletion? = nil) { diff --git a/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift b/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift index da4a0986..d60362b5 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Application/AppCoordinator.swift @@ -15,15 +15,22 @@ import CenterCetificatePageFeature import AccountDeregisterFeature import PostDetailForWorkerFeature import UserProfileFeature - import Domain import Core +import RxSwift + public class AppCoordinator: BaseCoordinator { + /// main router let router: Router + /// notification helper + let notificationHelper: RemoteNotificationHelper = .init() + + let disposeBag: DisposeBag = .init() + public init(router: Router) { self.router = router } @@ -51,6 +58,7 @@ extension AppCoordinator { func runSplashFlow() -> SplashCoordinator { let coordinator = SplashCoordinator(router: router) + coordinator.delegate = self coordinator.startFlow = { [weak self] destination in @@ -322,3 +330,32 @@ extension AppCoordinator { return coordinator } } + + +// MARK: watch push notifications +extension AppCoordinator: SplashCoordinatorDelegate { + + public func splashCoordinator(satisfiedAllCondition: Bool) { + + if !satisfiedAllCondition { return } + + notificationHelper + .deeplinks + .observe(on: MainScheduler.instance) + .subscribe (onNext: { [weak self] bundle in + + guard let self else { return } + + var currentCoordinator: Coordinator? = self + + bundle.deeplinks + .forEach { deeplink in + currentCoordinator = deeplink.execute( + with: currentCoordinator!, + userInfo: bundle.userInfo + ) + } + }) + .disposed(by: disposeBag) + } +} diff --git a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift similarity index 63% rename from project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift rename to project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift index 6352c7a7..50178f79 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/CenterMainPageDeepLink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift @@ -1,5 +1,5 @@ // -// CenterMainPageDeepLink.swift +// CenterMainPageDeeplink.swift // RootFeature // // Created by choijunios on 10/9/24. @@ -8,19 +8,19 @@ import Foundation import BaseFeature -class CenterMainPageDeepLink: DeepLinkExecutable { +class CenterMainPageDeeplink: DeeplinkExecutable { var name: String = "CenterMainPage" - var children: [DeepLinkExecutable] = [ - PostApplicantDeepLink() + var children: [DeeplinkExecutable] = [ + PostApplicantDeeplink() ] var isDestination: Bool = false init() { } - func execute(with coordinator: Coordinator, userInfo: [String : String]?) -> Coordinator? { + func execute(with coordinator: any BaseFeature.Coordinator, userInfo: [AnyHashable : Any]?) -> Coordinator? { guard let appCoordinator = coordinator as? AppCoordinator else { return nil diff --git a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift similarity index 62% rename from project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift rename to project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift index 9121f0f2..9a4e2f95 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/DeepLinks/PostApplicantDeepLink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift @@ -1,5 +1,5 @@ // -// PostApplicantDeepLink.swift +// PostApplicantDeeplink.swift // RootFeature // // Created by choijunios on 10/9/24. @@ -9,23 +9,23 @@ import Foundation import CenterMainPageFeature import BaseFeature -class PostApplicantDeepLink: DeepLinkExecutable { +class PostApplicantDeeplink: DeeplinkExecutable { var name: String = "PostApplicantPage" - var children: [DeepLinkExecutable] = [] + var children: [DeeplinkExecutable] = [] var isDestination: Bool = false init() { } - func execute(with coordinator: Coordinator, userInfo: [String : String]?) -> Coordinator? { + func execute(with coordinator: any BaseFeature.Coordinator, userInfo: [AnyHashable : Any]?) -> Coordinator? { guard let centerMainPageCoordinator = coordinator as? CenterMainPageCoordinator else { return nil } - guard let postId = userInfo?["postId"] else { return nil } + guard let postId = userInfo?["postId"] as? String else { return nil } centerMainPageCoordinator.presentPostApplicantPage(postId: postId) diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift new file mode 100644 index 00000000..5cf2c264 --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift @@ -0,0 +1,33 @@ +// +// SplashDeeplink.swift +// RootFeature +// +// Created by choijunios on 10/9/24. +// + +import Foundation +import BaseFeature + + +class SplashDeeplink: DeeplinkExecutable { + + var name: String = "SplashPage" + + var children: [DeeplinkExecutable] = [] + + var isDestination: Bool = false + + init() { } + + func execute(with coordinator: any BaseFeature.Coordinator, userInfo: [AnyHashable : Any]?) -> (any BaseFeature.Coordinator)? { + guard let appCoordinator = coordinator as? AppCoordinator else { + return nil + } + + + appCoordinator.runSplashFlow() + + + return appCoordinator + } +} diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift new file mode 100644 index 00000000..58c2f93a --- /dev/null +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift @@ -0,0 +1,50 @@ +// +// DeeplinkParser.swift +// RootFeature +// +// Created by choijunios on 10/9/24. +// + +import Foundation +import BaseFeature + +enum DeeplinkParserError: Error { + case rootNotFound + case childNotFound +} + +class DeeplinkParser { + + func makeDeeplinkList(components: [String]) throws -> [DeeplinkExecutable] { + + var deeplinks: [DeeplinkExecutable] = [] + + for component in components { + + if deeplinks.isEmpty { + let root = try findRoot(name: component) + deeplinks.append(root) + continue + } + + guard let parent = deeplinks.last, let child = parent.findChild(name: component) else { + throw DeeplinkParserError.childNotFound + } + + deeplinks.append(child) + } + + return deeplinks + } + + private func findRoot(name: String) throws -> DeeplinkExecutable { + switch name { + case "CenterMainPage": + return CenterMainPageDeeplink() + default: + throw DeeplinkParserError.rootNotFound + } + } +} + + diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift index b4d5de78..d539bdd3 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/FireBaseTokenRepository.swift @@ -7,6 +7,7 @@ import Foundation import Domain +import Core import FirebaseMessaging @@ -31,7 +32,7 @@ extension FCMTokenRepository: MessagingDelegate { public func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { if let fcmToken { - + printIfDebug(fcmToken) delegate?.notificationToken(freshToken: fcmToken) } } diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift index 4332f2c5..f0d0a4a3 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift @@ -7,22 +7,58 @@ import Foundation import UserNotifications +import BaseFeature +import Core + + +import RxSwift + +struct DeeplinkBundle { + let deeplinks: [DeeplinkExecutable] + let userInfo: [AnyHashable: Any]? +} class RemoteNotificationHelper: NSObject { + // Observable + let deeplinks: BehaviorSubject = .init( + value: .init(deeplinks: [], userInfo: nil) + ) + let deeplinkParser: DeeplinkParser = .init() + + override init() { + super.init() + UNUserNotificationCenter.current().delegate = self + } } extension RemoteNotificationHelper: UNUserNotificationCenterDelegate { /// 앱이 포그라운드에 있는 경우, 노티페이케이션이 도착하기만 하면 호출된다. - public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { - + func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { + print("!!") } /// 앱이 백그라운드에 있는 경우, 유저가 노티피케이션을 통해 액션을 선택한 경우 호출 - public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { + + let userInfo = response.notification.request.content.userInfo - print(response.notification.request.content.userInfo) + if let linkInfo = userInfo["link"] as? String { + + let testLinks = linkInfo.split(separator: "/").map(String.init) + print(testLinks) + do { + let parsedLinks = try deeplinkParser.makeDeeplinkList(components: testLinks) + deeplinks.onNext(.init( + deeplinks: parsedLinks, + userInfo: userInfo + )) + + } catch { + printIfDebug("딥링크 파싱실패 \(error.localizedDescription)") + } + } } } diff --git a/project/Projects/Presentation/Feature/Splash/Sources/SplashCoordinator.swift b/project/Projects/Presentation/Feature/Splash/Sources/SplashCoordinator.swift index fde2c16d..6bf0d149 100644 --- a/project/Projects/Presentation/Feature/Splash/Sources/SplashCoordinator.swift +++ b/project/Projects/Presentation/Feature/Splash/Sources/SplashCoordinator.swift @@ -36,6 +36,8 @@ public class SplashCoordinator: BaseCoordinator { public var startFlow: ((SplashCoordinatorDestination) -> ())! + public weak var delegate: SplashCoordinatorDelegate? + // #1. 네트워크 연결상태 확인 private let networkCheckingPassed: PublishSubject = .init() @@ -85,6 +87,7 @@ public class SplashCoordinator: BaseCoordinator { .subscribe(onNext: { (object, arg1) in let (_, _, userType) = arg1 object.startFlow(.mainPage(userType: userType)) + object.delegate?.splashCoordinator(satisfiedAllCondition: true) }) .disposed(by: disposeBag) } @@ -431,3 +434,7 @@ private extension SplashCoordinator { } } +public protocol SplashCoordinatorDelegate: AnyObject { + + func splashCoordinator(satisfiedAllCondition: Bool) +} From c47d0a5ed6b2675ca5e4dea3a8e06f66c7ea47f3 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Wed, 9 Oct 2024 17:41:08 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[IDLE-409]=20=EC=98=88=EC=8B=9C=EC=95=B1?= =?UTF-8?q?=20=EC=BB=B4=ED=8C=8C=EC=9D=BC=20=EC=97=90=EB=9F=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExampleApp/Sources/SceneDelegate.swift | 8 ++++---- .../ExampleApp/Sources/SceneDelegate.swift | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/project/Projects/Presentation/Feature/CenterCetificatePage/ExampleApp/Sources/SceneDelegate.swift b/project/Projects/Presentation/Feature/CenterCetificatePage/ExampleApp/Sources/SceneDelegate.swift index 80826e82..ff722baa 100644 --- a/project/Projects/Presentation/Feature/CenterCetificatePage/ExampleApp/Sources/SceneDelegate.swift +++ b/project/Projects/Presentation/Feature/CenterCetificatePage/ExampleApp/Sources/SceneDelegate.swift @@ -25,10 +25,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { window = UIWindow(windowScene: windowScene) window?.makeKeyAndVisible() - DependencyInjector.shared.assemble([ - DataAssembly(), - DomainAssembly() - ]) +// DependencyInjector.shared.assemble([ +// DataAssembly(), +// DomainAssembly() +// ]) coordiantor.start() diff --git a/project/Projects/Presentation/Feature/NotificationPage/ExampleApp/Sources/SceneDelegate.swift b/project/Projects/Presentation/Feature/NotificationPage/ExampleApp/Sources/SceneDelegate.swift index e1065453..0d4c53a6 100644 --- a/project/Projects/Presentation/Feature/NotificationPage/ExampleApp/Sources/SceneDelegate.swift +++ b/project/Projects/Presentation/Feature/NotificationPage/ExampleApp/Sources/SceneDelegate.swift @@ -58,7 +58,7 @@ public class TestNotificationPageUseCase: NotificationPageUseCase { public func getNotificationList() -> Single> { - let task = Single<[NotificationCellInfo]>.create { observer in + let task = Single>.create { observer in var mockData: [NotificationCellInfo] = [] @@ -77,12 +77,12 @@ public class TestNotificationPageUseCase: NotificationPageUseCase { contentsOf: (0..<5).map { _ in NotificationCellInfo.create(createdDay: -15) } ) - observer(.success(mockData)) + observer(.success(.success(mockData))) return Disposables.create { } } - return convert(task: task) + return task } }