Skip to content

Commit cd08941

Browse files
committed
feat: add menu bar ascii_mode display
- 切换 app 时 menu bar 状态跟随当前 session 的 ascii_mode 更新 - 增加配置 squirrel.yaml 中 menubar_ascii_mode 默认 true
1 parent d47b984 commit cd08941

4 files changed

Lines changed: 69 additions & 0 deletions

File tree

Squirrel.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
D26434552706A15100857391 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D26434542706A15100857391 /* QuartzCore.framework */; };
9191
E93074B70A5C264700470842 /* InputMethodKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E93074B60A5C264700470842 /* InputMethodKit.framework */; };
9292
F45E005F2B8CA81C00179B75 /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F45E005E2B8CA81C00179B75 /* UserNotifications.framework */; };
93+
4D2A6EB7-BA19-4424-8EE7-631DBEC1AA87 /* StatusBarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6C012-5161-4121-AC4F-E125D9F00676 /* StatusBarManager.swift */; };
9394
/* End PBXBuildFile section */
9495

9596
/* Begin PBXCopyFilesBuildPhase section */
@@ -297,6 +298,7 @@
297298
D26434542706A15100857391 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
298299
E93074B60A5C264700470842 /* InputMethodKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InputMethodKit.framework; path = /System/Library/Frameworks/InputMethodKit.framework; sourceTree = "<absolute>"; };
299300
F45E005E2B8CA81C00179B75 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
301+
FBA6C012-5161-4121-AC4F-E125D9F00676 /* StatusBarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StatusBarManager.swift; path = sources/StatusBarManager.swift; sourceTree = "<group>"; };
300302
/* End PBXFileReference section */
301303

302304
/* Begin PBXFrameworksBuildPhase section */
@@ -327,6 +329,7 @@
327329
B39771282BEDAF4A0093A49B /* SquirrelView.swift */,
328330
B39771242BED899F0093A49B /* SquirrelConfig.swift */,
329331
B35D2FE72BF00839009D156B /* BridgingFunctions.swift */,
332+
FBA6C012-5161-4121-AC4F-E125D9F00676 /* StatusBarManager.swift */,
330333
B38E9B8F2BE9AE1E0036ABEF /* Squirrel-Bridging-Header.h */,
331334
);
332335
name = Sources;
@@ -589,6 +592,7 @@
589592
B38E9B912BE9AE1E0036ABEF /* SquirrelApplicationDelegate.swift in Sources */,
590593
B39771272BED9B250093A49B /* SquirrelTheme.swift in Sources */,
591594
B35D2FE82BF00839009D156B /* BridgingFunctions.swift in Sources */,
595+
4D2A6EB7-BA19-4424-8EE7-631DBEC1AA87 /* StatusBarManager.swift in Sources */,
592596
);
593597
runOnlyForDeploymentPostprocessing = 0;
594598
};

sources/SquirrelApplicationDelegate.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
1919
var panel: SquirrelPanel?
2020
var enableNotifications = false
2121
let updateController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil)
22+
let statusBarManager = StatusBarManager()
2223
var supportsGentleScheduledUpdateReminders: Bool {
2324
true
2425
}
@@ -61,6 +62,7 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
6162
// swiftlint:disable:next notification_center_detachment
6263
NotificationCenter.default.removeObserver(self)
6364
DistributedNotificationCenter.default().removeObserver(self)
65+
statusBarManager.teardown()
6466
panel?.hide()
6567
}
6668

@@ -162,6 +164,8 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
162164
}
163165

164166
enableNotifications = config!.getString("show_notifications_when") != "never"
167+
let showStatusInMenuBar = config!.getBool("menubar_ascii_mode") ?? true
168+
statusBarManager.setup(enabled: showStatusInMenuBar)
165169
if let panel = panel, let config = self.config {
166170
panel.load(config: config, forDarkMode: false)
167171
panel.load(config: config, forDarkMode: true)
@@ -284,6 +288,7 @@ private extension SquirrelApplicationDelegate {
284288
func showStatusMessage(msgTextLong: String?, msgTextShort: String?) {
285289
if !(msgTextLong ?? "").isEmpty || !(msgTextShort ?? "").isEmpty {
286290
panel?.updateStatus(long: msgTextLong ?? "", short: msgTextShort ?? "")
291+
statusBarManager.updateStatus(text: msgTextShort ?? "")
287292
}
288293
}
289294

sources/SquirrelInputController.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ final class SquirrelInputController: IMKInputController {
194194
if keyboardLayout != "" {
195195
client?.overrideKeyboard(withKeyboardNamed: keyboardLayout)
196196
}
197+
if session != 0 {
198+
updateMenuBarStatus()
199+
}
197200
preedit = ""
198201
}
199202

@@ -295,6 +298,18 @@ final class SquirrelInputController: IMKInputController {
295298

296299
private extension SquirrelInputController {
297300

301+
func updateMenuBarStatus() {
302+
guard session != 0 else { return }
303+
let isAsciiMode = rimeAPI.get_option(session, "ascii_mode")
304+
"ascii_mode".withCString { name in
305+
let label = rimeAPI.get_state_label_abbreviated(session, name, isAsciiMode, true)
306+
if let str = label.str {
307+
let text = String(cString: str)
308+
NSApp.squirrelAppDelegate.statusBarManager.updateStatus(text: text)
309+
}
310+
}
311+
}
312+
298313
func onChordTimer(_: Timer) {
299314
// chord release triggered by timer
300315
var processedKeys = false

sources/StatusBarManager.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//
2+
// StatusBarManager.swift
3+
// Squirrel
4+
//
5+
6+
import AppKit
7+
8+
final class StatusBarManager {
9+
private var statusItem: NSStatusItem?
10+
11+
deinit {
12+
teardown()
13+
}
14+
15+
/// 根据配置初始化或销毁菜单栏图标
16+
/// - Parameters:
17+
/// - enabled: true 创建状态项,false 移除
18+
/// - initialText: 初始显示的文本,默认为空字符串
19+
func setup(enabled: Bool, initialText: String = "") {
20+
if enabled {
21+
if statusItem == nil {
22+
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
23+
}
24+
if !initialText.isEmpty {
25+
statusItem?.button?.title = initialText
26+
}
27+
} else {
28+
teardown()
29+
}
30+
}
31+
32+
/// 更新菜单栏显示的文本
33+
/// - Parameter text: 要显示的文本,如 "中" 或 "A"
34+
func updateStatus(text: String) {
35+
statusItem?.button?.title = text
36+
}
37+
38+
/// 清理资源,从菜单栏移除状态项
39+
func teardown() {
40+
if let item = statusItem {
41+
NSStatusBar.system.removeStatusItem(item)
42+
statusItem = nil
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)