From 92cf1985e234bb48accf842b16a2480a75d673ef Mon Sep 17 00:00:00 2001 From: Davide Date: Mon, 28 Oct 2024 23:38:01 +0100 Subject: [PATCH] Fix iOS app not reacting to open URL (#770) Resort to SwiftUI .onOpenURL(), seems to do fine for single URL on iOS (not on macOS). --- Passepartout.xcodeproj/project.pbxproj | 24 ++++++ Passepartout/App/AppDelegate.swift | 68 +--------------- Passepartout/App/PassepartoutApp.swift | 7 +- Passepartout/App/iOS/AppDelegate+iOS.swift | 34 ++++++++ .../App/macOS/AppDelegate+macOS.swift | 80 +++++++++++++++++++ 5 files changed, 145 insertions(+), 68 deletions(-) create mode 100644 Passepartout/App/iOS/AppDelegate+iOS.swift create mode 100644 Passepartout/App/macOS/AppDelegate+macOS.swift diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 26b22e85..e52a2ec1 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -21,6 +21,8 @@ 0EC797432B9378E000C093B7 /* Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC797412B9378E000C093B7 /* Shared.swift */; }; 0EC797442B93790600C093B7 /* Shared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EC797412B9378E000C093B7 /* Shared.swift */; }; 0EC9C0232CA5BD0B00C52954 /* AppUI in Frameworks */ = {isa = PBXBuildFile; productRef = 0EC9C0222CA5BD0B00C52954 /* AppUI */; }; + 0ED61CF82CD0418C008FE259 /* AppDelegate+macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED61CF72CD0418C008FE259 /* AppDelegate+macOS.swift */; }; + 0ED61CFA2CD04192008FE259 /* AppDelegate+iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ED61CF92CD04192008FE259 /* AppDelegate+iOS.swift */; }; 0EDE56EA2CABE40D0082D21C /* Intents.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0EDE56E62CABE40D0082D21C /* Intents.plist */; }; 0EDE56FA2CABE42E0082D21C /* PassepartoutIntents.appex in Embed ExtensionKit Extensions */ = {isa = PBXBuildFile; fileRef = 0EDE56F02CABE42E0082D21C /* PassepartoutIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 0EDE57002CABE4B50082D21C /* IntentsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE56E72CABE40D0082D21C /* IntentsExtension.swift */; }; @@ -88,6 +90,8 @@ 0EC797402B9378E000C093B7 /* Shared+App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Shared+App.swift"; sourceTree = ""; }; 0EC797412B9378E000C093B7 /* Shared.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Shared.swift; sourceTree = ""; }; 0ED1EFDA2C33059600CBD9BD /* App.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = App.plist; sourceTree = ""; }; + 0ED61CF72CD0418C008FE259 /* AppDelegate+macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+macOS.swift"; sourceTree = ""; }; + 0ED61CF92CD04192008FE259 /* AppDelegate+iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+iOS.swift"; sourceTree = ""; }; 0EDE56E52CABE40D0082D21C /* Intents.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Intents.entitlements; sourceTree = ""; }; 0EDE56E62CABE40D0082D21C /* Intents.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Intents.plist; sourceTree = ""; }; 0EDE56E72CABE40D0082D21C /* IntentsExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntentsExtension.swift; sourceTree = ""; }; @@ -166,6 +170,8 @@ 0E7E3D5A2B9345FD002BBDB4 /* App */ = { isa = PBXGroup; children = ( + 0ED61CF52CD0416A008FE259 /* iOS */, + 0ED61CF62CD04174008FE259 /* macOS */, 0ED1EFDA2C33059600CBD9BD /* App.plist */, 0E7E3D5B2B9345FD002BBDB4 /* App.entitlements */, 0E7C3CCC2C9AF44600B72E69 /* AppDelegate.swift */, @@ -197,6 +203,22 @@ path = Tunnel; sourceTree = ""; }; + 0ED61CF52CD0416A008FE259 /* iOS */ = { + isa = PBXGroup; + children = ( + 0ED61CF92CD04192008FE259 /* AppDelegate+iOS.swift */, + ); + path = iOS; + sourceTree = ""; + }; + 0ED61CF62CD04174008FE259 /* macOS */ = { + isa = PBXGroup; + children = ( + 0ED61CF72CD0418C008FE259 /* AppDelegate+macOS.swift */, + ); + path = macOS; + sourceTree = ""; + }; 0EDE56E82CABE40D0082D21C /* Intents */ = { isa = PBXGroup; children = ( @@ -370,7 +392,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0ED61CF82CD0418C008FE259 /* AppDelegate+macOS.swift in Sources */, 0E7C3CCD2C9AF44600B72E69 /* AppDelegate.swift in Sources */, + 0ED61CFA2CD04192008FE259 /* AppDelegate+iOS.swift in Sources */, 0E7E3D6B2B9345FD002BBDB4 /* PassepartoutApp.swift in Sources */, 0EC797422B9378E000C093B7 /* Shared+App.swift in Sources */, 0EC797432B9378E000C093B7 /* Shared.swift in Sources */, diff --git a/Passepartout/App/AppDelegate.swift b/Passepartout/App/AppDelegate.swift index 34e2529c..bda3fc9a 100644 --- a/Passepartout/App/AppDelegate.swift +++ b/Passepartout/App/AppDelegate.swift @@ -23,70 +23,4 @@ // along with Passepartout. If not, see . // -#if os(iOS) - -import AppUI -import UIKit - -final class AppDelegate: NSObject, UIApplicationDelegate { - func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - ImporterPipe.shared.send([url]) - return true - } -} - -#else - -import AppKit -import AppUI -import CommonLibrary -import PassepartoutKit -import SwiftUI - -final class AppDelegate: NSObject, NSApplicationDelegate { - - @AppStorage(AppPreference.confirmsQuit.key) - private var confirmsQuit = true - - func applicationDidFinishLaunching(_ notification: Notification) { - NSApp.windows[0].styleMask.remove(.closable) - } - - func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { - if confirmsQuit { - return quitConfirmationAlert() - } - return .terminateNow - } - - func application(_ application: NSApplication, open urls: [URL]) { - ImporterPipe.shared.send(urls) - } -} - -@MainActor -private extension AppDelegate { - func quitConfirmationAlert() -> NSApplication.TerminateReply { - let alert = NSAlert() - alert.alertStyle = .warning - alert.messageText = Strings.Alerts.ConfirmQuit.title(BundleConfiguration.mainDisplayName) - alert.informativeText = Strings.Alerts.ConfirmQuit.message - alert.addButton(withTitle: Strings.Global.ok) - alert.addButton(withTitle: Strings.Global.cancel) - alert.addButton(withTitle: Strings.Global.doNotAskAgain) - - switch alert.runModal() { - case .alertSecondButtonReturn: - return .terminateCancel - - case .alertThirdButtonReturn: - confirmsQuit = false - - default: - break - } - return .terminateNow - } -} - -#endif +import Foundation diff --git a/Passepartout/App/PassepartoutApp.swift b/Passepartout/App/PassepartoutApp.swift index 80b18099..f0c55771 100644 --- a/Passepartout/App/PassepartoutApp.swift +++ b/Passepartout/App/PassepartoutApp.swift @@ -52,7 +52,12 @@ struct PassepartoutApp: App { #if os(iOS) var body: some Scene { - WindowGroup(content: contentView) + WindowGroup { + contentView() + .onOpenURL { url in + ImporterPipe.shared.send([url]) + } + } } #else var body: some Scene { diff --git a/Passepartout/App/iOS/AppDelegate+iOS.swift b/Passepartout/App/iOS/AppDelegate+iOS.swift new file mode 100644 index 00000000..7330b231 --- /dev/null +++ b/Passepartout/App/iOS/AppDelegate+iOS.swift @@ -0,0 +1,34 @@ +// +// AppDelegate+iOS.swift +// Passepartout +// +// Created by Davide De Rosa on 10/28/24. +// Copyright (c) 2024 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +#if os(iOS) + +import AppUI +import UIKit + +final class AppDelegate: NSObject, UIApplicationDelegate { +} + +#endif diff --git a/Passepartout/App/macOS/AppDelegate+macOS.swift b/Passepartout/App/macOS/AppDelegate+macOS.swift new file mode 100644 index 00000000..a1f8fb68 --- /dev/null +++ b/Passepartout/App/macOS/AppDelegate+macOS.swift @@ -0,0 +1,80 @@ +// +// AppDelegate+macOS.swift +// Passepartout +// +// Created by Davide De Rosa on 10/28/24. +// Copyright (c) 2024 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +#if os(macOS) + +import AppKit +import AppUI +import CommonLibrary +import PassepartoutKit +import SwiftUI + +final class AppDelegate: NSObject, NSApplicationDelegate { + + @AppStorage(AppPreference.confirmsQuit.key) + private var confirmsQuit = true + + func applicationDidFinishLaunching(_ notification: Notification) { + NSApp.windows[0].styleMask.remove(.closable) + } + + func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { + if confirmsQuit { + return quitConfirmationAlert() + } + return .terminateNow + } + + func application(_ application: NSApplication, open urls: [URL]) { + ImporterPipe.shared.send(urls) + } +} + +@MainActor +private extension AppDelegate { + func quitConfirmationAlert() -> NSApplication.TerminateReply { + let alert = NSAlert() + alert.alertStyle = .warning + alert.messageText = Strings.Alerts.ConfirmQuit.title(BundleConfiguration.mainDisplayName) + alert.informativeText = Strings.Alerts.ConfirmQuit.message + alert.addButton(withTitle: Strings.Global.ok) + alert.addButton(withTitle: Strings.Global.cancel) + alert.addButton(withTitle: Strings.Global.doNotAskAgain) + + switch alert.runModal() { + case .alertSecondButtonReturn: + return .terminateCancel + + case .alertThirdButtonReturn: + confirmsQuit = false + + default: + break + } + return .terminateNow + } +} + +#endif