Create reusable expandable toggle component for all settings sections with auto-expand on enable and consistent alignment
This commit is contained in:
parent
c9d57e5b89
commit
a6c47240e7
@ -29,6 +29,15 @@ struct ExpandableToggleSection<Content: View>: View {
|
|||||||
}
|
}
|
||||||
.toggleStyle(.switch)
|
.toggleStyle(.switch)
|
||||||
.help(helpText)
|
.help(helpText)
|
||||||
|
.onChange(of: isEnabled) { _, newValue in
|
||||||
|
if newValue {
|
||||||
|
withAnimation(.easeInOut(duration: 0.2)) {
|
||||||
|
isExpanded = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isExpanded = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if isEnabled {
|
if isEnabled {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|||||||
@ -67,7 +67,6 @@ struct ExperimentalFeaturesSection: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.leading, 16)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,8 @@ struct SettingsView: View {
|
|||||||
@State private var isCustomSoundsExpanded = false
|
@State private var isCustomSoundsExpanded = false
|
||||||
@State private var isSystemMuteExpanded = false
|
@State private var isSystemMuteExpanded = false
|
||||||
@State private var isClipboardRestoreExpanded = false
|
@State private var isClipboardRestoreExpanded = false
|
||||||
|
@State private var isCustomCancelExpanded = false
|
||||||
|
@State private var isMiddleClickExpanded = false
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@ -136,81 +138,60 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Custom Cancel Shortcut
|
ExpandableToggleSection(
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
title: "Custom Cancel Shortcut",
|
||||||
HStack(spacing: 8) {
|
helpText: "Shortcut for cancelling the current recording session. Default: double-tap Escape.",
|
||||||
Toggle(isOn: $isCustomCancelEnabled.animation()) {
|
isEnabled: $isCustomCancelEnabled,
|
||||||
Text("Custom Cancel Shortcut")
|
isExpanded: $isCustomCancelExpanded
|
||||||
}
|
) {
|
||||||
.toggleStyle(.switch)
|
HStack(spacing: 12) {
|
||||||
.onChange(of: isCustomCancelEnabled) { _, newValue in
|
Text("Cancel Shortcut")
|
||||||
if !newValue {
|
.font(.system(size: 13, weight: .medium))
|
||||||
KeyboardShortcuts.setShortcut(nil, for: .cancelRecorder)
|
.foregroundColor(.secondary)
|
||||||
}
|
|
||||||
}
|
KeyboardShortcuts.Recorder(for: .cancelRecorder)
|
||||||
|
.controlSize(.small)
|
||||||
InfoTip(
|
|
||||||
title: "Dismiss Recording",
|
Spacer()
|
||||||
message: "Shortcut for cancelling the current recording session. Default: double-tap Escape."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if isCustomCancelEnabled {
|
.onChange(of: isCustomCancelEnabled) { _, newValue in
|
||||||
HStack(spacing: 12) {
|
if !newValue {
|
||||||
Text("Cancel Shortcut")
|
KeyboardShortcuts.setShortcut(nil, for: .cancelRecorder)
|
||||||
.font(.system(size: 13, weight: .medium))
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
|
|
||||||
KeyboardShortcuts.Recorder(for: .cancelRecorder)
|
|
||||||
.controlSize(.small)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.leading, 16)
|
|
||||||
.transition(.opacity.combined(with: .move(edge: .top)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
|
||||||
// Middle-Click Toggle
|
ExpandableToggleSection(
|
||||||
VStack(alignment: .leading, spacing: 12) {
|
title: "Enable Middle-Click Toggle",
|
||||||
|
helpText: "Use middle mouse button to toggle VoiceInk recording.",
|
||||||
|
isEnabled: $hotkeyManager.isMiddleClickToggleEnabled,
|
||||||
|
isExpanded: $isMiddleClickExpanded
|
||||||
|
) {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
Toggle("Enable Middle-Click Toggle", isOn: $hotkeyManager.isMiddleClickToggleEnabled)
|
Text("Activation Delay")
|
||||||
.toggleStyle(.switch)
|
.font(.system(size: 13, weight: .medium))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
InfoTip(
|
TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: {
|
||||||
title: "Middle-Click Toggle",
|
let formatter = NumberFormatter()
|
||||||
message: "Use middle mouse button to toggle VoiceInk recording."
|
formatter.numberStyle = .none
|
||||||
)
|
formatter.minimum = 0
|
||||||
}
|
return formatter
|
||||||
|
}())
|
||||||
|
.textFieldStyle(PlainTextFieldStyle())
|
||||||
|
.padding(EdgeInsets(top: 3, leading: 6, bottom: 3, trailing: 6))
|
||||||
|
.background(Color(NSColor.textBackgroundColor))
|
||||||
|
.cornerRadius(5)
|
||||||
|
.frame(width: 70)
|
||||||
|
|
||||||
if hotkeyManager.isMiddleClickToggleEnabled {
|
Text("ms")
|
||||||
HStack(spacing: 8) {
|
.foregroundColor(.secondary)
|
||||||
Text("Activation Delay")
|
|
||||||
.font(.system(size: 13, weight: .medium))
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
|
|
||||||
TextField("", value: $hotkeyManager.middleClickActivationDelay, formatter: {
|
Spacer()
|
||||||
let formatter = NumberFormatter()
|
|
||||||
formatter.numberStyle = .none
|
|
||||||
formatter.minimum = 0
|
|
||||||
return formatter
|
|
||||||
}())
|
|
||||||
.textFieldStyle(PlainTextFieldStyle())
|
|
||||||
.padding(EdgeInsets(top: 3, leading: 6, bottom: 3, trailing: 6))
|
|
||||||
.background(Color(NSColor.textBackgroundColor))
|
|
||||||
.cornerRadius(5)
|
|
||||||
.frame(width: 70)
|
|
||||||
|
|
||||||
Text("ms")
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.leading, 16)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +242,6 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.leading, 16)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
@ -289,7 +269,6 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.padding(.leading, 16)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user