Deep link fixed

This commit is contained in:
lumaa-dev 2024-09-26 00:58:52 +02:00
parent 0ca62fb0a2
commit e6ebb3a139
6 changed files with 138 additions and 62 deletions

View File

@ -4,52 +4,144 @@ import Foundation
import SwiftUI import SwiftUI
extension Navigator { extension Navigator {
public func handle(url: URL) -> OpenURLAction.Result { /// Handles the tapping links in posts, bios, etc...
/// - Parameter uni: Defines if the function is triggered by the ``UniversalNavigator``.
public func handle(url: URL, uni: Bool = false) -> OpenURLAction.Result {
print("\(url.absoluteString) TAPPED")
guard let client = self.client else { return .systemAction } guard let client = self.client else { return .systemAction }
let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path let path: String = url.absoluteString.replacingOccurrences(of: AppInfo.scheme, with: "") // remove all path
let urlPath: URL = URL(string: path)! let urlPath: URL = URL(string: path) ?? URL(string: "https://example.com/")!
if !url.absoluteString.starts(with: AppInfo.scheme) {
if client.isAuth && client.hasConnection(with: url) {
guard let actionType = urlPath.getActionType() else { fatalError("Couldn't get URLNav actionType") }
let server: String = urlPath.host() ?? client.server
let server: String = urlPath.host() ?? client.server print("actionType: \(actionType)")
let lastIndex = urlPath.pathComponents.count - 1
let actionType = urlPath.pathComponents[lastIndex - 1] if actionType == .account {
Task {
do {
print("search acct: \(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))")
let search: SearchResults = try await client.get(endpoint: Search.search(query: "\(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))", type: "accounts", offset: nil, following: nil), forceVersion: .v2)
print(search)
if let acc: Account = search.accounts.first, !search.accounts.isEmpty {
guard !uni else { return OpenURLAction.Result.discarded }
self.navigate(to: .account(acc: acc))
} else {
guard uni else { return OpenURLAction.Result.discarded }
self.presentedSheet = .safari(url: url)
}
} catch {
print(error)
}
if client.isAuth && client.hasConnection(with: url) { return OpenURLAction.Result.handled
if urlPath.lastPathComponent.starts(with: "@") {
Task {
do {
print("\(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))")
let search: SearchResults = try await client.get(endpoint: Search.search(query: "\(urlPath.lastPathComponent)@\(server.replacingOccurrences(of: "www.", with: ""))", type: "accounts", offset: nil, following: nil), forceVersion: .v2)
print(search)
let acc: Account = search.accounts.first ?? .placeholder()
self.navigate(to: .account(acc: acc))
} catch {
print(error)
} }
} } else if actionType == .tag {
return OpenURLAction.Result.handled Task {
} else { do {
self.presentedSheet = .safari(url: url) let tag: String = urlPath.lastPathComponent
} let search: SearchResults = try await client.get(endpoint: Search.search(query: "#\(tag)", type: "hashtags", offset: nil, following: nil), forceVersion: .v2)
} else { print(search)
Task { if let tgg: Tag = search.hashtags.first, !search.hashtags.isEmpty {
do { guard !uni else { return OpenURLAction.Result.discarded }
let connections: [String] = try await client.get(endpoint: Instances.peers) self.navigate(to: .timeline(timeline: .hashtag(tag: tgg.name, accountId: nil)))
client.addConnections(connections) } else {
guard uni else { return OpenURLAction.Result.discarded }
self.presentedSheet = .safari(url: url)
}
} catch {
print(error)
}
return OpenURLAction.Result.handled
if client.hasConnection(with: url) {
_ = self.handle(url: url)
} else {
self.presentedSheet = .safari(url: url)
} }
} catch { } else {
self.presentedSheet = .safari(url: url) self.presentedSheet = .safari(url: url)
} }
} } else {
print("clicked isn't handled properly")
return OpenURLAction.Result.handled Task {
do {
let connections: [String] = try await client.get(endpoint: Instances.peers)
client.addConnections(connections)
if client.hasConnection(with: url) {
_ = self.handle(url: url, uni: uni)
} else {
guard uni else { return OpenURLAction.Result.discarded }
print("clicked isn't connection")
self.presentedSheet = .safari(url: url)
}
} catch {
guard uni else { return OpenURLAction.Result.discarded }
self.presentedSheet = .safari(url: url)
}
return OpenURLAction.Result.handled
}
}
} else {
print("deeplink detected")
let actions: [String] = path.split(separator: /\/+/).map({ $0.lowercased().replacing(/\?(.)+$/, with: "") })
if !actions.isEmpty, let mainAction: String = actions.first {
if mainAction == "update" {
guard uni else { return OpenURLAction.Result.discarded }
self.presentedSheet = .update
} else if mainAction == "new" {
guard uni else { return OpenURLAction.Result.discarded }
var newContent: String = ""
if let queries: [String : String] = urlPath.getQueryParameters() {
newContent = queries["text"] ?? ""
}
self.presentedSheet = .post(content: newContent, replyId: nil, editId: nil)
}
}
} }
return OpenURLAction.Result.handled return OpenURLAction.Result.handled
} }
} }
private extension URL {
func getActionType() -> String.ActionType? {
let pathComponents = self.pathComponents
let subLinks = pathComponents.filter { $0 != "/" && !$0.isEmpty }
return subLinks.first?.getRecognizer()
}
func getQueryParameters() -> [String: String]? {
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: false), let queryItems = components.queryItems else {
print("Invalid URL or no query items")
return nil
}
// Convert query items into a dictionary
var queryDict = [String: String]()
for item in queryItems {
queryDict[item.name] = item.value
}
return queryDict
}
}
private extension String {
func getRecognizer() -> String.ActionType? {
if self.starts(with: "@") {
return .account
} else if self.starts(with: "tags") {
return .tag
}
return nil
}
enum ActionType: String {
case account = "account"
case tag = "tag"
}
}

View File

@ -78,13 +78,20 @@ struct ContentView: View {
} }
} }
} }
.environment(\.openURL, OpenURLAction { url in
return self.openURL(url)
})
.onOpenURL(perform: { url in .onOpenURL(perform: { url in
guard preferences.browserType == .inApp else { return } _ = openURL(url)
uniNavigator.presentedSheet = .safari(url: url)
let handled = uniNavigator.handle(url: url)
}) })
} }
private func openURL(_ url: URL) -> OpenURLAction.Result {
_ = uniNavigator.handle(url: url, uni: true)
_ = Navigator.shared.handle(url: url, uni: false)
return .handled
}
func recognizeAccount() async { func recognizeAccount() async {
let appAccount: AppAccount? = AppAccount.loadAsCurrent() let appAccount: AppAccount? = AppAccount.loadAsCurrent()
if appAccount == nil { if appAccount == nil {
@ -92,6 +99,7 @@ struct ContentView: View {
} else { } else {
let cli = Client(server: appAccount!.server, oauthToken: appAccount!.oauthToken) let cli = Client(server: appAccount!.server, oauthToken: appAccount!.oauthToken)
accountManager.setClient(cli) accountManager.setClient(cli)
navigator.client = cli
uniNavigator.client = cli uniNavigator.client = cli
// Check if token is still working // Check if token is still working

View File

@ -137,12 +137,6 @@ struct TimelineView: View {
} }
} }
} }
.environment(\.openURL, OpenURLAction { url in
// Open internal URL.
// guard preferences.browserType == .inApp else { return .systemAction }
let handled = navigator.handle(url: url)
return handled
})
.environmentObject(navigator) .environmentObject(navigator)
.background(Color.appBackground) .background(Color.appBackground)
.toolbarBackground(Color.appBackground, for: .navigationBar) .toolbarBackground(Color.appBackground, for: .navigationBar)

View File

@ -20,11 +20,6 @@ struct AccountView: View {
} }
} }
} }
.environment(\.openURL, OpenURLAction { url in
// Open internal URL.
let handled = navigator.handle(url: url)
return handled
})
.environmentObject(navigator) .environmentObject(navigator)
} }
} }

View File

@ -91,13 +91,6 @@ struct DiscoveryView: View {
.withAppRouter(navigator) .withAppRouter(navigator)
.navigationTitle(Text("discovery")) .navigationTitle(Text("discovery"))
} }
.environment(\.openURL, OpenURLAction { url in
// Open internal URL.
return .systemAction
// guard preferences.browserType == .inApp else { return .systemAction }
// let handled = navigator.handle(url: url)
// return handled
})
.environmentObject(navigator) .environmentObject(navigator)
.task { .task {
await fetchTrending() await fetchTrending()

View File

@ -94,12 +94,6 @@ struct NotificationsView: View {
} }
} }
} }
.environment(\.openURL, OpenURLAction { url in
// Open internal URL.
// guard preferences.browserType == .inApp else { return .systemAction }
let handled = navigator.handle(url: url)
return handled
})
.environmentObject(navigator) .environmentObject(navigator)
.task { .task {
loadingNotifs = true loadingNotifs = true