From 21ebba0d1ffa5b2a006e52d90025c5f55f0aa6f1 Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Sun, 5 Nov 2023 20:53:46 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E8=B0=83=E7=9F=ADshift=E6=8C=89?= =?UTF-8?q?=E9=94=AE=E7=9A=84=E6=A3=80=E6=B5=8B=E7=9A=84=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E9=97=B4=E9=9A=94=E4=B8=BA0.2s,=E9=98=B2=E6=AD=A2=E5=9C=A8?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E8=BE=93=E5=85=A5=E6=97=B6=E8=AF=AF=E8=A7=A6?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire/Utils/ModifierKeyUpChecker.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fire/Utils/ModifierKeyUpChecker.swift b/Fire/Utils/ModifierKeyUpChecker.swift index 85b2950..6039d4c 100644 --- a/Fire/Utils/ModifierKeyUpChecker.swift +++ b/Fire/Utils/ModifierKeyUpChecker.swift @@ -58,7 +58,7 @@ class ModifierKeyUpChecker { } } - private let delayInterval = 0.3 + private let delayInterval = 0.2 private var lastTime: Date = Date() From 2367b7e63ba2889087d10db7cf87e13223464305 Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Sun, 5 Nov 2023 20:54:30 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=A6=96=E9=80=89?= =?UTF-8?q?=E9=A1=B9=E4=B8=AD=E7=9A=84=E5=BA=94=E7=94=A8=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=90=8D=E5=92=8C=E5=9B=BE=E6=A0=87=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire/Preferences/ApplicationPane.swift | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Fire/Preferences/ApplicationPane.swift b/Fire/Preferences/ApplicationPane.swift index df7ad50..d5c3bcc 100644 --- a/Fire/Preferences/ApplicationPane.swift +++ b/Fire/Preferences/ApplicationPane.swift @@ -16,15 +16,18 @@ struct ApplicationSettingItemView: View { let onChange: () -> Void private func getDisplayName(_ identifier: String) -> String { - guard let info = Bundle.main.localizedInfoDictionary ?? Bundle.main.infoDictionary else { return identifier } - guard let displayName = ( - info["CFBundleDisplayName"] ?? - info["CFBundleName"]) as? String else { return identifier } + guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: identifier) else { + return identifier + } + let displayName = FileManager.default.displayName(atPath: url.path) return "\(displayName)(\(identifier))" } private func getIcon(_ identifier: String) -> NSImage { - return NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath) + guard let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: identifier) else { + return NSWorkspace.shared.icon(forFile: Bundle.main.bundlePath) + } + return NSWorkspace.shared.icon(forFile: url.path) } var body: some View { From 23b7102e3bcca62c127a6e447ceab473572c51f2 Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Sun, 5 Nov 2023 20:55:39 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=E5=8A=A0=E5=85=A5=E5=A4=B1?= =?UTF-8?q?=E5=8E=BB=E7=84=A6=E7=82=B9=E6=97=B6=E5=86=99=E5=85=A5=E5=8E=9F?= =?UTF-8?q?=E7=A0=81=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire/FireInputServer.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Fire/FireInputServer.swift b/Fire/FireInputServer.swift index b6793e0..32ba9ca 100644 --- a/Fire/FireInputServer.swift +++ b/Fire/FireInputServer.swift @@ -63,6 +63,7 @@ extension FireInputController { } } override func deactivateServer(_ sender: Any!) { + insertOriginText() clean() NSLog("[FireInputController] deactivate server: \(client()?.bundleIdentifier() ?? "no client deactivate")") } From e24e9c3f81db51ddded61fa1ec926d35236de487 Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Sun, 5 Nov 2023 20:57:42 +0800 Subject: [PATCH 4/6] =?UTF-8?q?feat(menu):=20=E6=B7=BB=E5=8A=A0=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E5=BA=94=E7=94=A8=E9=A2=84=E8=AE=BE=E7=9A=84=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E9=A1=B9=EF=BC=8C=E5=8F=AF=E4=B8=80=E9=94=AE=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=AD=A3=E5=9C=A8=E8=BE=93=E5=85=A5=E7=9A=84=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E9=A2=84=E8=AE=BE=E8=BE=93=E5=85=A5=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire.xcodeproj/project.pbxproj | 4 ++-- Fire/FireMenu.swift | 37 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Fire.xcodeproj/project.pbxproj b/Fire.xcodeproj/project.pbxproj index eaebcbd..8191421 100644 --- a/Fire.xcodeproj/project.pbxproj +++ b/Fire.xcodeproj/project.pbxproj @@ -187,7 +187,6 @@ 67C9A02D2AB53ED3000B5281 /* CandidatesWindow.swift */, 67C9A01D2AB53ED2000B5281 /* DictManager.swift */, 67C9A0142AB53ED2000B5281 /* en.lproj */, - 67C9A01A2AB53ED2000B5281 /* FireMenu.swift */, 67C9A0192AB53ED2000B5281 /* Info.plist */, 67C9A0242AB53ED3000B5281 /* Preferences */, 67C9A01E2AB53ED3000B5281 /* Resources */, @@ -196,8 +195,9 @@ 67C9A0112AB53EB0000B5281 /* Table */, 67C9A0052AB53E83000B5281 /* fire.pdf */, 67C9A0062AB53E83000B5281 /* Fire.swift */, - 67C9A0222AB53ED3000B5281 /* FireInputServer.swift */, 67C9A0072AB53E83000B5281 /* FireInputController.swift */, + 67C9A0222AB53ED3000B5281 /* FireInputServer.swift */, + 67C9A01A2AB53ED2000B5281 /* FireMenu.swift */, 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */, 67C9A0022AB53E83000B5281 /* InputSource.swift */, 67C9A0012AB53E83000B5281 /* MainMenu.xib */, diff --git a/Fire/FireMenu.swift b/Fire/FireMenu.swift index 574b192..a586807 100644 --- a/Fire/FireMenu.swift +++ b/Fire/FireMenu.swift @@ -9,6 +9,7 @@ import Foundation import AppKit import Sparkle +import Defaults extension FireInputController { /* -- menu actions start -- */ @@ -29,14 +30,48 @@ extension FireInputController { NSApp.setActivationPolicy(.accessory) FirePreferencesController.shared.showPane("用户词库") } + @objc func setAppicationMode(_ sender: Any!) { + if let menuWrapper = sender as? [String: Any], + let menuItem = menuWrapper["IMKCommandMenuItem"] as? NSMenuItem, + let dict = menuItem.representedObject as? [String: Any], + let bundleID = dict["bundleID"] as? String, + let mode = dict["mode"] as? InputMode { + NSLog("[FireInputController] setApplicationMode, \(bundleID), \(mode)") + var appSettings = Defaults[.appSettings] + appSettings[bundleID] = ApplicationSettingItem(bundleId: bundleID, inputMs: mode == .zhhans ? .zhhans : .enUS) + Defaults[.appSettings] = appSettings + } + } override func menu() -> NSMenu! { + NSLog("[FireInputController] menu") let menu = NSMenu() menu.items = [ NSMenuItem(title: "首选项", action: #selector(showPreferences(_:)), keyEquivalent: ""), NSMenuItem(title: "用户词库", action: #selector(showUserDictPrefs(_:)), keyEquivalent: ""), + ] + if !Defaults[.disableEnMode], + let controller = CandidatesWindow.shared.inputController, + let bundleID = controller.client()?.bundleIdentifier() { + var displayName = bundleID + if let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleID) { + displayName = FileManager.default.displayName(atPath: url.path) + } + let title = "设置“\(displayName)”的预设为\(Fire.shared.inputMode == .zhhans ? "中文" : "英文")" + let menuItem = NSMenuItem(title: title, action: #selector(setAppicationMode(_:)), keyEquivalent: "") + menuItem.representedObject = [ + "bundleID": bundleID, + "mode": Fire.shared.inputMode + ] + menu.items.append(contentsOf: [ + NSMenuItem.separator(), + menuItem, + ]) + } + menu.items.append(contentsOf: [ + NSMenuItem.separator(), NSMenuItem(title: "检查更新", action: #selector(checkForUpdates(_:)), keyEquivalent: ""), NSMenuItem(title: "关于业火输入法", action: #selector(openAbout(_:)), keyEquivalent: "") - ] + ]) return menu } } From a46a3d724799161b17afefeff5bd52c59d79f581 Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Tue, 7 Nov 2023 13:32:49 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat(app):=20=E4=BF=9D=E6=8C=81=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E6=9C=80=E5=90=8E=E4=BD=BF=E7=94=A8=E7=9A=84=E8=BE=93?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E5=BC=8F=E7=8A=B6=E6=80=81=E6=8C=81=E4=B9=85?= =?UTF-8?q?=E5=8C=96=EF=BC=8C=E6=94=AF=E6=8C=81=E5=BA=94=E7=94=A8=E9=87=8D?= =?UTF-8?q?=E5=90=AF=E5=90=8E=E4=BB=8D=E8=83=BD=E8=8E=B7=E5=8F=96=E4=B9=8B?= =?UTF-8?q?=E5=89=8D=E7=9A=84=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire.xcodeproj/project.pbxproj | 4 ++ Fire/FireInputServer.swift | 10 ++--- Fire/InputModeCache.swift | 59 ++++++++++++++++++++++++++ Fire/Preferences/ApplicationPane.swift | 12 ++++-- Fire/PunctuationConversion.swift | 2 +- Fire/types.swift | 10 ++--- 6 files changed, 83 insertions(+), 14 deletions(-) create mode 100644 Fire/InputModeCache.swift diff --git a/Fire.xcodeproj/project.pbxproj b/Fire.xcodeproj/project.pbxproj index 8191421..32f2376 100644 --- a/Fire.xcodeproj/project.pbxproj +++ b/Fire.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 451A556A2AF9F92D00AF57C1 /* InputModeCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451A55692AF9F92D00AF57C1 /* InputModeCache.swift */; }; 45B76CA92AEA6042009AFABD /* PunctuationConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */; }; 6753419E2AB54A3A00757F76 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6753419D2AB54A3A00757F76 /* main.cpp */; }; 675341A72AB54AEA00757F76 /* sqlite3.c in Sources */ = {isa = PBXBuildFile; fileRef = 675341A52AB54AEA00757F76 /* sqlite3.c */; }; @@ -68,6 +69,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 451A55692AF9F92D00AF57C1 /* InputModeCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputModeCache.swift; sourceTree = ""; }; 45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PunctuationConversion.swift; sourceTree = ""; }; 6753419B2AB54A3A00757F76 /* TableBuilder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TableBuilder; sourceTree = BUILT_PRODUCTS_DIR; }; 6753419D2AB54A3A00757F76 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; @@ -207,6 +209,7 @@ 67C99FF82AB53E62000B5281 /* Utils */, 67C99FEB2AB53DB2000B5281 /* AppDelegate.swift */, 67C99FF22AB53DB4000B5281 /* Fire.entitlements */, + 451A55692AF9F92D00AF57C1 /* InputModeCache.swift */, ); path = Fire; sourceTree = ""; @@ -442,6 +445,7 @@ 67C9A0412AB53ED3000B5281 /* ThemePane.swift in Sources */, 67C9A03E2AB53ED3000B5281 /* UserDictPane.swift in Sources */, 67C9A03F2AB53ED3000B5281 /* GeneralPane.swift in Sources */, + 451A556A2AF9F92D00AF57C1 /* InputModeCache.swift in Sources */, 67C9A00E2AB53E83000B5281 /* Fire.swift in Sources */, 67C9A0102AB53E83000B5281 /* types.swift in Sources */, 67C99FFF2AB53E62000B5281 /* TipsWindow.swift in Sources */, diff --git a/Fire/FireInputServer.swift b/Fire/FireInputServer.swift index 32ba9ca..fdce668 100644 --- a/Fire/FireInputServer.swift +++ b/Fire/FireInputServer.swift @@ -9,8 +9,6 @@ import Foundation import Defaults -private var inputModeCache: [String: InputMode] = [:] - extension FireInputController { /** * 根据当前输入的应用改变输入模式 @@ -25,7 +23,7 @@ extension FireInputController { return currentMode != Fire.shared.inputMode } // 启用APP缓存设置 - if Defaults[.keepAppInputMode], let mode = inputModeCache[identifier] { + if Defaults[.keepAppInputMode], let mode = InputModeCache.shared.get(identifier) { NSLog("[FireInputController] activeClientInputMode from cache: \(identifier), \(mode)") Fire.shared.toggleInputMode(mode, showTip: false) return currentMode != Fire.shared.inputMode @@ -34,9 +32,11 @@ extension FireInputController { } private func savePreviousClientInputMode() { - if let identifier = CandidatesWindow.shared.inputController?.client()?.bundleIdentifier() { + if Defaults[.keepAppInputMode], + let identifier = CandidatesWindow.shared.inputController?.client()?.bundleIdentifier(), + Defaults[.appSettings][identifier] == nil { // 缓存当前输入模式 - inputModeCache.updateValue(inputMode, forKey: identifier) + InputModeCache.shared.put(identifier, inputMode) } } diff --git a/Fire/InputModeCache.swift b/Fire/InputModeCache.swift new file mode 100644 index 0000000..7bedc10 --- /dev/null +++ b/Fire/InputModeCache.swift @@ -0,0 +1,59 @@ +// +// InputModeCache.swift +// Fire +// +// Created by qwertyyb on 2023/11/7. +// +import Defaults + +class InputModeCache { + let capacity = 100 + private var cache: [String: InputMode] = [:] + private var keys: [String] = [] + + private init() { + loadFromUserDefaults() + } + + func get(_ key: String) -> InputMode? { + if let value = cache[key] { + updateKeyOrder(key) + return value + } + return nil + } + + func put(_ key: String, _ value: InputMode) { + if cache[key] == nil { + if keys.count >= capacity { + let oldestKey = keys.removeFirst() + cache[oldestKey] = nil + } + keys.append(key) + } else { + updateKeyOrder(key) + } + cache[key] = value + saveToUserDefaults() + } + + private func updateKeyOrder(_ key: String) { + if let index = keys.firstIndex(of: key) { + keys.remove(at: index) + keys.append(key) + saveToUserDefaults() + } + } + + private func saveToUserDefaults() { + Defaults[.keepAppInputMode_keys] = keys + Defaults[.keepAppInputMode_cache] = cache + } + + private func loadFromUserDefaults() { + keys = Defaults[.keepAppInputMode_keys] + cache = Defaults[.keepAppInputMode_cache] + } + + static let shared = InputModeCache() +} diff --git a/Fire/Preferences/ApplicationPane.swift b/Fire/Preferences/ApplicationPane.swift index d5c3bcc..a32a0e9 100644 --- a/Fire/Preferences/ApplicationPane.swift +++ b/Fire/Preferences/ApplicationPane.swift @@ -109,10 +109,16 @@ struct ApplicationPane: View { HStack { Text("自动切换") Toggle("保持应用最后使用的输入模式", isOn: $keepAppInputMode) - .padding(.leading, 12) + .padding(.leading, 10) } HStack { - Picker("显示提示", selection: $appInputModeTipShowTime) { + Text("仅保留最近使用的\(InputModeCache.shared.capacity)个应用的输入模式") + .font(.footnote) + .padding(.leading, 70) + } + HStack { + Text("显示提示") + Picker("", selection: $appInputModeTipShowTime) { Text("仅在变化时显示").tag(AppInputModeTipShowTime.onlyChanged) Text("总是显示").tag(AppInputModeTipShowTime.always) Text("不显示") @@ -130,7 +136,7 @@ struct ApplicationPane: View { Text("添加") } } - .padding(.leading, 12) + .padding(.leading, 8) } ScrollView(.vertical) { if appSettings.count > 0 { diff --git a/Fire/PunctuationConversion.swift b/Fire/PunctuationConversion.swift index 047d85a..eda280c 100644 --- a/Fire/PunctuationConversion.swift +++ b/Fire/PunctuationConversion.swift @@ -2,7 +2,7 @@ // PunctuationConversion.swift // Fire // -// Created by 杨永榜 on 2023/10/26. +// Created by qwertyyb on 2023/10/26. // import Foundation diff --git a/Fire/types.swift b/Fire/types.swift index 4c4fd5a..4100a9a 100644 --- a/Fire/types.swift +++ b/Fire/types.swift @@ -119,11 +119,11 @@ extension Defaults.Keys { // 应用输入配置 static let keepAppInputMode = Key("keepAppInputMode", default: true) + static let keepAppInputMode_keys = Key<[String]>("keepAppInputMode_keys", default: []) + static let keepAppInputMode_cache = Key<[String: InputMode]>("keepAppInputMode_cache", default: [:]) + static let appInputModeTipShowTime = Key("appInputModeTipShowTime", default: .onlyChanged) - static let appSettings = Key<[String: ApplicationSettingItem]>( - "AppSettings", - default: [:] - ) + static let appSettings = Key<[String: ApplicationSettingItem]>("AppSettings", default: [:]) // 标点符号配置 static let punctuationMode = Key("punctuationMode", default: PunctuationMode.zhhans) static let customPunctuationSettings = Key<[String: String]>("customPunctuationSettings", default: punctuation) @@ -145,7 +145,7 @@ extension Defaults.Keys { // Key Type UserDefaults name Default value } -enum InputMode: String { +enum InputMode: String, Defaults.Serializable { case zhhans case enUS } From 0b513933e42b24d65d1a73c482e836be1d070bbe Mon Sep 17 00:00:00 2001 From: qwertyyb Date: Thu, 9 Nov 2023 11:56:59 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=E8=80=83=E8=99=91=E5=88=B0=E4=BC=9A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BE=93=E5=85=A5=E8=B4=9F=E6=8B=85=EF=BC=8C?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E6=A8=A1=E5=BC=8F=E4=B8=8B=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=A4=A7=E5=86=99=E5=AD=97=E6=AF=8D=E6=97=B6=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E7=9B=B4=E6=8E=A5=E4=B8=8A=E5=B1=8F=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Fire/FireInputController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fire/FireInputController.swift b/Fire/FireInputController.swift index 993d28d..fd39ba5 100644 --- a/Fire/FireInputController.swift +++ b/Fire/FireInputController.swift @@ -186,7 +186,7 @@ class FireInputController: IMKInputController { // 获取输入的字符 let string = event.characters! - guard let reg = try? NSRegularExpression(pattern: "^[a-z]+$") else { + guard let reg = try? NSRegularExpression(pattern: "^[a-zA-Z]+$") else { return nil } let match = reg.firstMatch(