From 711de847887a54b7731d199c920b5aca88ca5b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Coye=20de=20Brune=CC=81lis?= Date: Thu, 19 Dec 2024 09:01:25 +0100 Subject: [PATCH 1/3] refactor(UniversalLinksHelper): Public share deeplinks removed from UniversalLinksHelper --- kDriveCore/DI/FactoryService.swift | 3 + .../Utils/Deeplinks/DeeplinkService.swift | 61 +++++++++++++++++++ .../Utils/Deeplinks/PublicShareLink.swift | 20 ++++++ .../Utils/UniversalLinksHelper.swift | 34 ++++------- 4 files changed, 95 insertions(+), 23 deletions(-) create mode 100644 kDriveCore/Utils/Deeplinks/DeeplinkService.swift create mode 100644 kDriveCore/Utils/Deeplinks/PublicShareLink.swift rename {kDrive => kDriveCore}/Utils/UniversalLinksHelper.swift (88%) diff --git a/kDriveCore/DI/FactoryService.swift b/kDriveCore/DI/FactoryService.swift index ed72de093..5fb0de6e3 100644 --- a/kDriveCore/DI/FactoryService.swift +++ b/kDriveCore/DI/FactoryService.swift @@ -73,6 +73,9 @@ public enum FactoryService { }, Factory(type: FileProviderServiceable.self) { _, _ in FileProviderService() + }, + Factory(type: DeeplinkServiceable.self) { _, _ in + DeeplinkService() } ] return services diff --git a/kDriveCore/Utils/Deeplinks/DeeplinkService.swift b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift new file mode 100644 index 000000000..2554d7b37 --- /dev/null +++ b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift @@ -0,0 +1,61 @@ +/* + Infomaniak kDrive - iOS App + Copyright (C) 2024 Infomaniak Network SA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +import Foundation +import SwiftRegex + +public struct PublicShareLink { + public static let parsingRegex = Regex(pattern: #"^/app/share/([0-9]+)/([a-z0-9-]+)$"#) + + public let publicShareURL: URL + public let shareLinkUid: String + public let driveId: Int + + public init?(publicShareURL: URL) async { + guard let components = URLComponents(url: publicShareURL, resolvingAgainstBaseURL: true) else { + return nil + } + + let path = components.path + guard let matches = Self.parsingRegex?.matches(in: path) else { + return nil + } + + guard let firstMatch = matches.first, + let driveId = firstMatch[safe: 1], + let driveIdInt = Int(driveId), + let shareLinkUid = firstMatch[safe: 2] else { + return nil + } + + self.driveId = driveIdInt + self.shareLinkUid = shareLinkUid + self.publicShareURL = publicShareURL + } +} + +public protocol DeeplinkServiceable: AnyObject { + func setLastPublicShare(_ link: PublicShareLink) +} + +public class DeeplinkService: DeeplinkServiceable { + var lastPublicShareLink: PublicShareLink? + public func setLastPublicShare(_ link: PublicShareLink) { + lastPublicShareLink = link + } +} diff --git a/kDriveCore/Utils/Deeplinks/PublicShareLink.swift b/kDriveCore/Utils/Deeplinks/PublicShareLink.swift new file mode 100644 index 000000000..deba71ed1 --- /dev/null +++ b/kDriveCore/Utils/Deeplinks/PublicShareLink.swift @@ -0,0 +1,20 @@ +// +/* + Infomaniak kDrive - iOS App + Copyright (C) 2024 Infomaniak Network SA + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +import Foundation diff --git a/kDrive/Utils/UniversalLinksHelper.swift b/kDriveCore/Utils/UniversalLinksHelper.swift similarity index 88% rename from kDrive/Utils/UniversalLinksHelper.swift rename to kDriveCore/Utils/UniversalLinksHelper.swift index a343fbf54..4461c6d72 100644 --- a/kDrive/Utils/UniversalLinksHelper.swift +++ b/kDriveCore/Utils/UniversalLinksHelper.swift @@ -37,12 +37,6 @@ enum UniversalLinksHelper { displayMode: .file ) - /// Matches a public share link - static let publicShareLink = Link( - regex: Regex(pattern: #"^/app/share/([0-9]+)/([a-z0-9-]+)$"#)!, - displayMode: .file - ) - /// Matches a directory list link static let directoryLink = Link(regex: Regex(pattern: #"^/app/drive/([0-9]+)/files/([0-9]+)$"#)!, displayMode: .file) @@ -55,7 +49,7 @@ enum UniversalLinksHelper { /// Matches an office file link static let officeLink = Link(regex: Regex(pattern: #"^/app/office/([0-9]+)/([0-9]+)$"#)!, displayMode: .office) - static let all = [privateShareLink, publicShareLink, directoryLink, filePreview, officeLink] + static let all = [privateShareLink, directoryLink, filePreview, officeLink] } private enum DisplayMode { @@ -72,10 +66,8 @@ enum UniversalLinksHelper { let path = components.path DDLogInfo("[UniversalLinksHelper] Trying to open link with path: \(path)") - // Public share link regex - let shareLink = Link.publicShareLink - let matches = shareLink.regex.matches(in: path) - if await processPublicShareLink(matches: matches, publicShareURL: url) { + if let publicShare = await PublicShareLink(publicShareURL: url), + await processPublicShareLink(publicShare) { return true } @@ -91,22 +83,18 @@ enum UniversalLinksHelper { return false } - private static func processPublicShareLink(matches: [[String]], publicShareURL: URL) async -> Bool { - guard let firstMatch = matches.first, - let driveId = firstMatch[safe: 1], - let driveIdInt = Int(driveId), - let shareLinkUid = firstMatch[safe: 2] else { - return false - } + public static func processPublicShareLink(_ link: PublicShareLink) async -> Bool { + @InjectService var deeplinkService: DeeplinkServiceable + deeplinkService.setLastPublicShare(link) - // request metadata let apiFetcher = PublicShareApiFetcher() do { - let metadata = try await apiFetcher.getMetadata(driveId: driveIdInt, shareLinkUid: shareLinkUid) + let metadata = try await apiFetcher.getMetadata(driveId: link.driveId, shareLinkUid: link.shareLinkUid) + return await processPublicShareMetadata( metadata, - driveId: driveIdInt, - shareLinkUid: shareLinkUid, + driveId: link.driveId, + shareLinkUid: link.shareLinkUid, apiFetcher: apiFetcher ) } catch { @@ -118,7 +106,7 @@ enum UniversalLinksHelper { return false } - return await processPublicShareMetadataLimitation(limitation, publicShareURL: publicShareURL) + return await processPublicShareMetadataLimitation(limitation, publicShareURL: link.publicShareURL) } } From 909c5b796796f1a11d3e5c0944d553a971c34592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Coye=20de=20Brune=CC=81lis?= Date: Thu, 19 Dec 2024 09:48:33 +0100 Subject: [PATCH 2/3] feat(DeeplinkService): If app started with a public share link before authentication it is replayed after --- .../UI/Controller/LoginDelegateHandler.swift | 3 ++ .../Utils/Deeplinks/DeeplinkService.swift | 43 ++++++------------- .../Utils/Deeplinks/PublicShareLink.swift | 32 +++++++++++++- .../UniversalLinksHelper.swift | 7 +-- 4 files changed, 48 insertions(+), 37 deletions(-) rename kDriveCore/Utils/{ => Deeplinks}/UniversalLinksHelper.swift (98%) diff --git a/kDrive/UI/Controller/LoginDelegateHandler.swift b/kDrive/UI/Controller/LoginDelegateHandler.swift index 99e39567d..9c82b8c55 100644 --- a/kDrive/UI/Controller/LoginDelegateHandler.swift +++ b/kDrive/UI/Controller/LoginDelegateHandler.swift @@ -26,6 +26,7 @@ import kDriveResources public final class LoginDelegateHandler: InfomaniakLoginDelegate { @LazyInjectService var accountManager: AccountManageable @LazyInjectService var router: AppNavigable + @LazyInjectService var deeplinkService: DeeplinkServiceable var didStartLoginCallback: (() -> Void)? var didCompleteLoginCallback: (() -> Void)? @@ -57,6 +58,8 @@ public final class LoginDelegateHandler: InfomaniakLoginDelegate { } didCompleteLoginCallback?() + + deeplinkService.processDeeplinksPostAuthentication() } } diff --git a/kDriveCore/Utils/Deeplinks/DeeplinkService.swift b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift index 2554d7b37..c7df36f63 100644 --- a/kDriveCore/Utils/Deeplinks/DeeplinkService.swift +++ b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift @@ -17,40 +17,10 @@ */ import Foundation -import SwiftRegex - -public struct PublicShareLink { - public static let parsingRegex = Regex(pattern: #"^/app/share/([0-9]+)/([a-z0-9-]+)$"#) - - public let publicShareURL: URL - public let shareLinkUid: String - public let driveId: Int - - public init?(publicShareURL: URL) async { - guard let components = URLComponents(url: publicShareURL, resolvingAgainstBaseURL: true) else { - return nil - } - - let path = components.path - guard let matches = Self.parsingRegex?.matches(in: path) else { - return nil - } - - guard let firstMatch = matches.first, - let driveId = firstMatch[safe: 1], - let driveIdInt = Int(driveId), - let shareLinkUid = firstMatch[safe: 2] else { - return nil - } - - self.driveId = driveIdInt - self.shareLinkUid = shareLinkUid - self.publicShareURL = publicShareURL - } -} public protocol DeeplinkServiceable: AnyObject { func setLastPublicShare(_ link: PublicShareLink) + func processDeeplinksPostAuthentication() } public class DeeplinkService: DeeplinkServiceable { @@ -58,4 +28,15 @@ public class DeeplinkService: DeeplinkServiceable { public func setLastPublicShare(_ link: PublicShareLink) { lastPublicShareLink = link } + + public func processDeeplinksPostAuthentication() { + guard let lastPublicShareLink else { + return + } + + Task { + await UniversalLinksHelper.processPublicShareLink(lastPublicShareLink) + self.lastPublicShareLink = nil + } + } } diff --git a/kDriveCore/Utils/Deeplinks/PublicShareLink.swift b/kDriveCore/Utils/Deeplinks/PublicShareLink.swift index deba71ed1..556c48237 100644 --- a/kDriveCore/Utils/Deeplinks/PublicShareLink.swift +++ b/kDriveCore/Utils/Deeplinks/PublicShareLink.swift @@ -1,4 +1,3 @@ -// /* Infomaniak kDrive - iOS App Copyright (C) 2024 Infomaniak Network SA @@ -18,3 +17,34 @@ */ import Foundation +import SwiftRegex + +public struct PublicShareLink: Sendable { + public static let parsingRegex = Regex(pattern: #"^/app/share/([0-9]+)/([a-z0-9-]+)$"#) + + public let publicShareURL: URL + public let shareLinkUid: String + public let driveId: Int + + public init?(publicShareURL: URL) async { + guard let components = URLComponents(url: publicShareURL, resolvingAgainstBaseURL: true) else { + return nil + } + + let path = components.path + guard let matches = Self.parsingRegex?.matches(in: path) else { + return nil + } + + guard let firstMatch = matches.first, + let driveId = firstMatch[safe: 1], + let driveIdInt = Int(driveId), + let shareLinkUid = firstMatch[safe: 2] else { + return nil + } + + self.driveId = driveIdInt + self.shareLinkUid = shareLinkUid + self.publicShareURL = publicShareURL + } +} diff --git a/kDriveCore/Utils/UniversalLinksHelper.swift b/kDriveCore/Utils/Deeplinks/UniversalLinksHelper.swift similarity index 98% rename from kDriveCore/Utils/UniversalLinksHelper.swift rename to kDriveCore/Utils/Deeplinks/UniversalLinksHelper.swift index 4461c6d72..82e72631e 100644 --- a/kDriveCore/Utils/UniversalLinksHelper.swift +++ b/kDriveCore/Utils/Deeplinks/UniversalLinksHelper.swift @@ -20,13 +20,11 @@ import CocoaLumberjackSwift import Foundation import InfomaniakCore import InfomaniakDI -import kDriveCore import kDriveResources import SwiftRegex import UIKit -#if !ISEXTENSION -enum UniversalLinksHelper { +public enum UniversalLinksHelper { private struct Link { let regex: Regex let displayMode: DisplayMode @@ -57,7 +55,7 @@ enum UniversalLinksHelper { } @discardableResult - static func handleURL(_ url: URL) async -> Bool { + public static func handleURL(_ url: URL) async -> Bool { guard let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else { DDLogError("[UniversalLinksHelper] Failed to process url:\(url)") return false @@ -217,4 +215,3 @@ enum UniversalLinksHelper { } } } -#endif From f23e75328017308b32aef7392cd4ae70d8547480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Coye=20de=20Brune=CC=81lis?= Date: Thu, 2 Jan 2025 15:08:32 +0100 Subject: [PATCH 3/3] chore: PR Feedback --- kDriveCore/Utils/Deeplinks/DeeplinkService.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/kDriveCore/Utils/Deeplinks/DeeplinkService.swift b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift index c7df36f63..a9559c1d4 100644 --- a/kDriveCore/Utils/Deeplinks/DeeplinkService.swift +++ b/kDriveCore/Utils/Deeplinks/DeeplinkService.swift @@ -25,6 +25,7 @@ public protocol DeeplinkServiceable: AnyObject { public class DeeplinkService: DeeplinkServiceable { var lastPublicShareLink: PublicShareLink? + public func setLastPublicShare(_ link: PublicShareLink) { lastPublicShareLink = link }