Skip to content

Commit

Permalink
Create AsyncButton that cancel previous tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
mohamede1945 committed Dec 13, 2023
1 parent 8e945f2 commit 7a36d64
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 19 deletions.
2 changes: 1 addition & 1 deletion UI/NoorUI/Components/AppStoreDownloadButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct AppStoreDownloadButton: View {
let action: AsyncAction

var body: some View {
Button(asyncAction: action) {
AsyncButton(action: action) {
Group {
switch type {
case .pending:
Expand Down
4 changes: 2 additions & 2 deletions UI/NoorUI/Components/List/NoorListItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ public struct NoorListItem: View {
if let accessory, accessory.actionable {
// Use Tap gesture since tapping accessory button will also trigger the whole cell selection.
content
.onTapGesture(asyncAction: action)
.onAsyncTapGesture(asyncAction: action)
} else {
Button(asyncAction: action) {
AsyncButton(action: action) {
content
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private struct LastVerseButton: View {
let action: AsyncAction

var body: some View {
Button(asyncAction: action) {
AsyncButton(action: action) {
Text(label)
.foregroundColor(.white)
.padding(.vertical, 5)
Expand Down
9 changes: 3 additions & 6 deletions UI/NoorUI/Features/AyahMenu/AyahMenuView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,7 @@ private struct Row<Symbol: View>: View {
@ScaledMetric var verticalPadding = 12

var body: some View {
Button {
await action()
}
label: {
AsyncButton(action: action) {
HStack {
ZStack {
IconCircles()
Expand Down Expand Up @@ -314,8 +311,8 @@ private struct NoteCircles: View {
var body: some View {
HStack {
ForEach(Note.Color.sortedColors, id: \.self) { color in
Button(
asyncAction: { await tapped(color) },
AsyncButton(
action: { await tapped(color) },
label: { NoteCircle(color: color.color, selected: color == selectedColor) }
)
.shadow(color: Color.tertiarySystemGroupedBackground, radius: 1)
Expand Down
59 changes: 50 additions & 9 deletions UI/UIx/SwiftUI/Miscellaneous/AsyncAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,63 @@ public typealias AsyncAction = @MainActor @Sendable () async -> Void
public typealias ItemAction<Item> = @MainActor @Sendable (Item) -> Void
public typealias AsyncItemAction<Item> = @MainActor @Sendable (Item) async -> Void

extension Button {
public init(asyncAction: @escaping AsyncAction, @ViewBuilder label: () -> Label) {
self.init(action: {
Task {
await asyncAction()
public struct AsyncButton<Label: View>: View {
// MARK: Lifecycle

public init(action: @escaping AsyncAction, label: () -> Label) {
self.action = action
self.label = label()
}

// MARK: Public

public var body: some View {
Button {
// Cancel the previous task
currentTask?.cancel()

// Start a new task
currentTask = Task {
await action()
}
}, label: label)
} label: {
label
}
}

// MARK: Private

private let action: AsyncAction
private let label: Label

@State private var currentTask: Task<Void, Never>? = nil
}

extension View {
public func onTapGesture(count: Int = 1, asyncAction action: @escaping AsyncAction) -> some View {
onTapGesture(count: count, perform: {
Task {
public func onAsyncTapGesture(count: Int = 1, asyncAction action: @escaping AsyncAction) -> some View {
modifier(AsyncTapGestureModifier(count: count, action: action))
}
}

private struct AsyncTapGestureModifier: ViewModifier {
// MARK: Internal

let count: Int
let action: AsyncAction

func body(content: Content) -> some View {
content.onTapGesture(count: count, perform: {
// Cancel the previous task
currentTask?.cancel()

// Start a new task
currentTask = Task {
await action()
}
})
}

// MARK: Private

@State private var currentTask: Task<Void, Never>? = nil
}

0 comments on commit 7a36d64

Please sign in to comment.