From d7684ef5867bc7edf20aaaf519a428ca94ae7e17 Mon Sep 17 00:00:00 2001 From: Christoffer Winterkvist Date: Wed, 25 Oct 2023 21:17:15 +0200 Subject: [PATCH] Fix issue with debouning inside the `FocusPublisher` - The bug manifested itself with the user having to double click on commands in order to get them to focus. In addtion, keyboard navigation wasn't reliable. --- App/Sources/Core/Controllers/NSEventController.swift | 6 +++--- App/Sources/UI/Views/Focus/FocusPublisher.swift | 11 ++++++++--- .../UI/Views/Managers/DebounceSelectionManager.swift | 8 +++++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/App/Sources/Core/Controllers/NSEventController.swift b/App/Sources/Core/Controllers/NSEventController.swift index c2ad5db2..346fed6b 100644 --- a/App/Sources/Core/Controllers/NSEventController.swift +++ b/App/Sources/Core/Controllers/NSEventController.swift @@ -2,7 +2,7 @@ import Foundation import SwiftUI final class NSEventController: ObservableObject { - @Published var keyDown: Bool = false + @Published var repeatingKeyDown: Bool = false static let shared: NSEventController = .init() @@ -10,9 +10,9 @@ final class NSEventController: ObservableObject { NSEvent.addLocalMonitorForEvents(matching: [.keyUp, .keyDown]) { [weak self] event in guard let self else { return event } if event.type == .keyDown, event.isARepeat { - keyDown = true + repeatingKeyDown = true } else { - keyDown = false + repeatingKeyDown = false } return event } diff --git a/App/Sources/UI/Views/Focus/FocusPublisher.swift b/App/Sources/UI/Views/Focus/FocusPublisher.swift index f54a4f69..f22da087 100644 --- a/App/Sources/UI/Views/Focus/FocusPublisher.swift +++ b/App/Sources/UI/Views/Focus/FocusPublisher.swift @@ -30,8 +30,9 @@ final class FocusPublisher: ObservableObject where Element: Equatable, Element: Hashable, Element: Identifiable, Element.ID: CustomStringConvertible { - private let debouncer: FocusPublisherDebouncer = .init(milliseconds: 50) { elementID in + private lazy var debouncer: FocusPublisherDebouncer = .init(milliseconds: 50) { elementID in FocusableProxy.post(elementID) + self.focus = .elementID(elementID) } private(set) var focus: Focused = .elementID("-1" as! Element.ID) @@ -42,7 +43,11 @@ final class FocusPublisher: ObservableObject where Element: Equatable, } func publish(_ elementID: Element.ID) { - debouncer.process(elementID) - focus = .elementID(elementID) + if NSEventController.shared.repeatingKeyDown { + debouncer.process(elementID) + } else { + FocusableProxy.post(elementID) + focus = .elementID(elementID) + } } } diff --git a/App/Sources/UI/Views/Managers/DebounceSelectionManager.swift b/App/Sources/UI/Views/Managers/DebounceSelectionManager.swift index 7ffc8943..ec434893 100644 --- a/App/Sources/UI/Views/Managers/DebounceSelectionManager.swift +++ b/App/Sources/UI/Views/Managers/DebounceSelectionManager.swift @@ -14,13 +14,15 @@ final class DebounceSelectionManager { self.onUpdate = onUpdate self.subscription = subject .dropFirst() - .removeDuplicates() .debounce(for: .milliseconds(milliseconds), scheduler: DispatchQueue.main) - .sink { onUpdate($0) } + .removeDuplicates() + .sink { + onUpdate($0) + } } func process(_ snapshot: Snapshot) { - if NSEventController.shared.keyDown { + if NSEventController.shared.repeatingKeyDown { subject.send(snapshot) } else { onUpdate(snapshot)