diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 341ac46..82e07a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: device: 'iPhone 15' - version: '18.6' device: 'iPhone 16' - - version: '26.0' + - version: '26.0.1' device: 'iPhone 17' steps: diff --git a/README.md b/README.md index 1ef19aa..6a67195 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ LongPressButton(minimumDuration: 0.5, maximumDistance: 10) { } ``` +## Known limitations + +This package doesn't work with default buttons that are used inside of Lists. If you want to use this inside of a List apply a different style to the button. For example `plain` or `bordered`. + ## Installation ### Swift Package Manager diff --git a/Sources/LongPressButton/LongPressButton.swift b/Sources/LongPressButton/LongPressButton.swift index fa839a5..486341e 100644 --- a/Sources/LongPressButton/LongPressButton.swift +++ b/Sources/LongPressButton/LongPressButton.swift @@ -9,78 +9,43 @@ public struct LongPressButton: View { private let label: Label private let longPressActionName: Text? - @available(iOS, obsoleted: 26.0) @State private var didLongPress = false - @available(iOS, obsoleted: 26.0) - @State private var longPressTask: Task? public var body: some View { - button - .accessibilityAction { - action() - } - .accessibilityAction(named: longPressActionName ?? Text("Alternative Action")) { - longPressAction() - } - } - - @ViewBuilder - private var button: some View { - if #available(iOS 26.0, *) { - Button(action: {}) { - label - } - .simultaneousGesture(longPress.exclusively(before: tap)) - } else { - Button(action: performActionIfNeeded) { - label - } - .onLongPressGesture( - maximumDistance: maximumDistance, - perform: {}, - onPressingChanged: handleLongPress(isPressing:) - ) + Button(action: performActionIfNeeded) { + label + } + .simultaneousGesture(longPress.simultaneously(with: detectRelease)) + .accessibilityAction(named: longPressActionName ?? Text("Alternative Action")) { + longPressAction() } } private var longPress: some Gesture { LongPressGesture(minimumDuration: minimumDuration, maximumDistance: maximumDistance) .onEnded { _ in + didLongPress = true longPressAction() } } - private var tap: some Gesture { - TapGesture().onEnded { - action() + private var detectRelease: some Gesture { + DragGesture(minimumDistance: 0).onEnded { _ in + DispatchQueue.main.async { + // Mark long press as ended in next run loop to be sure that button action + // won't trigger together with it. + didLongPress = false + } } } - @available(iOS, obsoleted: 26.0) private func performActionIfNeeded() { - longPressTask?.cancel() if didLongPress { didLongPress = false } else { action() } } - - @available(iOS, obsoleted: 26.0) - private func handleLongPress(isPressing: Bool) { - longPressTask?.cancel() - guard isPressing else { return } - didLongPress = false - longPressTask = Task { - do { - try await Task.sleep(nanoseconds: UInt64(minimumDuration * 1_000_000_000)) - } catch { - return - } - didLongPress = true - longPressAction() - } - } } // MARK: - Initialization