Reuse modifier for navigation stacks with close button (#861)

Refactored:

- iOS
  - VPNProviderServerView
- macOS
  - AboutView
  - ProfileSplitView
- Both
  - ProfileCoordinator
  - VPNProviderServerCoordinator
This commit is contained in:
Davide 2024-11-13 19:17:00 +01:00 committed by GitHub
parent 1b9b9cbd5c
commit 2d698cabfe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 59 additions and 69 deletions

View File

@ -20,7 +20,7 @@ concurrency:
jobs: jobs:
run_tests: run_tests:
name: Run tests name: Run tests
runs-on: macos-14 runs-on: macos-15
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- uses: passepartoutvpn/action-prepare-xcode-build@master - uses: passepartoutvpn/action-prepare-xcode-build@master
@ -30,7 +30,7 @@ jobs:
bundle exec fastlane test bundle exec fastlane test
build_upload: build_upload:
name: Upload to ASC name: Upload to ASC
runs-on: macos-14 runs-on: macos-15
needs: run_tests needs: run_tests
strategy: strategy:
fail-fast: true fail-fast: true

View File

@ -17,7 +17,7 @@ concurrency:
jobs: jobs:
run_swift_tests: run_swift_tests:
name: Run SwiftPM tests name: Run SwiftPM tests
runs-on: macos-14 runs-on: macos-15
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: passepartoutvpn/action-prepare-xcode-build@master - uses: passepartoutvpn/action-prepare-xcode-build@master

View File

@ -30,23 +30,13 @@ import SwiftUI
extension AboutRouterView { extension AboutRouterView {
var body: some View { var body: some View {
NavigationStack(path: $path) {
AboutView( AboutView(
profileManager: profileManager, profileManager: profileManager,
navigationRoute: $navigationRoute navigationRoute: $navigationRoute
) )
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button {
dismiss()
} label: {
ThemeImage(.close)
}
}
}
.navigationDestination(for: NavigationRoute.self, destination: pushDestination) .navigationDestination(for: NavigationRoute.self, destination: pushDestination)
.themeNavigationDetail() .themeNavigationDetail()
} .themeNavigationStack(closable: true, path: $path)
} }
} }

View File

@ -36,10 +36,9 @@ extension AboutRouterView {
navigationRoute: $navigationRoute navigationRoute: $navigationRoute
) )
} detail: { } detail: {
NavigationStack(path: $path) {
pushDestination(for: navigationRoute) pushDestination(for: navigationRoute)
.navigationDestination(for: NavigationRoute.self, destination: pushDestination) .navigationDestination(for: NavigationRoute.self, destination: pushDestination)
} .themeNavigationStack(closable: false, path: $path)
.toolbar { .toolbar {
ToolbarItem(placement: .confirmationAction) { ToolbarItem(placement: .confirmationAction) {
Button(Strings.Global.ok) { Button(Strings.Global.ok) {

View File

@ -55,7 +55,7 @@ struct ProfileSplitView: View, Routable {
flow: flow flow: flow
) )
} detail: { } detail: {
NavigationStack(path: $detailPath) { Group {
switch selectedModuleId { switch selectedModuleId {
case ModuleListView.generalModuleId: case ModuleListView.generalModuleId:
detailView(for: .general) detailView(for: .general)
@ -64,6 +64,7 @@ struct ProfileSplitView: View, Routable {
detailView(for: .module(id: selectedModuleId)) detailView(for: .module(id: selectedModuleId))
} }
} }
.themeNavigationStack(path: $detailPath)
.toolbar(content: toolbarContent) .toolbar(content: toolbarContent)
.environment(\.navigationPath, $detailPath) .environment(\.navigationPath, $detailPath)
} }

View File

@ -44,7 +44,6 @@ struct VPNProviderServerCoordinator<Configuration>: View where Configuration: Pr
let onSelect: (VPNEntity<Configuration>) async throws -> Void let onSelect: (VPNEntity<Configuration>) async throws -> Void
var body: some View { var body: some View {
NavigationStack {
VPNProviderServerView( VPNProviderServerView(
moduleId: moduleId, moduleId: moduleId,
providerId: providerId, providerId: providerId,
@ -53,16 +52,7 @@ struct VPNProviderServerCoordinator<Configuration>: View where Configuration: Pr
filtersWithSelection: false, filtersWithSelection: false,
onSelect: onSelect onSelect: onSelect
) )
.toolbar { .themeNavigationStack(closable: true)
ToolbarItem(placement: .cancellationAction) {
Button {
dismiss()
} label: {
ThemeCloseLabel()
}
}
}
}
} }
} }

View File

@ -79,7 +79,7 @@ private extension VPNProviderServerView {
Button { Button {
isPresented = false isPresented = false
} label: { } label: {
ThemeImage(.close) ThemeCloseLabel()
} }
} }
} }

View File

@ -44,7 +44,7 @@ public struct SettingsView: View {
.navigationTitle(Strings.Global.settings) .navigationTitle(Strings.Global.settings)
#if os(iOS) #if os(iOS)
.themeNavigationDetail() .themeNavigationDetail()
.themeNavigationStack(if: true, closable: true, path: $path) .themeNavigationStack(closable: true, path: $path)
#endif #endif
} }
} }

View File

@ -75,8 +75,24 @@ extension View {
)) ))
} }
public func themeNavigationStack(if condition: Bool, closable: Bool = false, path: Binding<NavigationPath>) -> some View { public func themeNavigationStack(
modifier(ThemeNavigationStackModifier(condition: condition, closable: closable, path: path)) closable: Bool = false,
path: Binding<NavigationPath> = .constant(NavigationPath())
) -> some View {
modifier(ThemeNavigationStackModifier(closable: closable, path: path))
}
@ViewBuilder
public func themeNavigationStack(
if condition: Bool,
closable: Bool = false,
path: Binding<NavigationPath> = .constant(NavigationPath())
) -> some View {
if condition {
modifier(ThemeNavigationStackModifier(closable: closable, path: path))
} else {
self
}
} }
public func themeForm() -> some View { public func themeForm() -> some View {
@ -269,15 +285,12 @@ struct ThemeNavigationStackModifier: ViewModifier {
@Environment(\.dismiss) @Environment(\.dismiss)
private var dismiss private var dismiss
let condition: Bool
let closable: Bool let closable: Bool
@Binding @Binding
var path: NavigationPath var path: NavigationPath
func body(content: Content) -> some View { func body(content: Content) -> some View {
if condition {
NavigationStack(path: $path) { NavigationStack(path: $path) {
content content
.toolbar { .toolbar {
@ -292,9 +305,6 @@ struct ThemeNavigationStackModifier: ViewModifier {
} }
} }
} }
} else {
content
}
} }
} }