@@ -13,6 +13,11 @@ final class NewOrderHostingController: UIHostingController<NewOrder> {
1313 init ( viewModel: NewOrderViewModel ) {
1414 self . viewModel = viewModel
1515 super. init ( rootView: NewOrder ( viewModel: viewModel) )
16+
17+ // Needed because a `SwiftUI` cannot be dismissed when being presented by a UIHostingController
18+ rootView. dismissHandler = { [ weak self] in
19+ self ? . dismiss ( animated: true )
20+ }
1621 }
1722
1823 required dynamic init ? ( coder aDecoder: NSCoder ) {
@@ -40,7 +45,9 @@ final class NewOrderHostingController: UIHostingController<NewOrder> {
4045extension NewOrderHostingController {
4146 override func shouldPopOnBackButton( ) -> Bool {
4247 guard !viewModel. hasChanges else {
43- presentDiscardChangesActionSheet ( )
48+ presentDiscardChangesActionSheet ( onDiscard: { [ weak self] in
49+ self ? . discardOrderAndPop ( )
50+ } )
4451 return false
4552 }
4653 return true
@@ -49,13 +56,6 @@ extension NewOrderHostingController {
4956 override func shouldPopOnSwipeBack( ) -> Bool {
5057 return shouldPopOnBackButton ( )
5158 }
52-
53- private func presentDiscardChangesActionSheet( ) {
54- UIAlertController . presentDiscardChangesActionSheet ( viewController: self , onDiscard: { [ weak self] in
55- self ? . viewModel. discardOrder ( )
56- self ? . navigationController? . popViewController ( animated: true )
57- } )
58- }
5959}
6060
6161/// Intercepts to the dismiss drag gesture.
@@ -66,16 +66,37 @@ extension NewOrderHostingController: UIAdaptivePresentationControllerDelegate {
6666 }
6767
6868 func presentationControllerDidAttemptToDismiss( _ presentationController: UIPresentationController ) {
69- UIAlertController . presentDiscardChangesActionSheet ( viewController: self , onDiscard: { [ weak self] in
70- self ? . viewModel. discardOrder ( )
71- self ? . dismiss ( animated: true , completion: nil )
69+ presentDiscardChangesActionSheet ( onDiscard: { [ weak self] in
70+ self ? . discardOrderAndDismiss ( )
7271 } )
7372 }
7473}
7574
75+ /// Private methods
76+ ///
77+ private extension NewOrderHostingController {
78+ func presentDiscardChangesActionSheet( onDiscard: @escaping ( ) -> Void ) {
79+ UIAlertController . presentDiscardChangesActionSheet ( viewController: self , onDiscard: onDiscard)
80+ }
81+
82+ func discardOrderAndDismiss( ) {
83+ viewModel. discardOrder ( )
84+ dismiss ( animated: true )
85+ }
86+
87+ func discardOrderAndPop( ) {
88+ viewModel. discardOrder ( )
89+ navigationController? . popViewController ( animated: true )
90+ }
91+ }
92+
7693/// View to create a new manual order
7794///
7895struct NewOrder : View {
96+ /// Set this closure with UIKit dismiss code. Needed because we need access to the UIHostingController `dismiss` method.
97+ ///
98+ var dismissHandler : ( ( ) -> Void ) = { }
99+
79100 @ObservedObject var viewModel : NewOrderViewModel
80101
81102 /// Fix for breaking navbar button
@@ -113,14 +134,21 @@ struct NewOrder: View {
113134 . navigationTitle ( Localization . title)
114135 . navigationBarTitleDisplayMode ( . inline)
115136 . toolbar {
137+ ToolbarItem ( placement: . cancellationAction) {
138+ Button ( Localization . cancelButton) {
139+ dismissHandler ( )
140+ }
141+ . accessibilityIdentifier ( Accessibility . cancelButtonIdentifier)
142+ . renderedIf ( viewModel. shouldShowCancelButton)
143+ }
116144 ToolbarItem ( placement: . confirmationAction) {
117145 switch viewModel. navigationTrailingItem {
118146 case . create:
119147 Button ( Localization . createButton) {
120148 viewModel. createOrder ( )
121149 }
122150 . id ( navigationButtonID)
123- . accessibilityIdentifier ( " new-order-create-button " )
151+ . accessibilityIdentifier ( Accessibility . createButtonIdentifier )
124152 . disabled ( viewModel. disabled)
125153
126154 case . loading:
@@ -213,11 +241,17 @@ private extension NewOrder {
213241 enum Localization {
214242 static let title = NSLocalizedString ( " New Order " , comment: " Title for the order creation screen " )
215243 static let createButton = NSLocalizedString ( " Create " , comment: " Button to create an order on the New Order screen " )
244+ static let cancelButton = NSLocalizedString ( " Cancel " , comment: " Button to cancel the creation of an order on the New Order screen " )
216245 static let products = NSLocalizedString ( " Products " , comment: " Title text of the section that shows the Products when creating a new order " )
217246 static let addProduct = NSLocalizedString ( " Add Product " , comment: " Title text of the button that adds a product when creating a new order " )
218247 static let productRowAccessibilityHint = NSLocalizedString ( " Opens product detail. " ,
219248 comment: " Accessibility hint for selecting a product in a new order " )
220249 }
250+
251+ enum Accessibility {
252+ static let createButtonIdentifier = " new-order-create-button "
253+ static let cancelButtonIdentifier = " new-order-cancel-button "
254+ }
221255}
222256
223257struct NewOrder_Previews : PreviewProvider {
0 commit comments