From 2d698cabfe09176390d86ab6c0ae0d9780bfede3 Mon Sep 17 00:00:00 2001 From: Davide Date: Wed, 13 Nov 2024 19:17:00 +0100 Subject: [PATCH] Reuse modifier for navigation stacks with close button (#861) Refactored: - iOS - VPNProviderServerView - macOS - AboutView - ProfileSplitView - Both - ProfileCoordinator - VPNProviderServerCoordinator --- .github/workflows/release.yml | 4 +- .github/workflows/test.yml | 2 +- .../Views/About/iOS/AboutRouterView+iOS.swift | 24 +++------- .../About/macOS/AboutRouterView+macOS.swift | 17 ++++--- .../macOS/ProfileSplitView+macOS.swift | 3 +- .../VPNProviderServerCoordinator.swift | 28 ++++------- .../iOS/VPNProviderServerView+iOS.swift | 2 +- .../Views/Settings/SettingsView.swift | 2 +- .../UILibrary/Theme/UI/Theme+Modifiers.swift | 46 +++++++++++-------- 9 files changed, 59 insertions(+), 69 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index afa9db21..0dea2408 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ concurrency: jobs: run_tests: name: Run tests - runs-on: macos-14 + runs-on: macos-15 timeout-minutes: 15 steps: - uses: passepartoutvpn/action-prepare-xcode-build@master @@ -30,7 +30,7 @@ jobs: bundle exec fastlane test build_upload: name: Upload to ASC - runs-on: macos-14 + runs-on: macos-15 needs: run_tests strategy: fail-fast: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4a83546e..4d936faf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ concurrency: jobs: run_swift_tests: name: Run SwiftPM tests - runs-on: macos-14 + runs-on: macos-15 timeout-minutes: 10 steps: - uses: passepartoutvpn/action-prepare-xcode-build@master diff --git a/Passepartout/Library/Sources/AppUIMain/Views/About/iOS/AboutRouterView+iOS.swift b/Passepartout/Library/Sources/AppUIMain/Views/About/iOS/AboutRouterView+iOS.swift index 916f10bb..4595e400 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/About/iOS/AboutRouterView+iOS.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/About/iOS/AboutRouterView+iOS.swift @@ -30,23 +30,13 @@ import SwiftUI extension AboutRouterView { var body: some View { - NavigationStack(path: $path) { - AboutView( - profileManager: profileManager, - navigationRoute: $navigationRoute - ) - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button { - dismiss() - } label: { - ThemeImage(.close) - } - } - } - .navigationDestination(for: NavigationRoute.self, destination: pushDestination) - .themeNavigationDetail() - } + AboutView( + profileManager: profileManager, + navigationRoute: $navigationRoute + ) + .navigationDestination(for: NavigationRoute.self, destination: pushDestination) + .themeNavigationDetail() + .themeNavigationStack(closable: true, path: $path) } } diff --git a/Passepartout/Library/Sources/AppUIMain/Views/About/macOS/AboutRouterView+macOS.swift b/Passepartout/Library/Sources/AppUIMain/Views/About/macOS/AboutRouterView+macOS.swift index de33b511..fcfeb5fe 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/About/macOS/AboutRouterView+macOS.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/About/macOS/AboutRouterView+macOS.swift @@ -36,17 +36,16 @@ extension AboutRouterView { navigationRoute: $navigationRoute ) } detail: { - NavigationStack(path: $path) { - pushDestination(for: navigationRoute) - .navigationDestination(for: NavigationRoute.self, destination: pushDestination) - } - .toolbar { - ToolbarItem(placement: .confirmationAction) { - Button(Strings.Global.ok) { - dismiss() + pushDestination(for: navigationRoute) + .navigationDestination(for: NavigationRoute.self, destination: pushDestination) + .themeNavigationStack(closable: false, path: $path) + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button(Strings.Global.ok) { + dismiss() + } } } - } } .onLoad { navigationRoute = .links diff --git a/Passepartout/Library/Sources/AppUIMain/Views/Profile/macOS/ProfileSplitView+macOS.swift b/Passepartout/Library/Sources/AppUIMain/Views/Profile/macOS/ProfileSplitView+macOS.swift index 83827ad9..469c0b4c 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/Profile/macOS/ProfileSplitView+macOS.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/Profile/macOS/ProfileSplitView+macOS.swift @@ -55,7 +55,7 @@ struct ProfileSplitView: View, Routable { flow: flow ) } detail: { - NavigationStack(path: $detailPath) { + Group { switch selectedModuleId { case ModuleListView.generalModuleId: detailView(for: .general) @@ -64,6 +64,7 @@ struct ProfileSplitView: View, Routable { detailView(for: .module(id: selectedModuleId)) } } + .themeNavigationStack(path: $detailPath) .toolbar(content: toolbarContent) .environment(\.navigationPath, $detailPath) } diff --git a/Passepartout/Library/Sources/AppUIMain/Views/Provider/VPNProviderServerCoordinator.swift b/Passepartout/Library/Sources/AppUIMain/Views/Provider/VPNProviderServerCoordinator.swift index f200bc73..0f468d9c 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/Provider/VPNProviderServerCoordinator.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/Provider/VPNProviderServerCoordinator.swift @@ -44,25 +44,15 @@ struct VPNProviderServerCoordinator: View where Configuration: Pr let onSelect: (VPNEntity) async throws -> Void var body: some View { - NavigationStack { - VPNProviderServerView( - moduleId: moduleId, - providerId: providerId, - configurationType: Configuration.self, - selectedEntity: selectedEntity, - filtersWithSelection: false, - onSelect: onSelect - ) - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button { - dismiss() - } label: { - ThemeCloseLabel() - } - } - } - } + VPNProviderServerView( + moduleId: moduleId, + providerId: providerId, + configurationType: Configuration.self, + selectedEntity: selectedEntity, + filtersWithSelection: false, + onSelect: onSelect + ) + .themeNavigationStack(closable: true) } } diff --git a/Passepartout/Library/Sources/AppUIMain/Views/Provider/iOS/VPNProviderServerView+iOS.swift b/Passepartout/Library/Sources/AppUIMain/Views/Provider/iOS/VPNProviderServerView+iOS.swift index 96d22717..0f931b8f 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/Provider/iOS/VPNProviderServerView+iOS.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/Provider/iOS/VPNProviderServerView+iOS.swift @@ -79,7 +79,7 @@ private extension VPNProviderServerView { Button { isPresented = false } label: { - ThemeImage(.close) + ThemeCloseLabel() } } } diff --git a/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsView.swift b/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsView.swift index d634311a..cbd5c2d7 100644 --- a/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsView.swift +++ b/Passepartout/Library/Sources/AppUIMain/Views/Settings/SettingsView.swift @@ -44,7 +44,7 @@ public struct SettingsView: View { .navigationTitle(Strings.Global.settings) #if os(iOS) .themeNavigationDetail() - .themeNavigationStack(if: true, closable: true, path: $path) + .themeNavigationStack(closable: true, path: $path) #endif } } diff --git a/Passepartout/Library/Sources/UILibrary/Theme/UI/Theme+Modifiers.swift b/Passepartout/Library/Sources/UILibrary/Theme/UI/Theme+Modifiers.swift index 0cf64676..d894f694 100644 --- a/Passepartout/Library/Sources/UILibrary/Theme/UI/Theme+Modifiers.swift +++ b/Passepartout/Library/Sources/UILibrary/Theme/UI/Theme+Modifiers.swift @@ -75,8 +75,24 @@ extension View { )) } - public func themeNavigationStack(if condition: Bool, closable: Bool = false, path: Binding) -> some View { - modifier(ThemeNavigationStackModifier(condition: condition, closable: closable, path: path)) + public func themeNavigationStack( + closable: Bool = false, + path: Binding = .constant(NavigationPath()) + ) -> some View { + modifier(ThemeNavigationStackModifier(closable: closable, path: path)) + } + + @ViewBuilder + public func themeNavigationStack( + if condition: Bool, + closable: Bool = false, + path: Binding = .constant(NavigationPath()) + ) -> some View { + if condition { + modifier(ThemeNavigationStackModifier(closable: closable, path: path)) + } else { + self + } } public func themeForm() -> some View { @@ -269,31 +285,25 @@ 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: { - ThemeCloseLabel() - } + NavigationStack(path: $path) { + content + .toolbar { + if closable { + ToolbarItem(placement: .cancellationAction) { + Button { + dismiss() + } label: { + ThemeCloseLabel() } } } - } - } else { - content + } } } }