From 364ebc3205473e7c1c249ae0c7aa330b53692c55 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 17 Oct 2024 11:32:56 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[IDLE-447]=20=EB=94=A5=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DeepLink/DeeplinkBundle.swift | 18 ++++++ .../RemoteNotificationHelper.swift | 20 +++++++ .../DefualtNotificationCellViewModel.swift | 1 + .../Components/PostApplicantDeeplink.swift | 2 +- .../RemoteNotification/DeepLinkBundle.swift | 15 ----- .../RemoteNotificationHelper.swift | 55 +++++++++++-------- 6 files changed, 73 insertions(+), 38 deletions(-) create mode 100644 project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkBundle.swift create mode 100644 project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift delete mode 100644 project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/DeepLinkBundle.swift diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkBundle.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkBundle.swift new file mode 100644 index 00000000..1bba5349 --- /dev/null +++ b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkBundle.swift @@ -0,0 +1,18 @@ +// +// DeeplinkBundle.swift +// BaseFeature +// +// Created by choijunios on 10/17/24. +// + +import Foundation + +public struct DeeplinkBundle { + public let deeplinks: [DeeplinkExecutable] + public let userInfo: [AnyHashable: Any]? + + public init(deeplinks: [DeeplinkExecutable], userInfo: [AnyHashable : Any]?) { + self.deeplinks = deeplinks + self.userInfo = userInfo + } +} diff --git a/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift new file mode 100644 index 00000000..361bcb32 --- /dev/null +++ b/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift @@ -0,0 +1,20 @@ +// +// RemoteNotificationHelper.swift +// BaseFeature +// +// Created by choijunios on 10/17/24. +// + +import Foundation +import Domain + + +import RxSwift + +public protocol RemoteNotificationHelper { + + var deeplinks: BehaviorSubject { get } + + /// 인앱에서 발생한 Notification을 처리합니다. + func handleNotificationInApp(detail: NotificationDetailVO) +} diff --git a/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift b/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift index 98d146b5..4ade0373 100644 --- a/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift +++ b/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift @@ -22,6 +22,7 @@ class NotificationCellViewModel { // Injected @Injected var cacheRepository: CacheRepository @Injected var notificationsRepository: NotificationsRepository + @Injected var remoteNotificationHelper: RemoteNotificationHelper // Navigation var presentAlert: ((DefaultAlertObject) -> ())? diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift index 9a4e2f95..0f8301b7 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift @@ -25,7 +25,7 @@ class PostApplicantDeeplink: DeeplinkExecutable { return nil } - guard let postId = userInfo?["postId"] as? String else { return nil } + guard let postId = userInfo?["jobPostingId"] as? String else { return nil } centerMainPageCoordinator.presentPostApplicantPage(postId: postId) diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/DeepLinkBundle.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/DeepLinkBundle.swift deleted file mode 100644 index b3265708..00000000 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/DeepLinkBundle.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// DeepLinkBundle.swift -// RootFeature -// -// Created by choijunios on 10/15/24. -// - -import Foundation -import BaseFeature - - -public struct DeeplinkBundle { - public let deeplinks: [DeeplinkExecutable] - public let userInfo: [AnyHashable: Any]? -} diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift index 88064715..cc82fa07 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift @@ -8,18 +8,12 @@ import Foundation import UserNotifications import BaseFeature +import Domain import Core import RxSwift -public protocol RemoteNotificationHelper { - - var deeplinks: BehaviorSubject { get } -} - - - public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper { // Observable @@ -33,12 +27,28 @@ public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper super.init() UNUserNotificationCenter.current().delegate = self } + + public func handleNotificationInApp(detail: Domain.NotificationDetailVO) { + switch detail { + case .applicant(let id): + let desination: PreDefinedDeeplinkPath = .checkApplicantPage + do { + let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) + deeplinks.onNext(.init( + deeplinks: parsedLinks, + userInfo: ["jobPostingId": id] + )) + } catch { + printIfDebug("딥링크 파싱실패 \(error.localizedDescription)") + } + } + } } extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { enum PreDefinedDeeplinkPath: String { - case checkApplicantPage = "PostApplicantPage" + case checkApplicantPage = "APPLICANT" var links: [String] { switch self { @@ -57,25 +67,26 @@ extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { /// 앱이 백그라운드에 있는 경우, 유저가 노티피케이션을 통해 액션을 선택한 경우 호출 public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - handleDeepLink(notification: response.notification) + handleNotification(notification: response.notification) } - private func handleDeepLink(notification: UNNotification) { + private func handleNotification(notification: UNNotification) { let userInfo = notification.request.content.userInfo - if let linkInfo = userInfo["link"] as? String, let desination = PreDefinedDeeplinkPath(rawValue: linkInfo) { - - do { - let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) - deeplinks.onNext(.init( - deeplinks: parsedLinks, - userInfo: userInfo - )) - - } catch { - printIfDebug("딥링크 파싱실패 \(error.localizedDescription)") - } + let notificationId = userInfo["notificationId"] as? String + let notificationType = userInfo["notificationType"] as? String + + guard let notificationType, let desination = PreDefinedDeeplinkPath(rawValue: notificationType) else { return } + + do { + let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) + deeplinks.onNext(.init( + deeplinks: parsedLinks, + userInfo: userInfo + )) + } catch { + printIfDebug("딥링크 파싱실패 \(error.localizedDescription)") } } } From 2da4d71ab0015321ea4d62a9dbb0f6e20bfe0aa6 Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 17 Oct 2024 11:39:47 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[IDLE-447]=20=EC=95=8C=EB=A6=BC=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=EC=8B=9C=20=EC=95=A1=EC=85=98=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefualtNotificationCellViewModel.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift b/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift index 4ade0373..5eaa7b33 100644 --- a/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift +++ b/project/Projects/Presentation/Feature/NotificationPage/Sources/NotificationPageModule/ViewModel/DefualtNotificationCellViewModel.swift @@ -56,6 +56,21 @@ class NotificationCellViewModel { } // MARK: 클릭 이벤트 + + /// 딥링크 처리 + cellClicked + .unretained(self) + .subscribe(onNext: { (obj, _) in + + guard let notificationDetails = notificationVO.notificationDetails else { return } + + obj.remoteNotificationHelper + .handleNotificationInApp(detail: notificationDetails) + }) + .disposed(by: disposeBag) + + + /// 읽음 처리 let readRequestResult = cellClicked .unretained(self) .flatMap { (obj, _) in From 9b02f6446826e4fefe7555a06cb35e8ec677ae9b Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 17 Oct 2024 11:56:58 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[IDLE-447]=20BaseCoordinator=20findChild?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Coordinator/BaseCoordinator.swift | 10 +++++++++ .../Sources/CenterMainPageCoordinator.swift | 8 +++---- .../Components/PostApplicantDeeplink.swift | 22 ++++++++++++++++--- .../RemoteNotificationHelper.swift | 8 +++---- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift index 9715519b..c1a26230 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/Coordinator/BaseCoordinator.swift @@ -20,6 +20,16 @@ open class BaseCoordinator: Coordinator { open func start() { } + public func findChild(coordinatorType: T.Type) -> T? { + + for child in children { + if let target = child as? T { + return target + } + } + return nil + } + public func addChild(_ coordinator: Coordinator) { children.append(coordinator) diff --git a/project/Projects/Presentation/Feature/CenterMainPage/Sources/CenterMainPageCoordinator.swift b/project/Projects/Presentation/Feature/CenterMainPage/Sources/CenterMainPageCoordinator.swift index 877823f3..7243d2a3 100644 --- a/project/Projects/Presentation/Feature/CenterMainPage/Sources/CenterMainPageCoordinator.swift +++ b/project/Projects/Presentation/Feature/CenterMainPage/Sources/CenterMainPageCoordinator.swift @@ -149,9 +149,9 @@ public extension CenterMainPageCoordinator { } // MARK: SubPages -extension CenterMainPageCoordinator { +public extension CenterMainPageCoordinator { - public func presentPostApplicantPage(postId: String) { + func presentPostApplicantPage(postId: String) { let viewModel = PostApplicantViewModel(postId: postId) viewModel.createCellViewModel = { applicantVO in @@ -175,7 +175,7 @@ extension CenterMainPageCoordinator { router.push(module: viewController, animated: true) } - public func presentPostEditPage(postId: String) { + func presentPostEditPage(postId: String) { let viewModel = EditPostVM(id: postId) viewModel.exitPage = { [weak self] in self?.router.popModule(animated: true) @@ -190,7 +190,7 @@ extension CenterMainPageCoordinator { router.push(module: viewController, animated: true) } - public func presentPostDetailPage(postId: String, postState: PostState) { + func presentPostDetailPage(postId: String, postState: PostState) { let viewModel = PostDetailViewModel(postId: postId, postState: postState) viewModel.presentApplicantPage = { [weak self] postId in diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift index 0f8301b7..5262981b 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift @@ -20,15 +20,31 @@ class PostApplicantDeeplink: DeeplinkExecutable { init() { } func execute(with coordinator: any BaseFeature.Coordinator, userInfo: [AnyHashable : Any]?) -> Coordinator? { + + + var targetCoordinator: CenterMainPageCoordinator - guard let centerMainPageCoordinator = coordinator as? CenterMainPageCoordinator else { + if let centerMainCoordinator = coordinator as? CenterMainPageCoordinator { + + // 상위 Coordinator가 CenterMainPageCoordinator일 경우 + + targetCoordinator = centerMainCoordinator + + } else if let appCoordinator = coordinator as? AppCoordinator, let centerMainCoordinator = appCoordinator.findChild(coordinatorType: CenterMainPageCoordinator.self) { + + // 상위 Coordinator가 AppCoordinator일 경우 + + targetCoordinator = centerMainCoordinator + + } else { + return nil } guard let postId = userInfo?["jobPostingId"] as? String else { return nil } - centerMainPageCoordinator.presentPostApplicantPage(postId: postId) + targetCoordinator.presentPostApplicantPage(postId: postId) - return centerMainPageCoordinator + return targetCoordinator } } diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift index cc82fa07..fcedb890 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift @@ -31,7 +31,7 @@ public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper public func handleNotificationInApp(detail: Domain.NotificationDetailVO) { switch detail { case .applicant(let id): - let desination: PreDefinedDeeplinkPath = .checkApplicantPage + let desination: PreDefinedDeeplinkPath = .checkApplicant do { let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) deeplinks.onNext(.init( @@ -48,11 +48,11 @@ public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { enum PreDefinedDeeplinkPath: String { - case checkApplicantPage = "APPLICANT" + case checkApplicant = "APPLICANT" var links: [String] { switch self { - case .checkApplicantPage: + case .checkApplicant: ["CenterMainPage", "PostApplicantPage"] } } @@ -74,7 +74,7 @@ extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { let userInfo = notification.request.content.userInfo - let notificationId = userInfo["notificationId"] as? String + let _ = userInfo["notificationId"] as? String let notificationType = userInfo["notificationType"] as? String guard let notificationType, let desination = PreDefinedDeeplinkPath(rawValue: notificationType) else { return } From c6aa18dd2d74ec4d6572f1a9b49e2ffaeece40ab Mon Sep 17 00:00:00 2001 From: J0onYEong Date: Thu, 17 Oct 2024 12:15:03 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[IDLE-447]=20=EB=82=B4=EB=B6=80=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=ED=81=B4=EB=A6=AD=EC=8B=9C=20=EB=94=A5=EB=A7=81?= =?UTF-8?q?=ED=81=AC=20=EC=B2=98=EB=A6=AC=EB=B0=A9=EC=8B=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 화면을 Root부터 새롭게 시작하는 것이 아닌 현재 네비게이션을 유지한 채로 화면을 push하도록 구현 --- .../Sources/DeepLink/DeeplinkExecutable.swift | 8 ++-- .../RemoteNotificationHelper.swift | 24 ++++++++++ .../Components/CenterMainPageDeeplink.swift | 2 +- .../Components/PostApplicantDeeplink.swift | 2 +- .../Deeplinks/Components/SplashDeeplink.swift | 2 +- .../Sources/Deeplinks/DeeplinkParser.swift | 47 +++++++++++++++---- .../RemoteNotificationHelper.swift | 17 ++----- 7 files changed, 73 insertions(+), 29 deletions(-) diff --git a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift index a1676c6d..269bd5f7 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/DeepLink/DeeplinkExecutable.swift @@ -9,11 +9,11 @@ import Foundation public protocol DeeplinkTreeNode { - var name: String { get } + var component: DeepLinkPathComponent { get } var children: [DeeplinkExecutable] { get } var isDestination: Bool { get set } - func findChild(name: String) -> DeeplinkExecutable? + func findChild(component: DeepLinkPathComponent) -> DeeplinkExecutable? } public protocol DeeplinkExecutable: DeeplinkTreeNode { @@ -23,8 +23,8 @@ public protocol DeeplinkExecutable: DeeplinkTreeNode { public extension DeeplinkExecutable { - func findChild(name: String) -> DeeplinkExecutable? { - children.first(where: { $0.name == name }) + func findChild(component: DeepLinkPathComponent) -> DeeplinkExecutable? { + children.first(where: { $0.component == component }) } } diff --git a/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift index 361bcb32..fc06b4e3 100644 --- a/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift +++ b/project/Projects/Presentation/Feature/Base/Sources/Notifications/RemoteNotificationHelper.swift @@ -18,3 +18,27 @@ public protocol RemoteNotificationHelper { /// 인앱에서 발생한 Notification을 처리합니다. func handleNotificationInApp(detail: NotificationDetailVO) } + +public enum DeepLinkPathComponent { + case centerMainPage + case postApplicantPage + case splashPage +} + +public enum PreDefinedDeeplinkPath: String { + case postApplicant = "APPLICANT" + + public var outsideLinks: [DeepLinkPathComponent] { + switch self { + case .postApplicant: + [.centerMainPage, .postApplicantPage] + } + } + + public var insideLinks: [DeepLinkPathComponent] { + switch self { + case .postApplicant: + [.postApplicantPage] + } + } +} diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift index 50178f79..4add8e56 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/CenterMainPageDeeplink.swift @@ -10,7 +10,7 @@ import BaseFeature class CenterMainPageDeeplink: DeeplinkExecutable { - var name: String = "CenterMainPage" + var component: DeepLinkPathComponent = .centerMainPage var children: [DeeplinkExecutable] = [ PostApplicantDeeplink() diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift index 5262981b..6cb90775 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/PostApplicantDeeplink.swift @@ -11,7 +11,7 @@ import BaseFeature class PostApplicantDeeplink: DeeplinkExecutable { - var name: String = "PostApplicantPage" + var component: DeepLinkPathComponent = .postApplicantPage var children: [DeeplinkExecutable] = [] diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift index 5cf2c264..a15eff23 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/Components/SplashDeeplink.swift @@ -11,7 +11,7 @@ import BaseFeature class SplashDeeplink: DeeplinkExecutable { - var name: String = "SplashPage" + var component: DeepLinkPathComponent = .splashPage var children: [DeeplinkExecutable] = [] diff --git a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift index 58c2f93a..d17b885c 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/Deeplinks/DeeplinkParser.swift @@ -8,26 +8,46 @@ import Foundation import BaseFeature -enum DeeplinkParserError: Error { +enum DeeplinkParserError: LocalizedError { + case startPointNotFound case rootNotFound case childNotFound + + var errorDescription: String? { + switch self { + case .startPointNotFound: + "딥링크 시작지점을 찾을 수 없음" + case .rootNotFound: + "답링크 루트를 찾을 수 없음" + case .childNotFound: + "자식 딥링크를 찾을 수 없음" + } + } } class DeeplinkParser { - func makeDeeplinkList(components: [String]) throws -> [DeeplinkExecutable] { + func makeDeeplinkList(components: [DeepLinkPathComponent], startFromRoot: Bool = true) throws -> [DeeplinkExecutable] { var deeplinks: [DeeplinkExecutable] = [] for component in components { if deeplinks.isEmpty { - let root = try findRoot(name: component) - deeplinks.append(root) + + var start: DeeplinkExecutable! + + if startFromRoot { + start = try findRoot(component: component) + } else { + start = try findStartPoint(component: component) + } + + deeplinks.append(start) continue } - guard let parent = deeplinks.last, let child = parent.findChild(name: component) else { + guard let parent = deeplinks.last, let child = parent.findChild(component: component) else { throw DeeplinkParserError.childNotFound } @@ -37,14 +57,25 @@ class DeeplinkParser { return deeplinks } - private func findRoot(name: String) throws -> DeeplinkExecutable { - switch name { - case "CenterMainPage": + private func findRoot(component: DeepLinkPathComponent) throws -> DeeplinkExecutable { + switch component { + case .centerMainPage: return CenterMainPageDeeplink() default: throw DeeplinkParserError.rootNotFound } } + + private func findStartPoint(component: DeepLinkPathComponent) throws -> DeeplinkExecutable { + switch component { + case .centerMainPage: + return CenterMainPageDeeplink() + case .postApplicantPage: + return PostApplicantDeeplink() + default: + throw DeeplinkParserError.startPointNotFound + } + } } diff --git a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift index fcedb890..b64f28a8 100644 --- a/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift +++ b/project/Projects/Presentation/Feature/Root/Sources/RemoteNotification/RemoteNotificationHelper.swift @@ -31,9 +31,9 @@ public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper public func handleNotificationInApp(detail: Domain.NotificationDetailVO) { switch detail { case .applicant(let id): - let desination: PreDefinedDeeplinkPath = .checkApplicant + let desination: PreDefinedDeeplinkPath = .postApplicant do { - let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) + let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.insideLinks, startFromRoot: false) deeplinks.onNext(.init( deeplinks: parsedLinks, userInfo: ["jobPostingId": id] @@ -47,17 +47,6 @@ public class DefaultRemoteNotificationHelper: NSObject, RemoteNotificationHelper extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { - enum PreDefinedDeeplinkPath: String { - case checkApplicant = "APPLICANT" - - var links: [String] { - switch self { - case .checkApplicant: - ["CenterMainPage", "PostApplicantPage"] - } - } - } - /// 앱이 포그라운드에 있는 경우, 노티페이케이션이 도착하기만 하면 호출된다. public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { @@ -80,7 +69,7 @@ extension DefaultRemoteNotificationHelper: UNUserNotificationCenterDelegate { guard let notificationType, let desination = PreDefinedDeeplinkPath(rawValue: notificationType) else { return } do { - let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.links) + let parsedLinks = try deeplinkParser.makeDeeplinkList(components: desination.outsideLinks) deeplinks.onNext(.init( deeplinks: parsedLinks, userInfo: userInfo