Skip to content

Commit

Permalink
Merge pull request #38 from futuredapp/feature/Modal-navigation-stack…
Browse files Browse the repository at this point in the history
…-presentation-detents

Modal navigation stack presentation detents
  • Loading branch information
ssestak authored Feb 6, 2025
2 parents 7dbaa3f + f2025f1 commit b63b80a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
23 changes: 21 additions & 2 deletions Sources/FuturedArchitecture/Architecture/ModalCoverModel.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,32 @@
//
// ModalCoverModel.swift
//
//
//
// Created by Simon Sestak on 01/08/2024.
//

import SwiftUI
import Foundation

/// Style of the modally presented view.

public enum SheetDetent: Hashable {
case medium
case large
case fraction(CGFloat)

func detent() -> PresentationDetent {
switch self {
case .medium:
return .medium
case .large:
return .large
case let .fraction(fraction):
return .fraction(fraction)
}
}
}

/// Style of the modally presented view.
///
/// It is intended to be used with ``ModalCoverModel``. Style has been placed to
/// the global scope, since the Model is generic.
Expand Down
23 changes: 13 additions & 10 deletions Sources/FuturedArchitecture/Architecture/NavigationStackFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,34 @@ public struct NavigationStackFlow<Coordinator: NavigationStackCoordinator, Conte
@StateObject private var coordinator: Coordinator
@ViewBuilder private let content: () -> Content

/// Use in case when whole navigation stack should have detents.
@State private var navigationDetents: Set<PresentationDetent>?

/// - Parameters:
/// - detents: The set of detents which should be applied to the whole navigation stack.
/// - coordinator: The instance of the coordinator used as the model and retained as the ``SwiftUI.StateObject``
/// - content: The root view of this navigation stack. The ``navigationDestination(for:destination:)`` modifier
/// is applied to this content.
public init(coordinator: @autoclosure @escaping () -> Coordinator, content: @MainActor @escaping () -> Content) {
public init(
detents: Set<SheetDetent>? = nil,
coordinator: @autoclosure @escaping () -> Coordinator,
content: @MainActor @escaping () -> Content
) {
self.navigationDetents = detents == nil ? nil : Set(detents!.map { $0.detent() })
self._coordinator = StateObject(wrappedValue: coordinator())
self.content = content
}

#if os(macOS)
public var body: some View {
NavigationStack(path: $coordinator.path) {
content().navigationDestination(for: Coordinator.Destination.self, destination: coordinator.scene(for:))
}
.sheet(item: sheetBinding, onDismiss: coordinator.onModalDismiss, content: coordinator.scene(for:))
}
#else
public var body: some View {
NavigationStack(path: $coordinator.path) {
content().navigationDestination(for: Coordinator.Destination.self, destination: coordinator.scene(for:))
}
.presentationDetents(navigationDetents ?? [])
.sheet(item: sheetBinding, onDismiss: coordinator.onModalDismiss, content: coordinator.scene(for:))
#if !os(macOS)
.fullScreenCover(item: fullscreenCoverBinding, onDismiss: coordinator.onModalDismiss, content: coordinator.scene(for:))
#endif
}
#endif

private var sheetBinding: Binding<Coordinator.Destination?> {
.init {
Expand Down

0 comments on commit b63b80a

Please sign in to comment.