Add Deeplinking

This commit is contained in:
Djorkaeff Alexandre 2024-03-23 19:08:34 -03:00
parent 2de0accc1c
commit 94b9ff9466
8 changed files with 40 additions and 78 deletions

View File

@ -20,10 +20,10 @@ final class ErrorActionHandler {
case .server(let response):
router.present(error: response)
case .unauthorized:
router.route(to: .serverList)
database.remove()
serversDB.remove(server)
router.route(to: [.loading, .serverList]) {
self.database.remove()
self.serversDB.remove(self.server)
}
case .unknown:
print("Unexpected error on Client.")
}

View File

@ -3,11 +3,10 @@ import Foundation
protocol AppRouting {
func route(to route: Route)
func present(error: ErrorResponse)
func route(to routes: [Route], completion: (() -> Void)?)
}
final class AppRouter: ObservableObject {
@Published private(set) var route: Route = .loading
@Published var error: ErrorResponse?
@Published var server: Server? {
@ -23,7 +22,7 @@ final class AppRouter: ObservableObject {
@Storage(.currentServer) private var currentURL: URL?
private func registerDependencies(in server: Server) {
Store.register(Database.self, factory: RocketChatDatabase(server: server))
Store.register(Database.self, factory: server.database)
Store.register(RocketChatClientProtocol.self, factory: RocketChatClient(server: server))
Store.register(MessageSending.self, factory: MessageSender(server: server))
Store.register(ErrorActionHandling.self, factory: ErrorActionHandler(server: server))
@ -51,8 +50,6 @@ extension AppRouter: AppRouting {
room = nil
server = nil
}
self.route = route
}
func present(error: ErrorResponse) {
@ -64,6 +61,20 @@ extension AppRouter: AppRouting {
}
}
extension AppRouter {
func route(to routes: [Route], completion: (() -> Void)? = nil) {
guard let routeTo = routes.first else {
completion?()
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.route(to: routeTo)
self.route(to: Array(routes[1..<routes.count]), completion: completion)
}
}
}
enum Route: Equatable {
case loading
case serverList

View File

@ -16,6 +16,8 @@ public final class Server: NSManagedObject {
@NSManaged public var certificate: Data?
@NSManaged public var password: String?
lazy var database: Database = RocketChatDatabase(server: self)
@available(*, unavailable)
init() {
fatalError()

View File

@ -1,28 +0,0 @@
import Foundation
protocol Deeplinking {
func executeIfNeeded()
}
final class Deeplink: Deeplinking {
@Dependency private var database: ServersDatabase
@Dependency private var holder: NotificationResponseHolding
@Dependency private var router: AppRouting
func executeIfNeeded() {
guard let response = holder.response else {
return
}
guard let server = database.server(url: response.host) else {
return
}
guard let room = RocketChatDatabase(server: server).room(id: response.rid) else {
return
}
router.route(to: .room(server, room))
holder.clear()
}
}

View File

@ -2,6 +2,9 @@ import WatchKit
import UserNotifications
final class ExtensionDelegate: NSObject, WKApplicationDelegate {
let router = AppRouter()
let database = DefaultDatabase()
func applicationDidFinishLaunching() {
UNUserNotificationCenter.current().delegate = self
}
@ -16,40 +19,25 @@ extension ExtensionDelegate: UNUserNotificationCenterDelegate {
let userInfo = response.notification.request.content.userInfo
let ejson = userInfo["ejson"] as? String
let data = ejson?.data(using: .utf8)
guard let response = try? data?.decode(NotificationResponse.self) else { return }
NotificationResponseHolder.shared.setResponse(response)
deeplink(from: response)
completionHandler()
}
}
extension ExtensionDelegate {
private func deeplink(from response: NotificationResponse) {
guard let server = database.server(url: response.host) else { return }
guard let room = server.database.room(id: response.rid) else { return }
router.route(to: [.loading, .roomList(server), .room(server, room)])
}
}
struct NotificationResponse: Codable, Hashable {
let host: URL
let rid: String
}
protocol NotificationResponseHolding {
var response: NotificationResponse? { get }
func setResponse(_ response: NotificationResponse)
func clear()
}
final class NotificationResponseHolder: NotificationResponseHolding {
static let shared = NotificationResponseHolder()
private(set) var response: NotificationResponse?
func setResponse(_ response: NotificationResponse) {
self.response = response
}
func clear() {
response = nil
}
private init() {
}
}

View File

@ -5,23 +5,19 @@ import WatchKit
struct RocketChat_Watch_AppApp: App {
@WKApplicationDelegateAdaptor var delegate: ExtensionDelegate
private let router = AppRouter()
init() {
registerDependencies()
}
private func registerDependencies() {
Store.register(AppRouting.self, factory: router)
Store.register(ServersDatabase.self, factory: DefaultDatabase())
Store.register(AppRouting.self, factory: delegate.router)
Store.register(ServersDatabase.self, factory: delegate.database)
Store.register(ServersLoading.self, factory: ServersLoader())
Store.register(NotificationResponseHolding.self, factory: NotificationResponseHolder.shared)
Store.register(Deeplinking.self, factory: Deeplink())
}
var body: some Scene {
WindowGroup {
AppView(router: router)
AppView(router: delegate.router)
}
}
}

View File

@ -13,8 +13,6 @@ struct RoomListView: View {
@FetchRequest<Room> private var rooms: FetchedResults<Room>
@State private var roomID: String?
init(server: Server, roomsLoader: RoomsLoader) {
self.server = server
_roomsLoader = StateObject(wrappedValue: roomsLoader)
@ -49,6 +47,7 @@ struct RoomListView: View {
}
}
.navigationTitle("Rooms")
.navigationBarTitleDisplayMode(.inline)
.overlay {
if roomsLoader.state == .loading {
ProgressView()

View File

@ -176,13 +176,11 @@
1ED038C62B50A21800C007D4 /* WatchMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED038C32B50A1F500C007D4 /* WatchMessage.swift */; };
1ED038CA2B50A58400C007D4 /* ServersLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED038C92B50A58400C007D4 /* ServersLoader.swift */; };
1ED1EC892B867E2400F6620C /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED1EC882B867E2400F6620C /* ExtensionDelegate.swift */; };
1ED1EC8B2B86817100F6620C /* Deeplink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED1EC8A2B86817100F6620C /* Deeplink.swift */; };
1ED1EC902B86997F00F6620C /* MessageComposerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E29A3232B5874FF0093C03C /* MessageComposerView.swift */; };
1ED1EC912B86997F00F6620C /* Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EB375882B55DBFB00AEC3D7 /* Server.swift */; };
1ED1EC922B86997F00F6620C /* MessageActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E06561C2B7E9C1C0081B01F /* MessageActionView.swift */; };
1ED1EC932B86997F00F6620C /* MessageListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E29A3152B5868DF0093C03C /* MessageListView.swift */; };
1ED1EC942B86997F00F6620C /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4AFC162B5AF09C00E2AA7D /* Store.swift */; };
1ED1EC952B86997F00F6620C /* Deeplink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED1EC8A2B86817100F6620C /* Deeplink.swift */; };
1ED1EC962B86997F00F6620C /* SubscriptionsResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E29A2D82B585B070093C03C /* SubscriptionsResponse.swift */; };
1ED1EC972B86997F00F6620C /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED1EC882B867E2400F6620C /* ExtensionDelegate.swift */; };
1ED1EC982B86997F00F6620C /* SubscriptionsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E29A2DE2B585B070093C03C /* SubscriptionsRequest.swift */; };
@ -567,7 +565,6 @@
1ED038C32B50A1F500C007D4 /* WatchMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchMessage.swift; sourceTree = "<group>"; };
1ED038C92B50A58400C007D4 /* ServersLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServersLoader.swift; sourceTree = "<group>"; };
1ED1EC882B867E2400F6620C /* ExtensionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = "<group>"; };
1ED1EC8A2B86817100F6620C /* Deeplink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Deeplink.swift; sourceTree = "<group>"; };
1ED1ECDD2B86997F00F6620C /* Rocket.Chat Experimental.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Rocket.Chat Experimental.app"; sourceTree = BUILT_PRODUCTS_DIR; };
1ED59D4B22CBA77D00C54289 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = SOURCE_ROOT; };
1EDB30F12B5B453A00532C7E /* LoggedInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggedInView.swift; sourceTree = "<group>"; };
@ -1000,7 +997,6 @@
1ED033BE2B55BF94004F4930 /* Storage.swift */,
1ED038942B507B4D00C007D4 /* Assets.xcassets */,
1ED038962B507B4D00C007D4 /* Preview Content */,
1ED1EC8A2B86817100F6620C /* Deeplink.swift */,
1ED1EC882B867E2400F6620C /* ExtensionDelegate.swift */,
1E044F982B92798E00BCA2FD /* Localizable.xcstrings */,
);
@ -2080,7 +2076,6 @@
1EE096FA2BACD1F200780078 /* ToolbarItemPlacement+Extensions.swift in Sources */,
1E29A3162B5868DF0093C03C /* MessageListView.swift in Sources */,
1E4AFC172B5AF09C00E2AA7D /* Store.swift in Sources */,
1ED1EC8B2B86817100F6620C /* Deeplink.swift in Sources */,
1E29A2F42B585B070093C03C /* SubscriptionsResponse.swift in Sources */,
1EE097002BACD64C00780078 /* Binding+Extensions.swift in Sources */,
1ED1EC892B867E2400F6620C /* ExtensionDelegate.swift in Sources */,
@ -2164,7 +2159,6 @@
1EE096FB2BACD1F200780078 /* ToolbarItemPlacement+Extensions.swift in Sources */,
1ED1EC932B86997F00F6620C /* MessageListView.swift in Sources */,
1ED1EC942B86997F00F6620C /* Store.swift in Sources */,
1ED1EC952B86997F00F6620C /* Deeplink.swift in Sources */,
1ED1EC962B86997F00F6620C /* SubscriptionsResponse.swift in Sources */,
1EE097012BACD64C00780078 /* Binding+Extensions.swift in Sources */,
1ED1EC972B86997F00F6620C /* ExtensionDelegate.swift in Sources */,