-
Notifications
You must be signed in to change notification settings - Fork 498
feat(ui): status bar icon reflects ascii_mode #1122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
7b286ec
3dad524
049cab6
8480b25
150b3c9
a207eee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
| import UserNotifications | ||
| import Sparkle | ||
| import AppKit | ||
| import InputMethodKit | ||
|
|
||
| final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUStandardUserDriverDelegate, UNUserNotificationCenterDelegate { | ||
| static let rimeWikiURL = URL(string: "https://github.com/rime/home/wiki")! | ||
|
|
@@ -18,6 +19,8 @@ | |
| var config: SquirrelConfig? | ||
| var panel: SquirrelPanel? | ||
| var enableNotifications = false | ||
| var showStatusIcon: Bool = true | ||
| var statusItem: NSStatusItem? | ||
| let updateController = SPUStandardUpdaterController(startingUpdater: true, updaterDelegate: nil, userDriverDelegate: nil) | ||
| var supportsGentleScheduledUpdateReminders: Bool { | ||
| true | ||
|
|
@@ -54,6 +57,7 @@ | |
|
|
||
| func applicationWillFinishLaunching(_ notification: Notification) { | ||
| panel = SquirrelPanel(position: .zero) | ||
| refreshStatusItem() | ||
| addObservers() | ||
| } | ||
|
|
||
|
|
@@ -62,6 +66,16 @@ | |
| NotificationCenter.default.removeObserver(self) | ||
| DistributedNotificationCenter.default().removeObserver(self) | ||
| panel?.hide() | ||
| if let item = statusItem { | ||
| NSStatusBar.system.removeStatusItem(item) | ||
| statusItem = nil | ||
| } | ||
| } | ||
|
|
||
| func updateStatusIcon(asciiMode: Bool, schemaLabel: String?) { | ||
| DispatchQueue.main.async { [weak self] in | ||
| self?.applyStatusIcon(asciiMode: asciiMode, schemaLabel: schemaLabel) | ||
| } | ||
| } | ||
|
|
||
| func deploy() { | ||
|
|
@@ -162,6 +176,8 @@ | |
| } | ||
|
|
||
| enableNotifications = config!.getString("show_notifications_when") != "never" | ||
| showStatusIcon = config!.getBool("status_icon/show") ?? true | ||
| refreshStatusItem() | ||
| if let panel = panel, let config = self.config { | ||
| panel.load(config: config, forDarkMode: false) | ||
| panel.load(config: config, forDarkMode: true) | ||
|
|
@@ -225,6 +241,9 @@ | |
| let notifCenter = DistributedNotificationCenter.default() | ||
| notifCenter.addObserver(forName: .init("SquirrelReloadNotification"), object: nil, queue: nil, using: rimeNeedsReload) | ||
| notifCenter.addObserver(forName: .init("SquirrelSyncNotification"), object: nil, queue: nil, using: rimeNeedsSync) | ||
| notifCenter.addObserver(forName: .init(kTISNotifySelectedKeyboardInputSourceChanged as String), object: nil, queue: .main) { [weak self] _ in | ||
| self?.updateStatusItemVisibility() | ||
| } | ||
| } | ||
|
|
||
| func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply { | ||
|
|
@@ -235,7 +254,7 @@ | |
|
|
||
| } | ||
|
|
||
| private func notificationHandler(contextObject: UnsafeMutableRawPointer?, sessionId: RimeSessionId, messageTypeC: UnsafePointer<CChar>?, messageValueC: UnsafePointer<CChar>?) { | ||
| let delegate: SquirrelApplicationDelegate = Unmanaged<SquirrelApplicationDelegate>.fromOpaque(contextObject!).takeUnretainedValue() | ||
|
|
||
| let messageType = messageTypeC.map { String(cString: $0) } | ||
|
|
@@ -253,30 +272,42 @@ | |
| } | ||
| return | ||
| } | ||
| // off | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The code below needs cleanup. The control flow is not easy to understand. |
||
| if !delegate.enableNotifications { | ||
| return | ||
| } | ||
|
|
||
| if messageType == "schema", let messageValue = messageValue, let schemaName = try? /^[^\/]*\/(.*)$/.firstMatch(in: messageValue)?.output.1 { | ||
| delegate.showStatusMessage(msgTextLong: String(schemaName), msgTextShort: String(schemaName)) | ||
| return | ||
| } else if messageType == "option" { | ||
| if messageType == "option" { | ||
| let state = messageValue?.first != "!" | ||
| let optionName = if state { | ||
| messageValue | ||
| let optionName: String? | ||
| if state { | ||
| optionName = messageValue | ||
| } else if let value = messageValue { | ||
| optionName = String(value[value.index(after: value.startIndex)...]) | ||
| } else { | ||
| String(messageValue![messageValue!.index(after: messageValue!.startIndex)...]) | ||
| optionName = nil | ||
| } | ||
| if let optionName = optionName { | ||
| optionName.withCString { name in | ||
| let stateLabelLong = delegate.rimeAPI.get_state_label_abbreviated(sessionId, name, state, false) | ||
| let stateLabelLong = delegate.rimeAPI.get_state_label_abbreviated(sessionId, name, state, false) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra space |
||
| let stateLabelShort = delegate.rimeAPI.get_state_label_abbreviated(sessionId, name, state, true) | ||
| let longLabel = stateLabelLong.str.map { String(cString: $0) } | ||
| let longLabel = stateLabelLong.str .map { String(cString: $0) } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: extra spaces |
||
| let shortLabel = stateLabelShort.str.map { String(cString: $0) } | ||
| delegate.showStatusMessage(msgTextLong: longLabel, msgTextShort: shortLabel) | ||
| if optionName == "ascii_mode" { | ||
| delegate.updateStatusIcon(asciiMode: state, schemaLabel: shortLabel) | ||
| } | ||
| if delegate.enableNotifications { | ||
| delegate.showStatusMessage(msgTextLong: longLabel, msgTextShort: shortLabel) | ||
| } | ||
| } | ||
| } | ||
| return | ||
| } | ||
|
|
||
| // off | ||
| if !delegate.enableNotifications { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| return | ||
| } | ||
|
|
||
| if messageType == "schema", let messageValue = messageValue, let schemaName = try? /^[^\/]*\/(.*)$/.firstMatch(in: messageValue)?.output.1 { | ||
| delegate.showStatusMessage(msgTextLong: String(schemaName), msgTextShort: String(schemaName)) | ||
| return | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -287,6 +318,43 @@ | |
| } | ||
| } | ||
|
|
||
| func refreshStatusItem() { | ||
| if showStatusIcon { | ||
| if statusItem == nil { | ||
| setupStatusItem() | ||
| } | ||
| } else if let item = statusItem { | ||
| NSStatusBar.system.removeStatusItem(item) | ||
| statusItem = nil | ||
| } | ||
| } | ||
|
|
||
| func setupStatusItem() { | ||
| let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) | ||
| if let button = item.button { | ||
| button.font = NSFont.systemFont(ofSize: NSFont.systemFontSize, weight: .semibold) | ||
| button.toolTip = NSLocalizedString("Squirrel", comment: "") | ||
| } | ||
| statusItem = item | ||
| applyStatusIcon(asciiMode: false, schemaLabel: nil) | ||
| updateStatusItemVisibility() | ||
| } | ||
|
|
||
| func updateStatusItemVisibility() { | ||
| guard let statusItem = statusItem else { return } | ||
| let id = SquirrelInstaller.currentInputSourceID() ?? "" | ||
| statusItem.isVisible = id.hasPrefix("im.rime.inputmethod.Squirrel") | ||
| } | ||
|
|
||
| func applyStatusIcon(asciiMode: Bool, schemaLabel: String?) { | ||
| guard let button = statusItem?.button else { return } | ||
| if let schemaLabel = schemaLabel, !schemaLabel.isEmpty { | ||
| button.title = schemaLabel | ||
| } else { | ||
| button.title = asciiMode ? "A" : "中" | ||
| } | ||
| } | ||
|
|
||
| func shutdownRime() { | ||
| config?.close() | ||
| rimeAPI.finalize() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
可以簡化爲
show_status_icon誰知道會不會還有別的選項?
即使以後再加
status_icon的詳細配置,把開關單寫出來也沒問題。