mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-26 01:27:42 +00:00
change(ios/engine): usage of #3220's new typings, beter docs
This commit is contained in:
parent
3bf2d8f688
commit
315b2de2a0
7 changed files with 79 additions and 74 deletions
|
|
@ -11,7 +11,7 @@ import Foundation
|
|||
public class KeyboardKeymanPackage : TypedKeymanPackage<InstallableKeyboard> {
|
||||
internal var keyboards: [KMPKeyboard]!
|
||||
|
||||
override init(metadata: KMPMetadata, folder: URL) {
|
||||
override internal init(metadata: KMPMetadata, folder: URL) {
|
||||
super.init(metadata: metadata, folder: folder)
|
||||
self.keyboards = []
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,15 @@ public enum KMPError : String, Error {
|
|||
case resourceNotInPackage = "Resource cannot be found in specified package"
|
||||
}
|
||||
|
||||
/**
|
||||
* Common base class for the different KeymanPackage types.
|
||||
*/
|
||||
public class KeymanPackage {
|
||||
static private let kmpFile = "kmp.json"
|
||||
public let sourceFolder: URL
|
||||
internal let metadata: KMPMetadata
|
||||
|
||||
init(metadata: KMPMetadata, folder: URL) {
|
||||
internal init(metadata: KMPMetadata, folder: URL) {
|
||||
sourceFolder = folder
|
||||
self.metadata = metadata
|
||||
}
|
||||
|
|
@ -32,6 +35,21 @@ public class KeymanPackage {
|
|||
return metadata.packageType == .Keyboard
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of LanguageResource contained within the parsed Package.
|
||||
*/
|
||||
public func resourceType() -> LanguageResourceType {
|
||||
switch metadata.packageType {
|
||||
case .Keyboard:
|
||||
return .keyboard
|
||||
case .LexicalModel:
|
||||
return .lexicalModel
|
||||
default:
|
||||
// See KeymanPackage.parse below; an error is thrown there for case .Unsupported.
|
||||
fatalError("KeymanPackage.parse failed to block construction of unsupported KeymanPackage instance")
|
||||
}
|
||||
}
|
||||
|
||||
// to be overridden by subclasses
|
||||
public func defaultInfoHtml() -> String {
|
||||
return "base class!"
|
||||
|
|
@ -68,7 +86,13 @@ public class KeymanPackage {
|
|||
public var installableResourceSets: [[AnyLanguageResource]] {
|
||||
fatalError("abstract base method went unimplemented by derived class")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a decompressed KMP's metadata file, producing the typed KeymanPackage instance corresponding to it.
|
||||
*
|
||||
* Typecast the return value to either KeyboardKeymanPackage or LexicalModelKeymanPackage for richly-typed
|
||||
* information about the package's contents.
|
||||
*/
|
||||
static public func parse(_ folder: URL) -> KeymanPackage? {
|
||||
do {
|
||||
var path = folder
|
||||
|
|
@ -117,22 +141,6 @@ public class KeymanPackage {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func findMatch(_ resource: AnyLanguageResource) -> AnyLanguageResource? {
|
||||
let matchesFound: [AnyLanguageResource] = self.installableResourceSets.compactMap { set in
|
||||
let setMatches: [AnyLanguageResource] = set.compactMap { other in
|
||||
if resource.id == other.id && resource.languageID == other.languageID {
|
||||
return other
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return setMatches.count > 0 ? setMatches[0] : nil
|
||||
}
|
||||
|
||||
return matchesFound.count > 0 ? matchesFound[0] : nil
|
||||
}
|
||||
}
|
||||
|
||||
public class TypedKeymanPackage<TypedLanguageResource: LanguageResource>: KeymanPackage {
|
||||
|
|
@ -150,4 +158,20 @@ public class TypedKeymanPackage<TypedLanguageResource: LanguageResource>: Keyman
|
|||
public override var installableResourceSets: [[AnyLanguageResource]] {
|
||||
return installables
|
||||
}
|
||||
|
||||
public func findResource(withID fullID: TypedLanguageResource.FullID) -> TypedLanguageResource? {
|
||||
let matchesFound: [TypedLanguageResource] = self.installables.compactMap { set in
|
||||
let setMatches: [TypedLanguageResource] = set.compactMap { other in
|
||||
if fullID.id == other.id && fullID.languageID == other.languageID {
|
||||
return other
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return setMatches.count > 0 ? setMatches[0] : nil
|
||||
}
|
||||
|
||||
return matchesFound.count > 0 ? matchesFound[0] : nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import Foundation
|
|||
public class LexicalModelKeymanPackage : TypedKeymanPackage<InstallableLexicalModel> {
|
||||
internal var models : [KMPLexicalModel]!
|
||||
|
||||
override init(metadata: KMPMetadata, folder: URL) {
|
||||
override internal init(metadata: KMPMetadata, folder: URL) {
|
||||
super.init(metadata: metadata, folder: folder)
|
||||
self.models = []
|
||||
|
||||
|
|
|
|||
|
|
@ -619,7 +619,7 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
|
|||
|
||||
for resourceSet in kmp.installables {
|
||||
for resource in resourceSet {
|
||||
try ResourceFileManager.shared.install(resource, from: kmp)
|
||||
try ResourceFileManager.shared.install(resourceWithID: resource.fullID, from: kmp)
|
||||
// Install the keyboard for only the first language pairing defined in the package.
|
||||
break
|
||||
}
|
||||
|
|
@ -634,7 +634,7 @@ public class Manager: NSObject, UIGestureRecognizerDelegate {
|
|||
|
||||
try kmp.installables.forEach { resourceSet in
|
||||
try resourceSet.forEach { resource in
|
||||
try ResourceFileManager.shared.install(resource, from: kmp)
|
||||
try ResourceFileManager.shared.install(resourceWithID: resource.fullID, from: kmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,23 +179,15 @@ public class ResourceFileManager {
|
|||
}
|
||||
}
|
||||
|
||||
public func install(_ resourceToMatch: AnyLanguageResource, from package: KeymanPackage, usePackageDefinition: Bool = true) throws {
|
||||
public func install<ResourceType: LanguageResource,
|
||||
PackageType: TypedKeymanPackage<ResourceType>> (
|
||||
resourceWithID fullID: ResourceType.FullID,
|
||||
from package: PackageType) throws {
|
||||
|
||||
var res: AnyLanguageResource
|
||||
guard let r = package.findMatch(resourceToMatch) else {
|
||||
guard let resource = package.findResource(withID: fullID) else {
|
||||
throw KMPError.resourceNotInPackage
|
||||
}
|
||||
|
||||
if(usePackageDefinition) {
|
||||
res = r
|
||||
} else {
|
||||
// In case a KeymanEngine user wants a different definition than is in the source KMP.
|
||||
res = resourceToMatch
|
||||
}
|
||||
|
||||
// Now to lock down the reference, using 'let' to make it read-only.
|
||||
let resource = res
|
||||
|
||||
// (source, destination)
|
||||
var installableFiles: [(String, URL)] = [(resource.sourceFilename, Storage.active.resourceURL(for: resource)!)]
|
||||
let installableFonts: [(String, URL)] = resource.fonts.map { font in
|
||||
|
|
|
|||
|
|
@ -75,10 +75,13 @@ class FileManagementTests: XCTestCase {
|
|||
ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP) { kmp, error in
|
||||
XCTAssertNotNil(kmp, "Failed to prepare KMP for installation")
|
||||
XCTAssertNil(error, "Error occurred while preparing KMP for installation")
|
||||
XCTAssertNotNil(kmp as? KeyboardKeymanPackage, "KMP resource type improperly recognized - expected a keyboard package!")
|
||||
guard let kmp = kmp as? KeyboardKeymanPackage else {
|
||||
XCTFail("KMP resource type improperly recognized - expected a keyboard package!")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
try ResourceFileManager.shared.install(TestUtils.Keyboards.khmer_angkor, from: kmp!)
|
||||
try ResourceFileManager.shared.install(resourceWithID: TestUtils.Keyboards.khmer_angkor.fullID, from: kmp)
|
||||
} catch {
|
||||
XCTFail("Unexpected error during KeyboardPackage install")
|
||||
}
|
||||
|
|
@ -100,45 +103,17 @@ class FileManagementTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testInstallKeyboardFromPackageCustomDefinition() throws {
|
||||
// Modified installation - KeymanEngine user supplies external/literal definition for LanguageResource.
|
||||
// Separate test method b/c "tearDown()" cleans out installation artifacts from the other version.
|
||||
ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP) { kmp, error in
|
||||
XCTAssertNotNil(kmp, "Failed to prepare KMP for installation")
|
||||
XCTAssertNil(error, "Error occurred while preparing KMP for installation")
|
||||
XCTAssertNotNil(kmp as? KeyboardKeymanPackage, "KMP resource type improperly recognized - expected a keyboard package!")
|
||||
|
||||
do {
|
||||
try ResourceFileManager.shared.install(TestUtils.Keyboards.khmer_angkor, from: kmp!, usePackageDefinition: false)
|
||||
} catch {
|
||||
XCTFail("Unexpected error during KeyboardPackage install")
|
||||
}
|
||||
|
||||
let installURL = Storage.active.keyboardURL(forID: "khmer_angkor", version: "1.0.6")
|
||||
|
||||
XCTAssertTrue(FileManager.default.fileExists(atPath: installURL.path),
|
||||
"Could not find installed keyboard file")
|
||||
|
||||
let keyboards = Storage.active.userDefaults.userKeyboards!
|
||||
|
||||
XCTAssertEqual(keyboards.count, 1, "Unexpected number of keyboards were installed")
|
||||
XCTAssertEqual(keyboards[0].id, "khmer_angkor", "Installed keyboard ID mismatch")
|
||||
|
||||
// While the KMP's version of the specified InstallableKeyboard does specify Fonts,
|
||||
// the literal-based testing version does NOT. Since in this test, we're installing from the predefined, test-copy instance, we expect NOT to see the font from this test's install!
|
||||
let fontURL = Storage.active.fontURL(forKeyboardID: "khmer_angkor", filename: "Mondulkiri-R.ttf")
|
||||
XCTAssertFalse(FileManager.default.fileExists(atPath: fontURL.path))
|
||||
}
|
||||
}
|
||||
|
||||
func testInstallLexicalModelFromPackage() {
|
||||
ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.LexicalModels.mtntKMP) { kmp, error in
|
||||
XCTAssertNotNil(kmp, "Failed to prepare KMP for installation")
|
||||
XCTAssertNil(error, "Error occurred while preparing KMP for installation")
|
||||
XCTAssertNotNil(kmp as? LexicalModelKeymanPackage, "KMP resource type improperly recognized - expected a lexical model package!")
|
||||
guard let kmp = kmp as? LexicalModelKeymanPackage else {
|
||||
XCTFail("KMP resource type improperly recognized - expected a lexical model package!")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
try ResourceFileManager.shared.install(TestUtils.LexicalModels.mtnt, from: kmp!)
|
||||
try ResourceFileManager.shared.install(resourceWithID: TestUtils.LexicalModels.mtnt.fullID, from: kmp)
|
||||
} catch {
|
||||
XCTFail("Unexpected error during LexicalModelPackage install")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,13 +77,27 @@ class KeymanPackageTests: XCTestCase {
|
|||
|
||||
func testPackageFindResourceMatch() {
|
||||
ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.Keyboards.khmerAngkorKMP) { kmp, _ in
|
||||
XCTAssertNotNil(kmp!.findMatch(TestUtils.Keyboards.khmer_angkor))
|
||||
XCTAssertNil(kmp!.findMatch(TestUtils.LexicalModels.mtnt))
|
||||
guard let kmp = kmp as? KeyboardKeymanPackage else {
|
||||
XCTFail("Incorrect package type loaded for test")
|
||||
return
|
||||
}
|
||||
XCTAssertNotNil(kmp.findResource(withID: TestUtils.Keyboards.khmer_angkor.fullID))
|
||||
// This keyboard's not in the specified testing package.
|
||||
XCTAssertNil(kmp.findResource(withID: TestUtils.Keyboards.khmer10.fullID))
|
||||
|
||||
// Thanks to our package typing hierarchy, it's impossible to even TRY finding
|
||||
// a FullLexicalModelID within a KeyboardKeymanPackage!
|
||||
}
|
||||
|
||||
ResourceFileManager.shared.prepareKMPInstall(from: TestUtils.LexicalModels.mtntKMP) { kmp, _ in
|
||||
XCTAssertNotNil(kmp!.findMatch(TestUtils.LexicalModels.mtnt))
|
||||
XCTAssertNil(kmp!.findMatch(TestUtils.Keyboards.khmer_angkor))
|
||||
guard let kmp = kmp as? LexicalModelKeymanPackage else {
|
||||
XCTFail("Incorrect package type loaded for test")
|
||||
return
|
||||
}
|
||||
XCTAssertNotNil(kmp.findResource(withID: TestUtils.LexicalModels.mtnt.fullID))
|
||||
|
||||
// Thanks to our package typing hierarchy, it's impossible to even TRY finding
|
||||
// a FullKeyboardID within a LexicalModelKeymanPackage!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue