Add Deeplinking
This commit is contained in:
parent
2de0accc1c
commit
94b9ff9466
|
@ -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.")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 */,
|
||||
|
|
Loading…
Reference in New Issue