Files
Bitsy eb9ee9abd9 Hover overlay for cut-off cells, hold Option to freeze the list
- Resting the pointer 0.5 s on a cut-off name or path shows its full text
  (with highlights) in a click-through panel over the cell. It stays while
  hovered, updates in place when the list refreshes, and hides on move,
  exit, scroll, click or key press. Replaces AppKit's expansion tooltip,
  whose timing can't be set and which vanished when touched.
- Holding Option alone freezes the results: background refreshes are held
  back (the index keeps updating) and applied once on release, keeping the
  scroll position. Typing, sorting and filtering still apply. Released
  automatically when the app deactivates. "Frozen" shows in the status bar.
- README: current keyboard shortcuts, hover and Finder action.
  CHANGELOG: freeze key and hover overlay in 1.0.9.
2026-10-02 14:24:53 +02:00

59 lines
1.9 KiB
Swift

import AppKit
// FreezeKey reports whether the "freeze" key (⌥ Option) is held down while
// Allofit is active. Holding it pauses the background refreshes of the
// results, so rows don't move while the user reads or selects them; typing,
// sorting and filtering still apply. Released (or the app deactivated), the
// lists catch up once.
@MainActor
final class FreezeKey: ObservableObject {
// shared state for every window
static let shared = FreezeKey()
// true while ⌥ Option is held in Allofit
@Published private(set) var isHeld = false
// modifier-change monitor, alive for the app's lifetime
private var monitor: Any?
// app activation observers
private var observers: [NSObjectProtocol] = []
// starts following the modifier keys
private init() {
monitor = NSEvent.addLocalMonitorForEvents(matching: .flagsChanged) { [weak self] vEvent in
MainActor.assumeIsolated {
self?.update(inFlags: vEvent.modifierFlags)
}
return vEvent
}
// a key released while another app was frontmost never reaches the
// local monitor: re-read the state on (de)activation
for vName in [NSApplication.didResignActiveNotification, NSApplication.didBecomeActiveNotification] {
observers.append(NotificationCenter.default.addObserver(forName: vName, object: nil, queue: .main) { [weak self] vNote in
MainActor.assumeIsolated {
if vNote.name == NSApplication.didResignActiveNotification {
self?.setHeld(false)
} else {
self?.update(inFlags: NSEvent.modifierFlags)
}
}
})
}
}
// held when Option is down on its own (shortcuts such as ⌥⌘C don't
// freeze the list)
private func update(inFlags: NSEvent.ModifierFlags) {
let vMods = inFlags.intersection([.command, .option, .control, .shift])
setHeld(vMods == [.option])
}
// publishes a change of state
private func setHeld(_ inHeld: Bool) {
if isHeld != inHeld {
isHeld = inHeld
}
}
}