NotesRelease

Lumeira 1.1.8

Crash fix (shipped in 1.1.7):

Added

  • docs/KEYBOARD_SHORTCUTS.md — complete reference for all shortcuts and the dispatch architecture.
  • View menu now exposes Toggle Thumbnails, Toggle Info Panel, Toggle Histogram, Toggle Magnifier, Toggle Full Screen, Toggle Debug HUD, Fill Mode, Zoom In, Zoom Out, Rotate CW/CCW, Flip H/V, Toggle Slideshow, and Toggle Comparison so keyboard shortcuts are discoverable.
  • Shortcut rebinding detects conflicts: reassigning a key already used by another action prompts the user and leaves the displaced action Unassigned instead of silently shadowing it.
  • KeyEventTokenFactory and KeyBinding.matches regression tests ([ / ] via characters fallback, empty-key safety, modifier strictness).
  • KeyBinding.swiftUIKeyboardShortcut and the View.keyBindingShortcut(_:) modifier so menu items can attach a real, customizable .keyboardShortcut(...) driven by the user's current binding.

Fixed

  • Folder navigation (Next/Previous Sibling Folder) no longer wraps around at the endpoints; the bottom folder bar now correctly dims its arrows at the first/last folder. The app menu and the bar are now consistent.
  • [ and ] shortcuts now resolve through charactersIgnoringModifiers as well as the US physical key code, so the default folder-navigation bindings work on non-US keyboard layouts.
  • Removed the hidden, un-rebindable ⌘↑ / ⌘↓ overrides for first/last image. Home/End remain as the rebindable defaults, and users can now assign any shortcut they want without fighting a hardcoded override.
  • Menu items with modifier-bearing shortcuts now show the shortcut in the right-aligned native column instead of embedding it in the menu title string.
  • Plain-key bindings (F, M, digits, arrows, …) no longer hijack typing inside text fields, search fields, text views, and editable combo boxes. The NSEvent monitor skips dispatch when the first responder is editable text input.
  • Every action in KeyBinding.defaultBindings is now backed by a menu item with a real .keyBindingShortcut(...) (firstImage, lastImage, addToComparison, exitFullScreen were previously monitor-only and would have become unreachable if the user had rebound them to a modifier shortcut).
  • ShortcutKeyCatcherView no longer hard-codes US keyCode 53 for Escape; it now asks KeyEventTokenFactory for the semantic key, so Escape cancels rebinding on any keyboard layout.
  • Crash fix (shipped in 1.1.7): ImageViewport.dismantleNSView no longer writes to @Bindings during view teardown. SwiftUI holds exclusive access on the backing StoredLocation while invalidating subgraphs, and the previous flushPendingSyncState call tripped Swift exclusivity enforcement and aborted the process (EXC_CRASH / SIGABRT in swift_beginAccess) when a window was closed or a folder was switched mid-gesture. Dismantle now only cancels the pending debounce task — the 16 ms of unflushed zoom/pan is dropped, which is harmless since the view is being removed.
  • Double-click opens two windows. Finder-delivered file URLs are now intercepted by an NSApplicationDelegateAdaptor and forwarded to the existing window via Notification.Name.lumeiraOpenURLs, instead of relying on WindowGroup's default "open a new window per URL" behavior (which spawned a second window on cold launch). URLs delivered before the content view is listening are queued in PendingOpenURLs and drained .onAppear.

Changed

  • KeyBinding.matches(_:) ignores bindings with an empty key so "Unassigned" actions never fire.
  • Default bindings updated to match macOS conventions (existing user bindings are preserved on upgrade; only factory defaults / Reset to Defaults change):
    • Toggle Full Screen: Space → ⌃⌘F
    • First Sibling Folder: ⌘[ → ⌘⇧[
    • Last Sibling Folder: ⌘] → ⌘⇧]
    • Fill Mode: F → ⇧F
    • Fit to Window: ⇧⌘= → ⌘9
  • KeyBindingCommandMonitor now passes through events whose matched binding has any modifier, so SwiftUI's menu system (via real .keyboardShortcut) handles them. Plain-key bindings are still captured locally so they don't hijack text input in sheets.