diff --git a/Sources/CombineRextensions/StoreSheet.swift b/Sources/CombineRextensions/StoreSheet.swift index b38a7a5..aaea5e0 100644 --- a/Sources/CombineRextensions/StoreSheet.swift +++ b/Sources/CombineRextensions/StoreSheet.swift @@ -23,8 +23,49 @@ extension View { path: KeyPath, dismissAction: Action, producer: ViewProducer) -> some View { - return sheet(item: store.binding[path], - onDismiss: { store.dispatch(dismissAction) }, - content: producer.view) + return sheet( + item: store.binding[path], + onDismiss: { store.dispatch(dismissAction) }, + content: producer.view + ) + } +} + +// MARK: - Sheets from Store +extension View { + /// Presents a sheet when the given `Context` key path is non-nil. The view that will be shown + /// is created by the given `ViewProducer`. + /// + /// - Parameters: + /// - store: The view model containing the state. + /// - path: The key path pointing to the element to show as sheet. + /// - dismissAction: Action that should be dispatched to the store when a modal is dismissed. + /// - producer: The ViewProducer that transforms the given `Context` into a View. + public func storeSheet( + _ store: ObservableViewModel, + path: KeyPath, + dismissAction: Action, + producer: ViewProducer, + file: String = #file, + function: String = #function, + line: UInt = #line, + info: String? = nil) -> some View { + return sheet( + item: store.binding[path], + onDismiss: { + withAnimation { + store.dispatch( + dismissAction, + from: ActionSource( + file: file, + function: function, + line: line, + info: (info.map { $0 + " -> " } ?? "") + "View+StoreSheet.swift onDismiss closure" + ) + ) + } + }, + content: producer.view + ) } } diff --git a/Sources/CombineRextensions/ViewProducer.swift b/Sources/CombineRextensions/ViewProducer.swift index 3371c7c..646e6cc 100644 --- a/Sources/CombineRextensions/ViewProducer.swift +++ b/Sources/CombineRextensions/ViewProducer.swift @@ -47,3 +47,17 @@ extension ViewProducer where ProducedView == EmptyView { .init { _ in EmptyView() } } } + +extension ViewProducer where ProducedView == AnyView { + public static func pure() -> ViewProducer { + .init { _ in AnyView(EmptyView()) } + } +} + +#if DEBUG +extension ViewProducer { + public static var crash: ViewProducer { + . init { _ in fatalError("Debug ViewProducer crash") } + } +} +#endif