Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions mac/Config/Config.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
D83272A82F57614400F71698 /* KeymanSettings in Frameworks */ = {isa = PBXBuildFile; productRef = D83272A72F57614400F71698 /* KeymanSettings */; };
D88B79CA30472B3B00F10D14 /* Sentry-Dynamic in Frameworks */ = {isa = PBXBuildFile; productRef = D88B79C930472B3B00F10D14 /* Sentry-Dynamic */; };
D8F10B623048F12A00C1E597 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D8F10B613048F12A00C1E597 /* Localizable.xcstrings */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -32,6 +33,7 @@
D88F03C62F50ED5000C02A31 /* Keyman Configuration.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Keyman Configuration.app"; sourceTree = BUILT_PRODUCTS_DIR; };
D88F03D32F50ED5100C02A31 /* ConfigTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ConfigTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D88F03DD2F50ED5100C02A31 /* ConfigUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ConfigUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D8F10B613048F12A00C1E597 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
Expand Down Expand Up @@ -95,6 +97,7 @@
D88F03BD2F50ED5000C02A31 = {
isa = PBXGroup;
children = (
D8F10B613048F12A00C1E597 /* Localizable.xcstrings */,
D87D6F492FAF95400083A95E /* Installation */,
D88F03C82F50ED5000C02A31 /* Config */,
D88F03E02F50ED5100C02A31 /* ConfigUITests */,
Expand Down Expand Up @@ -243,6 +246,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8F10B623048F12A00C1E597 /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -361,6 +365,7 @@
REGISTER_APP_GROUPS = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
Expand Down Expand Up @@ -419,6 +424,7 @@
REGISTER_APP_GROUPS = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
};
name = Release;
};
Expand Down
4 changes: 2 additions & 2 deletions mac/Config/Config/AddKeyboardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ struct AddKeyboardView: View {
.font(.headline)

// Native progress bar bound to the coordinator's value (0.0 to 1.0)
ProgressView(value: downloadCoordinator.downloadProgress, total: 1.0)
ProgressView(value: downloadCoordinator.downloadProgressFraction, total: 1.0)
.progressViewStyle(.linear)
.frame(width: 250)

Text("\(Int(downloadCoordinator.downloadProgress * 100))%")
Text(downloadCoordinator.downloadProgressFraction, format: .percent.precision(.fractionLength(0)))
.font(.body)
.foregroundColor(.secondary)
}
Expand Down
6 changes: 3 additions & 3 deletions mac/Config/Config/DownloadCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import OSLog
public class DownloadCoordinator: NSObject, ObservableObject, WKNavigationDelegate, WKDownloadDelegate {
@Published var isDownloading = false
// progress is between 0.0 and 1.0
@Published var downloadProgress: Double = 0.0
@Published var downloadProgressFraction: Double = 0.0

@Published var showConfirmPackageSheet = false
@Published var installHelper: PackageInstallHelper?
Expand Down Expand Up @@ -100,13 +100,13 @@ public class DownloadCoordinator: NSObject, ObservableObject, WKNavigationDelega

// reset progress states
self.isDownloading = true
self.downloadProgress = 0.0
self.downloadProgressFraction = 0.0

progressObserver = download.progress.observe(\.fractionCompleted, options: [.new]) { [weak self] _, change in
guard let newValue = change.newValue else { return }

Task { @MainActor [weak self] in
self?.downloadProgress = newValue
self?.downloadProgressFraction = newValue
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions mac/Config/Config/IconButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public struct IconButtonView: View {
let action: () -> Void
let systemImage: String
let font: Font
let helpText: String
let helpText: LocalizedStringKey

public var body: some View {

Expand All @@ -32,7 +32,7 @@ public struct IconButtonView: View {
// the view for buttons with a label
public struct LabelButtonView: View {
let action: () -> Void
let label: String
let label: LocalizedStringKey
let systemImage: String
let font: Font

Expand Down
58 changes: 43 additions & 15 deletions mac/Config/Config/InstallDebugView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
*
* Created by Shawn Schantz on 2026-02-26
*
* Main view used for configuring Keyman
* Test view used for configuring Keyman
* Not included in ConfigApp.swift, but can be added temporarily for testing purposes
* All text and labels are marked verbatim, so that they do not get extracted for localization
*/

import SwiftUI
Expand All @@ -18,60 +20,86 @@ struct InstallDebugView: View {
Image(systemName: "gear")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Current task = \(taskText)")
Text(verbatim: "Current task = \(taskText)")
.onAppear() {
if let installTask = installation.currentTask() {
taskText = installTask.taskType.rawValue
}
}
}
HStack {
Button("Next...") {
Button {
installation.executeCurrentInstallationTask()
if let installTask = installation.currentTask() {
taskText = installTask.taskType.rawValue
}
} label: {
Text(verbatim: "Next...")
}
.disabled(installation.isInstallationComplete())
Button("Migrate Data") {
Button {
_ = installation.migrateData()
} label: {
Text(verbatim: "Migrate Data")
}
Button("Register Keyman") {
Button {
_ = installation.registerKeymanInputMethod()
} label: {
Text(verbatim: "Register Keyman")
}
Button("Enable Keyman") {
Button {
_ = installation.enableKeymanInputMethod()
} label: {
Text(verbatim: "Enable Keyman")
}
Button("Select Keyman") {
Button {
_ = installation.selectKeymanInputMethod()
} label: {
Text(verbatim: "Select Keyman")
}
Button("Check Permission") {
Button {
installation.checkAccessibilityPermissionGranted()
} label: {
Text(verbatim: "Check Permission")
}
Button("Request Permission") {
Button {
_ = installation.requestAccessibility()
} label: {
Text(verbatim: "Request Permission")
}
Spacer()
}
.padding()
HStack {
Button("Request Restart") {
Button {
_ = installation.notifyUserPromptedToRestart()
} label: {
Text(verbatim: "Request Restart")
}
Button("Check Restart") {
Button {
_ = installation.validateUserHasRestarted()
} label: {
Text(verbatim: "Check Restart")
}
Button("Set Displayed Complete") {
Button {
installation.setHasDisplayedInstallationComplete()
} label: {
Text(verbatim: "Set Displayed Complete")
}
Button("debug") {
Button {
installation.debug()
} label: {
Text(verbatim: "debug")
}
Button("Disable Keyman") {
Button {
_ = installation.disableKeymanInputMethod()
} label: {
Text(verbatim: "Disable Keyman")
}
Button("Kill Keyman") {
Button {
_ = installation.killKeymanInputMethod()
} label: {
Text(verbatim: "Kill Keyman")
}
Spacer()
}
Expand Down
2 changes: 1 addition & 1 deletion mac/Config/Config/MainConfigView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ struct MainConfigView: View {
.dropDestination(for: URL.self) { urls, _ in
// reject drop if it is more than one file
guard let droppedFileUrl = urls.first, urls.count < 2 else {
let error = DropKmpError.tooManyFiles
let error = DropKmpError.exceededFileDropLimit
self.alertMessage = error.localizedDescription
self.isShowingDropKmpAlert = true
return false // the drop failed
Expand Down
141 changes: 141 additions & 0 deletions mac/Config/Localizable.xcstrings
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"sourceLanguage" : "en",
"strings" : {
"Access has not been granted." : {

},
"Add Keyboard" : {

},
"Are you sure you want to delete the Keyman package '%@'?" : {

},
"Author:" : {

},
"Cancel" : {

},
"Checking..." : {

},
"Close" : {

},
"Configuration" : {

},
"Continue" : {

},
"Copy link" : {

},
"Copyright:" : {

},
"Delete" : {

},
"Downloading File..." : {

},
"Enable" : {

},
"Enable Keyman" : {

},
"enabled" : {

},
"Ensure Keyman.app is set to provide it with necessary control in System Settings > Privacy & Security > Accessibility." : {

},
"Finish installation" : {

},
"Fonts:" : {

},
"Grant Accessibility Permission" : {

},
"Help" : {

},
"Help not available." : {

},
"Install" : {

},
"Installation" : {

},
"Installation complete" : {

},
"Keyboards" : {

},
"Missing Keyman Components" : {

},
"OK" : {

},
"One or more Keyman components or permissions require your attention. Complete the following steps to restore your Keyman installation." : {

},
"Open Settings" : {

},
"Package Installation Failed" : {

},
"Package Version:" : {

},
"Proceed to continue with installation" : {

},
"Read me not available." : {

},
"Remove Package" : {

},
"Repairs Required" : {

},
"Resolve Issues" : {

},
"Restart Computer" : {

},
"Restart your Mac to complete the installation. After restarting, open Keyman Configuration again if it doesn't launch automatically." : {

},
"Run Keyman installer" : {

},
"Share Keyboard" : {

},
"Show keyboard help" : {

},
"To use Keyman, enable the Keyman input method in System Settings." : {

},
"Website:" : {

},
"Your Keyman input method is either missing or outdated. Run the Keyman installer to install a new version." : {

}
},
"version" : "1.2"
}
1 change: 1 addition & 0 deletions mac/KeymanSettings/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import PackageDescription

let package = Package(
name: "KeymanSettings",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v13)
Expand Down
Loading