Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Rework deeplinks #1358

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions kDrive/UI/Controller/LoginDelegateHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)?
Expand Down Expand Up @@ -57,6 +58,8 @@ public final class LoginDelegateHandler: InfomaniakLoginDelegate {
}

didCompleteLoginCallback?()

deeplinkService.processDeeplinksPostAuthentication()
}
}

Expand Down
3 changes: 3 additions & 0 deletions kDriveCore/DI/FactoryService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public enum FactoryService {
},
Factory(type: FileProviderServiceable.self) { _, _ in
FileProviderService()
},
Factory(type: DeeplinkServiceable.self) { _, _ in
DeeplinkService()
}
]
return services
Expand Down
43 changes: 43 additions & 0 deletions kDriveCore/Utils/Deeplinks/DeeplinkService.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
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 <http://www.gnu.org/licenses/>.
*/

import Foundation

public protocol DeeplinkServiceable: AnyObject {
func setLastPublicShare(_ link: PublicShareLink)
func processDeeplinksPostAuthentication()
}

public class DeeplinkService: DeeplinkServiceable {
var lastPublicShareLink: PublicShareLink?

public func setLastPublicShare(_ link: PublicShareLink) {
adrien-coye marked this conversation as resolved.
Show resolved Hide resolved
lastPublicShareLink = link
}

public func processDeeplinksPostAuthentication() {
guard let lastPublicShareLink else {
return
}

Task {
await UniversalLinksHelper.processPublicShareLink(lastPublicShareLink)
self.lastPublicShareLink = nil
}
}
}
50 changes: 50 additions & 0 deletions kDriveCore/Utils/Deeplinks/PublicShareLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
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 <http://www.gnu.org/licenses/>.
*/

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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -37,12 +35,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)

Expand All @@ -55,15 +47,15 @@ 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 {
case office, file
}

@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
Expand All @@ -72,10 +64,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
}

Expand All @@ -91,22 +81,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 {
Expand All @@ -118,7 +104,7 @@ enum UniversalLinksHelper {
return false
}

return await processPublicShareMetadataLimitation(limitation, publicShareURL: publicShareURL)
return await processPublicShareMetadataLimitation(limitation, publicShareURL: link.publicShareURL)
}
}

Expand Down Expand Up @@ -229,4 +215,3 @@ enum UniversalLinksHelper {
}
}
}
#endif
Loading