Merge pull request #223 from Ebullioscopic/ui/fixes

Update reversible swipe gestures
This commit is contained in:
Hariharan Mudaliar 2026-01-01 00:39:18 +05:30 • committed by GitHub
commit 4c06c88236
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 26 deletions

View file

@ -232,7 +232,7 @@ struct ContentView: View {
} }
} }
} }
.conditionalModifier(Defaults[.closeGestureEnabled] && Defaults[.enableGestures] && interactionsEnabled) { view in .conditionalModifier((Defaults[.closeGestureEnabled] || Defaults[.reverseScrollGestures]) && Defaults[.enableGestures] && interactionsEnabled) { view in
view view
.panGesture(direction: .up) { translation, phase in .panGesture(direction: .up) { translation, phase in
handleUpGesture(translation: translation, phase: phase) handleUpGesture(translation: translation, phase: phase)
@ -883,18 +883,38 @@ struct ContentView: View {
// MARK: - Gesture Handling // MARK: - Gesture Handling
private func handleDownGesture(translation: CGFloat, phase: NSEvent.Phase) { private func handleDownGesture(translation: CGFloat, phase: NSEvent.Phase) {
handleScrollGesture(isDownward: true, translation: translation, phase: phase)
}
private func handleUpGesture(translation: CGFloat, phase: NSEvent.Phase) {
handleScrollGesture(isDownward: false, translation: translation, phase: phase)
}
private func handleScrollGesture(isDownward: Bool, translation: CGFloat, phase: NSEvent.Phase) {
let reverse = Defaults[.reverseScrollGestures]
let shouldOpen = isDownward ? !reverse : reverse
if shouldOpen {
handleOpenScrollGesture(translation: translation, phase: phase)
} else {
guard Defaults[.closeGestureEnabled] else { return }
handleCloseScrollGesture(translation: translation, phase: phase)
}
}
private func handleOpenScrollGesture(translation: CGFloat, phase: NSEvent.Phase) {
guard vm.notchState == .closed else { return } guard vm.notchState == .closed else { return }
withAnimation(.smooth) { withAnimation(.smooth) {
gestureProgress = (translation / Defaults[.gestureSensitivity]) * 20 gestureProgress = (translation / Defaults[.gestureSensitivity]) * 20
} }
if phase == .ended { if phase == .ended {
withAnimation(.smooth) { withAnimation(.smooth) {
gestureProgress = .zero gestureProgress = .zero
} }
} }
if translation > Defaults[.gestureSensitivity] { if translation > Defaults[.gestureSensitivity] {
if Defaults[.enableHaptics] { if Defaults[.enableHaptics] {
triggerHapticIfAllowed() triggerHapticIfAllowed()
@ -905,29 +925,29 @@ struct ContentView: View {
openNotch() openNotch()
} }
} }
private func handleUpGesture(translation: CGFloat, phase: NSEvent.Phase) { private func handleCloseScrollGesture(translation: CGFloat, phase: NSEvent.Phase) {
if vm.notchState == .open && !vm.isHoveringCalendar && !vm.isScrollGestureActive { guard vm.notchState == .open, !vm.isHoveringCalendar, !vm.isScrollGestureActive else { return }
withAnimation(.smooth) {
gestureProgress = (translation / Defaults[.gestureSensitivity]) * -20
}
if phase == .ended {
withAnimation(.smooth) { withAnimation(.smooth) {
gestureProgress = (translation / Defaults[.gestureSensitivity]) * -20 gestureProgress = .zero
} }
}
if phase == .ended {
withAnimation(.smooth) { if translation > Defaults[.gestureSensitivity] {
gestureProgress = .zero withAnimation(.smooth) {
} gestureProgress = .zero
isHovering = false
} }
vm.close()
if translation > Defaults[.gestureSensitivity] {
withAnimation(.smooth) { if Defaults[.enableHaptics] {
gestureProgress = .zero triggerHapticIfAllowed()
isHovering = false
}
vm.close()
if Defaults[.enableHaptics] {
triggerHapticIfAllowed()
}
} }
} }
} }
@ -944,13 +964,19 @@ struct ContentView: View {
} }
if skipGestureActiveDirection == nil && translation > Defaults[.gestureSensitivity] { if skipGestureActiveDirection == nil && translation > Defaults[.gestureSensitivity] {
skipGestureActiveDirection = direction let effectiveDirection: MusicManager.SkipDirection
if Defaults[.reverseSwipeGestures] {
effectiveDirection = direction == .forward ? .backward : .forward
} else {
effectiveDirection = direction
}
skipGestureActiveDirection = effectiveDirection
if Defaults[.enableHaptics] { if Defaults[.enableHaptics] {
triggerHapticIfAllowed() triggerHapticIfAllowed()
} }
musicManager.handleSkipGesture(direction: direction) musicManager.handleSkipGesture(direction: effectiveDirection)
} }
} }

View file

@ -577,6 +577,8 @@ struct SettingsView: View {
SettingsSearchEntry(tab: .general, title: "Hide Dynamic Island during screenshots & recordings", keywords: ["privacy", "screenshot", "recording"], highlightID: SettingsTab.general.highlightID(for: "Hide Dynamic Island during screenshots & recordings")), SettingsSearchEntry(tab: .general, title: "Hide Dynamic Island during screenshots & recordings", keywords: ["privacy", "screenshot", "recording"], highlightID: SettingsTab.general.highlightID(for: "Hide Dynamic Island during screenshots & recordings")),
SettingsSearchEntry(tab: .general, title: "Enable gestures", keywords: ["gestures", "trackpad"], highlightID: SettingsTab.general.highlightID(for: "Enable gestures")), SettingsSearchEntry(tab: .general, title: "Enable gestures", keywords: ["gestures", "trackpad"], highlightID: SettingsTab.general.highlightID(for: "Enable gestures")),
SettingsSearchEntry(tab: .general, title: "Close gesture", keywords: ["pinch", "swipe"], highlightID: SettingsTab.general.highlightID(for: "Close gesture")), SettingsSearchEntry(tab: .general, title: "Close gesture", keywords: ["pinch", "swipe"], highlightID: SettingsTab.general.highlightID(for: "Close gesture")),
SettingsSearchEntry(tab: .general, title: "Reverse swipe gestures", keywords: ["reverse", "swipe", "media"], highlightID: SettingsTab.general.highlightID(for: "Reverse swipe gestures")),
SettingsSearchEntry(tab: .general, title: "Reverse scroll gestures", keywords: ["reverse", "scroll", "open", "close"], highlightID: SettingsTab.general.highlightID(for: "Reverse scroll gestures")),
SettingsSearchEntry(tab: .general, title: "Extend hover area", keywords: ["hover", "cursor"], highlightID: SettingsTab.general.highlightID(for: "Extend hover area")), SettingsSearchEntry(tab: .general, title: "Extend hover area", keywords: ["hover", "cursor"], highlightID: SettingsTab.general.highlightID(for: "Extend hover area")),
SettingsSearchEntry(tab: .general, title: "Enable haptics", keywords: ["haptic", "feedback"], highlightID: SettingsTab.general.highlightID(for: "Enable haptics")), SettingsSearchEntry(tab: .general, title: "Enable haptics", keywords: ["haptic", "feedback"], highlightID: SettingsTab.general.highlightID(for: "Enable haptics")),
SettingsSearchEntry(tab: .general, title: "Open notch on hover", keywords: ["hover to open", "auto open"], highlightID: SettingsTab.general.highlightID(for: "Open notch on hover")), SettingsSearchEntry(tab: .general, title: "Open notch on hover", keywords: ["hover to open", "auto open"], highlightID: SettingsTab.general.highlightID(for: "Open notch on hover")),
@ -845,6 +847,8 @@ struct GeneralSettings: View {
@Default(.enableMinimalisticUI) var enableMinimalisticUI @Default(.enableMinimalisticUI) var enableMinimalisticUI
@Default(.enableHorizontalMusicGestures) var enableHorizontalMusicGestures @Default(.enableHorizontalMusicGestures) var enableHorizontalMusicGestures
@Default(.musicGestureBehavior) var musicGestureBehavior @Default(.musicGestureBehavior) var musicGestureBehavior
@Default(.reverseSwipeGestures) var reverseSwipeGestures
@Default(.reverseScrollGestures) var reverseScrollGestures
private func highlightID(_ title: String) -> String { private func highlightID(_ title: String) -> String {
SettingsTab.general.highlightID(for: title) SettingsTab.general.highlightID(for: title)
@ -1003,6 +1007,9 @@ struct GeneralSettings: View {
Text(musicGestureBehavior.description) Text(musicGestureBehavior.description)
.font(.caption) .font(.caption)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
Defaults.Toggle("Reverse swipe gestures", key: .reverseSwipeGestures)
.settingsHighlight(id: highlightID("Reverse swipe gestures"))
} }
Defaults.Toggle("Close gesture", key: .closeGestureEnabled) Defaults.Toggle("Close gesture", key: .closeGestureEnabled)
@ -1015,6 +1022,9 @@ struct GeneralSettings: View {
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
} }
} }
Defaults.Toggle("Reverse open/close scroll gestures", key: .reverseScrollGestures)
.settingsHighlight(id: highlightID("Reverse scroll gestures"))
} }
} header: { } header: {
HStack { HStack {

View file

@ -520,6 +520,8 @@ extension Defaults.Keys {
static let gestureSensitivity = Key<CGFloat>("gestureSensitivity", default: 200.0) static let gestureSensitivity = Key<CGFloat>("gestureSensitivity", default: 200.0)
static let enableHorizontalMusicGestures = Key<Bool>("enableHorizontalMusicGestures", default: true) static let enableHorizontalMusicGestures = Key<Bool>("enableHorizontalMusicGestures", default: true)
static let musicGestureBehavior = Key<MusicSkipBehavior>("musicGestureBehavior", default: .track) static let musicGestureBehavior = Key<MusicSkipBehavior>("musicGestureBehavior", default: .track)
static let reverseSwipeGestures = Key<Bool>("reverseSwipeGestures", default: false)
static let reverseScrollGestures = Key<Bool>("reverseScrollGestures", default: false)
// MARK: Media playback // MARK: Media playback
static let coloredSpectrogram = Key<Bool>("coloredSpectrogram", default: true) static let coloredSpectrogram = Key<Bool>("coloredSpectrogram", default: true)