- 侧边栏 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 → 解决"灰色边栏 + 黑色卡顿" - 首页底部新增今日概览 + 风格预览
136 lines
4.2 KiB
Swift
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])
|
|
}
|
|
}
|