Skip to content

Commit

Permalink
[IDLE-447] 내부 알림 클릭시 딥링크 처리방식 추가
Browse files Browse the repository at this point in the history
화면을 Root부터 새롭게 시작하는 것이 아닌 현재 네비게이션을 유지한 채로 화면을 push하도록 구현
  • Loading branch information
J0onYEong committed Oct 17, 2024
1 parent 9d3d7a5 commit 23b5391
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 })
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import BaseFeature

class CenterMainPageDeeplink: DeeplinkExecutable {

var name: String = "CenterMainPage"
var component: DeepLinkPathComponent = .centerMainPage

var children: [DeeplinkExecutable] = [
PostApplicantDeeplink()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import BaseFeature

class PostApplicantDeeplink: DeeplinkExecutable {

var name: String = "PostApplicantPage"
var component: DeepLinkPathComponent = .postApplicantPage

var children: [DeeplinkExecutable] = []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import BaseFeature

class SplashDeeplink: DeeplinkExecutable {

var name: String = "SplashPage"
var component: DeepLinkPathComponent = .splashPage

var children: [DeeplinkExecutable] = []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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) {

Expand All @@ -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
Expand Down

0 comments on commit 23b5391

Please sign in to comment.