Skip to content

Commit

Permalink
Merge pull request #122 from qwertyyb/feature/shift-key-up
Browse files Browse the repository at this point in the history
feat: 调短shift按键的检测时间,降低误触发概率;一键设置正在输入应用的预设输入模式
  • Loading branch information
qwertyyb authored Nov 10, 2023
2 parents 4bc0674 + 0b51393 commit 2ec5206
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 24 deletions.
8 changes: 6 additions & 2 deletions Fire.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand Down Expand Up @@ -68,6 +69,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
451A55692AF9F92D00AF57C1 /* InputModeCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputModeCache.swift; sourceTree = "<group>"; };
45B76CA82AEA6042009AFABD /* PunctuationConversion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PunctuationConversion.swift; sourceTree = "<group>"; };
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 = "<group>"; };
Expand Down Expand Up @@ -187,7 +189,6 @@
67C9A02D2AB53ED3000B5281 /* CandidatesWindow.swift */,
67C9A01D2AB53ED2000B5281 /* DictManager.swift */,
67C9A0142AB53ED2000B5281 /* en.lproj */,
67C9A01A2AB53ED2000B5281 /* FireMenu.swift */,
67C9A0192AB53ED2000B5281 /* Info.plist */,
67C9A0242AB53ED3000B5281 /* Preferences */,
67C9A01E2AB53ED3000B5281 /* Resources */,
Expand All @@ -196,8 +197,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 */,
Expand All @@ -207,6 +209,7 @@
67C99FF82AB53E62000B5281 /* Utils */,
67C99FEB2AB53DB2000B5281 /* AppDelegate.swift */,
67C99FF22AB53DB4000B5281 /* Fire.entitlements */,
451A55692AF9F92D00AF57C1 /* InputModeCache.swift */,
);
path = Fire;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down
2 changes: 1 addition & 1 deletion Fire/FireInputController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
11 changes: 6 additions & 5 deletions Fire/FireInputServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import Foundation
import Defaults

private var inputModeCache: [String: InputMode] = [:]

extension FireInputController {
/**
* 根据当前输入的应用改变输入模式
Expand All @@ -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
Expand All @@ -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)
}
}

Expand All @@ -63,6 +63,7 @@ extension FireInputController {
}
}
override func deactivateServer(_ sender: Any!) {
insertOriginText()
clean()
NSLog("[FireInputController] deactivate server: \(client()?.bundleIdentifier() ?? "no client deactivate")")
}
Expand Down
37 changes: 36 additions & 1 deletion Fire/FireMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Foundation
import AppKit
import Sparkle
import Defaults

extension FireInputController {
/* -- menu actions start -- */
Expand All @@ -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
}
}
59 changes: 59 additions & 0 deletions Fire/InputModeCache.swift
Original file line number Diff line number Diff line change
@@ -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()
}
25 changes: 17 additions & 8 deletions Fire/Preferences/ApplicationPane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -106,10 +109,16 @@ struct ApplicationPane: View {
HStack {
Text("自动切换")
Toggle("保持应用最后使用的输入模式", isOn: $keepAppInputMode)
.padding(.leading, 12)
.padding(.leading, 10)
}
HStack {
Text("仅保留最近使用的\(InputModeCache.shared.capacity)个应用的输入模式")
.font(.footnote)
.padding(.leading, 70)
}
HStack {
Picker("显示提示", selection: $appInputModeTipShowTime) {
Text("显示提示")
Picker("", selection: $appInputModeTipShowTime) {
Text("仅在变化时显示").tag(AppInputModeTipShowTime.onlyChanged)
Text("总是显示").tag(AppInputModeTipShowTime.always)
Text("不显示")
Expand All @@ -127,7 +136,7 @@ struct ApplicationPane: View {
Text("添加")
}
}
.padding(.leading, 12)
.padding(.leading, 8)
}
ScrollView(.vertical) {
if appSettings.count > 0 {
Expand Down
2 changes: 1 addition & 1 deletion Fire/PunctuationConversion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// PunctuationConversion.swift
// Fire
//
// Created by 杨永榜 on 2023/10/26.
// Created by qwertyyb on 2023/10/26.
//

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Fire/Utils/ModifierKeyUpChecker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ModifierKeyUpChecker {
}
}

private let delayInterval = 0.3
private let delayInterval = 0.2

private var lastTime: Date = Date()

Expand Down
10 changes: 5 additions & 5 deletions Fire/types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ extension Defaults.Keys {

// 应用输入配置
static let keepAppInputMode = Key<Bool>("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>("appInputModeTipShowTime", default: .onlyChanged)
static let appSettings = Key<[String: ApplicationSettingItem]>(
"AppSettings",
default: [:]
)
static let appSettings = Key<[String: ApplicationSettingItem]>("AppSettings", default: [:])
// 标点符号配置
static let punctuationMode = Key<PunctuationMode>("punctuationMode", default: PunctuationMode.zhhans)
static let customPunctuationSettings = Key<[String: String]>("customPunctuationSettings", default: punctuation)
Expand All @@ -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
}
Expand Down

0 comments on commit 2ec5206

Please sign in to comment.