Merge pull request #236 from zonble/master

Adds a validator for candidate keys in the preference window.
This commit is contained in:
Lukhnos Liu 2022-01-16 08:11:09 -08:00 committed by GitHub
commit f2d3ca3c78
4 changed files with 100 additions and 44 deletions

View File

@ -146,36 +146,6 @@ struct ComposingBufferSize {
}
}
@propertyWrapper
struct ComposingKeys {
let key: String
let defaultValue: String? = kCandidateKeys
lazy var container: UserDefault = {
UserDefault(key: key, defaultValue: defaultValue) }()
var wrappedValue: String? {
mutating get {
let value = container.wrappedValue
if let value = value {
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
return nil
}
}
return value
}
set {
let value = newValue
if let value = value {
if value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
container.wrappedValue = nil
return
}
}
container.wrappedValue = value
}
}
}
// MARK: -
@objc enum KeyboardLayout: Int {
@ -293,12 +263,65 @@ class Preferences: NSObject {
@UserDefault(key: kCandidateKeyLabelFontName, defaultValue: nil)
@objc static var candidateKeyLabelFontName: String?
@ComposingKeys(key: kCandidateKeys)
@objc static var candidateKeys: String?
@UserDefault(key: kCandidateKeys, defaultValue: kDefaultKeys)
@objc static var candidateKeys: String
@objc static var defaultKeys: String {
@objc static var defaultCandidateKeys: String {
kDefaultKeys
}
@objc static var suggestedCandidateKeys: [String] {
[kDefaultKeys, "asdfghjkl", "asdfzxcvb"]
}
static func validate(candidateKeys: String) throws {
let trimmed = candidateKeys.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty {
throw CandidateKeyError.empty
}
if !trimmed.canBeConverted(to: .ascii) {
throw CandidateKeyError.invalidCharacters
}
if trimmed.contains(" ") {
throw CandidateKeyError.containSpace
}
if trimmed.count < 4 {
throw CandidateKeyError.tooShort
}
if trimmed.count > 15 {
throw CandidateKeyError.tooLong
}
let set = Set(Array(trimmed))
if set.count != trimmed.count {
throw CandidateKeyError.duplicatedCharacters
}
}
enum CandidateKeyError: Error, LocalizedError {
case empty
case invalidCharacters
case containSpace
case duplicatedCharacters
case tooShort
case tooLong
var errorDescription: String? {
switch self {
case .empty:
return NSLocalizedString("Candidates keys cannot be empty.", comment: "")
case .invalidCharacters:
return NSLocalizedString("Candidate keys can only contain latin characters and numbers.", comment: "")
case .containSpace:
return NSLocalizedString("Candidate keys cannot contain space.", comment: "")
case .duplicatedCharacters:
return NSLocalizedString("There should not be duplicated keys.", comment: "")
case .tooShort:
return NSLocalizedString("The length of your candidate keys can not be less than 4 characters.", comment: "")
case .tooLong:
return NSLocalizedString("The length of your candidate keys can not be larger than 15 characters.", comment: "")
}
}
}
@UserDefault(key: kPhraseReplacementEnabledKey, defaultValue: false)
@objc static var phraseReplacementEnabled: Bool

View File

@ -126,11 +126,11 @@ import Carbon
basisKeyboardLayoutButton.select(chosenItem ?? usKeyboardLayoutItem)
selectionKeyComboBox.usesDataSource = false
selectionKeyComboBox.removeAllItems()
selectionKeyComboBox.addItems(withObjectValues: [Preferences.defaultKeys, "asdfghjkl", "asdfzxcvb"])
selectionKeyComboBox.addItems(withObjectValues: Preferences.suggestedCandidateKeys)
var candidateSelectionKeys = Preferences.candidateKeys ?? Preferences.defaultKeys
var candidateSelectionKeys = Preferences.candidateKeys
if candidateSelectionKeys.isEmpty {
candidateSelectionKeys = Preferences.defaultKeys
candidateSelectionKeys = Preferences.defaultCandidateKeys
}
selectionKeyComboBox.stringValue = candidateSelectionKeys
@ -143,17 +143,25 @@ import Carbon
}
@IBAction func changeSelectionKeyAction(_ sender: Any) {
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
selectionKeyComboBox.stringValue = Preferences.defaultKeys
Preferences.candidateKeys = nil
NSSound.beep()
guard let keys = (sender as AnyObject).stringValue?.trimmingCharacters(in: .whitespacesAndNewlines) else {
return
}
selectionKeyComboBox.stringValue = keys
do {
try Preferences.validate(candidateKeys: keys)
Preferences.candidateKeys = keys
}
catch Preferences.CandidateKeyError.empty {
selectionKeyComboBox.stringValue = Preferences.candidateKeys
}
catch {
if let window = window {
let alert = NSAlert(error: error)
alert.beginSheetModal(for: window) { response in
self.selectionKeyComboBox.stringValue = Preferences.candidateKeys
}
}
}
}
}

View File

@ -76,3 +76,16 @@
"Edit Phrase Replacement Table" = "Edit Phrase Replacement Table";
"Use Phrase Replacement" = "Use Phrase Replacement";
"Candidates keys cannot be empty." = "Candidates keys cannot be empty.";
"Candidate keys can only contain latin characters and numbers." = "Candidate keys can only contain latin characters and numbers.";
"Candidate keys cannot contain space." = "Candidate keys cannot contain space.";
"There should not be duplicated keys." = "There should not be duplicated keys.";
"The length of your candidate keys can not be less than 4 characters." = "The length of your candidate keys can not be less than 4 characters.";
"The length of your candidate keys can not be larger than 15 characters." = "The length of your candidate keys can not be larger than 15 characters.";

View File

@ -76,3 +76,15 @@
"Edit Phrase Replacement Table" = "編輯詞彙替換表格";
"Use Phrase Replacement" = "使用詞彙替換";
"Candidates keys cannot be empty." = "選字鍵不可為空。";
"Candidate keys can only contain latin characters and numbers." = "選字鍵只可包含英數與半型標點。";
"Candidate keys cannot contain space." = "選字鍵不可包含空白。";
"There should not be duplicated keys." = "選字鍵中不可包含重複的字元。";
"The length of your candidate keys can not be less than 4 characters." = "選字按鍵數量不可小於 4。";
"The length of your candidate keys can not be larger than 15 characters." = "選字按鍵數量不可大於 15。";