Add 3D Touch items (#267)

- Enable/Disable VPN

- Reconnect (if enabled)

Move lifecycle operations to SceneDelegate.
This commit is contained in:
Davide De Rosa 2023-03-19 20:04:31 +01:00 committed by GitHub
parent 4a2dec9c6a
commit 7346bfc65c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 18 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- 3D Touch items. [#267](https://github.com/passepartoutvpn/passepartout-apple/pull/267)
- Prompt for password interactively. [#3](https://github.com/passepartoutvpn/passepartout-apple/issues/3)
- Ukranian translations (Dmitry Chirkin). [#243](https://github.com/passepartoutvpn/passepartout-apple/pull/243)
- Restore DNS "Domain" setting. [#260](https://github.com/passepartoutvpn/passepartout-apple/pull/260)

View File

@ -25,6 +25,8 @@
0E0BD27627B2EB2200583AC5 /* DonateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27527B2EB2200583AC5 /* DonateView.swift */; };
0E0BD27927B2EBE500583AC5 /* ShortcutsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0BD27827B2EBE500583AC5 /* ShortcutsView.swift */; };
0E0C0729236087A100155AAC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E0C072B236087A100155AAC /* InfoPlist.strings */; };
0E0F4C5A29C761850022E884 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0F4C5929C761850022E884 /* SceneDelegate.swift */; };
0E0F4C5C29C76B790022E884 /* SceneDelegate+Shortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0F4C5B29C76B790022E884 /* SceneDelegate+Shortcuts.swift */; };
0E12BC8F27F62C8600B2F912 /* Validators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E12BC8E27F62C8500B2F912 /* Validators.swift */; };
0E1B5F5C29C506AD00FE7D18 /* ProfileView+Diagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1B5F5B29C506AC00FE7D18 /* ProfileView+Diagnostics.swift */; };
0E1F5628287F0ECB00F8ADD7 /* ProviderProfileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1F5627287F0ECB00F8ADD7 /* ProviderProfileItem.swift */; };
@ -304,6 +306,8 @@
0E0BD27827B2EBE500583AC5 /* ShortcutsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsView.swift; sourceTree = "<group>"; };
0E0C072A236087A100155AAC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0E0C072C236087C800155AAC /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; };
0E0F4C5929C761850022E884 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
0E0F4C5B29C76B790022E884 /* SceneDelegate+Shortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SceneDelegate+Shortcuts.swift"; sourceTree = "<group>"; };
0E12BC8E27F62C8500B2F912 /* Validators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Validators.swift; sourceTree = "<group>"; };
0E1B5F5B29C506AC00FE7D18 /* ProfileView+Diagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileView+Diagnostics.swift"; sourceTree = "<group>"; };
0E1C0A52238FFF97009FC087 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -875,6 +879,8 @@
0E0C072B236087A100155AAC /* InfoPlist.strings */,
0E3FC6852867A3F9009B851C /* AppDelegate.swift */,
0E2A8D4727ADF87F00207D04 /* PassepartoutApp.swift */,
0E0F4C5929C761850022E884 /* SceneDelegate.swift */,
0E0F4C5B29C76B790022E884 /* SceneDelegate+Shortcuts.swift */,
);
path = App;
sourceTree = "<group>";
@ -1420,6 +1426,7 @@
0E5349C827C176D100C71BB3 /* EndpointView+WireGuard.swift in Sources */,
0EBC076027EC587900208AD9 /* SwiftGen+Strings.swift in Sources */,
0E0392772818732D00827C10 /* BuildProducts.swift in Sources */,
0E0F4C5C29C76B790022E884 /* SceneDelegate+Shortcuts.swift in Sources */,
0E5683B927C2825D00EAF1CD /* DiagnosticsView.swift in Sources */,
0E3FC6862867A3F9009B851C /* AppDelegate.swift in Sources */,
0E71ACFD27C1321A00F85C4B /* ActivityView.swift in Sources */,
@ -1456,6 +1463,7 @@
0ED7D62F2867328A009F2F8F /* Constants+Library.swift in Sources */,
0E5467FA2867AA0A00F74D1C /* MacBundleDelegate.swift in Sources */,
0E0BD27327B2EA2C00583AC5 /* MainView.swift in Sources */,
0E0F4C5A29C761850022E884 /* SceneDelegate.swift in Sources */,
0EB17EBA27D2560300D473B5 /* PassepartoutProviders+Extensions.swift in Sources */,
0E3B7FDA27E51A0200C66F13 /* ProfileView+Provider.swift in Sources */,
0E5468062867AEC500F74D1C /* MacMenu.swift in Sources */,

View File

@ -25,6 +25,7 @@
import Foundation
import UIKit
import PassepartoutLibrary
class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
private let mac = MacBundle.shared
@ -39,4 +40,10 @@ class AppDelegate: NSObject, UIApplicationDelegate, ObservableObject {
#endif
return true
}
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
let sceneConfiguration = UISceneConfiguration(name: "SceneDelegate", sessionRole: connectingSceneSession.role)
sceneConfiguration.delegateClass = SceneDelegate.self
return sceneConfiguration
}
}

View File

@ -380,6 +380,23 @@ extension View {
}
}
// MARK: Shortcuts
extension ShortcutType {
var themeImageName: String {
switch self {
case .enableVPN:
return "power"
case .disableVPN:
return "xmark"
case .reconnectVPN:
return "arrow.clockwise"
}
}
}
// MARK: Animations
extension View {

View File

@ -0,0 +1,87 @@
//
// SceneDelegate+Shortcuts.swift
// Passepartout
//
// Created by Davide De Rosa on 3/19/23.
// Copyright (c) 2023 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 <http://www.gnu.org/licenses/>.
//
import SwiftUI
import PassepartoutLibrary
enum ShortcutType: String {
case enableVPN
case disableVPN
case reconnectVPN
}
extension SceneDelegate {
func rebuildShortcutItems() {
let items: [UIApplicationShortcutItem]
if VPNManager.shared.currentState.isEnabled {
items = [
ShortcutType.disableVPN.shortcutItem(withTitle: L10n.Shortcuts.Add.Items.DisableVpn.caption),
ShortcutType.reconnectVPN.shortcutItem(withTitle: L10n.Global.Strings.reconnect)
]
} else if ProfileManager.shared.hasActiveProfile {
items = [
ShortcutType.enableVPN.shortcutItem(withTitle: L10n.Shortcuts.Add.Items.EnableVpn.caption)
]
} else {
items = []
}
UIApplication.shared.shortcutItems = items
}
func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
switch shortcutItem.type {
case ShortcutType.enableVPN.rawValue:
Task {
try await VPNManager.shared.connectWithActiveProfile(toServer: nil)
}
case ShortcutType.disableVPN.rawValue:
Task {
await VPNManager.shared.disable()
}
case ShortcutType.reconnectVPN.rawValue:
Task {
await VPNManager.shared.reconnect()
}
default:
break
}
}
}
private extension ShortcutType {
func shortcutItem(withTitle title: String) -> UIApplicationShortcutItem {
UIApplicationShortcutItem(
type: rawValue,
localizedTitle: title,
localizedSubtitle: nil,
icon: .init(systemImageName: themeImageName)
)
}
}

View File

@ -0,0 +1,41 @@
//
// SceneDelegate.swift
// Passepartout
//
// Created by Davide De Rosa on 3/19/23.
// Copyright (c) 2023 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 <http://www.gnu.org/licenses/>.
//
import SwiftUI
import PassepartoutLibrary
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
func sceneDidEnterBackground(_ scene: UIScene) {
ProfileManager.shared.persist()
#if targetEnvironment(macCatalyst)
MacBundle.shared.utils.sendAppToBackground()
#endif
rebuildShortcutItems()
}
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
handleShortcutItem(shortcutItem)
}
}

View File

@ -53,7 +53,6 @@ extension OrganizerView {
Text("Scene")
.hidden()
.onAppear(perform: onAppear)
.onChange(of: scenePhase, perform: onScenePhase)
}
private func onAppear() {
@ -79,22 +78,5 @@ extension OrganizerView {
profileManager.currentProfileId = activeProfileId
}
}
private func onScenePhase(_ phase: ScenePhase) {
switch phase {
case .background:
persist()
#if targetEnvironment(macCatalyst)
MacBundle.shared.utils.sendAppToBackground()
#endif
default:
break
}
}
private func persist() {
profileManager.persist()
}
}
}