ServiceMenu // Filter some services if readings are unavailable.
This commit is contained in:
parent
9411686d03
commit
0107e7cd78
|
@ -69,6 +69,8 @@ public extension AppDelegate {
|
||||||
|
|
||||||
SpeechSputnik.shared.refreshStatus() // 根據現狀條件決定是否初期化語音引擎。
|
SpeechSputnik.shared.refreshStatus() // 根據現狀條件決定是否初期化語音引擎。
|
||||||
|
|
||||||
|
CandidateTextService.enableFinalSanityCheck()
|
||||||
|
|
||||||
// 一旦發現與使用者半衰模組的觀察行為有關的崩潰標記被開啟:
|
// 一旦發現與使用者半衰模組的觀察行為有關的崩潰標記被開啟:
|
||||||
// 如果有開啟 Debug 模式的話,就將既有的半衰記憶資料檔案更名+打上當時的時間戳。
|
// 如果有開啟 Debug 模式的話,就將既有的半衰記憶資料檔案更名+打上當時的時間戳。
|
||||||
// 如果沒有開啟 Debug 模式的話,則將半衰記憶資料直接清空。
|
// 如果沒有開啟 Debug 模式的話,則將半衰記憶資料直接清空。
|
||||||
|
|
|
@ -12,6 +12,28 @@ import Shared
|
||||||
import Tekkon
|
import Tekkon
|
||||||
|
|
||||||
public extension CandidateTextService {
|
public extension CandidateTextService {
|
||||||
|
// MARK: - Final Sanity Check Implementation.
|
||||||
|
|
||||||
|
static func enableFinalSanityCheck() {
|
||||||
|
finalSanityCheck = finalSanityCheckImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func finalSanityCheckImplemented(_ target: CandidateTextService) -> Bool {
|
||||||
|
switch target.value {
|
||||||
|
case .url: return true
|
||||||
|
case let .selector(strSelector):
|
||||||
|
guard target.candidateText != "%s" else { return true } // 防止誤傷到編輯器。
|
||||||
|
switch strSelector {
|
||||||
|
case "copyUnicodeMetadata:": return true
|
||||||
|
case _ where strSelector.hasPrefix("copyRuby"),
|
||||||
|
_ where strSelector.hasPrefix("copyBraille"),
|
||||||
|
_ where strSelector.hasPrefix("copyInline"):
|
||||||
|
return !target.reading.joined().isEmpty // 以便應對 [""] 的情況。
|
||||||
|
default: return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Selector Methods, CandidatePairServicable, and the Coordinator.
|
// MARK: - Selector Methods, CandidatePairServicable, and the Coordinator.
|
||||||
|
|
||||||
var responseFromSelector: String? {
|
var responseFromSelector: String? {
|
||||||
|
|
|
@ -24,6 +24,21 @@ class CandidateServiceCoordinatorTests: XCTestCase {
|
||||||
#"Braille 2018: %s"# + "\t" + #"@SEL:copyBraille2018:"#,
|
#"Braille 2018: %s"# + "\t" + #"@SEL:copyBraille2018:"#,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
func testSelector_FinalSanityCheck() throws {
|
||||||
|
var stacked = Self.testDataMap.parseIntoCandidateTextServiceStack(
|
||||||
|
candidate: "胡桃", reading: [] // 故意使用空 Reading
|
||||||
|
)
|
||||||
|
let count1 = stacked.count
|
||||||
|
print("Current Count before Sanity Check ON: \(stacked.count)")
|
||||||
|
CandidateTextService.enableFinalSanityCheck()
|
||||||
|
stacked = Self.testDataMap.parseIntoCandidateTextServiceStack(
|
||||||
|
candidate: "胡桃", reading: [] // 故意使用空 Reading
|
||||||
|
)
|
||||||
|
let count2 = stacked.count
|
||||||
|
print("Current Count after Sanity Check ON: \(stacked.count)")
|
||||||
|
XCTAssertGreaterThan(count1, count2)
|
||||||
|
}
|
||||||
|
|
||||||
func testSelector_UnicodeMetadata() throws {
|
func testSelector_UnicodeMetadata() throws {
|
||||||
let stacked = Self.testDataMap.parseIntoCandidateTextServiceStack(
|
let stacked = Self.testDataMap.parseIntoCandidateTextServiceStack(
|
||||||
candidate: "胡桃", reading: ["ㄏㄨˊ", "ㄊㄠˊ"]
|
candidate: "胡桃", reading: ["ㄏㄨˊ", "ㄊㄠˊ"]
|
||||||
|
|
|
@ -26,6 +26,8 @@ public struct CandidateTextService: Codable {
|
||||||
public let value: ServiceValue
|
public let value: ServiceValue
|
||||||
public let candidateText: String
|
public let candidateText: String
|
||||||
|
|
||||||
|
public static var finalSanityCheck: ((CandidateTextService) -> Bool)?
|
||||||
|
|
||||||
public init?(key: String, definedValue: String, param: String = #"%s"#, reading: [String] = []) {
|
public init?(key: String, definedValue: String, param: String = #"%s"#, reading: [String] = []) {
|
||||||
guard !key.isEmpty, !definedValue.isEmpty, definedValue.first != "#" else { return nil }
|
guard !key.isEmpty, !definedValue.isEmpty, definedValue.first != "#" else { return nil }
|
||||||
candidateText = param
|
candidateText = param
|
||||||
|
@ -62,6 +64,8 @@ public struct CandidateTextService: Codable {
|
||||||
}
|
}
|
||||||
guard let finalServiceValue = finalServiceValue else { return nil }
|
guard let finalServiceValue = finalServiceValue else { return nil }
|
||||||
value = finalServiceValue
|
value = finalServiceValue
|
||||||
|
let finalSanityCheckResult = Self.finalSanityCheck?(self) ?? true
|
||||||
|
if !finalSanityCheckResult { return nil }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue