diff --git a/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift b/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift index d9cd649..e2fe3ab 100644 --- a/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift +++ b/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift @@ -1,8 +1,10 @@ import FluidMenuBarExtra import NetworkExtension +import os import SDWebImageSVGCoder import SDWebImageSwiftUI import SwiftUI +import UserNotifications import VPNLib @main @@ -17,8 +19,8 @@ struct DesktopApp: App { Window("Sign In", id: Windows.login.rawValue) { LoginForm() .environmentObject(appDelegate.state) - } - .windowResizability(.contentSize) + }.handlesExternalEvents(matching: Set()) // Don't handle deep links + .windowResizability(.contentSize) SwiftUI.Settings { SettingsView() .environmentObject(appDelegate.vpn) @@ -30,18 +32,22 @@ struct DesktopApp: App { .environmentObject(appDelegate.state) .environmentObject(appDelegate.fileSyncDaemon) .environmentObject(appDelegate.vpn) - } + }.handlesExternalEvents(matching: Set()) // Don't handle deep links } } @MainActor class AppDelegate: NSObject, NSApplicationDelegate { + private var logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "app-delegate") private var menuBar: MenuBarController? let vpn: CoderVPNService let state: AppState let fileSyncDaemon: MutagenDaemon + let urlHandler: URLHandler + let notifDelegate: NotifDelegate override init() { + notifDelegate = NotifDelegate() vpn = CoderVPNService() let state = AppState(onChange: vpn.configureTunnelProviderProtocol) vpn.onStart = { @@ -65,6 +71,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { await fileSyncDaemon.tryStart() } self.fileSyncDaemon = fileSyncDaemon + urlHandler = URLHandler(state: state, vpn: vpn) + // `delegate` is weak + UNUserNotificationCenter.current().delegate = notifDelegate } func applicationDidFinishLaunching(_: Notification) { @@ -134,6 +143,22 @@ class AppDelegate: NSObject, NSApplicationDelegate { return true } + func application(_: NSApplication, open urls: [URL]) { + guard let url = urls.first else { + // We only accept one at time, for now + return + } + do { try urlHandler.handle(url) } catch let handleError { + Task { + do { + try await sendNotification(title: "Failed to handle link", body: handleError.description) + } catch let notifError { + logger.error("Failed to send notification (\(handleError.description)): \(notifError)") + } + } + } + } + private func displayIconHiddenAlert() { let alert = NSAlert() alert.alertStyle = .informational diff --git a/Coder-Desktop/Coder-Desktop/Info.plist b/Coder-Desktop/Coder-Desktop/Info.plist index 5e59b25..4712604 100644 --- a/Coder-Desktop/Coder-Desktop/Info.plist +++ b/Coder-Desktop/Coder-Desktop/Info.plist @@ -2,6 +2,21 @@ + CFBundleURLTypes + + + CFBundleTypeRole + Editor + CFBundleURLIconFile + 1024Icon + CFBundleURLName + com.coder.Coder-Desktop + CFBundleURLSchemes + + coder + + + NSAppTransportSecurity