54 lines
1.5 KiB
Swift
54 lines
1.5 KiB
Swift
//
|
|
// https://mczachurski.dev
|
|
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
|
// Licensed under the MIT License.
|
|
//
|
|
|
|
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 {
|
|
HapticService.shared.touch()
|
|
defer {
|
|
Task { @MainActor in
|
|
withAnimation {
|
|
self.isDuringAction = false
|
|
}
|
|
}
|
|
}
|
|
|
|
withAnimation {
|
|
self.isDuringAction = true
|
|
}
|
|
|
|
await primaryAction()
|
|
}
|
|
}.disabled(isDuringAction)
|
|
}
|
|
}
|