diff --git a/Passepartout/App/AppDelegate.swift b/Passepartout/App/AppDelegate.swift
index 7d897c32..02cdf4e2 100644
--- a/Passepartout/App/AppDelegate.swift
+++ b/Passepartout/App/AppDelegate.swift
@@ -33,21 +33,8 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
#else
import AppKit
-import CommonLibrary
-import PassepartoutKit
final class AppDelegate: NSObject, NSApplicationDelegate {
- func applicationDidFinishLaunching(_ notification: Notification) {
- NSWindow.allowsAutomaticWindowTabbing = false
-
- // XXX: hack to only retain "Edit" menu
- NSApp.mainMenu?.items = NSApp.mainMenu?.items.filter {
- [BundleConfiguration.main.displayName, "Edit"].contains($0.title)
- } ?? []
- }
-
- func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
- true
- }
}
+
#endif
diff --git a/Passepartout/App/PassepartoutApp.swift b/Passepartout/App/PassepartoutApp.swift
index a7e5de8d..05414538 100644
--- a/Passepartout/App/PassepartoutApp.swift
+++ b/Passepartout/App/PassepartoutApp.swift
@@ -53,6 +53,11 @@ struct PassepartoutApp: App {
#else
Window(appName, id: appName, content: content)
.defaultSize(width: 600.0, height: 400.0)
+
+// Settings {
+// SettingsView()
+// .frame(minWidth: 300, minHeight: 100)
+// }
#endif
}
}
diff --git a/Passepartout/Library/Sources/AppUI/L10n/SwiftGen+Strings.swift b/Passepartout/Library/Sources/AppUI/L10n/SwiftGen+Strings.swift
index a4a52feb..ab3dc25b 100644
--- a/Passepartout/Library/Sources/AppUI/L10n/SwiftGen+Strings.swift
+++ b/Passepartout/Library/Sources/AppUI/L10n/SwiftGen+Strings.swift
@@ -139,6 +139,8 @@ internal enum Strings {
}
}
internal enum Global {
+ /// About
+ internal static let about = Strings.tr("Localizable", "global.about", fallback: "About")
/// Account
internal static let account = Strings.tr("Localizable", "global.account", fallback: "Account")
/// Address
@@ -397,46 +399,44 @@ internal enum Strings {
}
}
internal enum Views {
- internal enum Advanced {
- /// Lock app access
- internal static let lockInBackground = Strings.tr("Localizable", "views.advanced.lock_in_background", fallback: "Lock app access")
- /// Advanced
- internal static let title = Strings.tr("Localizable", "views.advanced.title", fallback: "Advanced")
+ internal enum About {
+ /// About
+ internal static let title = Strings.tr("Localizable", "views.about.title", fallback: "About")
internal enum Credits {
/// Licenses
- internal static let licenses = Strings.tr("Localizable", "views.advanced.credits.licenses", fallback: "Licenses")
+ internal static let licenses = Strings.tr("Localizable", "views.about.credits.licenses", fallback: "Licenses")
/// Notices
- internal static let notices = Strings.tr("Localizable", "views.advanced.credits.notices", fallback: "Notices")
+ internal static let notices = Strings.tr("Localizable", "views.about.credits.notices", fallback: "Notices")
/// Credits
- internal static let title = Strings.tr("Localizable", "views.advanced.credits.title", fallback: "Credits")
+ internal static let title = Strings.tr("Localizable", "views.about.credits.title", fallback: "Credits")
/// Translations
- internal static let translations = Strings.tr("Localizable", "views.advanced.credits.translations", fallback: "Translations")
+ internal static let translations = Strings.tr("Localizable", "views.about.credits.translations", fallback: "Translations")
}
internal enum Links {
/// Links
- internal static let title = Strings.tr("Localizable", "views.advanced.links.title", fallback: "Links")
+ internal static let title = Strings.tr("Localizable", "views.about.links.title", fallback: "Links")
internal enum Rows {
/// Disclaimer
- internal static let disclaimer = Strings.tr("Localizable", "views.advanced.links.rows.disclaimer", fallback: "Disclaimer")
+ internal static let disclaimer = Strings.tr("Localizable", "views.about.links.rows.disclaimer", fallback: "Disclaimer")
/// Home page
- internal static let homePage = Strings.tr("Localizable", "views.advanced.links.rows.home_page", fallback: "Home page")
+ internal static let homePage = Strings.tr("Localizable", "views.about.links.rows.home_page", fallback: "Home page")
/// Join community
- internal static let joinCommunity = Strings.tr("Localizable", "views.advanced.links.rows.join_community", fallback: "Join community")
+ internal static let joinCommunity = Strings.tr("Localizable", "views.about.links.rows.join_community", fallback: "Join community")
/// Privacy policy
- internal static let privacyPolicy = Strings.tr("Localizable", "views.advanced.links.rows.privacy_policy", fallback: "Privacy policy")
+ internal static let privacyPolicy = Strings.tr("Localizable", "views.about.links.rows.privacy_policy", fallback: "Privacy policy")
/// Write a review
- internal static let writeReview = Strings.tr("Localizable", "views.advanced.links.rows.write_review", fallback: "Write a review")
+ internal static let writeReview = Strings.tr("Localizable", "views.about.links.rows.write_review", fallback: "Write a review")
}
internal enum Sections {
/// Support
- internal static let support = Strings.tr("Localizable", "views.advanced.links.sections.support", fallback: "Support")
+ internal static let support = Strings.tr("Localizable", "views.about.links.sections.support", fallback: "Support")
/// Web
- internal static let web = Strings.tr("Localizable", "views.advanced.links.sections.web", fallback: "Web")
+ internal static let web = Strings.tr("Localizable", "views.about.links.sections.web", fallback: "Web")
}
}
internal enum Sections {
/// Resources
- internal static let resources = Strings.tr("Localizable", "views.advanced.sections.resources", fallback: "Resources")
+ internal static let resources = Strings.tr("Localizable", "views.about.sections.resources", fallback: "Resources")
}
}
internal enum Diagnostics {
@@ -479,10 +479,6 @@ internal enum Strings {
/// Make a donation
internal static let title = Strings.tr("Localizable", "views.donate.title", fallback: "Make a donation")
}
- internal enum Lockable {
- /// Passepartout is locked
- internal static let message = Strings.tr("Localizable", "views.lockable.message", fallback: "Passepartout is locked")
- }
internal enum Profile {
internal enum ModuleList {
internal enum Section {
@@ -543,6 +539,20 @@ internal enum Strings {
internal static let newProfile = Strings.tr("Localizable", "views.profiles.toolbar.new_profile", fallback: "New profile")
}
}
+ internal enum Settings {
+ internal enum Rows {
+ /// Lock in background
+ internal static let lockInBackground = Strings.tr("Localizable", "views.settings.rows.lock_in_background", fallback: "Lock in background")
+ internal enum LockInBackground {
+ /// Passepartout is locked
+ internal static let message = Strings.tr("Localizable", "views.settings.rows.lock_in_background.message", fallback: "Passepartout is locked")
+ }
+ }
+ internal enum Sections {
+ /// Lock
+ internal static let lock = Strings.tr("Localizable", "views.settings.sections.lock", fallback: "Lock")
+ }
+ }
}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
diff --git a/Passepartout/Library/Sources/AppUI/Resources/en.lproj/Localizable.strings b/Passepartout/Library/Sources/AppUI/Resources/en.lproj/Localizable.strings
index 0df659ed..9d8695d5 100644
--- a/Passepartout/Library/Sources/AppUI/Resources/en.lproj/Localizable.strings
+++ b/Passepartout/Library/Sources/AppUI/Resources/en.lproj/Localizable.strings
@@ -1,5 +1,6 @@
// MARK: Global
+"global.about" = "About";
"global.account" = "Account";
"global.address" = "Address";
"global.addresses" = "Addresses";
@@ -119,23 +120,26 @@
"views.profile.rows.add_module" = "Add module";
"views.profile.module_list.section.footer" = "Drag modules to rearrange them, as their order determines priority.";
-"views.advanced.title" = "Advanced";
-"views.advanced.sections.resources" = "Resources";
-"views.advanced.lock_in_background" = "Lock app access";
+"views.settings.sections.lock" = "Lock";
+"views.settings.rows.lock_in_background" = "Lock in background";
+"views.settings.rows.lock_in_background.message" = "Passepartout is locked";
-"views.advanced.links.title" = "Links";
-"views.advanced.links.sections.support" = "Support";
-"views.advanced.links.sections.web" = "Web";
-"views.advanced.links.rows.join_community" = "Join community";
-"views.advanced.links.rows.write_review" = "Write a review";
-"views.advanced.links.rows.home_page" = "Home page";
-"views.advanced.links.rows.disclaimer" = "Disclaimer";
-"views.advanced.links.rows.privacy_policy" = "Privacy policy";
+"views.about.title" = "About";
+"views.about.sections.resources" = "Resources";
-"views.advanced.credits.title" = "Credits";
-"views.advanced.credits.licenses" = "Licenses";
-"views.advanced.credits.notices" = "Notices";
-"views.advanced.credits.translations" = "Translations";
+"views.about.links.title" = "Links";
+"views.about.links.sections.support" = "Support";
+"views.about.links.sections.web" = "Web";
+"views.about.links.rows.join_community" = "Join community";
+"views.about.links.rows.write_review" = "Write a review";
+"views.about.links.rows.home_page" = "Home page";
+"views.about.links.rows.disclaimer" = "Disclaimer";
+"views.about.links.rows.privacy_policy" = "Privacy policy";
+
+"views.about.credits.title" = "Credits";
+"views.about.credits.licenses" = "Licenses";
+"views.about.credits.notices" = "Notices";
+"views.about.credits.translations" = "Translations";
"views.donate.title" = "Make a donation";
@@ -152,8 +156,6 @@
"views.diagnostics.report_issue.title" = "Report issue";
"views.diagnostics.alerts.report_issue.email" = "The device is not configured to send e-mails.";
-"views.lockable.message" = "Passepartout is locked";
-
// MARK: - Module views
"modules.dns.servers.add" = "Add address";
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedRouterView.swift b/Passepartout/Library/Sources/AppUI/Views/About/AboutRouterView.swift
similarity index 95%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedRouterView.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/AboutRouterView.swift
index a5e885da..cb93de36 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedRouterView.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/AboutRouterView.swift
@@ -1,5 +1,5 @@
//
-// AdvancedRouterView.swift
+// AboutRouterView.swift
// Passepartout
//
// Created by Davide De Rosa on 8/22/24.
@@ -28,7 +28,7 @@ import CommonLibrary
import PassepartoutKit
import SwiftUI
-struct AdvancedRouterView: View {
+struct AboutRouterView: View {
@Environment(\.dismiss)
var dismiss
@@ -43,7 +43,7 @@ struct AdvancedRouterView: View {
}
}
-extension AdvancedRouterView {
+extension AboutRouterView {
enum NavigationRoute: Hashable {
case donate
@@ -94,7 +94,7 @@ extension AdvancedRouterView {
}
#Preview {
- AdvancedRouterView(
+ AboutRouterView(
tunnel: .mock
)
.environmentObject(Theme())
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedView.swift b/Passepartout/Library/Sources/AppUI/Views/About/AboutView.swift
similarity index 68%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedView.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/AboutView.swift
index 31293395..834c002a 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/AdvancedView.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/AboutView.swift
@@ -1,5 +1,5 @@
//
-// AdvancedView.swift
+// AboutView.swift
// Passepartout
//
// Created by Davide De Rosa on 8/23/24.
@@ -28,27 +28,19 @@ import PassepartoutKit
import SwiftUI
import UtilsLibrary
-struct AdvancedView: View {
-
- @AppStorage(AppPreference.locksInBackground.key)
- private var locksInBackground = false
-
+struct AboutView: View {
let identifiers: Constants.Identifiers
@Binding
- var navigationRoute: AdvancedRouterView.NavigationRoute?
+ var navigationRoute: AboutRouterView.NavigationRoute?
var body: some View {
listView
- .navigationTitle(Strings.Views.Advanced.title)
+ .navigationTitle(Strings.Views.About.title)
}
}
-extension AdvancedView {
- var lockInBackgroundToggle: some View {
- Toggle(Strings.Views.Advanced.lockInBackground, isOn: $locksInBackground)
- }
-
+extension AboutView {
var donateLink: some View {
navLink(Strings.Views.Donate.title, to: .donate)
}
@@ -58,22 +50,22 @@ extension AdvancedView {
}
var linksLink: some View {
- navLink(Strings.Views.Advanced.Links.title, to: .links)
+ navLink(Strings.Views.About.Links.title, to: .links)
}
var creditsLink: some View {
- navLink(Strings.Views.Advanced.Credits.title, to: .credits)
+ navLink(Strings.Views.About.Credits.title, to: .credits)
}
}
-private extension AdvancedView {
- func navLink(_ title: String, to route: AdvancedRouterView.NavigationRoute) -> some View {
+private extension AboutView {
+ func navLink(_ title: String, to route: AboutRouterView.NavigationRoute) -> some View {
NavigationLink(title, value: route)
}
}
#Preview {
- AdvancedView(
+ AboutView(
identifiers: Constants.shared.identifiers,
navigationRoute: .constant(nil)
)
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/CreditsView.swift b/Passepartout/Library/Sources/AppUI/Views/About/CreditsView.swift
similarity index 82%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/CreditsView.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/CreditsView.swift
index dc3c954e..45244475 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/CreditsView.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/CreditsView.swift
@@ -30,15 +30,15 @@ struct CreditsView: View {
var body: some View {
GenericCreditsView(
credits: Self.credits,
- licensesHeader: Strings.Views.Advanced.Credits.licenses,
- noticesHeader: Strings.Views.Advanced.Credits.notices,
- translationsHeader: Strings.Views.Advanced.Credits.translations,
+ licensesHeader: Strings.Views.About.Credits.licenses,
+ noticesHeader: Strings.Views.About.Credits.notices,
+ translationsHeader: Strings.Views.About.Credits.translations,
errorDescription: {
AppError($0)
.localizedDescription
}
)
- .navigationTitle(Strings.Views.Advanced.Credits.title)
+ .navigationTitle(Strings.Views.About.Credits.title)
.themeForm()
}
}
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/DonateView.swift b/Passepartout/Library/Sources/AppUI/Views/About/DonateView.swift
similarity index 100%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/DonateView.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/DonateView.swift
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/LinksView.swift b/Passepartout/Library/Sources/AppUI/Views/About/LinksView.swift
similarity index 67%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/LinksView.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/LinksView.swift
index 120edf99..3f3a0980 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/LinksView.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/LinksView.swift
@@ -32,7 +32,7 @@ struct LinksView: View {
supportSection
webSection
}
- .navigationTitle(Strings.Views.Advanced.Links.title)
+ .navigationTitle(Strings.Views.About.Links.title)
.themeForm()
}
}
@@ -44,21 +44,21 @@ private extension LinksView {
var supportSection: some View {
Section {
- Link(Strings.Views.Advanced.Links.Rows.joinCommunity, destination: constants.websites.subreddit)
- Link(Strings.Views.Advanced.Links.Rows.writeReview, destination: constants.urlForReview)
+ Link(Strings.Views.About.Links.Rows.joinCommunity, destination: constants.websites.subreddit)
+ Link(Strings.Views.About.Links.Rows.writeReview, destination: constants.urlForReview)
} header: {
- Text(Strings.Views.Advanced.Links.Sections.support)
+ Text(Strings.Views.About.Links.Sections.support)
}
}
var webSection: some View {
Section {
- Link(Strings.Views.Advanced.Links.Rows.homePage, destination: constants.websites.home)
+ Link(Strings.Views.About.Links.Rows.homePage, destination: constants.websites.home)
Link(Strings.Unlocalized.faq, destination: constants.websites.faq)
- Link(Strings.Views.Advanced.Links.Rows.disclaimer, destination: constants.websites.disclaimer)
- Link(Strings.Views.Advanced.Links.Rows.privacyPolicy, destination: constants.websites.privacyPolicy)
+ Link(Strings.Views.About.Links.Rows.disclaimer, destination: constants.websites.disclaimer)
+ Link(Strings.Views.About.Links.Rows.privacyPolicy, destination: constants.websites.privacyPolicy)
} header: {
- Text(Strings.Views.Advanced.Links.Sections.web)
+ Text(Strings.Views.About.Links.Sections.web)
}
}
}
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedRouterView+iOS.swift b/Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutRouterView+iOS.swift
similarity index 94%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedRouterView+iOS.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutRouterView+iOS.swift
index 0ba4a763..413ef044 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedRouterView+iOS.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutRouterView+iOS.swift
@@ -1,5 +1,5 @@
//
-// AdvancedRouterView+iOS.swift
+// AboutRouterView+iOS.swift
// Passepartout
//
// Created by Davide De Rosa on 8/26/24.
@@ -28,10 +28,10 @@
import CommonLibrary
import SwiftUI
-extension AdvancedRouterView {
+extension AboutRouterView {
var body: some View {
NavigationStack {
- AdvancedView(
+ AboutView(
identifiers: Constants.shared.identifiers,
navigationRoute: $navigationRoute
)
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedView+iOS.swift b/Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutView+iOS.swift
similarity index 83%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedView+iOS.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutView+iOS.swift
index 99006022..e9a33a0e 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/iOS/AdvancedView+iOS.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/iOS/AboutView+iOS.swift
@@ -1,5 +1,5 @@
//
-// AdvancedView+iOS.swift
+// AboutView+iOS.swift
// Passepartout
//
// Created by Davide De Rosa on 8/27/24.
@@ -27,21 +27,16 @@
import SwiftUI
-extension AdvancedView {
+extension AboutView {
var listView: some View {
List {
- Section {
- lockInBackgroundToggle
- } header: {
- Text(Strings.Global.settings)
- }
Section {
// TODO: donations
// donateLink
linksLink
creditsLink
} header: {
- Text(Strings.Views.Advanced.Sections.resources)
+ Text(Strings.Views.About.Sections.resources)
}
Section {
diagnosticsLink
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedRouterView+macOS.swift b/Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutRouterView+macOS.swift
similarity index 94%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedRouterView+macOS.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutRouterView+macOS.swift
index fdfdcf00..67f1bad8 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedRouterView+macOS.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutRouterView+macOS.swift
@@ -1,5 +1,5 @@
//
-// AdvancedRouterView+macOS.swift
+// AboutRouterView+macOS.swift
// Passepartout
//
// Created by Davide De Rosa on 8/26/24.
@@ -28,10 +28,10 @@
import CommonLibrary
import SwiftUI
-extension AdvancedRouterView {
+extension AboutRouterView {
var body: some View {
NavigationSplitView {
- AdvancedView(
+ AboutView(
identifiers: Constants.shared.identifiers,
navigationRoute: $navigationRoute
)
diff --git a/Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedView+macOS.swift b/Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutView+macOS.swift
similarity index 86%
rename from Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedView+macOS.swift
rename to Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutView+macOS.swift
index 56ea5f16..d27f2ca6 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Advanced/macOS/AdvancedView+macOS.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/About/macOS/AboutView+macOS.swift
@@ -1,5 +1,5 @@
//
-// AdvancedView+macOS.swift
+// AboutView+macOS.swift
// Passepartout
//
// Created by Davide De Rosa on 8/27/24.
@@ -27,14 +27,9 @@ import SwiftUI
#if os(macOS)
-extension AdvancedView {
+extension AboutView {
var listView: some View {
List(selection: $navigationRoute) {
- Section {
- lockInBackgroundToggle
- } header: {
- Text(Strings.Global.settings)
- }
Section {
// TODO: donations
// donateLink
diff --git a/Passepartout/Library/Sources/AppUI/Views/App/AppInlineCoordinator.swift b/Passepartout/Library/Sources/AppUI/Views/App/AppInlineCoordinator.swift
index 60eb45b0..ec1386c3 100644
--- a/Passepartout/Library/Sources/AppUI/Views/App/AppInlineCoordinator.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/App/AppInlineCoordinator.swift
@@ -71,11 +71,10 @@ private extension AppInlineCoordinator {
enum ModalRoute: String, Identifiable {
case settings
- var id: [String] {
- switch self {
- case .settings:
- return ["settings"]
- }
+ case about
+
+ var id: String {
+ rawValue
}
}
@@ -103,6 +102,9 @@ private extension AppInlineCoordinator {
onSettings: {
modalRoute = .settings
},
+ onAbout: {
+ modalRoute = .about
+ },
onNewProfile: enterDetail
)
}
@@ -127,7 +129,10 @@ private extension AppInlineCoordinator {
func modalDestination(for item: ModalRoute?) -> some View {
switch item {
case .settings:
- AdvancedRouterView(tunnel: tunnel)
+ SettingsView()
+
+ case .about:
+ AboutRouterView(tunnel: tunnel)
default:
EmptyView()
diff --git a/Passepartout/Library/Sources/AppUI/Views/App/AppModalCoordinator.swift b/Passepartout/Library/Sources/AppUI/Views/App/AppModalCoordinator.swift
index a1f866a5..d10b689e 100644
--- a/Passepartout/Library/Sources/AppUI/Views/App/AppModalCoordinator.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/App/AppModalCoordinator.swift
@@ -62,19 +62,15 @@ struct AppModalCoordinator: View {
// MARK: - Destinations
extension AppModalCoordinator {
- enum ModalRoute: Identifiable {
+ enum ModalRoute: String, Identifiable {
case editProfile
case settings
- var id: [String] {
- switch self {
- case .editProfile:
- return ["editProfile"]
+ case about
- case .settings:
- return ["settings"]
- }
+ var id: String {
+ rawValue
}
}
@@ -102,6 +98,9 @@ extension AppModalCoordinator {
onSettings: {
modalRoute = .settings
},
+ onAbout: {
+ modalRoute = .about
+ },
onNewProfile: enterDetail
)
}
@@ -121,7 +120,10 @@ extension AppModalCoordinator {
}
case .settings:
- AdvancedRouterView(tunnel: tunnel)
+ SettingsView()
+
+ case .about:
+ AboutRouterView(tunnel: tunnel)
default:
EmptyView()
diff --git a/Passepartout/Library/Sources/AppUI/Views/App/AppToolbar.swift b/Passepartout/Library/Sources/AppUI/Views/App/AppToolbar.swift
index 0ec9717f..3e1f02b2 100644
--- a/Passepartout/Library/Sources/AppUI/Views/App/AppToolbar.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/App/AppToolbar.swift
@@ -45,18 +45,20 @@ struct AppToolbar: ToolbarContent {
let onSettings: () -> Void
+ let onAbout: () -> Void
+
let onNewProfile: (Profile) -> Void
var body: some ToolbarContent {
if hsClass == .regular && vsClass == .regular {
ToolbarItemGroup {
addProfileMenu
- settingsButton
+ aboutButton
layoutPicker
}
} else {
ToolbarItem(placement: .navigation) {
- settingsButton
+ moreMenu
}
ToolbarItemGroup(placement: .primaryAction) {
addProfileMenu
@@ -75,9 +77,24 @@ private extension AppToolbar {
)
}
+ var moreMenu: some View {
+ Menu {
+ settingsButton
+ aboutButton
+ } label: {
+ ThemeImage(.moreDetails)
+ }
+ }
+
var settingsButton: some View {
Button(action: onSettings) {
- ThemeImage(.advanced)
+ ThemeImageLabel(Strings.Global.settings, .settings)
+ }
+ }
+
+ var aboutButton: some View {
+ Button(action: onAbout) {
+ ThemeImageLabel(Strings.Global.about, .info)
}
}
@@ -95,6 +112,7 @@ private extension AppToolbar {
layout: .constant(.list),
isImporting: .constant(false),
onSettings: {},
+ onAbout: {},
onNewProfile: { _ in}
)
}
diff --git a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift
index d30f2aee..5fc2051e 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift
@@ -161,7 +161,7 @@ private extension DiagnosticsView {
}
}
- func navLink(_ title: String, to value: AdvancedRouterView.NavigationRoute) -> some View {
+ func navLink(_ title: String, to value: AboutRouterView.NavigationRoute) -> some View {
NavigationLink(title, value: value)
}
}
diff --git a/Passepartout/Library/Sources/AppUI/Views/Settings/SettingsView.swift b/Passepartout/Library/Sources/AppUI/Views/Settings/SettingsView.swift
new file mode 100644
index 00000000..a2dc31b7
--- /dev/null
+++ b/Passepartout/Library/Sources/AppUI/Views/Settings/SettingsView.swift
@@ -0,0 +1,61 @@
+//
+// SettingsView.swift
+// Passepartout
+//
+// Created by Davide De Rosa on 9/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 .
+//
+
+import CommonLibrary
+import SwiftUI
+
+public struct SettingsView: View {
+
+ @AppStorage(AppPreference.locksInBackground.key)
+ private var locksInBackground = false
+
+ @State
+ private var path = NavigationPath()
+
+ public init() {
+ }
+
+ public var body: some View {
+ Form {
+ Section {
+ lockInBackgroundToggle
+ } header: {
+ Text(Strings.Views.Settings.Sections.lock)
+ }
+ }
+ .themeForm()
+ .navigationTitle(Strings.Global.settings)
+#if os(iOS)
+ .themeNavigationDetail()
+ .themeNavigationStack(if: true, closable: true, path: $path)
+#endif
+ }
+}
+
+private extension SettingsView {
+ var lockInBackgroundToggle: some View {
+ Toggle(Strings.Views.Settings.Rows.lockInBackground, isOn: $locksInBackground)
+ }
+}
diff --git a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+ImageName.swift b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+ImageName.swift
index b575029b..153b42b6 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+ImageName.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+ImageName.swift
@@ -28,7 +28,6 @@ import Foundation
extension Theme {
public enum ImageName {
case add
- case advanced
case close
case contextDuplicate
case contextRemove
@@ -47,6 +46,7 @@ extension Theme {
case profilesGrid
case profilesList
case remove
+ case settings
case share
case show
case sleeping
diff --git a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+UI.swift b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+UI.swift
index fc9e66bb..c253bcd7 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+UI.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme+UI.swift
@@ -102,6 +102,40 @@ struct ThemeItemModalModifier: ViewModifier where Modal: View, T: Iden
}
}
+struct ThemeNavigationStackModifier: ViewModifier {
+
+ @Environment(\.dismiss)
+ private var dismiss
+
+ let condition: Bool
+
+ let closable: Bool
+
+ @Binding
+ var path: NavigationPath
+
+ func body(content: Content) -> some View {
+ if condition {
+ NavigationStack(path: $path) {
+ content
+ .toolbar {
+ if closable {
+ ToolbarItem(placement: .cancellationAction) {
+ Button {
+ dismiss()
+ } label: {
+ ThemeImage(.close)
+ }
+ }
+ }
+ }
+ }
+ } else {
+ content
+ }
+ }
+}
+
struct ThemePlainButtonModifier: ViewModifier {
let action: () -> Void
}
@@ -228,7 +262,7 @@ struct ThemeLockScreenModifier: ViewModifier {
do {
let isAuthorized = try await context.evaluatePolicy(
policy,
- localizedReason: Strings.Views.Lockable.message
+ localizedReason: Strings.Views.Settings.Rows.LockInBackground.message
)
return isAuthorized
} catch {
diff --git a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme.swift b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme.swift
index 2a4f395b..9f382dd4 100644
--- a/Passepartout/Library/Sources/AppUI/Views/Theme/Theme.swift
+++ b/Passepartout/Library/Sources/AppUI/Views/Theme/Theme.swift
@@ -79,7 +79,6 @@ public final class Theme: ObservableObject {
var systemImage: (ImageName) -> String = {
switch $0 {
case .add: return "plus"
- case .advanced: return "gearshape"
case .close: return "xmark"
case .contextDuplicate: return "plus.square.on.square"
case .contextRemove: return "trash"
@@ -98,6 +97,7 @@ public final class Theme: ObservableObject {
case .profilesGrid: return "square.grid.2x2"
case .profilesList: return "rectangle.grid.1x2"
case .remove: return "minus"
+ case .settings: return "gearshape"
case .share: return "square.and.arrow.up"
case .show: return "eye"
case .sleeping: return "powersleep"
@@ -160,15 +160,8 @@ extension View {
))
}
- @ViewBuilder
- public func themeNavigationStack(if condition: Bool, path: Binding) -> some View {
- if condition {
- NavigationStack(path: path) {
- self
- }
- } else {
- self
- }
+ public func themeNavigationStack(if condition: Bool, closable: Bool = false, path: Binding) -> some View {
+ modifier(ThemeNavigationStackModifier(condition: condition, closable: closable, path: path))
}
public func themePlainButton(action: @escaping () -> Void) -> some View {