TeraEditingProtectionActions.swift (2063B)
1 import SwiftUI 2 3 /// Present a discard confirmation only from the surface the user is acting on, 4 /// including when the editor is underneath the saved-work sheet. 5 struct TeraEditingProtectionActions: View { 6 @ObservedObject var protection: TeraEditingProtection 7 @State private var confirmsDiscard = false 8 @State private var didConfirmDiscard = false 9 @State private var discardToken: UUID? 10 11 var body: some View { 12 Group { 13 if protection.failed { 14 failureSection 15 } 16 } 17 .confirmationDialog("Discard the current unsaved changes?", isPresented: $confirmsDiscard, titleVisibility: .visible) { 18 Button("Discard and continue", role: .destructive) { 19 didConfirmDiscard = true 20 if let discardToken { 21 protection.discard(token: discardToken) 22 } 23 } 24 Button("Keep editing", role: .cancel) { cancelConfirmation() } 25 } message: { 26 Text("Previously saved drafts and submitted operations remain on this device.") 27 } 28 .onChange(of: confirmsDiscard) { _, presented in 29 // Popovers omit the cancel button. A late dismissal belongs only to the 30 // choice that opened it, even if another request has already failed. 31 if !presented, !didConfirmDiscard { 32 cancelConfirmation() 33 } 34 } 35 } 36 37 private var failureSection: some View { 38 Section("Keep your editing") { 39 Text("Saving could not be confirmed. Your current editing is still here.") 40 Button("Retry save and continue") { protection.retry() } 41 .accessibilityIdentifier("tera.add.protection.retry") 42 Button("Discard unsaved changes…", role: .destructive) { 43 discardToken = protection.choiceToken 44 didConfirmDiscard = false 45 confirmsDiscard = true 46 } 47 .accessibilityIdentifier("tera.add.protection.discard") 48 Button("Keep editing") { protection.cancel() } 49 .accessibilityIdentifier("tera.add.protection.keep") 50 } 51 } 52 53 private func cancelConfirmation() { 54 if let discardToken { 55 protection.cancel(token: discardToken) 56 } 57 } 58 }