From b121934b178eec4185b4ed02b1ae81e22edd4c1f Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Wed, 25 Sep 2024 13:18:03 +0900 Subject: [PATCH 1/5] =?UTF-8?q?[IDLE-393]=20FCM=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=EB=B0=8F=20DI=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Idle-iOS.entitlements | 5 +- .../ProjectDescriptionHelpers/InfoPlist.swift | 3 -- .../Dependency.swift | 7 ++- project/Projects/App/Project.swift | 4 ++ .../Projects/App/Sources/AppDelegate.swift | 40 ++++------------ .../Sources/DI/Assembly/DataAssembly.swift | 5 ++ .../RemoteNotification/FCMService.swift | 47 +++++++++++++++++++ .../Data/DataSource/Service/FCMService.swift | 22 +++++++++ .../Worker/WorkerRegisterCoordinator.swift | 10 ++-- 9 files changed, 102 insertions(+), 41 deletions(-) rename project/{Projects => Entitlements}/App/Idle-iOS.entitlements (70%) create mode 100644 project/Projects/App/Sources/RemoteNotification/FCMService.swift create mode 100644 project/Projects/Data/DataSource/Service/FCMService.swift diff --git a/project/Projects/App/Idle-iOS.entitlements b/project/Entitlements/App/Idle-iOS.entitlements similarity index 70% rename from project/Projects/App/Idle-iOS.entitlements rename to project/Entitlements/App/Idle-iOS.entitlements index 0c67376e..903def2a 100644 --- a/project/Projects/App/Idle-iOS.entitlements +++ b/project/Entitlements/App/Idle-iOS.entitlements @@ -1,5 +1,8 @@ - + + aps-environment + development + diff --git a/project/Plugins/ConfigurationPlugin/ProjectDescriptionHelpers/InfoPlist.swift b/project/Plugins/ConfigurationPlugin/ProjectDescriptionHelpers/InfoPlist.swift index 6fb1f096..36a607b6 100644 --- a/project/Plugins/ConfigurationPlugin/ProjectDescriptionHelpers/InfoPlist.swift +++ b/project/Plugins/ConfigurationPlugin/ProjectDescriptionHelpers/InfoPlist.swift @@ -46,9 +46,6 @@ public enum IdleInfoPlist { ], "NMFClientId": "$(NAVER_API_CLIENT_ID)", - - // 앱추적 허용 메세지 - "NSUserTrackingUsageDescription": "사용자 맞춤 서비스 제공을 위해 권한을 허용해 주세요. 권한을 허용하지 않을 경우, 앱 사용에 제약이 있을 수 있습니다.", // 네트워크 사용 메세지 "NSLocalNetworkUsageDescription": "이 앱은 로컬 네트워크를 통해 서버에 연결하여 데이터를 주고받기 위해 로컬 네트워크 접근 권한이 필요합니다." diff --git a/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift b/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift index 85e41042..38d20d45 100644 --- a/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift +++ b/project/Plugins/DependencyPlugin/ProjectDescriptionHelpers/Dependency.swift @@ -48,11 +48,14 @@ public extension ModuleDependency { public static let RxMoya: TargetDependency = .external(name: "RxMoya") public static let FSCalendar: TargetDependency = .external(name: "FSCalendar") public static let NaverMapSDKForSPM: TargetDependency = .external(name: "Junios.NMapSDKForSPM") + public static let Amplitude: TargetDependency = .external(name: "AmplitudeSwift") + public static let SDWebImageWebPCoder: TargetDependency = .external(name: "SDWebImageWebPCoder") + + // FireBase public static let FirebaseRemoteConfig: TargetDependency = .external(name: "FirebaseRemoteConfig") public static let FirebaseCrashlytics: TargetDependency = .external(name: "FirebaseCrashlytics") public static let FirebaseAnalytics: TargetDependency = .external(name: "FirebaseAnalytics") - public static let Amplitude: TargetDependency = .external(name: "AmplitudeSwift") - public static let SDWebImageWebPCoder: TargetDependency = .external(name: "SDWebImageWebPCoder") + public static let FirebaseMessaging: TargetDependency = .external(name: "FirebaseMessaging") } } diff --git a/project/Projects/App/Project.swift b/project/Projects/App/Project.swift index 1d467150..e26c09f2 100644 --- a/project/Projects/App/Project.swift +++ b/project/Projects/App/Project.swift @@ -27,6 +27,7 @@ let project = Project( infoPlist: IdleInfoPlist.mainApp, sources: ["Sources/**"], resources: ["Resources/**"], + entitlements: .file(path: .relativeToRoot("Entitlements/App/Idle-iOS.entitlements")), scripts: [ .crashlyticsScript ], @@ -43,6 +44,9 @@ let project = Project( // Logger D.App.ConcreteLogger, + + // ThirdParty + D.ThirdParty.FirebaseMessaging, ], settings: .settings( configurations: IdleConfiguration.appConfigurations diff --git a/project/Projects/App/Sources/AppDelegate.swift b/project/Projects/App/Sources/AppDelegate.swift index 69eba4b1..10f8f43a 100644 --- a/project/Projects/App/Sources/AppDelegate.swift +++ b/project/Projects/App/Sources/AppDelegate.swift @@ -10,19 +10,23 @@ import AppTrackingTransparency import AdSupport import PresentationCore import FirebaseCore +import UserNotifications + @main -class AppDelegate: UIResponder, UIApplicationDelegate { +class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. - DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: { [weak self] in - self?.requestTrackingAuthorization() - }) // FireBase setting FirebaseApp.configure() + // 앱실행시 알람수신 동의를 받음 + UNUserNotificationCenter.current().delegate = self + UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { _, _ in }) + + application.registerForRemoteNotifications() + return true } @@ -39,29 +43,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } - - private func requestTrackingAuthorization() { - ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in - switch status { - case .authorized: - // Tracking authorization dialog was shown - // and we are authorized - printIfDebug("앱추적권한: Authorized") - - // 추적을 허용한 사용자 식별자 - printIfDebug(ASIdentifierManager.shared().advertisingIdentifier) - case .denied: - // Tracking authorization dialog was - // shown and permission is denied - printIfDebug("앱추적권한: Denied") - case .notDetermined: - // Tracking authorization dialog has not been shown - printIfDebug("앱추적권한: Not Determined") - case .restricted: - printIfDebug("앱추적권한: Restricted") - @unknown default: - printIfDebug("앱추적권한: Unknown") - } - }) - } + } diff --git a/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift b/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift index 5dab7c15..437fd6f3 100644 --- a/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift +++ b/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift @@ -21,6 +21,11 @@ public struct DataAssembly: Assembly { return DefaultLocalStorageService() } + container.register(FCMService.self) { _ in + return DefaultFCMService() + } + .inObjectScope(.container) + // MARK: 캐싱 레포지토리 container.register(CacheRepository.self) { _ in return DefaultCacheRepository() diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift new file mode 100644 index 00000000..9007cecd --- /dev/null +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -0,0 +1,47 @@ +// +// FCMService.swift +// Idle-iOS +// +// Created by choijunios on 9/24/24. +// + +import Foundation +import FirebaseMessaging +import DataSource + +class DefaultFCMService: NSObject, FCMService { + + override public init() { + super.init() + Messaging.messaging().delegate = self + } +} + +extension DefaultFCMService: MessagingDelegate { + + func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { + print("FCM토큰(new): \(String(describing: fcmToken))") + + let userId = "" + + if let fcmToken { + + sendTokenToServer(identifier: userId, fcmToken: fcmToken) + } + } +} + + +extension DefaultFCMService: 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/Data/DataSource/Service/FCMService.swift b/project/Projects/Data/DataSource/Service/FCMService.swift new file mode 100644 index 00000000..5da96dc1 --- /dev/null +++ b/project/Projects/Data/DataSource/Service/FCMService.swift @@ -0,0 +1,22 @@ +// +// FCMService.swift +// DataSource +// +// Created by choijunios on 9/25/24. +// + +import Foundation + +public protocol FCMService { + + /// 현재 기기의 FCM 토큰을 획득합니다. + func sendTokenToServer(identifier: String, fcmToken: String) +} + +public extension FCMService { + + func sendTokenToServer(identifier: String, fcmToken: String) { + + // 토큰 서버전송 + } +} diff --git a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift index ec0ccb09..731974af 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/Coordinator/Worker/WorkerRegisterCoordinator.swift @@ -12,8 +12,8 @@ import PresentationCore enum WorkerRegisterStage: Int { case registerFinished=0 - case info=1 - case phoneNumber=2 + case phoneNumber=1 + case info=2 case address=3 case finish=4 @@ -21,10 +21,10 @@ enum WorkerRegisterStage: Int { switch self { case .registerFinished: "" - case .info: - "input|personalInfo" case .phoneNumber: "input|phoneNumber" + case .info: + "input|personalInfo" case .address: "input|address" case .finish: @@ -94,7 +94,7 @@ public class WorkerRegisterCoordinator: ChildCoordinator { navigationController.pushViewController(vc, animated: true) - excuteStage(.info, moveTo: .next) + excuteStage(.phoneNumber, moveTo: .next) // MARK: 시작 로깅 logger.startWorkerRegister() From df5e135e56089d18957c802ef4601ae21e83e8a4 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 26 Sep 2024 12:52:20 +0900 Subject: [PATCH 2/5] =?UTF-8?q?[IDLE-393]=20NotificationUseCase=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RemoteNotification/FCMService.swift | 4 +--- .../Data/DataSource/Service/FCMService.swift | 22 ------------------- .../NotificationUseCase.swift | 17 ++++++++++++++ 3 files changed, 18 insertions(+), 25 deletions(-) delete mode 100644 project/Projects/Data/DataSource/Service/FCMService.swift create mode 100644 project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index 9007cecd..f81bdea5 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -7,9 +7,8 @@ import Foundation import FirebaseMessaging -import DataSource -class DefaultFCMService: NSObject, FCMService { +class DefaultFCMService: NSObject { override public init() { super.init() @@ -26,7 +25,6 @@ extension DefaultFCMService: MessagingDelegate { if let fcmToken { - sendTokenToServer(identifier: userId, fcmToken: fcmToken) } } } diff --git a/project/Projects/Data/DataSource/Service/FCMService.swift b/project/Projects/Data/DataSource/Service/FCMService.swift deleted file mode 100644 index 5da96dc1..00000000 --- a/project/Projects/Data/DataSource/Service/FCMService.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// FCMService.swift -// DataSource -// -// Created by choijunios on 9/25/24. -// - -import Foundation - -public protocol FCMService { - - /// 현재 기기의 FCM 토큰을 획득합니다. - func sendTokenToServer(identifier: String, fcmToken: String) -} - -public extension FCMService { - - func sendTokenToServer(identifier: String, fcmToken: String) { - - // 토큰 서버전송 - } -} diff --git a/project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift b/project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift new file mode 100644 index 00000000..71793b82 --- /dev/null +++ b/project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift @@ -0,0 +1,17 @@ +// +// NotificationUseCase.swift +// UseCaseInterface +// +// Created by choijunios on 9/26/24. +// + +import Foundation + +public protocol NotificationUseCase { + + /// 유저와 매치되는 노티피케이션 토큰을 서버로 전송합니다. + func setNotificationToken(token: String, completion: @escaping (Bool) -> ()) + + /// 유저와 매치되는 노티피케이션 토큰을 서버로부터 제거합니다. + func deleteNotificationToken(completion: @escaping (Bool) -> ()) +} From 90c37fefe3cb5347e58de889fa4587417d732aad Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 26 Sep 2024 13:04:07 +0900 Subject: [PATCH 3/5] =?UTF-8?q?[IDLE-393]=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=83=9D=EC=84=B1=ED=9B=84=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DI/Assembly/DataAssembly.swift | 5 ---- .../Sources/DI/Assembly/DomainAssembly.swift | 4 +++ .../RemoteNotification/FCMService.swift | 21 ++++++++++----- .../Projects/App/Sources/SceneDelegate.swift | 12 +++++++-- .../DefaultNotificationUseCase.swift | 26 +++++++++++++++++++ 5 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 project/Projects/Domain/ConcreteUseCase/Notification/DefaultNotificationUseCase.swift diff --git a/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift b/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift index 437fd6f3..5dab7c15 100644 --- a/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift +++ b/project/Projects/App/Sources/DI/Assembly/DataAssembly.swift @@ -21,11 +21,6 @@ public struct DataAssembly: Assembly { return DefaultLocalStorageService() } - container.register(FCMService.self) { _ in - return DefaultFCMService() - } - .inObjectScope(.container) - // MARK: 캐싱 레포지토리 container.register(CacheRepository.self) { _ in return DefaultCacheRepository() diff --git a/project/Projects/App/Sources/DI/Assembly/DomainAssembly.swift b/project/Projects/App/Sources/DI/Assembly/DomainAssembly.swift index b0ad4a5e..3b24b323 100644 --- a/project/Projects/App/Sources/DI/Assembly/DomainAssembly.swift +++ b/project/Projects/App/Sources/DI/Assembly/DomainAssembly.swift @@ -82,5 +82,9 @@ public struct DomainAssembly: Assembly { userInfoLocalRepository: userInfoLocalRepository ) } + + container.register(NotificationUseCase.self) { resolver in + DefaultNotificationUseCase() + } } } diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index f81bdea5..2b4fd21c 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -6,9 +6,15 @@ // import Foundation +import UseCaseInterface +import PresentationCore + + import FirebaseMessaging -class DefaultFCMService: NSObject { +class FCMService: NSObject { + + @Injected var notificationUseCase: NotificationUseCase override public init() { super.init() @@ -16,21 +22,24 @@ class DefaultFCMService: NSObject { } } -extension DefaultFCMService: MessagingDelegate { +extension FCMService: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { - print("FCM토큰(new): \(String(describing: fcmToken))") - - let userId = "" if let fcmToken { + print("FCM토큰: \(fcmToken)") + + notificationUseCase.setNotificationToken(token: fcmToken) { isSuccess in + + print(isSuccess ? "토큰 전송 성공" : "토큰 전송 실패") + } } } } -extension DefaultFCMService: UNUserNotificationCenterDelegate { +extension FCMService: UNUserNotificationCenterDelegate { /// 앱이 포그라운드에 있는 경우, 노티페이케이션이 도착하기만 하면 호출된다. public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { diff --git a/project/Projects/App/Sources/SceneDelegate.swift b/project/Projects/App/Sources/SceneDelegate.swift index 102b573f..95bd3753 100644 --- a/project/Projects/App/Sources/SceneDelegate.swift +++ b/project/Projects/App/Sources/SceneDelegate.swift @@ -12,7 +12,11 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - var rootCoordinator: RootCoordinator? + // RootCoordinator + var rootCoordinator: RootCoordinator! + + // FCMService + var fcmService: FCMService! func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { @@ -28,8 +32,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { LoggerAssembly(), DataAssembly(), DomainAssembly(), - ]) + ]) + + // FCMService + fcmService = FCMService() + // RootCoordinator rootCoordinator = RootCoordinator( dependency: .init( navigationController: rootNavigationController, diff --git a/project/Projects/Domain/ConcreteUseCase/Notification/DefaultNotificationUseCase.swift b/project/Projects/Domain/ConcreteUseCase/Notification/DefaultNotificationUseCase.swift new file mode 100644 index 00000000..a01da62a --- /dev/null +++ b/project/Projects/Domain/ConcreteUseCase/Notification/DefaultNotificationUseCase.swift @@ -0,0 +1,26 @@ +// +// DefaultNotificationUseCase.swift +// ConcreteUseCase +// +// Created by choijunios on 9/26/24. +// + +import Foundation +import UseCaseInterface + +public class DefaultNotificationUseCase: NotificationUseCase { + + public init() { } + + public func setNotificationToken(token: String, completion: @escaping (Bool) -> ()) { + + //TODO: 구체적 스팩 산정 후 구현 + completion(true) + } + + public func deleteNotificationToken(completion: @escaping (Bool) -> ()) { + + //TODO: 구체적 스팩 산정 후 구현 + completion(true) + } +} From 0994a42f024ab59118930520c0aeda22d8ac4f9d Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 26 Sep 2024 13:52:18 +0900 Subject: [PATCH 4/5] =?UTF-8?q?[IDLE-393]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=95=84=EC=9B=83=EC=8B=9C=20=ED=86=A0?= =?UTF-8?q?=ED=81=B0=20=EC=A0=84=EC=86=A1=EA=B8=B0=EB=8A=A5=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 --- .../RemoteNotification/FCMService.swift | 37 +++++++++++++++++++ .../AuthInOutStreamManager+PhoneNumber.swift | 4 ++ .../Center/Login/CenterLoginViewModel.swift | 10 ++++- .../ViewModel/Setting/CenterSettingVM.swift | 4 ++ .../Setting/PasswordForDeregisterVM.swift | 8 +++- ...PhoneNumberValidationForDeregisterVM.swift | 3 ++ .../ViewModel/Seting/WorkerSettingVM.swift | 4 ++ .../RemoteNotification.swift | 14 +++++++ 8 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift diff --git a/project/Projects/App/Sources/RemoteNotification/FCMService.swift b/project/Projects/App/Sources/RemoteNotification/FCMService.swift index 2b4fd21c..2df4dd9f 100644 --- a/project/Projects/App/Sources/RemoteNotification/FCMService.swift +++ b/project/Projects/App/Sources/RemoteNotification/FCMService.swift @@ -6,6 +6,7 @@ // import Foundation +import BaseFeature import UseCaseInterface import PresentationCore @@ -19,6 +20,42 @@ 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 { + + notificationUseCase.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 } + + notificationUseCase.deleteNotificationToken(completion: { result in + print("FCMService 토큰 삭제 \(result ? "완료" : "실패")") + }) + } } } diff --git a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift index 323c8d85..f23ccfcb 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/AuthInOutStreamManager/AuthInOutStreamManager+PhoneNumber.swift @@ -95,6 +95,10 @@ 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/Auth/Sources/ViewModel/Center/Login/CenterLoginViewModel.swift b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterLoginViewModel.swift index 1b56836f..1bd598ac 100644 --- a/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterLoginViewModel.swift +++ b/project/Projects/Presentation/Feature/Auth/Sources/ViewModel/Center/Login/CenterLoginViewModel.swift @@ -5,14 +5,17 @@ // Created by choijunios on 7/10/24. // -import RxSwift +import Foundation import BaseFeature -import RxCocoa import UseCaseInterface import RepositoryInterface import Entity import PresentationCore + +import RxSwift +import RxCocoa + public class CenterLoginViewModel: BaseViewModel, ViewModelType { // Init @@ -60,6 +63,9 @@ public class CenterLoginViewModel: BaseViewModel, ViewModelType { .subscribe(onNext: { [weak self] _ in guard let self else { return } + // 원격 알림 토큰 저장요청 + NotificationCenter.default.post(name: .requestTransportTokenToServer, object: nil) + self.coordinator?.authFinished() }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/CenterSettingVM.swift b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/CenterSettingVM.swift index c0777fad..53c9a415 100644 --- a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/CenterSettingVM.swift +++ b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/CenterSettingVM.swift @@ -161,6 +161,10 @@ public class CenterSettingVM: BaseViewModel, CenterSettingVMable { signOutSuccess .subscribe(onNext: { [weak self] _ in + + // 로그이아웃 성공 -> 원격알림 토큰 제거 + NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) + self?.coordinator?.popToRoot() }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/PasswordForDeregisterVM.swift b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/PasswordForDeregisterVM.swift index 70cafdbd..d3f1a7fe 100644 --- a/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/PasswordForDeregisterVM.swift +++ b/project/Projects/Presentation/Feature/Center/Sources/ViewModel/Setting/PasswordForDeregisterVM.swift @@ -5,11 +5,14 @@ // Created by choijunios on 8/21/24. // +import Foundation import BaseFeature import UseCaseInterface +import Entity + + import RxCocoa import RxSwift -import Entity public class PasswordForDeregisterVM: BaseViewModel { @@ -44,6 +47,9 @@ public class PasswordForDeregisterVM: BaseViewModel { .observe(on: MainScheduler.asyncInstance) .subscribe(onNext: { [weak self] _ in + // 회원탈퇴 성공 -> 원격알림 토큰 제거 + NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) + // RootCoordinator로 이동 self?.coordinator?.popToRoot() }) diff --git a/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift b/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift index df0bb6ad..148744f0 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Screen/Worker/PhoneNumberValidationForDeregisterVM.swift @@ -80,6 +80,9 @@ class PhoneNumberValidationForDeregisterVM: BaseViewModel, PhoneNumberValidation .observe(on: MainScheduler.asyncInstance) .subscribe(onNext: { [weak self] _ in + // 회원탈퇴 성공 -> 원격알림 토큰 제거 + NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) + // RootCoordinator로 이동 self?.coordinator?.popToRoot() }) diff --git a/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/Seting/WorkerSettingVM.swift b/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/Seting/WorkerSettingVM.swift index 49593ca9..00a7a347 100644 --- a/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/Seting/WorkerSettingVM.swift +++ b/project/Projects/Presentation/Feature/Worker/Sources/ViewModel/Seting/WorkerSettingVM.swift @@ -153,6 +153,10 @@ public class WorkerSettingVM: BaseViewModel, WorkerSettingVMable { signOutSuccess .subscribe(onNext: { [weak self] _ in + + // 로그이아웃 성공 -> 원격알림 토큰 제거 + NotificationCenter.default.post(name: .requestDeleteTokenFromServer, object: nil) + self?.coordinator?.popToRoot() }) .disposed(by: disposeBag) diff --git a/project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift b/project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift new file mode 100644 index 00000000..a4f64697 --- /dev/null +++ b/project/Projects/Presentation/PresentationCore/Sources/NotificationName+Extension/RemoteNotification.swift @@ -0,0 +1,14 @@ +// +// 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 dae6b2f0a00b8b30020fc7053208ea88d02b8612 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 26 Sep 2024 14:06:43 +0900 Subject: [PATCH 5/5] =?UTF-8?q?[IDLE-393]=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=BA=90=EC=8B=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20disabling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/Projects/Data/ConcretesTests/ImageCachingTest.swift | 2 ++ .../RemoteNotification/NotificationUseCase.swift | 0 2 files changed, 2 insertions(+) rename project/Projects/Domain/{RepositoryInterface => UseCaseInterface}/RemoteNotification/NotificationUseCase.swift (100%) diff --git a/project/Projects/Data/ConcretesTests/ImageCachingTest.swift b/project/Projects/Data/ConcretesTests/ImageCachingTest.swift index f8369bfd..69d00a7e 100644 --- a/project/Projects/Data/ConcretesTests/ImageCachingTest.swift +++ b/project/Projects/Data/ConcretesTests/ImageCachingTest.swift @@ -33,6 +33,8 @@ class ImageCachingTest: XCTestCase { } } + return + // 디스크 캐싱 내역 삭제 _ = cacheRepository.clearImageCacheDirectory() diff --git a/project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift b/project/Projects/Domain/UseCaseInterface/RemoteNotification/NotificationUseCase.swift similarity index 100% rename from project/Projects/Domain/RepositoryInterface/RemoteNotification/NotificationUseCase.swift rename to project/Projects/Domain/UseCaseInterface/RemoteNotification/NotificationUseCase.swift