2022-11-29 10:46:02 +00:00
|
|
|
import Foundation
|
|
|
|
import SwiftUI
|
2022-12-17 12:37:46 +00:00
|
|
|
import Models
|
2022-12-27 07:31:47 +00:00
|
|
|
import Network
|
2022-11-29 10:46:02 +00:00
|
|
|
|
|
|
|
public enum RouteurDestinations: Hashable {
|
|
|
|
case accountDetail(id: String)
|
2022-12-17 12:37:46 +00:00
|
|
|
case accountDetailWithAccount(account: Account)
|
2022-11-29 10:46:02 +00:00
|
|
|
case statusDetail(id: String)
|
2022-12-21 19:26:38 +00:00
|
|
|
case hashTag(tag: String, account: String?)
|
2023-01-02 18:23:44 +00:00
|
|
|
case list(list: Models.List)
|
2022-12-23 17:47:19 +00:00
|
|
|
case followers(id: String)
|
|
|
|
case following(id: String)
|
2022-12-24 12:41:25 +00:00
|
|
|
case favouritedBy(id: String)
|
|
|
|
case rebloggedBy(id: String)
|
2022-11-29 10:46:02 +00:00
|
|
|
}
|
|
|
|
|
2022-12-20 08:37:07 +00:00
|
|
|
public enum SheetDestinations: Identifiable {
|
2023-01-05 11:21:54 +00:00
|
|
|
case newStatusEditor(visibility: Models.Visibility)
|
2022-12-27 12:38:10 +00:00
|
|
|
case editStatusEditor(status: Status)
|
|
|
|
case replyToStatusEditor(status: Status)
|
|
|
|
case quoteStatusEditor(status: Status)
|
2023-01-04 17:37:58 +00:00
|
|
|
case mentionStatusEditor(account: Account, visibility: Models.Visibility)
|
2023-01-02 18:23:44 +00:00
|
|
|
case listEdit(list: Models.List)
|
|
|
|
case listAddAccount(account: Account)
|
2022-12-23 09:41:55 +00:00
|
|
|
|
2022-12-20 08:37:07 +00:00
|
|
|
public var id: String {
|
|
|
|
switch self {
|
2023-01-04 17:37:58 +00:00
|
|
|
case .editStatusEditor, .newStatusEditor, .replyToStatusEditor, .quoteStatusEditor, .mentionStatusEditor:
|
2022-12-23 09:41:55 +00:00
|
|
|
return "statusEditor"
|
2023-01-02 18:23:44 +00:00
|
|
|
case .listEdit:
|
|
|
|
return "listEdit"
|
|
|
|
case .listAddAccount:
|
|
|
|
return "listAddAccount"
|
2022-12-20 08:37:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-30 15:55:13 +00:00
|
|
|
@MainActor
|
2022-11-29 10:46:02 +00:00
|
|
|
public class RouterPath: ObservableObject {
|
2022-12-27 07:31:47 +00:00
|
|
|
public var client: Client?
|
|
|
|
|
2022-11-29 10:46:02 +00:00
|
|
|
@Published public var path: [RouteurDestinations] = []
|
2022-12-20 08:37:07 +00:00
|
|
|
@Published public var presentedSheet: SheetDestinations?
|
2022-11-29 10:46:02 +00:00
|
|
|
|
|
|
|
public init() {}
|
|
|
|
|
|
|
|
public func navigate(to: RouteurDestinations) {
|
|
|
|
path.append(to)
|
|
|
|
}
|
2022-12-19 14:51:25 +00:00
|
|
|
|
|
|
|
public func handleStatus(status: AnyStatus, url: URL) -> OpenURLAction.Result {
|
2022-12-20 14:37:51 +00:00
|
|
|
if url.pathComponents.contains(where: { $0 == "tags" }),
|
|
|
|
let tag = url.pathComponents.last {
|
2022-12-21 19:26:38 +00:00
|
|
|
navigate(to: .hashTag(tag: tag, account: nil))
|
2022-12-20 14:37:51 +00:00
|
|
|
return .handled
|
|
|
|
} else if let mention = status.mentions.first(where: { $0.url == url }) {
|
2022-12-19 14:51:25 +00:00
|
|
|
navigate(to: .accountDetail(id: mention.id))
|
|
|
|
return .handled
|
2022-12-27 07:31:47 +00:00
|
|
|
} else if let client = client,
|
2022-12-30 15:55:13 +00:00
|
|
|
let id = Int(url.lastPathComponent) {
|
|
|
|
if url.absoluteString.contains(client.server) {
|
|
|
|
navigate(to: .statusDetail(id: String(id)))
|
|
|
|
} else {
|
|
|
|
Task {
|
2023-01-01 08:19:00 +00:00
|
|
|
await navigateToStatusFrom(url: url)
|
2022-12-30 15:55:13 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-27 07:31:47 +00:00
|
|
|
return .handled
|
2022-12-19 14:51:25 +00:00
|
|
|
}
|
|
|
|
return .systemAction
|
|
|
|
}
|
2022-12-23 14:28:22 +00:00
|
|
|
|
|
|
|
public func handle(url: URL) -> OpenURLAction.Result {
|
|
|
|
if url.pathComponents.contains(where: { $0 == "tags" }),
|
|
|
|
let tag = url.pathComponents.last {
|
|
|
|
navigate(to: .hashTag(tag: tag, account: nil))
|
|
|
|
return .handled
|
2023-01-01 10:40:18 +00:00
|
|
|
} else if url.lastPathComponent.first == "@", let host = url.host {
|
|
|
|
let acct = "\(url.lastPathComponent)@\(host)"
|
|
|
|
Task {
|
|
|
|
await navigateToAccountFrom(acct: acct, url: url)
|
|
|
|
}
|
|
|
|
return .handled
|
2022-12-23 14:28:22 +00:00
|
|
|
}
|
|
|
|
return .systemAction
|
|
|
|
}
|
2023-01-01 08:19:00 +00:00
|
|
|
|
|
|
|
public func navigateToStatusFrom(url: URL) async {
|
|
|
|
guard let client else { return }
|
|
|
|
Task {
|
|
|
|
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: url.absoluteString,
|
|
|
|
type: "statuses",
|
|
|
|
offset: nil,
|
|
|
|
following: nil),
|
|
|
|
forceVersion: .v2)
|
|
|
|
if let status = results?.statuses.first {
|
|
|
|
navigate(to: .statusDetail(id: status.id))
|
|
|
|
} else {
|
|
|
|
await UIApplication.shared.open(url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-01 10:40:18 +00:00
|
|
|
public func navigateToAccountFrom(acct: String, url: URL) async {
|
2023-01-01 08:19:00 +00:00
|
|
|
guard let client else { return }
|
|
|
|
Task {
|
|
|
|
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: acct,
|
|
|
|
type: "accounts",
|
|
|
|
offset: nil,
|
|
|
|
following: nil),
|
|
|
|
forceVersion: .v2)
|
|
|
|
if let account = results?.accounts.first {
|
|
|
|
navigate(to: .accountDetailWithAccount(account: account))
|
2023-01-01 10:40:18 +00:00
|
|
|
} else {
|
|
|
|
await UIApplication.shared.open(url)
|
2023-01-01 08:19:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-29 10:46:02 +00:00
|
|
|
}
|