Impressia/Vernissage/Widgets/ActionMenu.swift

53 lines
1.5 KiB
Swift
Raw Normal View History

2023-01-22 17:41:11 +01:00
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
2023-03-28 10:35:38 +02:00
// Licensed under the Apache License 2.0.
2023-01-22 17:41:11 +01:00
//
import SwiftUI
struct ActionMenu<Label: View, Content: View>: View {
@State private var isDuringAction = false
private let primaryAction: () async -> Void
private let label: () -> Label
private let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content, @ViewBuilder label: @escaping () -> Label, primaryAction: @escaping () async -> Void) {
self.label = label
self.content = content
self.primaryAction = primaryAction
}
var body: some View {
Menu {
content()
} label: {
if isDuringAction {
LoadingIndicator(isVisible: .constant(true))
.transition(.opacity)
} else {
label()
.transition(.opacity)
}
} primaryAction: {
Task {
2023-02-19 12:49:44 +01:00
HapticService.shared.fireHaptic(of: .buttonPress)
2023-01-22 17:41:11 +01:00
defer {
Task { @MainActor in
withAnimation {
self.isDuringAction = false
}
}
}
2023-01-22 17:41:11 +01:00
withAnimation {
self.isDuringAction = true
}
2023-01-22 17:41:11 +01:00
await primaryAction()
}
}.disabled(isDuringAction)
}
}