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)
|
||
|
}
|
||
|
}
|