11//
2- // EditDetail .swift
2+ // SwiftUIView .swift
33//
44// Copyright 2022 FlowAllocator LLC
55//
1818
1919import SwiftUI
2020
21- struct EditDetail < Element, Detail> : View
22- where Element: Identifiable ,
23- Detail: View
21+ struct EditDetailBase < Element, Detail> : View
22+ where Element: Identifiable ,
23+ Detail: View
2424{
2525 @Environment ( \. presentationMode) var presentationMode : Binding < PresentationMode >
26-
27- typealias DetailContent = ( DetailerContext < Element > , Binding < Element > ) -> Detail
26+
27+ typealias DetailContent = ( DetailerContext < Element > ) -> Detail
2828 typealias Validate < T> = ( KeyPath < Element , T > ) -> Void
29-
29+
3030 // MARK: Parameters
31-
32- // NOTE `element` not a binding, because we don't want to change data live
33- // NOTE `isAdd` will be set to `false` on dismissal of sheet
34-
31+
3532 var config : DetailerConfig < Element >
36- @ State var element : Element
33+ var element : Element
3734 @Binding var isAdd : Bool
3835 var detailContent : DetailContent
39-
36+
4037 // MARK: Locals
41-
38+
4239 @State private var invalidFields : Set < AnyKeyPath > = Set ( )
4340 @State private var showValidationAlert = false
4441 @State private var alertMessage : String ? = nil
45-
42+
4643 private var context : DetailerContext < Element > {
4744 DetailerContext < Element > ( config: config,
4845 onValidate: validateAction,
4946 isAdd: isAdd)
5047 }
51-
48+
5249 private var isDeleteAvailable : Bool {
5350 config. onDelete != nil
5451 }
@@ -60,29 +57,29 @@ struct EditDetail<Element, Detail>: View
6057 private var isSaveAvailable : Bool {
6158 config. onSave != nil
6259 }
63-
60+
6461 private var canSave : Bool {
6562 isSaveAvailable && invalidFields. isEmpty
6663 }
67-
64+
6865 // MARK: Views
69-
66+
7067 var body : some View {
7168 VStack ( alignment: . leading) { // .leading needed to keep title from centering
72- #if os(macOS)
69+ #if os(macOS)
7370 Text ( config. titler ( element) ) . font ( . largeTitle)
74- #endif
71+ #endif
7572 // this is where the user will typically declare a Form or VStack
76- detailContent ( context, $element )
73+ detailContent ( context)
7774 // .animation(.default)
7875 }
7976 . alert ( isPresented: $showValidationAlert) {
8077 Alert ( title: Text ( " Validation Failure " ) ,
8178 message: Text ( alertMessage ?? " Requires valid entry before save. " ) )
8279 }
83- #if os(macOS)
80+ #if os(macOS)
8481 . padding( )
85- #endif
82+ #endif
8683 . toolbar {
8784 ToolbarItem ( placement: . destructiveAction) {
8885 Button ( action: deleteAction) {
@@ -92,7 +89,7 @@ struct EditDetail<Element, Detail>: View
9289 . opacity ( isDeleteAvailable ? 1 : 0 )
9390 . disabled ( !canDelete)
9491 }
95-
92+
9693 ToolbarItem ( placement: . cancellationAction) {
9794 Button ( action: cancelAction) {
9895 Text ( " Cancel " )
@@ -107,18 +104,18 @@ struct EditDetail<Element, Detail>: View
107104 . disabled ( !canSave)
108105 }
109106 }
110- #if os(macOS)
107+ #if os(macOS)
111108 // NOTE on macOS, this seems to be needed to avoid excessive height
112109 . frame( minWidth: config. minWidth, maxWidth: . infinity, maxHeight: . infinity, alignment: . leading)
113- #endif
114-
115- #if os(iOS) || targetEnvironment(macCatalyst)
110+ #endif
111+
112+ #if os(iOS) || targetEnvironment(macCatalyst)
116113 . navigationTitle( config. titler ( element) )
117- #endif
114+ #endif
118115 }
119-
116+
120117 // MARK: Action Handlers
121-
118+
122119 // NOTE: should be invoked via async to avoid updating the state during view render
123120 private func validateAction( _ anyKeyPath: AnyKeyPath , _ result: Bool ) {
124121 if result {
@@ -133,40 +130,40 @@ struct EditDetail<Element, Detail>: View
133130 }
134131 }
135132 }
136-
133+
137134 private func saveAction( ) {
138135 guard let _onSave = config. onSave else { return }
139-
136+
140137 // display any validation changes
141138 let messages = config. onValidate ( context, element)
142139 if messages. count > 0 {
143140 alertMessage = config. onValidate ( context, element) . joined ( separator: " \n \n " )
144141 showValidationAlert = true
145142 return
146143 }
147-
144+
148145 let invalidCount = invalidFields. count
149146 if invalidCount > 0 {
150147 alertMessage = " \( invalidCount) field(s) require valid values before you can save. "
151148 showValidationAlert = true
152149 return
153150 }
154-
151+
155152 _onSave ( context, element)
156153 dismissAction ( )
157154 }
158-
155+
159156 private func deleteAction( ) {
160157 guard let _onDelete = config. onDelete else { return }
161158 _onDelete ( element. id)
162159 dismissAction ( )
163160 }
164-
161+
165162 private func cancelAction( ) {
166163 config. onCancel ( context, element)
167164 dismissAction ( )
168165 }
169-
166+
170167 private func dismissAction( ) {
171168 isAdd = false
172169 presentationMode. wrappedValue. dismiss ( )
0 commit comments