Files
wehub-resource-sync 1d1286fadb
Build / Build and test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:18:38 +08:00

290 lines
10 KiB
Swift

import SwiftUI
import MacToolsPluginKit
struct MouseEnhancerSettingsView: View {
@ObservedObject var store: MouseEnhancerStore
let localization: PluginLocalization
let onChange: () -> Void
var body: some View {
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.section) {
mouseSection
trackpadSection
}
}
private var mouseSection: some View {
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.sectionHeaderContent) {
sectionHeader(title: localization.string("settings.mouse.sectionTitle", defaultValue: "鼠标"), icon: "computermouse")
VStack(spacing: 0) {
toggleRow(
title: localization.string("settings.mouse.vertical.title", defaultValue: "垂直反转"),
description: localization.string("settings.mouse.vertical.description", defaultValue: "反转鼠标上下滚动方向。"),
icon: "arrow.up.and.down",
isOn: mouseVerticalBinding
)
PluginSettingsListDivider()
toggleRow(
title: localization.string("settings.mouse.horizontal.title", defaultValue: "水平反转"),
description: localization.string("settings.mouse.horizontal.description", defaultValue: "反转鼠标左右滚动方向。"),
icon: "arrow.left.and.right",
isOn: mouseHorizontalBinding
)
}
.pluginSettingsCardBackground(.host)
}
}
private var trackpadSection: some View {
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.sectionHeaderContent) {
sectionHeader(title: localization.string("settings.trackpad.sectionTitle", defaultValue: "触控板"), icon: "hand.draw")
VStack(spacing: 0) {
toggleRow(
title: localization.string("settings.trackpad.vertical.title", defaultValue: "垂直反转"),
description: localization.string("settings.trackpad.vertical.description", defaultValue: "反转触控板和 Magic Mouse 上下滚动方向。"),
icon: "arrow.up.and.down",
isOn: trackpadVerticalBinding
)
PluginSettingsListDivider()
toggleRow(
title: localization.string("settings.trackpad.horizontal.title", defaultValue: "水平反转"),
description: localization.string("settings.trackpad.horizontal.description", defaultValue: "反转触控板和 Magic Mouse 左右滚动方向。"),
icon: "arrow.left.and.right",
isOn: trackpadHorizontalBinding
)
PluginSettingsListDivider()
toggleRow(
title: localization.string("settings.middleClick.title", defaultValue: "模拟鼠标中键"),
description: localization.string("settings.middleClick.description", defaultValue: "触控板轻点模拟鼠标中键点击。"),
icon: "hand.tap",
isOn: middleClickEnabledBinding
)
if store.configuration.middleClickEnabled {
PluginSettingsListDivider()
fingerCountRow
}
}
.pluginSettingsCardBackground(.host)
}
}
private var fingerCountRow: some View {
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.rowContentControl) {
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.rowTitleDescription) {
HStack(spacing: PluginSettingsTheme.Spacing.controlCluster) {
Image(systemName: "hand.raised")
.pluginSettingsRowIconStyle()
Text(localization.string("settings.middleClick.fingerCount.title", defaultValue: "手指数量"))
.font(PluginSettingsTheme.Typography.emphasizedRowTitle)
}
Text(localization.string(
"settings.middleClick.fingerCount.description",
defaultValue: "用指定数量的手指在触控板上轻点,将模拟鼠标中键点击。"
))
.font(PluginSettingsTheme.Typography.rowDescription)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
HStack(spacing: PluginSettingsTheme.Spacing.controlCluster) {
ForEach([3, 4, 5], id: \.self) { count in
FingerCountButton(
count: count,
isSelected: store.configuration.middleClickFingerCount == count,
localization: localization,
action: {
store.setMiddleClickFingerCount(count)
onChange()
}
)
}
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.pluginSettingsListRowPadding()
}
private func sectionHeader(title: String, icon: String) -> some View {
Label(title, systemImage: icon)
.font(PluginSettingsTheme.Typography.sectionTitle)
.foregroundStyle(.secondary)
}
private func toggleRow(
title: String,
description: String,
icon: String,
isOn: Binding<Bool>
) -> some View {
MouseEnhancerToggleRow(
title: title,
description: description,
icon: icon,
isOn: isOn
)
}
private var mouseVerticalBinding: Binding<Bool> {
Binding(
get: { store.configuration.reverseMouseVertical },
set: { value in
store.setReverseMouseVertical(value)
onChange()
}
)
}
private var mouseHorizontalBinding: Binding<Bool> {
Binding(
get: { store.configuration.reverseMouseHorizontal },
set: { value in
store.setReverseMouseHorizontal(value)
onChange()
}
)
}
private var trackpadVerticalBinding: Binding<Bool> {
Binding(
get: { store.configuration.reverseTrackpadVertical },
set: { value in
store.setReverseTrackpadVertical(value)
onChange()
}
)
}
private var trackpadHorizontalBinding: Binding<Bool> {
Binding(
get: { store.configuration.reverseTrackpadHorizontal },
set: { value in
store.setReverseTrackpadHorizontal(value)
onChange()
}
)
}
private var middleClickEnabledBinding: Binding<Bool> {
Binding(
get: { store.configuration.middleClickEnabled },
set: { value in
store.setMiddleClickEnabled(value)
onChange()
}
)
}
}
private struct MouseEnhancerToggleRow: View {
let title: String
let description: String
let icon: String
@Binding var isOn: Bool
@State private var toggleID = UUID()
init(
title: String,
description: String,
icon: String,
isOn: Binding<Bool>
) {
self.title = title
self.description = description
self.icon = icon
_isOn = isOn
}
var body: some View {
HStack(spacing: PluginSettingsTheme.Spacing.rowContentControl) {
Image(systemName: icon)
.pluginSettingsRowIconStyle()
VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.rowTitleDescription) {
Text(title)
.font(PluginSettingsTheme.Typography.emphasizedRowTitle)
Text(description)
.font(PluginSettingsTheme.Typography.rowDescription)
.foregroundStyle(.secondary)
.fixedSize(horizontal: false, vertical: true)
}
Spacer(minLength: PluginSettingsTheme.Spacing.rowContentControl)
Toggle("", isOn: $isOn)
.labelsHidden()
.toggleStyle(.switch)
.controlSize(.small)
.id(toggleID)
}
.pluginSettingsListRowPadding()
.onAppear {
DispatchQueue.main.async {
toggleID = UUID()
}
}
}
}
private struct FingerCountButton: View {
let count: Int
let isSelected: Bool
let localization: PluginLocalization
let action: () -> Void
var body: some View {
Button(action: action) {
VStack(spacing: PluginSettingsTheme.Spacing.controlCluster) {
Image(systemName: "hand.raised")
.pluginSettingsRowIconStyle(isSelected ? Color.accentColor : Color.primary)
Text(localization.format("settings.middleClick.fingerCount.optionFormat", defaultValue: "%d指", count))
.font(PluginSettingsTheme.Typography.secondaryLabel.weight(.semibold))
}
.frame(maxWidth: .infinity)
.frame(height: PluginSettingsTheme.Size.controlHeight * 2)
.foregroundStyle(isSelected ? Color.accentColor : Color.primary)
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.background(
RoundedRectangle(cornerRadius: PluginSettingsTheme.Radius.control, style: .continuous)
.fill(
isSelected
? PluginSettingsTheme.Palette.activeControlBackground
: PluginSettingsTheme.Palette.recessedControlBackground
)
)
.overlay(
RoundedRectangle(cornerRadius: PluginSettingsTheme.Radius.control, style: .continuous)
.strokeBorder(
isSelected
? Color.accentColor.opacity(0.35)
: Color.clear,
lineWidth: PluginSettingsTheme.Stroke.standard
)
)
}
}
#Preview {
MouseEnhancerSettingsView(
store: MouseEnhancerStore(storage: UserDefaultsPluginStorage(pluginID: "mouse-enhancer-preview")),
localization: PluginLocalization(bundle: .main),
onChange: {}
)
.frame(width: 440)
.padding(24)
}