Files
openless/Sources/OpenLessApp/MenuBarController.swift
T
baiqing 88a5a97812 feat: 1.0.03 — 侧边栏重构 + 词汇表 chip 布局 + 风格页 + 关掉自动学词
- 侧边栏 4 → 6 项:首页 / 历史记录 / 词汇表 / 风格 / 帮助中心 / 设置
- 词典 → 词汇表,整页改 chip 流式布局:phrase + hitCount,hover ✕ 删除,
  批量输入(每行一个),重置统计 / 清除全部
- DictionaryEntry 加 hitCount + 兼容旧 dictionary.json 解码
- DictationCoordinator 在润色后扫描最终文本递增命中数;
  删除 learnTerms 自动学词路径
- 润色模式 → 风格 (StyleTab):4 张模式卡 + 启用开关;
  关闭时跳过 Ark 直接插入原文 (UserPreferences.polishEnabled)
- 帮助中心:快速上手 4 步、快捷键速查、FAQ、GitHub 外链
- 设置 Tab 合并 Volc ASR + Ark 凭据、录音、授权、隐私、关于 + 检查更新
- 胶囊:NSPanel 220×96, hasShadow=false;macOS 26 分支去掉 SwiftUI 阴影
  → 解决"红绿灯外圈黑边"
- 侧边栏视觉:strokeBorder 0.08 → 0.04、阴影 radius 16 → 6
  → 解决"灰色边栏 + 黑色卡顿"
- 首页底部新增今日概览 + 风格预览
2026-04-28 11:16:40 +08:00

136 lines
4.2 KiB
Swift

import AppKit
import OpenLessCore
import OpenLessPersistence
@MainActor
final class MenuBarController {
private let statusItem: NSStatusItem
private let actions: MenuActions
private weak var coordinator: DictationCoordinator?
init(coordinator: DictationCoordinator) {
self.coordinator = coordinator
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
if let button = statusItem.button {
button.image = StatusBarIcon.image()
button.imageScaling = .scaleProportionallyDown
button.imagePosition = .imageOnly
button.toolTip = "OpenLess — 点击菜单选择模式 / 退出"
button.setAccessibilityLabel("OpenLess")
}
actions = MenuActions(coordinator: coordinator)
statusItem.menu = buildMenu()
}
func refreshMenu() {
statusItem.menu = buildMenu()
}
private func buildMenu() -> NSMenu {
let menu = NSMenu()
let title = NSMenuItem(title: "OpenLess", action: nil, keyEquivalent: "")
title.isEnabled = false
menu.addItem(title)
menu.addItem(.separator())
let toggle = NSMenuItem(title: "开始 / 停止录音", action: #selector(MenuActions.toggleDictation), keyEquivalent: "")
toggle.target = actions
menu.addItem(toggle)
menu.addItem(.separator())
let modeHeader = NSMenuItem(title: "润色模式", action: nil, keyEquivalent: "")
modeHeader.isEnabled = false
menu.addItem(modeHeader)
let currentMode = UserPreferences.shared.polishMode
for mode in PolishMode.allCases {
let item = NSMenuItem(
title: mode.displayName,
action: #selector(MenuActions.selectMode(_:)),
keyEquivalent: ""
)
item.target = actions
item.state = (mode == currentMode) ? .on : .off
item.representedObject = mode.rawValue
menu.addItem(item)
}
menu.addItem(.separator())
let home = NSMenuItem(title: "打开首页…", action: #selector(MenuActions.openHome), keyEquivalent: "")
home.target = actions
menu.addItem(home)
let history = NSMenuItem(title: "打开历史记录…", action: #selector(MenuActions.openHistory), keyEquivalent: "")
history.target = actions
menu.addItem(history)
let dictionary = NSMenuItem(title: "打开词汇表…", action: #selector(MenuActions.openDictionary), keyEquivalent: "")
dictionary.target = actions
menu.addItem(dictionary)
let settings = NSMenuItem(title: "打开设置…", action: #selector(MenuActions.openSettings), keyEquivalent: ",")
settings.target = actions
menu.addItem(settings)
let revealLog = NSMenuItem(title: "在 Finder 中显示日志", action: #selector(MenuActions.revealLog), keyEquivalent: "l")
revealLog.target = actions
menu.addItem(revealLog)
menu.addItem(.separator())
let quit = NSMenuItem(
title: "退出 OpenLess",
action: #selector(NSApplication.terminate(_:)),
keyEquivalent: "q"
)
menu.addItem(quit)
return menu
}
}
@MainActor
private final class MenuActions: NSObject {
private weak var coordinator: DictationCoordinator?
init(coordinator: DictationCoordinator) {
self.coordinator = coordinator
}
@objc func selectMode(_ sender: NSMenuItem) {
guard let raw = sender.representedObject as? String,
let mode = PolishMode(rawValue: raw) else { return }
UserPreferences.shared.polishMode = mode
Log.write("切换润色模式 → \(mode.displayName)")
coordinator?.menuBar?.refreshMenu()
}
@objc func openSettings() {
coordinator?.openSettings()
}
@objc func openHome() {
coordinator?.openHome()
}
@objc func openHistory() {
coordinator?.openHistory()
}
@objc func openDictionary() {
coordinator?.openDictionary()
}
@objc func toggleDictation() {
coordinator?.toggleDictationFromMenu()
}
@objc func revealLog() {
NSWorkspace.shared.activateFileViewerSelecting([Log.fileURL])
}
}