foolbear
foolbear

Reputation: 964

How to show multiple kinds of ConfirmationDialog?

Unlike sheet, ConfirmationDialog have no init func with parameter item: Binding<Item?>, the only one isPresented: Binding to control title and buttons.

for example, in one view, there are 3 kinds(NOT pieces) of deletion actions need to confirm with different title and buttons for each.

I don't want to separate to 3 views or 3 isPresented bindings. any suggestion?

Upvotes: 2

Views: 476

Answers (1)

foolbear
foolbear

Reputation: 964

Yes, we can use "presenting data: T?" to identify the kinds of ConfirmationDialog, just like Binding<Item?> of sheet. I think apple design "isPresented: Binding" just to simplify usage without presenting. OR it's not necessary.

here is an example (also see the whole code about ConfirmationDialog):

enum ConfirmationID {
    case test1
    case test2
    case test3
    
    var id: ConfirmationID { self }
}

struct ConfirmationItem: Identifiable {
    var id: ConfirmationID
    var item: String
}

struct ConfirmationDialog0: View {
    @State private var messages: [Int] = (0..<5).map { $0 }
    @State private var isPresented: Bool = false
    @State private var confirmationItem: ConfirmationItem?
    
    var body: some View {
        NavigationView {
            GeometryReader { proxy in
                ScrollView {
                    HStack {
                        Button("test 1") {
                            confirmationItem = ConfirmationItem(id: .test1, item: "test 1")
                            isPresented = true
                        }
                        Button("test 2") {
                            confirmationItem = ConfirmationItem(id: .test2, item: "test 2")
                            isPresented = true
                        }
                        Button("test 3") {
                            confirmationItem = ConfirmationItem(id: .test3, item: "test 3")
                            isPresented = true
                        }
                    }
                    List {
                        ForEach(messages, id: \.self) { message in
                            itemView0(message: message) { _ in
                                withAnimation {
                                    messages = messages.filter { $0 != message }
                                }
                            }
                        }
                    }
                    .frame(height: proxy.size.height)
                }
            }
            .navigationTitle("WRONG if .destructive!")
            .confirmationDialog("CONFIRM", isPresented: $isPresented, titleVisibility: .visible, presenting: confirmationItem, actions: confirmationDialogActionsView, message: confirmationDialogMassageView)
        }
    }
    
    @ViewBuilder
    func confirmationDialogActionsView(item: ConfirmationItem) -> some View {
//        Group {
            switch item.id {
            case .test1:
                Button(action: {}) {
                    Text("do with item \(item.item): ") + Text(Image(systemName: "star")) + Text(" World!")
                } // NOTE: Text(Image(systemName: "star")) does not work
            case .test2:
                Button("delete with item \(item.item)", role: .destructive) {}
                Button(action: {}) {
                    Text("""
delete with item \(item.item)
CANNOT undo this action!!!
""")
                } // NOTE: multiple lines text does not work. FYI: https://developer.apple.com/documentation/swiftui/view/confirmationdialog(_:ispresented:titlevisibility:presenting:actions:)-51pyu
            case .test3:
                Button(action: {}) {
                    VStack {
                        Text("play with item \(item.item)")
                        Text("Have a good time!") // NOTE: multiple texts do not work either.
                    }
                }
            }
            Button("Cancel", role: .cancel) {
                confirmationItem = nil
            }
//        }
    }
    
    func confirmationDialogMassageView(item: ConfirmationItem) -> some View {
        switch item.id {
        case .test1:
            return Text("Confirm to do with item \(item.item)")
        case .test2:
            return Text("Confirm to delete item \(item.item)")
        case .test3:
            return Text("Confirm to play with item \(item.item)")
        }
    }
}

struct itemView0: View {
    @State private var confirmationShown = false
    let message: Int
    let onDelete: (Int) -> Void
    
    var body: some View {
        Text("\(message)")
            .swipeActions {
                Button(
                    role: .none,//.destructive,
                    action: { confirmationShown = true }
                ) {
                    Image(systemName: "trash")
                }
                .tint(Color.red)
            }
            .confirmationDialog(
                "Are you sure?",
                isPresented: $confirmationShown,
                titleVisibility: .visible,
                presenting: message
            ) { message in
                Button("Yes, delete: \(message)") {
                    onDelete(message)
                }.keyboardShortcut(.defaultAction)

                Button("No", role: .cancel) {}
            } message: { message in
                Text("\(message)")
            }
    }
}

Upvotes: 1

Related Questions