Files
openless/Sources/OpenLessApp/Settings/SettingsView.swift
T
baiqing d94be8080d refactor(settings): split 1697-line SettingsView.swift into single-responsibility files
按用户的"800 行红线、单一职责"约束拆分。零行为变化,只是物理文件结构。

- SettingsView.swift  87 (root: 枚举 + 导航模型 + 主分发)
- SettingsComponents.swift  218 (SettingsPage / GlassSection / GlassPanel /
  MetricTile / Notification 名 / polishModeHint / isFilled)
- Sidebar.swift  270 (FixedSidebar + 状态卡 + stats + WindowCanvasBackground)
- Tabs/HomeTab.swift  161
- Tabs/HistoryTab.swift  50
- Tabs/DictionaryTab.swift  349 (含 Chip + ChipFlow + EditorSheet)
- Tabs/StyleTab.swift  123 (含 StyleCard)
- Tabs/HelpTab.swift  100
- Tabs/SettingsHubTab.swift  184
- Tabs/LegacyTabs.swift  172 (Overview/Hotkey/Modes/Privacy 旧版孤儿,原样搬)

private 改成默认 internal 让跨文件可见,封装边界仍止于 OpenLessApp 模块内部。
项目最长文件从 1697 行 → 566 行 (DictationCoordinator),全部在 800 红线下。
2026-04-28 13:13:37 +08:00

88 lines
2.6 KiB
Swift

import AppKit
import SwiftUI
import OpenLessCore
import OpenLessHotkey
import OpenLessPersistence
import OpenLessRecorder
import OpenLessASR
import OpenLessPolish
// 设置窗口的根入口:导航枚举 + 模型 + 主分发。
// 共享组件、侧边栏、各 Tab、遗留 Tab、通知名都在同目录其他文件里。
enum OpenLessMainTab: String, CaseIterable, Identifiable {
case home
case history
case dictionary
case polish
case help
case settings
var id: String { rawValue }
var title: String {
switch self {
case .home: return "首页"
case .history: return "历史记录"
case .dictionary: return "词汇表"
case .polish: return "风格"
case .help: return "帮助中心"
case .settings: return "设置"
}
}
var symbol: String {
switch self {
case .home: return "chart.line.uptrend.xyaxis"
case .history: return "clock"
case .dictionary: return "text.book.closed"
case .polish: return "paintpalette"
case .help: return "questionmark.circle"
case .settings: return "gearshape"
}
}
}
@MainActor
final class SettingsNavigationModel: ObservableObject {
@Published var selection: OpenLessMainTab
init(selection: OpenLessMainTab = .home) {
self.selection = selection
}
}
struct SettingsView: View {
@ObservedObject private var navigation: SettingsNavigationModel
init(navigation: SettingsNavigationModel) {
self.navigation = navigation
}
var body: some View {
HStack(spacing: 14) {
FixedSidebar(selection: $navigation.selection)
Group {
switch navigation.selection {
case .home: HomeTab()
case .history: HistoryTab()
case .dictionary: DictionaryTab()
case .polish: StyleTab()
case .help: HelpTab()
case .settings: SettingsHubTab()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
// 右栏顶部留点空白,避免内容贴到 title bar 区域。
.padding(.top, 12)
}
// 左/下/右用相等 12pt;上方为 0,让侧边栏顶边贴窗口顶,
// 红绿灯(系统画在 title bar 层)就自然落在侧边栏的圆角矩形内部。
.padding(.leading, 12)
.padding(.trailing, 12)
.padding(.bottom, 12)
.background(WindowCanvasBackground())
.frame(minWidth: 1040, minHeight: 700)
}
}