Files
Outpost/Outpost/Support/PointerCursorHover.swift
T
Puranjay Savar Mattas f01c2b9467 feat: pointer cursor preference
App-side chrome: new "Pointer Cursor" toggle (Settings -> Editor,
outpost.pointerCursorEnabled, on by default) driving a shared
.pointerCursorOnHover() view modifier (push/pop NSCursor.pointingHand,
macOS-only, no-op on iOS) wired onto every clickable sidebar/list row:
collection tree rows + disclosure chevron, flat collection list,
document outline rows, collection-overview tab bar + document/search
rows, global search results, command palette rows.

In-document link hover: MarkdownEditorConfiguration gets a new
pointerCursorOverLinksWhileEditing flag (default true). Read-only mode
already showed a pointing hand over links unconditionally; editable
mode never did (I-beam only) until now - applyReadOnlyCursor in
NativeTextView+CursorRects.swift now applies the same over any .link
range while editing too, gated by the flag. Wiki links already carry
.link alongside their own custom .wikiLinkID, so they're covered with
no extra work.

Closes out the last item from the original preferences-wiring scope.
2026-08-20 22:21:36 +01:00

39 lines
1.1 KiB
Swift

import SwiftUI
#if os(macOS)
import AppKit
/// Pointing-hand cursor while the mouse is over a clickable sidebar/list row,
/// gated by the "Pointer Cursor" setting (Settings → Editor → Pointer Cursor).
/// `didPush` tracks whether this instance actually pushed a cursor, so a
/// mid-hover toggle of the preference can never leave `NSCursor`'s push/pop
/// stack unbalanced — pop only fires for a push this same hover made.
private struct PointerCursorOnHover: ViewModifier {
@AppStorage("outpost.pointerCursorEnabled") private var isEnabled = true
@State private var didPush = false
func body(content: Content) -> some View {
content.onHover { hovering in
if hovering {
guard isEnabled else { return }
NSCursor.pointingHand.push()
didPush = true
} else if didPush {
NSCursor.pop()
didPush = false
}
}
}
}
extension View {
func pointerCursorOnHover() -> some View {
modifier(PointerCursorOnHover())
}
}
#else
extension View {
func pointerCursorOnHover() -> some View { self }
}
#endif