Repo // Checking J / K key validity as candidate keys.

This commit is contained in:
ShikiSuen 2024-02-12 01:08:20 +08:00
parent 072d39790e
commit 89d07b2edd
11 changed files with 50 additions and 11 deletions

View File

@ -193,6 +193,8 @@ public extension vChewingLM.LMCassette {
}
}
// Post process.
// Package 便 J / K
//
if CandidateKey.validate(keys: selectionKeys) != nil { selectionKeys = "1234567890" }
if !keysUsedInCharDef.intersection(selectionKeys.map(\.description)).isEmpty {
areCandidateKeysShiftHeld = true

View File

@ -323,7 +323,7 @@ import SwiftExtension
didSet {
let optimized = candidateKeys.lowercased().deduplicated
if candidateKeys != optimized { candidateKeys = optimized }
if CandidateKey.validate(keys: candidateKeys) != nil {
if validate(candidateKeys: candidateKeys) != nil {
candidateKeys = Self.kDefaultCandidateKeys
}
}

View File

@ -24,6 +24,15 @@ extension PrefMgr {
}
}
// MARK: Guarded Method for Validating Candidate Keys.
public extension PrefMgr {
func validate(candidateKeys: String) -> String? {
let excluded = useJKtoMoveCompositorCursorInCandidateState ? "jk" : ""
return CandidateKey.validate(keys: candidateKeys, excluding: excluded)
}
}
// MARK: Auto parameter fix procedures, executed everytime on SessionCtl.activateServer().
public extension PrefMgr {

View File

@ -149,7 +149,7 @@ extension SessionCtl: CtlCandidateDelegate {
cassetteQuick: if state.type == .ofInputting, state.isCandidateContainer {
guard PrefMgr.shared.cassetteEnabled else { break cassetteQuick }
guard let cinCandidateKey = inputMode.langModel.cassetteSelectionKey,
CandidateKey.validate(keys: cinCandidateKey) == nil
PrefMgr.shared.validate(candidateKeys: cinCandidateKey) == nil
else {
return "1234567890"
}

View File

@ -52,7 +52,11 @@ public extension SettingsPanesCocoa {
UserDef.kMoveCursorAfterSelectingCandidate.render(fixWidth: contentWidth)
UserDef.kUseDynamicCandidateWindowOrigin.render(fixWidth: contentWidth)
UserDef.kDodgeInvalidEdgeCandidateCursorPosition.render(fixWidth: contentWidth)
UserDef.kUseJKtoMoveCompositorCursorInCandidateState.render(fixWidth: contentWidth)
UserDef.kUseJKtoMoveCompositorCursorInCandidateState
.render(fixWidth: contentWidth) { renderable in
renderable.currentControl?.target = self
renderable.currentControl?.action = #selector(self.useJKToMoveBufferCursorDidSet(_:))
}
}?.boxed()
NSView()
}
@ -84,12 +88,17 @@ public extension SettingsPanesCocoa {
window.callAlert(title: title.localized, text: explanation.localized)
}
@IBAction func useJKToMoveBufferCursorDidSet(_: NSControl) {
// didSet
PrefMgr.shared.candidateKeys = PrefMgr.shared.candidateKeys
}
@IBAction func candidateKeysDidSet(_ sender: NSComboBox) {
let keys = sender.stringValue.trimmingCharacters(
in: .whitespacesAndNewlines
).lowercased().deduplicated
// Start Error Handling.
guard let errorResult = CandidateKey.validate(keys: keys) else {
guard let errorResult = PrefMgr.shared.validate(candidateKeys: keys) else {
PrefMgr.shared.candidateKeys = keys
return
}

View File

@ -69,7 +69,12 @@ public struct VwrSettingsPaneCandidates: View {
.disabled(useRearCursorMode)
}
UserDef.kDodgeInvalidEdgeCandidateCursorPosition.bind($dodgeInvalidEdgeCandidateCursorPosition).render()
UserDef.kUseJKtoMoveCompositorCursorInCandidateState.bind($useJKtoMoveCompositorCursorInCandidateState).render()
UserDef.kUseJKtoMoveCompositorCursorInCandidateState.bind(
$useJKtoMoveCompositorCursorInCandidateState.didChange {
// didSet
PrefMgr.shared.candidateKeys = PrefMgr.shared.candidateKeys
}
).render()
}
Section {
VwrSettingsPaneCandidates_SelectionKeys()
@ -144,7 +149,7 @@ private struct VwrSettingsPaneCandidates_SelectionKeys: View {
let value = candidateKeys
let keys = value.trimmingCharacters(in: .whitespacesAndNewlines).lowercased().deduplicated
// Start Error Handling.
if let errorResult = CandidateKey.validate(keys: keys) {
if let errorResult = PrefMgr.shared.validate(candidateKeys: keys) {
if let window = CtlSettingsUI.shared?.window, !keys.isEmpty {
IMEApp.buzz()
let alert = NSAlert(error: NSLocalizedString("Invalid Selection Keys.", comment: ""))

View File

@ -144,7 +144,7 @@ public enum KeyboardParser: Int, CaseIterable {
public enum CandidateKey {
public static var defaultKeys: String { suggestions[0] }
public static let suggestions: [String] = [
"123456", "123456789", "234567890", "QWERTYUIO", "QWERTASDF", "ASDFGHJKL", "ASDFZXCVB",
"123456", "123456789", "234567890", "QWERTYUIO", "QWERTASDF", "ASDFGH", "ASDFZXCVB",
]
///
@ -160,7 +160,11 @@ public enum CandidateKey {
+ NSLocalizedString(
"Candidate keys can only contain printable ASCII characters like alphanumericals.",
comment: ""
) + "\n" + "- " + NSLocalizedString("Candidate keys cannot contain space.", comment: "")
) + "\n" + "- " + NSLocalizedString(
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes", comment: ""
) + "\n" + "- " + NSLocalizedString(
"Candidate keys cannot contain space.", comment: ""
)
case .countMismatch:
return "- "
+ NSLocalizedString(
@ -177,12 +181,18 @@ public enum CandidateKey {
/// ```
/// .trimmingCharacters(in: .whitespacesAndNewlines).deduplicated
/// ```
/// - Parameter candidateKeys:
/// - Parameters:
/// - candidateKeys:
/// - excluding:
/// - Returns: nil
public static func validate(keys candidateKeys: String) -> String? {
public static func validate(
keys candidateKeys: String, excluding forbiddenChars: String = ""
) -> String? {
let candidateKeys = candidateKeys.lowercased()
let forbiddenChars = forbiddenChars.lowercased()
var result = ValidationError.noError
charValidityCheck: for neta in candidateKeys {
if String(neta) == " " {
if String(neta) == " " || forbiddenChars.contains(neta) {
result = CandidateKey.ValidationError.invalidCharacters
break charValidityCheck
}

View File

@ -195,6 +195,7 @@
"i18n:aboutWindow.LICENSE_TITLE" = "MIT-NTL License:";
"i18n:aboutWindow.OK_BUTTON" = "I Accept";
"i18n:aboutWindow.WEBSITE_BUTTON" = "Website";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "Candidates cannot have those keys who are assigned for other purposes.";
"i18n:securityAgentHelper.warningMessage.footer" = "When this message shows up, vChewing has already attempted to call DisableSecureEventInput() trying to make itself selectable in the input method menu again. Your suggested further steps:\n\n0. Keep a screenshot of this dialog (if you don't have one) for further purposes.\n\n1. If vChewing is still not selectable in the input method menu, you are suggested to manually terminate the processes listed above to force-release their SecureEventInput states. This will make vChewing available immediately.\n\n2. If the process belongs to an app from Mac App Store, please report its abuse of SecureEventInput to Apple. Apple may take actions to such apps if necessary, including pulling them off from the Mac App Store until the problem gets solved by the developers of such apps.\n\n3. Whether this process is from Mac App Store or not, you report this abuse to the related app vendor / developer. You may give them the screenshot of this alert message since it should have enough information to help the vendor / developer troubleshoot the issue.";
"i18n:securityAgentHelper.warningMessage.header" = "vChewing has detected that the following background processes are abusing the SecureEventInput, hindering all 3rd-party input methods from being able to switch to.\n\nIt is fine to use SecureEventInput for sensitive input fields. However, an app calling EnableSecureEventInput() is responsible to call DisableSecureEventInput() immediately right after the input field loses focus. This situation may also happen if an app is hanging in the background (or working as a helper application in the background) with its SecureEventInput left enabled.\n\nThe found processes are:";
"i18n:securityAgentHelper.warningMessage.title" = "SecureEventInput Abuse Detected";

View File

@ -195,6 +195,7 @@
"i18n:aboutWindow.LICENSE_TITLE" = "MIT商標不許可ライセンス (MIT-NTL License):";
"i18n:aboutWindow.OK_BUTTON" = "うむ";
"i18n:aboutWindow.WEBSITE_BUTTON" = "公式HP";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "他の用途に指定したキーは言選りには使えません。";
"i18n:securityAgentHelper.warningMessage.footer" = "このメッセージが出た時に、威注音がすでに「DisableSecureEventInput()」を実行してみました。これで入力ソースメニューで威注音は利用できる状態になったかもしれませんが、下記のステップはおすすめです:\n\nイ今のこのメッセージの画面のスクリーンショットを撮って置いてください。後ほど使えます。\n\nロもし、今でも入力ソースメニューで威注音は利用できぬ状態でしたら、上記のプロセスを強制中止してください。そうすれば、それぞれのSecureEventInput状態は解消できて、入力ソースメニューで威注音はすぐ利用できることになります。\n\nハもし、該当プロセスは Mac App Store のアプリからのものでしたら、該当アプリを Apple 社にご通報ください。状況と必要性次第、該当アプリは Mac App Store からしばらく取り下がて、支障解決まで Mac App Store 提供中止になるかもしれません。\n\nニ該当プロセスは Mac App Store からダウンロードしたものか否か、それぞれの開発元にこの支障をご通報ください。今のこのメッセージの画面のスクリーンショットを該当開発元に送れば、必要なる情報は該当開発元に全部お知らせすることができます。";
"i18n:securityAgentHelper.warningMessage.header" = "威注音入力アプリ略称「威注音」は「他のバックグラウンド・プロセスがSecureEventInputを正しく利用していない」と検出しました。このような不正利用は「システム内蔵入力以外の全ての入力アプリがメニューで灰色状態で選べなくて使えない」の元凶です。\n\nセンシティブな資料の記入どころでSecureEventInputをEnableSecureEventInput()で使うのは当然ですが、「入力中」状態が終わった後必ずDisableSecureEventInput()で状態解消すべきだと義務です。いくつかヘルパーアプリも、あるいはSecureEventInputを呼び起こしてからすぐ固まったアプリも、この状態になりやすいです。特に、他のアプリの画面へ切り替えたとしても、固まったアプリのSecureEventInput状態は自動的に解消できません。\n\n検出した該当プロセスは:";
"i18n:securityAgentHelper.warningMessage.title" = "SecureEventInput の不正利用が検出";

View File

@ -195,6 +195,7 @@
"i18n:aboutWindow.LICENSE_TITLE" = "麻理去商标授权合约 (MIT-NTL License):";
"i18n:aboutWindow.OK_BUTTON" = "确定";
"i18n:aboutWindow.WEBSITE_BUTTON" = "网站";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "无法将已挪作他用的按键设为选字键。";
"i18n:securityAgentHelper.warningMessage.footer" = "当这则讯息呈现出来的时候,威注音已经尝试呼叫 `DisableSecureEventInput()` 来试图解除这个状态。以下是威注音建议您采取的行动:\n\n0. 将这则讯息视窗留一份屏幕撷图、以备接下来的需要。\n\n1. 如果输入法选单内的威注音仍旧处于无法选取的状态(下文简称「灰色不可用状态」),则请考虑结束上述进程、以迫使其释放各自的 SecureEventInput 状态。这将立刻解除威注音的灰色不可用状态。\n\n2. 如果该进程所属的 App 来自于 Mac App Store 的话,请向 Apple 检举其对 SecureEventInput 的滥用。Apple 会在必要的情况下对这类 App 采取措施,比如:临时下架,直至软件开发者解决相关故障。\n\n3. 无论该进程是否来自于 Mac App Store也都请您向相关的开发者/提供方提报该故障。您可以将这则讯息的屏幕撷图给他们看,因为里面已经包含了用以检测该故障的必要资讯。";
"i18n:securityAgentHelper.warningMessage.header" = "威注音有检测到下述后台进程有在滥用 SecureEventInput。这种滥用会导致系统内的所有第三方输入法全都无法正常使用在输入法选单内会变成灰色。\n\n针对需要填写敏感数据的场合使用 SecureEventInput 无可厚非。但是,用 EnableSecureEventInput() 开启该模式之后,就有义务在输入窗格失焦的那一刻呼叫 DisableSecureEventInput() 来结束这种状态。这种状态还常见于后台辅助 App 当中、或者某个 App 在叫出该模式之后失去响应这样的话哪怕被切换到后台SecureEventInput 也不会自动解除)。\n\n被侦测到的进程如下:";
"i18n:securityAgentHelper.warningMessage.title" = "检测到对 SecureEventInput 的滥用行为";

View File

@ -195,6 +195,7 @@
"i18n:aboutWindow.LICENSE_TITLE" = "麻理去商標授權合約 (MIT-NTL License):";
"i18n:aboutWindow.OK_BUTTON" = "確定";
"i18n:aboutWindow.WEBSITE_BUTTON" = "網站";
"i18n:CandidateKey.ValidationError.AssignedForOtherPurposes" = "無法將已挪作他用的按鍵設為選字鍵。";
"i18n:securityAgentHelper.warningMessage.footer" = "當這則訊息呈現出來的時候,威注音已經嘗試呼叫 `DisableSecureEventInput()` 來試圖解除這個狀態。以下是威注音建議您採取的行動:\n\n0. 將這則訊息視窗留一份螢幕擷圖、以備接下來的需要。\n\n1. 如果輸入法選單內的威注音仍舊處於無法選取的狀態(下文簡稱「灰色不可用狀態」),則請考慮結束上述執行緒、以迫使其釋放各自的 SecureEventInput 狀態。這將立刻解除威注音的灰色不可用狀態。\n\n2. 如果該執行緒所屬的 App 來自於 Mac App Store 的話,請向 Apple 檢舉其對 SecureEventInput 的濫用。Apple 會在必要的情況下對這類 App 採取措施,比如:臨時下架,直至軟體研發方解決相關故障。\n\n3. 無論該執行緒是否來自於 Mac App Store也都請您向相關的研發方/提供方提報該故障。您可以將這則訊息的螢幕擷圖給他們看,因為裡面已經包含了用以偵測該故障的必要資訊。";
"i18n:securityAgentHelper.warningMessage.header" = "威注音有偵測到下述後檯執行緒有在濫用 SecureEventInput。這種濫用會導致系統內的所有第三方輸入法全都無法正常使用在輸入法選單內會變成灰色。\n\n針對需要填寫敏感資料的場合使用 SecureEventInput 無可厚非。但是,用 EnableSecureEventInput() 開啟該模式之後,就有義務在輸入窗格失焦的那一刻呼叫 DisableSecureEventInput() 來結束這種狀態。這種狀態還常見於後檯輔助 App 當中、或者某個 App 在叫出該模式之後失去回應這樣的話哪怕被切換到後檯SecureEventInput 也不會自動解除)。\n\n被偵測到的執行緒如下:";
"i18n:securityAgentHelper.warningMessage.title" = "偵測到對 SecureEventInput 的濫用行為";