spiegel-keyman/mac/KeymanSettings/Sources/Model/KeymanPackage.swift
Shawn Schantz af09f89bc9
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
feat(mac): add functions from removing keyboard
also added comments for Settings
renamed activeKeyboards to enabledKeyboards via
settings migration for Keyman 19
2026-04-27 15:47:16 -04:00

157 lines
4.4 KiB
Swift

/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by Shawn Schantz on 2026-02-24
*
* Wrapper object that represents a Keyman package as loaded from a .KMP file
* Mostly immutable, but can be marked as enabled/disabled
*
*/
import Foundation
import AppKit
// MARK: - Root
public class KeymanPackage: Identifiable, Hashable, Equatable {
static let defaultImage: NSImage? = {
var image: NSImage? = nil
if let imageUrl = Bundle.main.url(forResource: "SideImage", withExtension: "bmp") {
image = NSImage(contentsOf: imageUrl)
}
return image
}()
public var id = UUID()
let source: PackageSource
public var keyboards: [Keyboard]
// the URL of the directory in which the package is contained
public let sourceDirectoryUrl: URL
// the URL of the kmp.json file for the package
public let jsonFileUrl: URL
public let readmeFileUrl: URL?
public let graphicFileUrl: URL?
public let graphicImage: NSImage?
// computed properties for convenience
public var packageName: String {
return source.info.name.description
}
public var packageVersion: String {
return source.info.version.description
}
public var copyright: String? {
if let copy = source.info.copyright?.description {
return copy
} else {
return nil
}
}
init(packageSource: PackageSource) {
self.source = packageSource
self.sourceDirectoryUrl = packageSource.directoryUrl!
self.jsonFileUrl = packageSource.jsonFileUrl!
if let readmeFilename = packageSource.readmeFilename {
let fileUrl = sourceDirectoryUrl.appendingPathComponent(readmeFilename)
self.readmeFileUrl = fileUrl
} else {
self.readmeFileUrl = nil
}
self.graphicFileUrl = KeymanPackage.buildGraphicFileUrl(source: packageSource)
self.graphicImage = KeymanPackage.loadImage(imageUrl: self.graphicFileUrl)
var keyboardsArray = [Keyboard]()
if let keyboards = source.keyboards {
for keyboardSource in keyboards {
let keyboard = Keyboard(keyboardSource: keyboardSource, directoryUrl: self.sourceDirectoryUrl)
keyboardsArray.append(keyboard)
}
}
self.keyboards = keyboardsArray
// ConfigLogger.shared.testLogger.debug("package created for: \(packageSource.packageName)")
print("package created for: \(packageSource.packageName)")
}
public func isKeyboardEnabled(keyboardId: String) -> Bool {
var enabled = false
if let keyboard = self.keyboards.first(where: { $0.keyboardId == keyboardId }) {
enabled = keyboard.enabled
}
return enabled
}
public func enableKeyboard(keyboardId: String, enabled: Bool) {
let keyboard = self.keyboards.first(where: { $0.keyboardId == keyboardId })
if (keyboard != nil) {
keyboard!.enabled = enabled
}
}
public func getKeyboardSettingsKey(for keyboardId: String) -> String? {
guard let keyboard = self.keyboards.first(where: { $0.keyboardId == keyboardId }) else {
return nil
}
return keyboard.keyboardSettingsKey
}
public func getEnabledKeyboardsSettingsKeys() -> [String] {
var settingsKeyArray = [String]()
self.keyboards.forEach { keyboard in
if (keyboard.enabled) {
settingsKeyArray.append(keyboard.keyboardSettingsKey)
}
}
return settingsKeyArray
}
public func validate() -> Bool {
var validKeyboards = self.keyboards.isEmpty == false
self.keyboards.forEach { keyboard in
if (validKeyboards && !keyboard.validateKmxFile()) {
validKeyboards = false
}
}
return validKeyboards
}
static func buildGraphicFileUrl(source: PackageSource) -> URL? {
var fileUrl: URL? = nil
if let graphicFilename = source.graphicFilename {
fileUrl = source.directoryUrl!.appendingPathComponent(graphicFilename)
}
return fileUrl
}
static func loadImage(imageUrl: URL?) -> NSImage? {
var packageImage: NSImage? = nil;
if let fileUrl = imageUrl, let image = NSImage(contentsOf: fileUrl) {
packageImage = image
} else {
packageImage = KeymanPackage.defaultImage
}
return packageImage
}
public func hash(into hasher: inout Hasher) {
hasher.combine(id) // only combine the unique ID
}
// Custom Equatable conformance (required by Hashable)
public static func == (lhs: KeymanPackage, rhs: KeymanPackage) -> Bool {
return lhs.id == rhs.id // only compare unique IDs
}
}