Files
gart/code/Hex-main/Hex/Features/Settings/HotKeySectionView.swift
T

126 lines
4.4 KiB
Swift
Executable File

import ComposableArchitecture
import HexCore
import Inject
import SwiftUI
struct HotKeySectionView: View {
@ObserveInjection var inject
@Bindable var store: StoreOf<SettingsFeature>
var body: some View {
Section("Hot Key") {
let hotKey = store.hexSettings.hotkey
let key = store.isSettingHotKey ? nil : hotKey.key
let modifiers = store.isSettingHotKey ? store.currentModifiers : hotKey.modifiers
VStack(spacing: 12) {
// Hot key view
HStack {
Spacer()
HotKeyView(modifiers: modifiers, key: key, isActive: store.isSettingHotKey)
.animation(.spring(), value: key)
.animation(.spring(), value: modifiers)
Spacer()
}
.contentShape(Rectangle())
.onTapGesture {
store.send(.startSettingHotKey)
}
if !store.isSettingHotKey,
hotKey.key == nil,
!hotKey.modifiers.isEmpty {
ModifierSideControls(
modifiers: hotKey.modifiers,
onSelect: { kind, side in
store.send(.setModifierSide(kind, side))
}
)
.transition(.opacity)
}
}
Label {
Toggle(
"Enable double-tap lock",
isOn: Binding(
get: { store.hexSettings.doubleTapLockEnabled },
set: { store.send(.setDoubleTapLockEnabled($0)) }
)
)
} icon: {
Image(systemName: "hand.tap")
}
// Double-tap only mode applies to key+modifier combinations.
if hotKey.key != nil {
Label {
Toggle(
"Use double-tap only",
isOn: Binding(
get: { store.hexSettings.useDoubleTapOnly },
set: { store.send(.setUseDoubleTapOnly($0)) }
)
)
.disabled(!store.hexSettings.doubleTapLockEnabled)
} icon: {
Image(systemName: "hand.tap.fill")
}
}
// Minimum key time (for modifier-only shortcuts)
if store.hexSettings.hotkey.key == nil {
Label {
Slider(
value: Binding(
get: { store.hexSettings.minimumKeyTime },
set: { store.send(.setMinimumKeyTime($0)) }
),
in: 0.0 ... 2.0,
step: 0.1
) {
Text("Ignore below \(store.hexSettings.minimumKeyTime, specifier: "%.1f")s")
}
} icon: {
Image(systemName: "clock")
}
}
}
.enableInjection()
}
}
private struct ModifierSideControls: View {
@ObserveInjection var inject
var modifiers: Modifiers
var onSelect: (Modifier.Kind, Modifier.Side) -> Void
var body: some View {
VStack(alignment: .leading, spacing: 8) {
ForEach(modifiers.kinds, id: \.self) { kind in
if kind.supportsSideSelection {
let binding = Binding<Modifier.Side>(
get: { modifiers.side(for: kind) ?? .either },
set: { onSelect(kind, $0) }
)
VStack(alignment: .leading, spacing: 4) {
Text("\(kind.symbol) \(kind.displayName)")
.settingsCaption()
Picker("Modifier side", selection: binding) {
ForEach(Modifier.Side.allCases, id: \.self) { side in
Text(side.displayName)
.tag(side)
.disabled(!kind.supportsSideSelection && side != .either)
}
}
.pickerStyle(.segmented)
}
}
}
}
.enableInjection()
}
}