From 5c77062bca1c3cf8d19f890444137e79a5de49bb Mon Sep 17 00:00:00 2001 From: sgschantz Date: Mon, 26 Jan 2026 10:50:41 -0500 Subject: [PATCH 01/17] maint(ios): build with Xcode 26 attempt build using swift packages instead of carthage --- ios/Cartfile | 4 - ios/Cartfile.resolved | 4 - .../KeymanEngine.xcodeproj/project.pbxproj | 103 +++++++++++--- ios/engine/build.sh | 25 ---- .../Keyman/Keyman.xcodeproj/project.pbxproj | 126 +++++++++++++----- .../xcshareddata/swiftpm/Package.resolved | 42 ++++++ 6 files changed, 213 insertions(+), 91 deletions(-) delete mode 100644 ios/Cartfile delete mode 100644 ios/Cartfile.resolved create mode 100644 ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/ios/Cartfile b/ios/Cartfile deleted file mode 100644 index 9ffc07d330..0000000000 --- a/ios/Cartfile +++ /dev/null @@ -1,4 +0,0 @@ -github "weichsel/ZIPFoundation" ~> 0.9 -github "devicekit/DeviceKit" ~> 5.0 -github "ashleymills/Reachability.swift" -github "getsentry/sentry-cocoa" ~> 8.38.0 diff --git a/ios/Cartfile.resolved b/ios/Cartfile.resolved deleted file mode 100644 index ca05da1ae9..0000000000 --- a/ios/Cartfile.resolved +++ /dev/null @@ -1,4 +0,0 @@ -github "ashleymills/Reachability.swift" "v5.2.4" -github "devicekit/DeviceKit" "5.5.0" -github "getsentry/sentry-cocoa" "8.44.0" -github "weichsel/ZIPFoundation" "0.9.19" diff --git a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj index 94dea1d5c7..387701c095 100644 --- a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj +++ b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj @@ -26,8 +26,11 @@ 1645D5972036C9F80076C51B /* KMPKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1645D5962036C9F80076C51B /* KMPKeyboard.swift */; }; 165EB3A12098993900040A69 /* KeyboardError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB3A02098993900040A69 /* KeyboardError.swift */; }; 29084CAB2CD48B5D004070E7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29084CAA2CD48B5D004070E7 /* Images.xcassets */; }; - 296EF2C72AFA26C700E3E384 /* ZIPFoundation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */; }; 29B30C232B564F9900C342A4 /* KeymanEngineLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B30C222B564F9900C342A4 /* KeymanEngineLogger.swift */; }; + 29C3F3F52F2525F7000D1C6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3F42F2525F7000D1C6F /* DeviceKit */; }; + 29C3F3F82F25261D000D1C6F /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3F72F25261D000D1C6F /* Reachability */; }; + 29C3F3FB2F25263C000D1C6F /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3FA2F25263C000D1C6F /* ZIPFoundation */; }; + 29C3F3FE2F2526B7000D1C6F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3FD2F2526B7000D1C6F /* Sentry */; }; 29E202BD2CCB7541008B4740 /* KeyboardHeightViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E202BC2CCB7541008B4740 /* KeyboardHeightViewController.swift */; }; 377D10DE26846B8900467431 /* SpacebarTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377D10DD26846B8900467431 /* SpacebarTextViewController.swift */; }; 6CD5DFAA150F6DC8007A5DDE /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 6CD5DFA8150F6DC8007A5DDE /* icon.png */; }; @@ -121,9 +124,6 @@ CE46D65D247B93C9005FD506 /* (null) in Resources */ = {isa = PBXBuildFile; }; CE5C8BE324B5B3BA00FAFB7F /* Queries+LexicalModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5C8BE224B5B3BA00FAFB7F /* Queries+LexicalModel.swift */; }; CE5C8BE524B5BD1C00FAFB7F /* QueryModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5C8BE424B5BD1C00FAFB7F /* QueryModelTests.swift */; }; - CE5EDDC726522EAA001733AC /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDC226522EAA001733AC /* Sentry.xcframework */; }; - CE5EDDC826522EAA001733AC /* Reachability.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDC326522EAA001733AC /* Reachability.xcframework */; }; - CE5EDDD52652372A001733AC /* DeviceKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */; }; CE67D961228A6F190029F2B5 /* KeyboardCommandStructs.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE67D960228A6F190029F2B5 /* KeyboardCommandStructs.swift */; }; CE71705823A9C14D00A924A1 /* ResourceFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE71705723A9C14D00A924A1 /* ResourceFileManager.swift */; }; CE71705F23A9C97F00A924A1 /* PackageInstallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE71705E23A9C97F00A924A1 /* PackageInstallViewController.swift */; }; @@ -307,7 +307,6 @@ 2949146F2738DA6700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/ResourceInfoView.strings"; sourceTree = ""; }; 294914702738DD7400400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/Localizable.strings"; sourceTree = ""; }; 294914712738DD9700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "ff-NG"; path = "ff-NG.lproj/Localizable.stringsdict"; sourceTree = ""; }; - 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ZIPFoundation.xcframework; path = ../../Carthage/Build/ZIPFoundation.xcframework; sourceTree = ""; }; 297810FE297FAEDF007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/ResourceInfoView.strings; sourceTree = ""; }; 297810FF297FAEF8007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/Localizable.strings; sourceTree = ""; }; 29781100297FAF06007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = kn; path = kn.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -433,9 +432,6 @@ CE4459D323FBBB34003151FD /* KeymanEngineTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeymanEngineTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; CE5C8BE224B5B3BA00FAFB7F /* Queries+LexicalModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Queries+LexicalModel.swift"; sourceTree = ""; }; CE5C8BE424B5BD1C00FAFB7F /* QueryModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryModelTests.swift; sourceTree = ""; }; - CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = DeviceKit.xcframework; path = ../../Carthage/Build/DeviceKit.xcframework; sourceTree = ""; }; - CE5EDDC226522EAA001733AC /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../../Carthage/Build/Sentry.xcframework; sourceTree = ""; }; - CE5EDDC326522EAA001733AC /* Reachability.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Reachability.xcframework; path = ../../Carthage/Build/Reachability.xcframework; sourceTree = ""; }; CE67D960228A6F190029F2B5 /* KeyboardCommandStructs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardCommandStructs.swift; sourceTree = ""; }; CE71705723A9C14D00A924A1 /* ResourceFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceFileManager.swift; sourceTree = ""; }; CE71705E23A9C97F00A924A1 /* PackageInstallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageInstallViewController.swift; sourceTree = ""; }; @@ -562,10 +558,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 296EF2C72AFA26C700E3E384 /* ZIPFoundation.xcframework in Frameworks */, - CE5EDDD52652372A001733AC /* DeviceKit.xcframework in Frameworks */, - CE5EDDC726522EAA001733AC /* Sentry.xcframework in Frameworks */, - CE5EDDC826522EAA001733AC /* Reachability.xcframework in Frameworks */, + 29C3F3F52F2525F7000D1C6F /* DeviceKit in Frameworks */, + 29C3F3F82F25261D000D1C6F /* Reachability in Frameworks */, + 29C3F3FB2F25263C000D1C6F /* ZIPFoundation in Frameworks */, + 29C3F3FE2F2526B7000D1C6F /* Sentry in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -949,10 +945,6 @@ F243888114BBD43000A3E055 /* Frameworks */ = { isa = PBXGroup; children = ( - 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */, - CE5EDDC326522EAA001733AC /* Reachability.xcframework */, - CE5EDDC226522EAA001733AC /* Sentry.xcframework */, - CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */, 9A079DE52231A69D00581263 /* Foundation.framework */, ); name = Frameworks; @@ -1221,6 +1213,12 @@ vi, ); mainGroup = F243887314BBD43000A3E055; + packageReferences = ( + 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */, + 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */, + 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */, + 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */, + ); productRefGroup = F243887F14BBD43000A3E055 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1889,7 +1887,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -1900,6 +1898,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -1945,7 +1944,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -1957,6 +1956,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -2108,7 +2108,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; + FRAMEWORK_SEARCH_PATHS = ""; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2140,7 +2140,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -2151,6 +2151,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -2383,7 +2384,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; + FRAMEWORK_SEARCH_PATHS = ""; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2426,7 +2427,7 @@ DEFINES_MODULE = YES; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; + FRAMEWORK_SEARCH_PATHS = ""; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2581,6 +2582,64 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/devicekit/DeviceKit.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.7.0; + }; + }; + 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ashleymills/Reachability.swift"; + requirement = { + branch = master; + kind = branch; + }; + }; + 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; + requirement = { + kind = exactVersion; + version = 0.9.20; + }; + }; + 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 9.2.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 29C3F3F42F2525F7000D1C6F /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; + 29C3F3F72F25261D000D1C6F /* Reachability */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */; + productName = Reachability; + }; + 29C3F3FA2F25263C000D1C6F /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; + 29C3F3FD2F2526B7000D1C6F /* Sentry */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = Sentry; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = F243887514BBD43000A3E055 /* Project object */; } diff --git a/ios/engine/build.sh b/ios/engine/build.sh index 39bd26118c..dc003db456 100755 --- a/ios/engine/build.sh +++ b/ios/engine/build.sh @@ -28,7 +28,6 @@ if builder_is_debug_build; then fi builder_describe_outputs \ - configure /ios/Carthage/Build \ build /ios/build/Build/Products/Release/KeymanEngine.xcframework # Base definitions (must be before do_clean call) @@ -58,29 +57,6 @@ fi function do_clean () { # Possible TODO: can we clean the engine target without also cleaning the app target? rm -rf "$BUILD_PATH" - rm -rf Carthage -} - -function carthage_die() { - local msg="$1" - - # Don't leave a trace of the failed folder; we'd have to rebuild stuff anyway. - # This way, a later re-run doesn't think `configure` succeeded when it did not. - rm -rf Carthage - builder_die "$1" -} - -function do_carthage() { - # Carthage setup must be handled from the directory with the Cartfile / Cartfile.resolved, it seems. - pushd .. > /dev/null - - carthage checkout || carthage_die "Carthage dependency checkout failed" - - # --no-use-binaries: due to https://github.com/Carthage/Carthage/issues/3134, - # which affects the sentry-cocoa dependency. - carthage build --use-xcframeworks --no-use-binaries --platform iOS || carthage_die "Carthage dependency loading failed" - - popd > /dev/null } function do_packages() { @@ -92,7 +68,6 @@ function do_packages() { function do_configure ( ) { do_packages - do_carthage } # Manages KeymanEngine.bundle, which is included inside the :engine target. diff --git a/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj b/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj index 7292a3f91d..9997aadfaf 100644 --- a/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj +++ b/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj @@ -14,9 +14,11 @@ 162E2C9F2092D36800F40769 /* UIDevice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 162E2C9E2092D36800F40769 /* UIDevice+Extensions.swift */; }; 165EB39A2097165B00040A69 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB3992097165B00040A69 /* UIColor+Extensions.swift */; }; 165EB39C2097181D00040A69 /* KMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB39B2097181D00040A69 /* KMView.swift */; }; - 296EF2C42AFA267500E3E384 /* ZIPFoundation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */; }; - 296EF2C52AFA267500E3E384 /* ZIPFoundation.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 29B30C212B56325D00C342A4 /* KeymanLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29CA9A612B4F9B0B00EAB099 /* KeymanLogger.swift */; }; + 29C3F4012F2526CA000D1C6F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4002F2526CA000D1C6F /* Sentry */; }; + 29C3F4042F2526E5000D1C6F /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4032F2526E5000D1C6F /* ZIPFoundation */; }; + 29C3F4072F2526F2000D1C6F /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4062F2526F2000D1C6F /* Reachability */; }; + 29C3F40A2F25270A000D1C6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4092F25270A000D1C6F /* DeviceKit */; }; 29CA9A622B4F9B0B00EAB099 /* KeymanLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29CA9A612B4F9B0B00EAB099 /* KeymanLogger.swift */; }; 981AFA8F19EF44DE006706BF /* 724-info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9815725518E4F0930014DF0C /* 724-info@2x.png */; }; 981AFA9619EF44DE006706BF /* MainViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98ABADCE176935E500B62590 /* MainViewController_iPhone.xib */; }; @@ -148,12 +150,6 @@ CE80AD33257F2B4A008D2150 /* KeymanEngine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; }; CE80AD34257F2B4B008D2150 /* KeymanEngine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CEBD34322654FE3500EB2EA8 /* KeymanEngine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; }; - CEBD343B2654FEB400EB2EA8 /* DeviceKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */; }; - CEBD343C2654FEB400EB2EA8 /* DeviceKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - CEBD343F2654FEB400EB2EA8 /* Reachability.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */; }; - CEBD34402654FEB400EB2EA8 /* Reachability.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - CEBD34412654FEB400EB2EA8 /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */; }; - CEBD34422654FEB400EB2EA8 /* Sentry.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CEF4E55623E95B7B0065B9C7 /* ImageBanner.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEF4E55523E95B7B0065B9C7 /* ImageBanner.xib */; }; CEF4E55723E95B7B0065B9C7 /* ImageBanner.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEF4E55523E95B7B0065B9C7 /* ImageBanner.xib */; }; CEF4E55923E967140065B9C7 /* ImageBannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF4E55823E967140065B9C7 /* ImageBannerViewController.swift */; }; @@ -178,10 +174,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - CEBD34402654FEB400EB2EA8 /* Reachability.xcframework in Embed Frameworks */, - 296EF2C52AFA267500E3E384 /* ZIPFoundation.xcframework in Embed Frameworks */, - CEBD343C2654FEB400EB2EA8 /* DeviceKit.xcframework in Embed Frameworks */, - CEBD34422654FEB400EB2EA8 /* Sentry.xcframework in Embed Frameworks */, CE80AD34257F2B4B008D2150 /* KeymanEngine.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -200,7 +192,6 @@ 16A9229D20325253003CC98E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Keyman/Info.plist; sourceTree = SOURCE_ROOT; }; 293EA3E027059C6900545EED /* ha */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ha; path = ha.lproj/Localizable.strings; sourceTree = ""; }; 294914742738DF7700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/Localizable.strings"; sourceTree = ""; }; - 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ZIPFoundation.xcframework; path = ../../Carthage/Build/ZIPFoundation.xcframework; sourceTree = ""; }; 297810FD297FA818007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/Localizable.strings; sourceTree = ""; }; 298566B829802828004ACA95 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 298566C42980C493004ACA95 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; @@ -336,9 +327,6 @@ CEACC90E25F07D58006EAB45 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; CEACC90F25F07D5A006EAB45 /* km */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = km; path = km.lproj/Localizable.strings; sourceTree = ""; }; CEACC91225F07D77006EAB45 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = DeviceKit.xcframework; path = ../../Carthage/Build/DeviceKit.xcframework; sourceTree = ""; }; - CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Reachability.xcframework; path = ../../Carthage/Build/Reachability.xcframework; sourceTree = ""; }; - CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../../Carthage/Build/Sentry.xcframework; sourceTree = ""; }; CEBD3458265511B700EB2EA8 /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/Localizable.strings; sourceTree = ""; }; CEEC468226F2F7BA009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; CEEF81B92673019600EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; @@ -352,11 +340,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CEBD343F2654FEB400EB2EA8 /* Reachability.xcframework in Frameworks */, - 296EF2C42AFA267500E3E384 /* ZIPFoundation.xcframework in Frameworks */, - CEBD343B2654FEB400EB2EA8 /* DeviceKit.xcframework in Frameworks */, - CEBD34412654FEB400EB2EA8 /* Sentry.xcframework in Frameworks */, CE80AD33257F2B4A008D2150 /* KeymanEngine.framework in Frameworks */, + 29C3F40A2F25270A000D1C6F /* DeviceKit in Frameworks */, + 29C3F4072F2526F2000D1C6F /* Reachability in Frameworks */, + 29C3F4012F2526CA000D1C6F /* Sentry in Frameworks */, + 29C3F4042F2526E5000D1C6F /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -537,10 +525,6 @@ 98ABADB2176935E400B62590 /* Frameworks */ = { isa = PBXGroup; children = ( - 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */, - CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */, - CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */, - CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */, CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */, ); name = Frameworks; @@ -799,6 +783,12 @@ vi, ); mainGroup = 98ABADA7176935E400B62590; + packageReferences = ( + 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */, + 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */, + 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */, + 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */, + ); productRefGroup = 98ABADB1176935E400B62590 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1127,9 +1117,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -1147,6 +1139,7 @@ PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; @@ -1163,9 +1156,11 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; INFOPLIST_FILE = Keyman/Info.plist; @@ -1181,6 +1176,7 @@ PRODUCT_NAME = Keyman; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Distribution"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; @@ -1220,10 +1216,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(PROJECT_DIR)", - "$(SRCROOT)/../../Carthage/Build/", - ); + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1275,10 +1268,7 @@ COPY_PHASE_STRIP = YES; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(PROJECT_DIR)", - "$(SRCROOT)/../../Carthage/Build/", - ); + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1309,8 +1299,10 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 3YE4W86L3G; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1336,6 +1328,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development SWKeyboard"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution SWKeyboard"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1419,10 +1412,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(PROJECT_DIR)", - "$(SRCROOT)/../../Carthage/Build/", - ); + FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1452,9 +1442,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -1472,6 +1464,7 @@ PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; @@ -1490,8 +1483,10 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 3YE4W86L3G; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1517,6 +1512,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development SWKeyboard"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution SWKeyboard"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1561,6 +1557,64 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 9.2.0; + }; + }; + 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; + requirement = { + kind = exactVersion; + version = 0.9.20; + }; + }; + 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/ashleymills/Reachability.swift"; + requirement = { + branch = master; + kind = branch; + }; + }; + 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/devicekit/DeviceKit.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.7.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 29C3F4002F2526CA000D1C6F /* Sentry */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */; + productName = Sentry; + }; + 29C3F4032F2526E5000D1C6F /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; + 29C3F4062F2526F2000D1C6F /* Reachability */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */; + productName = Reachability; + }; + 29C3F4092F25270A000D1C6F /* DeviceKit */ = { + isa = XCSwiftPackageProductDependency; + package = 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */; + productName = DeviceKit; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 98ABADA8176935E400B62590 /* Project object */; } diff --git a/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000000..8f79325601 --- /dev/null +++ b/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,42 @@ +{ + "originHash" : "a373bd824b59e33f7208114e4d77d167cc3f88776f323dd66ef0d5e716c837af", + "pins" : [ + { + "identity" : "devicekit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/devicekit/DeviceKit.git", + "state" : { + "revision" : "581df61650bc457ec00373a592a84be3e7468eb1", + "version" : "5.7.0" + } + }, + { + "identity" : "reachability.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ashleymills/Reachability.swift", + "state" : { + "branch" : "master", + "revision" : "21d1dc412cfecbe6e34f1f4c4eb88d3f912654a6" + } + }, + { + "identity" : "sentry-cocoa", + "kind" : "remoteSourceControl", + "location" : "https://github.com/getsentry/sentry-cocoa.git", + "state" : { + "revision" : "de66bd4fa0661c81455e8ad2509ed6f0e39025dc", + "version" : "9.2.0" + } + }, + { + "identity" : "zipfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weichsel/ZIPFoundation.git", + "state" : { + "revision" : "22787ffb59de99e5dc1fbfe80b19c97a904ad48d", + "version" : "0.9.20" + } + } + ], + "version" : 3 +} From de81102da2331f8bc27d8af79d59f710b5edbe70 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Mon, 26 Jan 2026 12:36:35 -0500 Subject: [PATCH 02/17] chore(ios): Revert "maint(ios): build with Xcode 26" This reverts commit 5c77062bca1c3cf8d19f890444137e79a5de49bb. --- ios/Cartfile | 4 + ios/Cartfile.resolved | 4 + .../KeymanEngine.xcodeproj/project.pbxproj | 103 +++----------- ios/engine/build.sh | 25 ++++ .../Keyman/Keyman.xcodeproj/project.pbxproj | 126 +++++------------- .../xcshareddata/swiftpm/Package.resolved | 42 ------ 6 files changed, 91 insertions(+), 213 deletions(-) create mode 100644 ios/Cartfile create mode 100644 ios/Cartfile.resolved delete mode 100644 ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/ios/Cartfile b/ios/Cartfile new file mode 100644 index 0000000000..9ffc07d330 --- /dev/null +++ b/ios/Cartfile @@ -0,0 +1,4 @@ +github "weichsel/ZIPFoundation" ~> 0.9 +github "devicekit/DeviceKit" ~> 5.0 +github "ashleymills/Reachability.swift" +github "getsentry/sentry-cocoa" ~> 8.38.0 diff --git a/ios/Cartfile.resolved b/ios/Cartfile.resolved new file mode 100644 index 0000000000..ca05da1ae9 --- /dev/null +++ b/ios/Cartfile.resolved @@ -0,0 +1,4 @@ +github "ashleymills/Reachability.swift" "v5.2.4" +github "devicekit/DeviceKit" "5.5.0" +github "getsentry/sentry-cocoa" "8.44.0" +github "weichsel/ZIPFoundation" "0.9.19" diff --git a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj index 387701c095..94dea1d5c7 100644 --- a/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj +++ b/ios/engine/KMEI/KeymanEngine.xcodeproj/project.pbxproj @@ -26,11 +26,8 @@ 1645D5972036C9F80076C51B /* KMPKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1645D5962036C9F80076C51B /* KMPKeyboard.swift */; }; 165EB3A12098993900040A69 /* KeyboardError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB3A02098993900040A69 /* KeyboardError.swift */; }; 29084CAB2CD48B5D004070E7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 29084CAA2CD48B5D004070E7 /* Images.xcassets */; }; + 296EF2C72AFA26C700E3E384 /* ZIPFoundation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */; }; 29B30C232B564F9900C342A4 /* KeymanEngineLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29B30C222B564F9900C342A4 /* KeymanEngineLogger.swift */; }; - 29C3F3F52F2525F7000D1C6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3F42F2525F7000D1C6F /* DeviceKit */; }; - 29C3F3F82F25261D000D1C6F /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3F72F25261D000D1C6F /* Reachability */; }; - 29C3F3FB2F25263C000D1C6F /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3FA2F25263C000D1C6F /* ZIPFoundation */; }; - 29C3F3FE2F2526B7000D1C6F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F3FD2F2526B7000D1C6F /* Sentry */; }; 29E202BD2CCB7541008B4740 /* KeyboardHeightViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29E202BC2CCB7541008B4740 /* KeyboardHeightViewController.swift */; }; 377D10DE26846B8900467431 /* SpacebarTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377D10DD26846B8900467431 /* SpacebarTextViewController.swift */; }; 6CD5DFAA150F6DC8007A5DDE /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 6CD5DFA8150F6DC8007A5DDE /* icon.png */; }; @@ -124,6 +121,9 @@ CE46D65D247B93C9005FD506 /* (null) in Resources */ = {isa = PBXBuildFile; }; CE5C8BE324B5B3BA00FAFB7F /* Queries+LexicalModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5C8BE224B5B3BA00FAFB7F /* Queries+LexicalModel.swift */; }; CE5C8BE524B5BD1C00FAFB7F /* QueryModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE5C8BE424B5BD1C00FAFB7F /* QueryModelTests.swift */; }; + CE5EDDC726522EAA001733AC /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDC226522EAA001733AC /* Sentry.xcframework */; }; + CE5EDDC826522EAA001733AC /* Reachability.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDC326522EAA001733AC /* Reachability.xcframework */; }; + CE5EDDD52652372A001733AC /* DeviceKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */; }; CE67D961228A6F190029F2B5 /* KeyboardCommandStructs.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE67D960228A6F190029F2B5 /* KeyboardCommandStructs.swift */; }; CE71705823A9C14D00A924A1 /* ResourceFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE71705723A9C14D00A924A1 /* ResourceFileManager.swift */; }; CE71705F23A9C97F00A924A1 /* PackageInstallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE71705E23A9C97F00A924A1 /* PackageInstallViewController.swift */; }; @@ -307,6 +307,7 @@ 2949146F2738DA6700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/ResourceInfoView.strings"; sourceTree = ""; }; 294914702738DD7400400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/Localizable.strings"; sourceTree = ""; }; 294914712738DD9700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "ff-NG"; path = "ff-NG.lproj/Localizable.stringsdict"; sourceTree = ""; }; + 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ZIPFoundation.xcframework; path = ../../Carthage/Build/ZIPFoundation.xcframework; sourceTree = ""; }; 297810FE297FAEDF007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/ResourceInfoView.strings; sourceTree = ""; }; 297810FF297FAEF8007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/Localizable.strings; sourceTree = ""; }; 29781100297FAF06007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = kn; path = kn.lproj/Localizable.stringsdict; sourceTree = ""; }; @@ -432,6 +433,9 @@ CE4459D323FBBB34003151FD /* KeymanEngineTestHost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeymanEngineTestHost.app; sourceTree = BUILT_PRODUCTS_DIR; }; CE5C8BE224B5B3BA00FAFB7F /* Queries+LexicalModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Queries+LexicalModel.swift"; sourceTree = ""; }; CE5C8BE424B5BD1C00FAFB7F /* QueryModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryModelTests.swift; sourceTree = ""; }; + CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = DeviceKit.xcframework; path = ../../Carthage/Build/DeviceKit.xcframework; sourceTree = ""; }; + CE5EDDC226522EAA001733AC /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../../Carthage/Build/Sentry.xcframework; sourceTree = ""; }; + CE5EDDC326522EAA001733AC /* Reachability.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Reachability.xcframework; path = ../../Carthage/Build/Reachability.xcframework; sourceTree = ""; }; CE67D960228A6F190029F2B5 /* KeyboardCommandStructs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardCommandStructs.swift; sourceTree = ""; }; CE71705723A9C14D00A924A1 /* ResourceFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceFileManager.swift; sourceTree = ""; }; CE71705E23A9C97F00A924A1 /* PackageInstallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PackageInstallViewController.swift; sourceTree = ""; }; @@ -558,10 +562,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 29C3F3F52F2525F7000D1C6F /* DeviceKit in Frameworks */, - 29C3F3F82F25261D000D1C6F /* Reachability in Frameworks */, - 29C3F3FB2F25263C000D1C6F /* ZIPFoundation in Frameworks */, - 29C3F3FE2F2526B7000D1C6F /* Sentry in Frameworks */, + 296EF2C72AFA26C700E3E384 /* ZIPFoundation.xcframework in Frameworks */, + CE5EDDD52652372A001733AC /* DeviceKit.xcframework in Frameworks */, + CE5EDDC726522EAA001733AC /* Sentry.xcframework in Frameworks */, + CE5EDDC826522EAA001733AC /* Reachability.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -945,6 +949,10 @@ F243888114BBD43000A3E055 /* Frameworks */ = { isa = PBXGroup; children = ( + 296EF2C62AFA26C700E3E384 /* ZIPFoundation.xcframework */, + CE5EDDC326522EAA001733AC /* Reachability.xcframework */, + CE5EDDC226522EAA001733AC /* Sentry.xcframework */, + CE5EDDBB26522EA3001733AC /* DeviceKit.xcframework */, 9A079DE52231A69D00581263 /* Foundation.framework */, ); name = Frameworks; @@ -1213,12 +1221,6 @@ vi, ); mainGroup = F243887314BBD43000A3E055; - packageReferences = ( - 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */, - 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */, - 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */, - 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */, - ); productRefGroup = F243887F14BBD43000A3E055 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1887,7 +1889,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -1898,7 +1900,6 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -1944,7 +1945,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -1956,7 +1957,6 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; ENABLE_NS_ASSERTIONS = NO; - FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; @@ -2108,7 +2108,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2140,7 +2140,7 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; @@ -2151,7 +2151,6 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ""; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -2384,7 +2383,7 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2427,7 +2426,7 @@ DEFINES_MODULE = YES; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../../Carthage/Build/"; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; @@ -2582,64 +2581,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCRemoteSwiftPackageReference section */ - 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/devicekit/DeviceKit.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 5.7.0; - }; - }; - 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/ashleymills/Reachability.swift"; - requirement = { - branch = master; - kind = branch; - }; - }; - 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; - requirement = { - kind = exactVersion; - version = 0.9.20; - }; - }; - 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 9.2.0; - }; - }; -/* End XCRemoteSwiftPackageReference section */ - -/* Begin XCSwiftPackageProductDependency section */ - 29C3F3F42F2525F7000D1C6F /* DeviceKit */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F3F32F2525F7000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */; - productName = DeviceKit; - }; - 29C3F3F72F25261D000D1C6F /* Reachability */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F3F62F25261D000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */; - productName = Reachability; - }; - 29C3F3FA2F25263C000D1C6F /* ZIPFoundation */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F3F92F25263C000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */; - productName = ZIPFoundation; - }; - 29C3F3FD2F2526B7000D1C6F /* Sentry */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F3FC2F2526B7000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */; - productName = Sentry; - }; -/* End XCSwiftPackageProductDependency section */ }; rootObject = F243887514BBD43000A3E055 /* Project object */; } diff --git a/ios/engine/build.sh b/ios/engine/build.sh index dc003db456..39bd26118c 100755 --- a/ios/engine/build.sh +++ b/ios/engine/build.sh @@ -28,6 +28,7 @@ if builder_is_debug_build; then fi builder_describe_outputs \ + configure /ios/Carthage/Build \ build /ios/build/Build/Products/Release/KeymanEngine.xcframework # Base definitions (must be before do_clean call) @@ -57,6 +58,29 @@ fi function do_clean () { # Possible TODO: can we clean the engine target without also cleaning the app target? rm -rf "$BUILD_PATH" + rm -rf Carthage +} + +function carthage_die() { + local msg="$1" + + # Don't leave a trace of the failed folder; we'd have to rebuild stuff anyway. + # This way, a later re-run doesn't think `configure` succeeded when it did not. + rm -rf Carthage + builder_die "$1" +} + +function do_carthage() { + # Carthage setup must be handled from the directory with the Cartfile / Cartfile.resolved, it seems. + pushd .. > /dev/null + + carthage checkout || carthage_die "Carthage dependency checkout failed" + + # --no-use-binaries: due to https://github.com/Carthage/Carthage/issues/3134, + # which affects the sentry-cocoa dependency. + carthage build --use-xcframeworks --no-use-binaries --platform iOS || carthage_die "Carthage dependency loading failed" + + popd > /dev/null } function do_packages() { @@ -68,6 +92,7 @@ function do_packages() { function do_configure ( ) { do_packages + do_carthage } # Manages KeymanEngine.bundle, which is included inside the :engine target. diff --git a/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj b/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj index 9997aadfaf..7292a3f91d 100644 --- a/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj +++ b/ios/keyman/Keyman/Keyman.xcodeproj/project.pbxproj @@ -14,11 +14,9 @@ 162E2C9F2092D36800F40769 /* UIDevice+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 162E2C9E2092D36800F40769 /* UIDevice+Extensions.swift */; }; 165EB39A2097165B00040A69 /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB3992097165B00040A69 /* UIColor+Extensions.swift */; }; 165EB39C2097181D00040A69 /* KMView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165EB39B2097181D00040A69 /* KMView.swift */; }; + 296EF2C42AFA267500E3E384 /* ZIPFoundation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */; }; + 296EF2C52AFA267500E3E384 /* ZIPFoundation.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 29B30C212B56325D00C342A4 /* KeymanLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29CA9A612B4F9B0B00EAB099 /* KeymanLogger.swift */; }; - 29C3F4012F2526CA000D1C6F /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4002F2526CA000D1C6F /* Sentry */; }; - 29C3F4042F2526E5000D1C6F /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4032F2526E5000D1C6F /* ZIPFoundation */; }; - 29C3F4072F2526F2000D1C6F /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4062F2526F2000D1C6F /* Reachability */; }; - 29C3F40A2F25270A000D1C6F /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 29C3F4092F25270A000D1C6F /* DeviceKit */; }; 29CA9A622B4F9B0B00EAB099 /* KeymanLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29CA9A612B4F9B0B00EAB099 /* KeymanLogger.swift */; }; 981AFA8F19EF44DE006706BF /* 724-info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9815725518E4F0930014DF0C /* 724-info@2x.png */; }; 981AFA9619EF44DE006706BF /* MainViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98ABADCE176935E500B62590 /* MainViewController_iPhone.xib */; }; @@ -150,6 +148,12 @@ CE80AD33257F2B4A008D2150 /* KeymanEngine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; }; CE80AD34257F2B4B008D2150 /* KeymanEngine.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CEBD34322654FE3500EB2EA8 /* KeymanEngine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */; }; + CEBD343B2654FEB400EB2EA8 /* DeviceKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */; }; + CEBD343C2654FEB400EB2EA8 /* DeviceKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CEBD343F2654FEB400EB2EA8 /* Reachability.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */; }; + CEBD34402654FEB400EB2EA8 /* Reachability.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CEBD34412654FEB400EB2EA8 /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */; }; + CEBD34422654FEB400EB2EA8 /* Sentry.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; CEF4E55623E95B7B0065B9C7 /* ImageBanner.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEF4E55523E95B7B0065B9C7 /* ImageBanner.xib */; }; CEF4E55723E95B7B0065B9C7 /* ImageBanner.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEF4E55523E95B7B0065B9C7 /* ImageBanner.xib */; }; CEF4E55923E967140065B9C7 /* ImageBannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF4E55823E967140065B9C7 /* ImageBannerViewController.swift */; }; @@ -174,6 +178,10 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + CEBD34402654FEB400EB2EA8 /* Reachability.xcframework in Embed Frameworks */, + 296EF2C52AFA267500E3E384 /* ZIPFoundation.xcframework in Embed Frameworks */, + CEBD343C2654FEB400EB2EA8 /* DeviceKit.xcframework in Embed Frameworks */, + CEBD34422654FEB400EB2EA8 /* Sentry.xcframework in Embed Frameworks */, CE80AD34257F2B4B008D2150 /* KeymanEngine.framework in Embed Frameworks */, ); name = "Embed Frameworks"; @@ -192,6 +200,7 @@ 16A9229D20325253003CC98E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Keyman/Info.plist; sourceTree = SOURCE_ROOT; }; 293EA3E027059C6900545EED /* ha */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ha; path = ha.lproj/Localizable.strings; sourceTree = ""; }; 294914742738DF7700400732 /* ff-NG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ff-NG"; path = "ff-NG.lproj/Localizable.strings"; sourceTree = ""; }; + 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ZIPFoundation.xcframework; path = ../../Carthage/Build/ZIPFoundation.xcframework; sourceTree = ""; }; 297810FD297FA818007C886D /* kn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kn; path = kn.lproj/Localizable.strings; sourceTree = ""; }; 298566B829802828004ACA95 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 298566C42980C493004ACA95 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; @@ -327,6 +336,9 @@ CEACC90E25F07D58006EAB45 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; CEACC90F25F07D5A006EAB45 /* km */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = km; path = km.lproj/Localizable.strings; sourceTree = ""; }; CEACC91225F07D77006EAB45 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = DeviceKit.xcframework; path = ../../Carthage/Build/DeviceKit.xcframework; sourceTree = ""; }; + CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Reachability.xcframework; path = ../../Carthage/Build/Reachability.xcframework; sourceTree = ""; }; + CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../../Carthage/Build/Sentry.xcframework; sourceTree = ""; }; CEBD3458265511B700EB2EA8 /* am */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = am; path = am.lproj/Localizable.strings; sourceTree = ""; }; CEEC468226F2F7BA009A5B7D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; CEEF81B92673019600EE6A07 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/Localizable.strings"; sourceTree = ""; }; @@ -340,11 +352,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CEBD343F2654FEB400EB2EA8 /* Reachability.xcframework in Frameworks */, + 296EF2C42AFA267500E3E384 /* ZIPFoundation.xcframework in Frameworks */, + CEBD343B2654FEB400EB2EA8 /* DeviceKit.xcframework in Frameworks */, + CEBD34412654FEB400EB2EA8 /* Sentry.xcframework in Frameworks */, CE80AD33257F2B4A008D2150 /* KeymanEngine.framework in Frameworks */, - 29C3F40A2F25270A000D1C6F /* DeviceKit in Frameworks */, - 29C3F4072F2526F2000D1C6F /* Reachability in Frameworks */, - 29C3F4012F2526CA000D1C6F /* Sentry in Frameworks */, - 29C3F4042F2526E5000D1C6F /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -525,6 +537,10 @@ 98ABADB2176935E400B62590 /* Frameworks */ = { isa = PBXGroup; children = ( + 296EF2C32AFA267500E3E384 /* ZIPFoundation.xcframework */, + CEBD34352654FEB400EB2EA8 /* DeviceKit.xcframework */, + CEBD34372654FEB400EB2EA8 /* Reachability.xcframework */, + CEBD34382654FEB400EB2EA8 /* Sentry.xcframework */, CE80AD32257F2B4A008D2150 /* KeymanEngine.framework */, ); name = Frameworks; @@ -783,12 +799,6 @@ vi, ); mainGroup = 98ABADA7176935E400B62590; - packageReferences = ( - 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */, - 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */, - 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */, - 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */, - ); productRefGroup = 98ABADB1176935E400B62590 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -1117,11 +1127,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -1139,7 +1147,6 @@ PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; @@ -1156,11 +1163,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; INFOPLIST_FILE = Keyman/Info.plist; @@ -1176,7 +1181,6 @@ PRODUCT_NAME = Keyman; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Distribution"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 5.0; @@ -1216,7 +1220,10 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(SRCROOT)/../../Carthage/Build/", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1268,7 +1275,10 @@ COPY_PHASE_STRIP = YES; ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(SRCROOT)/../../Carthage/Build/", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -1299,10 +1309,8 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 3YE4W86L3G; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1328,7 +1336,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development SWKeyboard"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution SWKeyboard"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1412,7 +1419,10 @@ ENABLE_BITCODE = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(PROJECT_DIR)", + "$(SRCROOT)/../../Carthage/Build/", + ); GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -1442,11 +1452,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Keyman/Keyman.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 3YE4W86L3G; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Keyman/Keyman-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; @@ -1464,7 +1472,6 @@ PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution"; SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; @@ -1483,10 +1490,8 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CODE_SIGN_ENTITLEMENTS = SWKeyboard/SWKeyboard.entitlements; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = 3YE4W86L3G; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 3YE4W86L3G; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1512,7 +1517,6 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "Keyman Development SWKeyboard"; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Keyman Distribution SWKeyboard"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = ""; SWIFT_OBJC_BRIDGING_HEADER = ""; @@ -1557,64 +1561,6 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ - -/* Begin XCRemoteSwiftPackageReference section */ - 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 9.2.0; - }; - }; - 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; - requirement = { - kind = exactVersion; - version = 0.9.20; - }; - }; - 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/ashleymills/Reachability.swift"; - requirement = { - branch = master; - kind = branch; - }; - }; - 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/devicekit/DeviceKit.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 5.7.0; - }; - }; -/* End XCRemoteSwiftPackageReference section */ - -/* Begin XCSwiftPackageProductDependency section */ - 29C3F4002F2526CA000D1C6F /* Sentry */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F3FF2F2526CA000D1C6F /* XCRemoteSwiftPackageReference "sentry-cocoa" */; - productName = Sentry; - }; - 29C3F4032F2526E5000D1C6F /* ZIPFoundation */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F4022F2526E5000D1C6F /* XCRemoteSwiftPackageReference "ZIPFoundation" */; - productName = ZIPFoundation; - }; - 29C3F4062F2526F2000D1C6F /* Reachability */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F4052F2526F2000D1C6F /* XCRemoteSwiftPackageReference "Reachability" */; - productName = Reachability; - }; - 29C3F4092F25270A000D1C6F /* DeviceKit */ = { - isa = XCSwiftPackageProductDependency; - package = 29C3F4082F25270A000D1C6F /* XCRemoteSwiftPackageReference "DeviceKit" */; - productName = DeviceKit; - }; -/* End XCSwiftPackageProductDependency section */ }; rootObject = 98ABADA8176935E400B62590 /* Project object */; } diff --git a/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved deleted file mode 100644 index 8f79325601..0000000000 --- a/ios/keymanios.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ /dev/null @@ -1,42 +0,0 @@ -{ - "originHash" : "a373bd824b59e33f7208114e4d77d167cc3f88776f323dd66ef0d5e716c837af", - "pins" : [ - { - "identity" : "devicekit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/devicekit/DeviceKit.git", - "state" : { - "revision" : "581df61650bc457ec00373a592a84be3e7468eb1", - "version" : "5.7.0" - } - }, - { - "identity" : "reachability.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/ashleymills/Reachability.swift", - "state" : { - "branch" : "master", - "revision" : "21d1dc412cfecbe6e34f1f4c4eb88d3f912654a6" - } - }, - { - "identity" : "sentry-cocoa", - "kind" : "remoteSourceControl", - "location" : "https://github.com/getsentry/sentry-cocoa.git", - "state" : { - "revision" : "de66bd4fa0661c81455e8ad2509ed6f0e39025dc", - "version" : "9.2.0" - } - }, - { - "identity" : "zipfoundation", - "kind" : "remoteSourceControl", - "location" : "https://github.com/weichsel/ZIPFoundation.git", - "state" : { - "revision" : "22787ffb59de99e5dc1fbfe80b19c97a904ad48d", - "version" : "0.9.20" - } - } - ], - "version" : 3 -} From aa86cfceca3b3813f021cd74b3609e1aa9fdd6d3 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Mon, 26 Jan 2026 12:46:05 -0500 Subject: [PATCH 03/17] maint(ios): upgrade Sentry version --- ios/Cartfile | 2 +- ios/Cartfile.resolved | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/Cartfile b/ios/Cartfile index 9ffc07d330..f0eb983c5e 100644 --- a/ios/Cartfile +++ b/ios/Cartfile @@ -1,4 +1,4 @@ github "weichsel/ZIPFoundation" ~> 0.9 github "devicekit/DeviceKit" ~> 5.0 github "ashleymills/Reachability.swift" -github "getsentry/sentry-cocoa" ~> 8.38.0 +github "getsentry/sentry-cocoa" ~> 8.57.3 diff --git a/ios/Cartfile.resolved b/ios/Cartfile.resolved index ca05da1ae9..54775dca04 100644 --- a/ios/Cartfile.resolved +++ b/ios/Cartfile.resolved @@ -1,4 +1,4 @@ github "ashleymills/Reachability.swift" "v5.2.4" -github "devicekit/DeviceKit" "5.5.0" -github "getsentry/sentry-cocoa" "8.44.0" -github "weichsel/ZIPFoundation" "0.9.19" +github "devicekit/DeviceKit" "5.7.0" +github "getsentry/sentry-cocoa" "8.58.0" +github "weichsel/ZIPFoundation" "0.9.20" From d9bbffcd1239cd13518eeda79b1e044acfabeffd Mon Sep 17 00:00:00 2001 From: sgschantz Date: Wed, 28 Jan 2026 18:20:06 -0500 Subject: [PATCH 04/17] maint(ios): update sentry version Fixes: #15475 --- ios/Cartfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Cartfile b/ios/Cartfile index f0eb983c5e..49beca6729 100644 --- a/ios/Cartfile +++ b/ios/Cartfile @@ -1,4 +1,4 @@ github "weichsel/ZIPFoundation" ~> 0.9 github "devicekit/DeviceKit" ~> 5.0 github "ashleymills/Reachability.swift" -github "getsentry/sentry-cocoa" ~> 8.57.3 +github "getsentry/sentry-cocoa" ~> 8.58 From 4cfb7402da81dc09116e75e6c2b3f8faf01d7df7 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 16 Feb 2026 05:01:11 +0100 Subject: [PATCH 05/17] Revise port lookup and dependencies in README Updated the port lookup table and website dependencies in the README. --- docs/websites/README.md | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/websites/README.md b/docs/websites/README.md index 3c68874019..9813fcc2ae 100644 --- a/docs/websites/README.md +++ b/docs/websites/README.md @@ -60,14 +60,19 @@ The link file also appears locally. ##### Port lookup table After this, you can access the website at the following ports: -| Website | URL | with website-local-proxy running | Docker Container Name | -|----------------|-----------------------|-----------------------------------|------------------------| -| keyman.com | http://localhost:8053 | http://keyman.com.localhost | keyman-website | -| s.keyman.com | http://localhost:8054 | http://s.keyman.com.localhost | s-keyman-website | -| help.keyman | http://localhost:8055 | http://help.keyman.com.localhost | help-keyman-website | -| keymanweb.com | http://localhost:8057 | http://keymanweb.com.localhost | web-keyman-website | -| | | http://web.keyman.com.localhost | | -| api.keyman.com | http://localhost:8058 | http://api.keyman.com.localhost | api-keyman-com-website | +| Website | URL | with website-local-proxy running | Docker Container Name | +|--------------------|-----------------------|--------------------------------------------|------------------------| +| keyman.com | http://localhost:8053 | http://keyman.com.localhost | keyman-website | +| s.keyman.com | http://localhost:8054 | http://s.keyman.com.localhost | s-keyman-website | +| help.keyman | http://localhost:8055 | http://help.keyman.com.localhost | help-keyman-website | +| keymanweb.com | http://localhost:8057 | http://keymanweb.com.localhost | web-keyman-website | +| | | http://web.keyman.com.localhost | | +| api.keyman.com | http://localhost:8058 | http://api.keyman.com.localhost | api-keyman-com-website | +| status.keyman.com* | http://localhost:8060 | http://status-backend.keyman.com.localhost | status-keyman-website | +| | http://localhost:8061 | http://status.keyman.com.localhost | status-keyman-public | + +\* Note that status.keyman.com runs in two containers in development to allow for live reload and separation of logs for backend and frontend. +In production, only port 8060 is used. #### Remove the Docker container and image 1. Run `./build.sh clean`. @@ -96,15 +101,15 @@ Refer to **Port lookup table** above for Docker container names The table below shows server-side dependencies for each website -|Website | Depends On | -|----------------------|------------- | -| s.keyman.com |

| -| downloads.keyman.com |

| -| api.keyman.com | downloads.keyman.com
s.keyman.com | -| keymanweb.com | api.keyman.com | +| Website | Depends On | +|----------------------|----------------------------------------| +| s.keyman.com |

| +| downloads.keyman.com |

| +| api.keyman.com | downloads.keyman.com
s.keyman.com | +| keymanweb.com | api.keyman.com | | keyman.com | api.keyman.com
downloads.keyman.com | | help.keyman.com | api.keyman.com
downloads.keyman.com | - +| status.keyman.com | api.keyman.com
downloads.keyman.com | --------- From 2a96eae14d1e39c1c02874e0355809c6746bf9ec Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Mon, 16 Feb 2026 12:01:20 -0600 Subject: [PATCH 06/17] auto: increment master version to 19.0.204 Test-bot: skip Build-bot: skip --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index b406ebf4a9..a24f4ba447 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 19.0.203 alpha 2026-02-16 + +* docs: Add status.keyman.com info to website readme (#15591) + ## 19.0.202 alpha 2026-02-12 * fix(linux): check for existing file before trying to install (#15573) diff --git a/VERSION.md b/VERSION.md index 312b5b0587..846c888483 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.203 \ No newline at end of file +19.0.204 \ No newline at end of file From b7975973af3fcb7f83b131057fdf9e6bfe4997b9 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 18 Feb 2026 09:08:49 +0700 Subject: [PATCH 07/17] maint(web): ensure Web build scripts handle paths with spaces properly The command shortcuts that were used by Web scripts to create bundles via `esbuild` were not properly handling the $KEYMAN_ROOT path when it contained a space. These changes will rectify this behavior and permit builds for such cases. Build-bot: skip build:web Test-bot: skip --- web/build.sh | 7 ++-- web/common.inc.sh | 2 +- web/src/app/browser/build.sh | 34 +++++++++---------- web/src/app/ui/build.sh | 12 +++---- web/src/app/webview/build.sh | 24 ++++++------- web/src/engine/attachment/build.sh | 4 +-- web/src/engine/common/web-utils/build.sh | 9 +++-- web/src/engine/element-wrappers/build.sh | 4 +-- web/src/engine/events/build.sh | 4 +-- web/src/engine/interfaces/build.sh | 4 +-- web/src/engine/js-processor/build.sh | 4 +-- web/src/engine/keyboard-storage/build.sh | 12 +++---- web/src/engine/keyboard/build.sh | 12 +++---- web/src/engine/main/build.sh | 4 +-- web/src/engine/osk/build.sh | 4 +-- web/src/engine/osk/gesture-processor/build.sh | 6 ++-- .../osk/gesture-processor/src/tools/build.sh | 6 ++-- .../src/tools/host-fixture/extract-fixture.sh | 2 +- web/src/engine/predictive-text/build.sh | 2 -- .../predictive-text/worker-main/build.sh | 7 ++-- .../predictive-text/worker-thread/build.sh | 16 ++++----- web/src/engine/sentry-manager/build.sh | 6 ++-- web/src/tools/testing/bulk_rendering/build.sh | 6 ++-- web/src/tools/testing/recorder/build.sh | 4 +-- 24 files changed, 92 insertions(+), 103 deletions(-) diff --git a/web/build.sh b/web/build.sh index 2d7aed9a48..cbbaaca183 100755 --- a/web/build.sh +++ b/web/build.sh @@ -9,6 +9,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/build/utils.inc.sh" +. "$KEYMAN_ROOT/web/common.inc.sh" # ################################ Main script ################################ @@ -75,8 +76,6 @@ builder_describe_outputs \ build:tools "/web/build/tools/building/sourcemap-root/index.js" \ build:test-pages "/web/build/test-resources/sentry-manager.js" -BUNDLE_CMD="node ${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" - #### Build action definitions #### ##################### TODO: call child action, verify things work as expected! @@ -107,8 +106,8 @@ precompile() { # types built-in to Node aren't available, and @web/test-runner doesn't do # treeshaking when loading the imports. We work around by pre-compiling. for f in "${DIR}"/*.js; do - ${BUNDLE_CMD} "${f}" \ - --out "${f%.js}".mjs \ + node "${LIB_BUNDLER}" "${f}" \ + --out "${f%.js}".mjs \ --format esm done } diff --git a/web/common.inc.sh b/web/common.inc.sh index 32249094a3..c88c081900 100644 --- a/web/common.inc.sh +++ b/web/common.inc.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # -BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" +LIB_BUNDLER="${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" # Compiles all build products corresponding to the specified target. # This should be called from the working directory of a child project's diff --git a/web/src/app/browser/build.sh b/web/src/app/browser/build.sh index a61ce1517c..7a168a5d46 100755 --- a/web/src/app/browser/build.sh +++ b/web/src/app/browser/build.sh @@ -49,25 +49,25 @@ compile_and_copy() { BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/browser" SRC_ROOT="${KEYMAN_ROOT}/web/src/app/browser/src" - $BUNDLE_CMD "${SRC_ROOT}/debug-main.js" \ - --out "${BUILD_ROOT}/debug/keymanweb.js" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/debug" \ - --target "es6" + node "${LIB_BUNDLER}" "${SRC_ROOT}/debug-main.js" \ + --out "${BUILD_ROOT}/debug/keymanweb.js" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/debug" \ + --target "es6" - $BUNDLE_CMD "${SRC_ROOT}/release-main.js" \ - --out "${BUILD_ROOT}/release/keymanweb.js" \ - --charset "utf8" \ - --profile "${BUILD_ROOT}/filesize-profile.log" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/release" \ - --minify \ - --target "es6" + node "${LIB_BUNDLER}" "${SRC_ROOT}/release-main.js" \ + --out "${BUILD_ROOT}/release/keymanweb.js" \ + --charset "utf8" \ + --profile "${BUILD_ROOT}/filesize-profile.log" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/release" \ + --minify \ + --target "es6" - $BUNDLE_CMD "${BUILD_ROOT}/obj/test-index.js" \ - --out "${BUILD_ROOT}/lib/index.mjs" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/browser/lib" \ - --format esm + node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/test-index.js" \ + --out "${BUILD_ROOT}/lib/index.mjs" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/browser/lib" \ + --format esm mkdir -p "$KEYMAN_ROOT/web/build/app/resources/osk" cp -R "$KEYMAN_ROOT/web/src/resources/osk/." "$KEYMAN_ROOT/web/build/app/resources/osk/" diff --git a/web/src/app/ui/build.sh b/web/src/app/ui/build.sh index 045cdac8d0..145cea8e4b 100755 --- a/web/src/app/ui/build.sh +++ b/web/src/app/ui/build.sh @@ -51,13 +51,13 @@ compile_and_copy() { for type in ${types[@]} do filename="kmwui${type}" - $BUNDLE_CMD "${BUILD_ROOT}/obj/$filename.js" \ - --out "${BUILD_ROOT}/debug/$filename.js" \ - --sourceRoot "@keymanapp/keyman/web/build/app/ui/debug" + node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/$filename.js" \ + --out "${BUILD_ROOT}/debug/$filename.js" \ + --sourceRoot "@keymanapp/keyman/web/build/app/ui/debug" - $BUNDLE_CMD "${BUILD_ROOT}/obj/$filename.js" \ - --out "${BUILD_ROOT}/release/$filename.js" \ - --sourceRoot "@keymanapp/keyman/web/build/app/ui/release" \ + node "${LIB_BUNDLER}" "${BUILD_ROOT}/obj/$filename.js" \ + --out "${BUILD_ROOT}/release/$filename.js" \ + --sourceRoot "@keymanapp/keyman/web/build/app/ui/release" \ --minify done diff --git a/web/src/app/webview/build.sh b/web/src/app/webview/build.sh index 32534e6950..72708eabea 100755 --- a/web/src/app/webview/build.sh +++ b/web/src/app/webview/build.sh @@ -43,19 +43,19 @@ compile_and_copy() { BUILD_ROOT="${KEYMAN_ROOT}/web/build/app/webview" SRC_ROOT="${KEYMAN_ROOT}/web/src/app/webview/src" - $BUNDLE_CMD "${SRC_ROOT}/debug-main.js" \ - --out "${BUILD_ROOT}/debug/keymanweb-webview.js" \ - --charset "utf8" \ - --sourceRoot "@keymanapp/keyman/web/build/app/webview/debug" \ - --target "es6" + node "${LIB_BUNDLER}" "${SRC_ROOT}/debug-main.js" \ + --out "${BUILD_ROOT}/debug/keymanweb-webview.js" \ + --charset "utf8" \ + --sourceRoot "@keymanapp/keyman/web/build/app/webview/debug" \ + --target "es6" - $BUNDLE_CMD "${SRC_ROOT}/release-main.js" \ - --out "${BUILD_ROOT}/release/keymanweb-webview.js" \ - --charset "utf8" \ - --profile "${BUILD_ROOT}/filesize-profile.log" \ - --sourceRoot "@keymanapp/keyman/web/build/app/webview/release" \ - --minify \ - --target "es6" + node "${LIB_BUNDLER}" "${SRC_ROOT}/release-main.js" \ + --out "${BUILD_ROOT}/release/keymanweb-webview.js" \ + --charset "utf8" \ + --profile "${BUILD_ROOT}/filesize-profile.log" \ + --sourceRoot "@keymanapp/keyman/web/build/app/webview/release" \ + --minify \ + --target "es6" mkdir -p "$KEYMAN_ROOT/web/build/app/resources/osk" cp -R "$KEYMAN_ROOT/web/src/resources/osk/." "$KEYMAN_ROOT/web/build/app/resources/osk/" diff --git a/web/src/engine/attachment/build.sh b/web/src/engine/attachment/build.sh index 042c5aa83e..0c37fb62c1 100755 --- a/web/src/engine/attachment/build.sh +++ b/web/src/engine/attachment/build.sh @@ -36,8 +36,8 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/common/web-utils/build.sh b/web/src/engine/common/web-utils/build.sh index 23d38cb952..f7e78c954e 100755 --- a/web/src/engine/common/web-utils/build.sh +++ b/web/src/engine/common/web-utils/build.sh @@ -15,8 +15,6 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" SUBPROJECT_NAME=engine/common/web-utils BUILD_DIR="/web/src/engine/common/web-utils/build" -BUNDLE_CMD="node ${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" - ################################ Main script ################################ builder_describe \ @@ -37,12 +35,13 @@ function do_build() { # May be useful one day, for building a mass .d.ts for KMW as a whole. # So... tsc does declaration-bundling on its own pretty well, at least for local development. tsc --emitDeclarationOnly --outFile "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.d.ts" - + echo 'a' # One of the functions (timedPromise) is quite helpful for automated testing, even in the DOM. # So, to make sure it's easily-accessible for the DOM-based tests... - ${BUNDLE_CMD} "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ - --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ --format esm + echo 'b' } function do_test() { diff --git a/web/src/engine/element-wrappers/build.sh b/web/src/engine/element-wrappers/build.sh index 055c93b00e..18d7f2c0ed 100755 --- a/web/src/engine/element-wrappers/build.sh +++ b/web/src/engine/element-wrappers/build.sh @@ -34,8 +34,8 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/events/build.sh b/web/src/engine/events/build.sh index eeeb144949..256404680f 100755 --- a/web/src/engine/events/build.sh +++ b/web/src/engine/events/build.sh @@ -35,8 +35,8 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/interfaces/build.sh b/web/src/engine/interfaces/build.sh index 3ea80fdc7a..8611be7ad4 100755 --- a/web/src/engine/interfaces/build.sh +++ b/web/src/engine/interfaces/build.sh @@ -36,8 +36,8 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/js-processor/build.sh b/web/src/engine/js-processor/build.sh index 6d5989b515..8faaaeded5 100755 --- a/web/src/engine/js-processor/build.sh +++ b/web/src/engine/js-processor/build.sh @@ -31,8 +31,8 @@ builder_parse "$@" do_build () { compile "${SUBPROJECT_NAME}" - ${BUNDLE_CMD} "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/keyboard-storage/build.sh b/web/src/engine/keyboard-storage/build.sh index a6a233bfd8..fc38ed3993 100755 --- a/web/src/engine/keyboard-storage/build.sh +++ b/web/src/engine/keyboard-storage/build.sh @@ -34,16 +34,16 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/domCloudRequester.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/dom-cloud-requester.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/domCloudRequester.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/dom-cloud-requester.mjs" \ --format esm - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/nodeCloudRequester.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/node-cloud-requester.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/nodeCloudRequester.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/node-cloud-requester.mjs" \ --format esm \ --platform node } diff --git a/web/src/engine/keyboard/build.sh b/web/src/engine/keyboard/build.sh index 7260bc5cc6..3a79bbe64c 100755 --- a/web/src/engine/keyboard/build.sh +++ b/web/src/engine/keyboard/build.sh @@ -49,20 +49,20 @@ function do_build() { # Base product - the main keyboard processor builder_echo "Bundle base product - the main keyboard processor" - ${BUNDLE_CMD} "${BUILD_DIR}/obj/index.js" \ - --out "${BUILD_DIR}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${BUILD_DIR}/obj/index.js" \ + --out "${BUILD_DIR}/lib/index.mjs" \ --format esm # The DOM-oriented keyboard loader builder_echo "Bundle the DOM-oriented keyboard loader" - ${BUNDLE_CMD} "${BUILD_DIR}/obj/keyboards/loaders/dom-keyboard-loader.js" \ - --out "${BUILD_DIR}/lib/dom-keyboard-loader.mjs" \ + node "${LIB_BUNDLER}" "${BUILD_DIR}/obj/keyboards/loaders/dom-keyboard-loader.js" \ + --out "${BUILD_DIR}/lib/dom-keyboard-loader.mjs" \ --format esm # The Node-oriented keyboard loader builder_echo "Bundle the Node-oriented keyboard loader" - ${BUNDLE_CMD} "${BUILD_DIR}/obj/keyboards/loaders/node-keyboard-loader.js" \ - --out "${BUILD_DIR}/lib/node-keyboard-loader.mjs" \ + node "${LIB_BUNDLER}" "${BUILD_DIR}/obj/keyboards/loaders/node-keyboard-loader.js" \ + --out "${BUILD_DIR}/lib/node-keyboard-loader.mjs" \ --format esm \ --platform node diff --git a/web/src/engine/main/build.sh b/web/src/engine/main/build.sh index 6cca867d88..54a12cc841 100755 --- a/web/src/engine/main/build.sh +++ b/web/src/engine/main/build.sh @@ -41,8 +41,8 @@ builder_parse "$@" do_build () { compile $SUBPROJECT_NAME - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/osk/build.sh b/web/src/engine/osk/build.sh index 8c82560f4e..09ab1818c3 100755 --- a/web/src/engine/osk/build.sh +++ b/web/src/engine/osk/build.sh @@ -49,8 +49,8 @@ do_configure() { do_build() { compile "${SUBPROJECT_NAME}" - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/${SUBPROJECT_NAME}/lib/index.mjs" \ --format esm echo "Validating gesture model and set references" diff --git a/web/src/engine/osk/gesture-processor/build.sh b/web/src/engine/osk/gesture-processor/build.sh index 77c5e3454e..d207e8d587 100755 --- a/web/src/engine/osk/gesture-processor/build.sh +++ b/web/src/engine/osk/gesture-processor/build.sh @@ -12,8 +12,6 @@ SUBPROJECT_NAME=engine/osk/gesture-processor . "${KEYMAN_ROOT}/resources/build/utils.inc.sh" . "$KEYMAN_ROOT/resources/build/node.inc.sh" -BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" - BUILD_DIR="/web/src/engine/osk/gesture-processor/build" ################################ Main script ################################ @@ -46,8 +44,8 @@ function do_build_module() { # Build tsc --build $builder_verbose - $BUNDLE_CMD "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ - --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ + node "$LIB_BUNDLER" "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ --format esm } diff --git a/web/src/engine/osk/gesture-processor/src/tools/build.sh b/web/src/engine/osk/gesture-processor/src/tools/build.sh index 735e943ecc..0fe33fe784 100755 --- a/web/src/engine/osk/gesture-processor/src/tools/build.sh +++ b/web/src/engine/osk/gesture-processor/src/tools/build.sh @@ -9,8 +9,6 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$KEYMAN_ROOT/web/common.inc.sh" . "$KEYMAN_ROOT/resources/build/utils.inc.sh" -BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" - BASE_DIR="/web/src/engine/osk/gesture-processor" BUILD_DIR="${BASE_DIR}/build" @@ -71,8 +69,8 @@ function do_build_fixture() { function do_build_testmodule() { compile "" "${THIS_SCRIPT_PATH}/unit-test-resources" "${KEYMAN_ROOT}/${BUILD_DIR}/tools" - $BUNDLE_CMD "${KEYMAN_ROOT}/${BUILD_DIR}/tools/obj/index.js" \ - --out "${KEYMAN_ROOT}/${BUILD_DIR}/tools/lib/index.mjs" \ + node "$LIB_BUNDLER" "${KEYMAN_ROOT}/${BUILD_DIR}/tools/obj/index.js" \ + --out "${KEYMAN_ROOT}/${BUILD_DIR}/tools/lib/index.mjs" \ --format "esm" } diff --git a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh index f8a1998104..f0549af298 100755 --- a/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh +++ b/web/src/engine/osk/gesture-processor/src/tools/host-fixture/extract-fixture.sh @@ -7,7 +7,7 @@ set -eu # This script operates from the perspective of its own directory. THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -cd $(dirname "$THIS_SCRIPT") +cd "$(dirname "$THIS_SCRIPT")" # On Windows, `node extractor.cjs` cannot be directly piped; that requires `node.exe`. # But that doesn't make sense on other platforms, so... wrapper script. diff --git a/web/src/engine/predictive-text/build.sh b/web/src/engine/predictive-text/build.sh index f4872bcd7f..10637db851 100755 --- a/web/src/engine/predictive-text/build.sh +++ b/web/src/engine/predictive-text/build.sh @@ -40,8 +40,6 @@ builder_describe_outputs \ build:worker-main "/web/src/engine/worker-main/build/obj/lmlayer.js" \ build:worker-thread "/web/src/engine/worker-thread/build/obj/worker-main.wrapped.js" -BUNDLE_CMD="node ${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" - #### Build action definitions #### # We can run all clean & configure actions at once without much issue. diff --git a/web/src/engine/predictive-text/worker-main/build.sh b/web/src/engine/predictive-text/worker-main/build.sh index 0fc63bfb32..1cfe2ff0dc 100755 --- a/web/src/engine/predictive-text/worker-main/build.sh +++ b/web/src/engine/predictive-text/worker-main/build.sh @@ -13,8 +13,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$KEYMAN_ROOT/resources/build/utils.inc.sh" . "$KEYMAN_ROOT/resources/build/node.inc.sh" - -BUNDLE_CMD="node $KEYMAN_ROOT/web/src/tools/es-bundling/build/common-bundle.mjs" +. "$KEYMAN_ROOT/web/common.inc.sh" ################################ Main script ################################ @@ -47,8 +46,8 @@ function do_build() { tsc -b ./tsconfig.all.json # esbuild-bundled products at this level are not intended to be used for anything but testing. - $BUNDLE_CMD "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/obj/web/index.js" \ - --out "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs" \ + node "$LIB_BUNDLER" "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/obj/web/index.js" \ + --out "${KEYMAN_ROOT}/web/src/engine/predictive-text/worker-main/build/lib/web/index.mjs" \ --format esm } diff --git a/web/src/engine/predictive-text/worker-thread/build.sh b/web/src/engine/predictive-text/worker-thread/build.sh index 25276eaa6e..0b950479b6 100755 --- a/web/src/engine/predictive-text/worker-thread/build.sh +++ b/web/src/engine/predictive-text/worker-thread/build.sh @@ -19,9 +19,7 @@ WORKER_OUTPUT_FILENAME=build/lib/worker-main.js INTERMEDIATE=./build/intermediate LIB=./build/lib -bundle_cmd="node ${KEYMAN_ROOT}/web/src/tools/es-bundling/build/common-bundle.mjs" - -SRCMAP_CLEANER="node $KEYMAN_ROOT/web/build/tools/building/sourcemap-root/index.js" +SRCMAP_CLEANER="${KEYMAN_ROOT}/web/build/tools/building/sourcemap-root/index.js" ################################ Main script ################################ @@ -62,26 +60,26 @@ function do_build() { # The ES6 target needs no polyfills - we go straight to the wrapped version. - $bundle_cmd src/main/worker-main.ts \ - --out $INTERMEDIATE/worker-main.js \ + node "$LIB_BUNDLER" src/main/worker-main.ts \ + --out $INTERMEDIATE/worker-main.js \ --charset "utf8" \ --target "es6" \ --sourceRoot '@keymanapp/keyman/web/src/engine/predictive-text/worker-thread/src/main' - $SRCMAP_CLEANER \ + node "$SRCMAP_CLEANER" \ $INTERMEDIATE/worker-main.js.map \ $INTERMEDIATE/worker-main.js.map \ --clean - $bundle_cmd src/main/worker-main.ts \ - --out $INTERMEDIATE/worker-main.min.js \ + node "$LIB_BUNDLER" src/main/worker-main.ts \ + --out $INTERMEDIATE/worker-main.min.js \ --minify \ --charset "utf8" \ --profile build/filesize-profile.log \ --target "es6" \ --sourceRoot '@keymanapp/keyman/web/src/engine/predictive-text/worker-thread/src/main' - $SRCMAP_CLEANER \ + node "$SRCMAP_CLEANER" \ $INTERMEDIATE/worker-main.min.js.map \ $INTERMEDIATE/worker-main.min.js.map \ --clean diff --git a/web/src/engine/sentry-manager/build.sh b/web/src/engine/sentry-manager/build.sh index 1054e152bc..6c5dd03064 100755 --- a/web/src/engine/sentry-manager/build.sh +++ b/web/src/engine/sentry-manager/build.sh @@ -39,9 +39,9 @@ fi if builder_start_action build; then tsc --build "$THIS_SCRIPT_PATH/src/tsconfig.json" - $BUNDLE_CMD "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/lib/index.js" \ - --sourceRoot "@keymanapp/keyman/web/src/engine/sentry-manager/build/lib/" + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/src/engine/sentry-manager/build/lib/index.js" \ + --sourceRoot "@keymanapp/keyman/web/src/engine/sentry-manager/build/lib/" builder_finish_action success build fi diff --git a/web/src/tools/testing/bulk_rendering/build.sh b/web/src/tools/testing/bulk_rendering/build.sh index 6c93d9862c..578a1056ab 100755 --- a/web/src/tools/testing/bulk_rendering/build.sh +++ b/web/src/tools/testing/bulk_rendering/build.sh @@ -31,9 +31,9 @@ builder_parse "$@" function do_build ( ) { tsc --build "$THIS_SCRIPT_PATH/tsconfig.json" $builder_verbose - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/renderer_core.js" \ - --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/bulk_render.js" \ - --sourceRoot "@keymanapp/keyman/web/build/$SUBPROJECT_NAME/lib/" + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/renderer_core.js" \ + --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/bulk_render.js" \ + --sourceRoot "@keymanapp/keyman/web/build/$SUBPROJECT_NAME/lib/" # To ensure it's available to the testing pages when served via localhost or build agent. cp "${KEYMAN_ROOT}/node_modules/@zip.js/zip.js/dist/zip.min.js" \ diff --git a/web/src/tools/testing/recorder/build.sh b/web/src/tools/testing/recorder/build.sh index 7a9b0187ec..ab8f3c6471 100755 --- a/web/src/tools/testing/recorder/build.sh +++ b/web/src/tools/testing/recorder/build.sh @@ -33,8 +33,8 @@ do_build ( ) { compile $SUBPROJECT_NAME # Base product - the main keyboard processor - $BUNDLE_CMD "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/index.js" \ - --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/index.mjs" \ + node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/obj/index.js" \ + --out "${KEYMAN_ROOT}/web/build/$SUBPROJECT_NAME/lib/index.mjs" \ --format esm } From 5c445d470ce410d43fce39a17d4d752ac2b2cd47 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Wed, 18 Feb 2026 12:59:17 +0700 Subject: [PATCH 08/17] change(web): remove temp debug shell-script echo statements --- web/src/engine/common/web-utils/build.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/engine/common/web-utils/build.sh b/web/src/engine/common/web-utils/build.sh index f7e78c954e..8be7be6df3 100755 --- a/web/src/engine/common/web-utils/build.sh +++ b/web/src/engine/common/web-utils/build.sh @@ -35,13 +35,11 @@ function do_build() { # May be useful one day, for building a mass .d.ts for KMW as a whole. # So... tsc does declaration-bundling on its own pretty well, at least for local development. tsc --emitDeclarationOnly --outFile "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.d.ts" - echo 'a' # One of the functions (timedPromise) is quite helpful for automated testing, even in the DOM. # So, to make sure it's easily-accessible for the DOM-based tests... node "${LIB_BUNDLER}" "${KEYMAN_ROOT}/${BUILD_DIR}/obj/index.js" \ --out "${KEYMAN_ROOT}/${BUILD_DIR}/lib/index.mjs" \ --format esm - echo 'b' } function do_test() { From 32bb1c85026c152128a62c8fc225d4c7a3ed084c Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 17 Feb 2026 17:39:27 +0100 Subject: [PATCH 09/17] fix(core): fix iterator in backspace handling This change replaces the reverse iterator loop that holds a stale iterator across `pop_back()` calls with a pattern that directly accesses `context.back()` on each iteration. This avoids undefined behavior from iterator invalidation when mutating the list or vector. While so far the previous code didn't show problems, it might still access released memory depending on the implementation. The documentation for `pop_back()` says "References and iterators to the erased element are invalidated", so the previous implementation was clearly wrong. Test-bot: skip --- core/src/ldml/ldml_processor.cpp | 8 ++++---- core/tests/unit/ldml/ldml.cpp | 21 ++++++++++----------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/core/src/ldml/ldml_processor.cpp b/core/src/ldml/ldml_processor.cpp index 63e7995273..04dd15ab83 100644 --- a/core/src/ldml/ldml_processor.cpp +++ b/core/src/ldml/ldml_processor.cpp @@ -233,15 +233,15 @@ void ldml_event_state::emit_backspace() { // Find out what the last actual character was and remove it. // attempt to get the last char // TODO-LDML: emoji backspace - auto end = state->context().rbegin(); - while (end != state->context().rend()) { - if (end->type == KM_CORE_CT_CHAR) { + while (!state->context().empty()) { + auto end = state->context().back(); + if (end.type == KM_CORE_CT_CHAR) { actions.code_points_to_delete++; state->context().pop_back(); return; } // else loop again - assert(end->type != KM_CORE_CT_END); // inappropriate here. + assert(end.type != KM_CORE_CT_END); // inappropriate here. state->context().pop_back(); } /* diff --git a/core/tests/unit/ldml/ldml.cpp b/core/tests/unit/ldml/ldml.cpp index b040df7e76..bfe4d03123 100644 --- a/core/tests/unit/ldml/ldml.cpp +++ b/core/tests/unit/ldml/ldml.cpp @@ -157,21 +157,20 @@ apply_action( matched_text = true; // no text to match as context is empty. } // now, we need to simulate what ldml_processor::emit_backspace() is going to do. - auto end = context.rbegin(); - while (end != context.rend()) { - if (end->type == KM_CORE_CT_CHAR) { - test_assert(!matched_text); - test_assert_equal(end->character, ch); // expect popped char to be same as what's in context - matched_text = true; - context.pop_back(); - break; // exit on first real char - } - test_assert(end->type != KM_CORE_CT_END); // inappropriate here. + while (!context.empty()) { + if (context.back().type == KM_CORE_CT_CHAR) { + test_assert(!matched_text); + test_assert_equal(context.back().character, ch); // expect popped char to be same as what's in context + matched_text = true; context.pop_back(); + break; // exit on first real char } - test_assert(matched_text); + test_assert(context.back().type != KM_CORE_CT_END); // inappropriate here. + context.pop_back(); } + test_assert(matched_text); break; + } case KM_CORE_IT_PERSIST_OPT: std::cout << " + TODO-LDML: persist_opt()" << std::endl; break; From df2b675202732768b2830d5a2ee69c801b62f909 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 18 Feb 2026 16:08:59 +0100 Subject: [PATCH 10/17] fix(core): changed ldml tests to use context list instead of vector Production code uses a list of context items, so this change modifies the tests to also use a list instead of a vector to more closely match production code. Addresses code review comment. Test-bot: skip --- core/tests/unit/ldml/ldml.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/core/tests/unit/ldml/ldml.cpp b/core/tests/unit/ldml/ldml.cpp index bfe4d03123..2acced0018 100644 --- a/core/tests/unit/ldml/ldml.cpp +++ b/core/tests/unit/ldml/ldml.cpp @@ -40,7 +40,7 @@ namespace { -void print_context(std::u16string &text_store, km_core_state *&test_state, std::vector &test_context); +void print_context(std::u16string &text_store, km_core_state *&test_state, std::list &test_context); bool g_beep_found = false; @@ -68,10 +68,10 @@ string_to_hex(const std::u16string &input) { void -copy_context_items_to_vector(km_core_context_item *citems, std::vector &vector) { - vector.clear(); +copy_context_items_to_list(km_core_context_item *citems, std::list &list) { + list.clear(); for(km_core_context_item *ci = citems; ci->type != KM_CORE_CT_END; ci++) { - vector.emplace_back(*ci); + list.emplace_back(*ci); } } @@ -81,9 +81,9 @@ apply_action( km_core_state *test_state, km_core_action_item const &act, std::u16string &text_store, - std::vector &context, + std::list &context, km::tests::LdmlTestSource &test_source, - std::vector &test_context) { + std::list &test_context) { // print_context(text_store, test_state, test_context); switch (act.type) { @@ -183,9 +183,9 @@ apply_action( // We replace the cached context with the current application context km_core_status status = context_items_from_utf16(text_store.c_str(), &new_context_items); test_assert(status == KM_CORE_STATUS_OK); - copy_context_items_to_vector(new_context_items, context); + copy_context_items_to_list(new_context_items, context); // also update the test context - copy_context_items_to_vector(new_context_items, test_context); + copy_context_items_to_list(new_context_items, test_context); // TODO-LDML: now we need to SET the core context! status = km_core_context_set(km_core_state_context(test_state), new_context_items); km_core_context_items_dispose(new_context_items); @@ -211,9 +211,9 @@ apply_actions( km_core_state *test_state, km_core_actions const *actions, std::u16string &text_store, - std::vector &context, + std::list &context, km::tests::LdmlTestSource &test_source, - std::vector &test_context + std::list &test_context ) { if(actions->do_alert) { @@ -244,7 +244,7 @@ apply_actions( } void -print_context(std::u16string &text_store, km_core_state *&test_state, std::vector &test_context) { +print_context(std::u16string &text_store, km_core_state *&test_state, std::list &test_context) { // Compare context and text store at each step - should be identical size_t n = 0; km_core_context_item *citems = nullptr; @@ -279,7 +279,7 @@ print_context(std::u16string &text_store, km_core_state *&test_state, std::vecto std::cout << "test_context : "; std::cout.fill('0'); - for (auto i = test_context.begin(); i < test_context.end(); i++) { + for (auto i = test_context.begin(); i != test_context.end(); i++) { switch (i->type) { case KM_CORE_CT_CHAR: std::cout << "U+" << std::setw(4) << std::hex << i->character << std::dec << " "; @@ -301,7 +301,7 @@ print_context(std::u16string &text_store, km_core_state *&test_state, std::vecto * verify the current context */ void -verify_context(std::u16string &text_store, km_core_state *&test_state, std::vector &test_context, bool fully_normalized_mode, bool normalization_enabled) { +verify_context(std::u16string &text_store, km_core_state *&test_state, std::list &test_context, bool fully_normalized_mode, bool normalization_enabled) { // Compare context and text store at each step - should be identical print_context(text_store, test_state, test_context); @@ -434,7 +434,7 @@ run_test(const km::core::path &source, const km::core::path &compiled, km::tests g_beep_found = false; - std::vector test_context; + std::list test_context; km_core_context_item *citems = nullptr; // setup test_context @@ -447,7 +447,7 @@ run_test(const km::core::path &source, const km::core::path &compiled, km::tests } // Make a copy of the setup context for the test - copy_context_items_to_vector(citems, test_context); + copy_context_items_to_list(citems, test_context); km_core_context_items_dispose(citems); // Setup baseline text store From b405bf58421dd4f1042f9128cced1989cebe72f4 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 18 Feb 2026 17:34:02 +0100 Subject: [PATCH 11/17] refactor(core): simplify loop for removing text Instead of using an iterator to loop over the context items, incrementing a counter on each iteration, and then finally removing the calculated number of context items from the list, this change loops through the list and looks at the last context item, removing it if necessary. Follows: #15596 Test-bot: skip --- core/src/ldml/ldml_processor.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/core/src/ldml/ldml_processor.cpp b/core/src/ldml/ldml_processor.cpp index 04dd15ab83..17e4d634eb 100644 --- a/core/src/ldml/ldml_processor.cpp +++ b/core/src/ldml/ldml_processor.cpp @@ -415,26 +415,25 @@ void ldml_event_state::remove_text(std::u32string &str, size_t length) { // str is the string to remove, so it should be at least as long as length assert(length <= str.length()); - /** track how many context items have been removed, via push_backspace() */ - size_t contextRemoved = 0; - for (auto c = state->context().rbegin(); length > 0 && c != state->context().rend(); c++, contextRemoved++) { + while (length > 0 && !state->context().empty()) { #ifndef NDEBUG /** last char of context */ km_core_usv lastCtx = str.back(); #endif - uint8_t type = c->type; + auto lastStateCtx = state->context().back(); + uint8_t type = lastStateCtx.type; assert(type == KM_CORE_BT_CHAR || type == KM_CORE_BT_MARKER); if (type == KM_CORE_BT_CHAR) { // single char, drop it length--; - assert(c->character == lastCtx); + assert(lastStateCtx.character == lastCtx); str.pop_back(); // Cause prior char to be removed actions.code_points_to_delete++; } else if (type == KM_CORE_BT_MARKER) { assert(length >= 3); // #3 - the marker. - assert(lastCtx == c->marker); + assert(lastCtx == lastStateCtx.marker); str.pop_back(); length--; // #2 - the code @@ -447,13 +446,9 @@ ldml_event_state::remove_text(std::u32string &str, size_t length) { // Nothing in actions length--; } - } - assert(length == 0); - // now, pop the context items - for (size_t i = 0; i < contextRemoved; i++) { - // we don't pop during the above loop because the iterator gets confused state->context().pop_back(); } + assert(length == 0); } void From a91f098ed6ba9f9ac57122eea416696dc120658c Mon Sep 17 00:00:00 2001 From: Shawn Schantz Date: Thu, 19 Feb 2026 11:21:54 -0500 Subject: [PATCH 12/17] maint(ios): resolved warnings for Xcode 26 the keyboard is blank when running in the simulator unsure why and removing these warnings does not resolve the issue --- ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift | 2 +- .../Installation/PackageInstallViewController.swift | 4 ++-- .../Classes/Keyboard/KeymanWebDelegate.swift | 2 +- .../Classes/Keyboard/KeymanWebViewController.swift | 7 +++++-- .../KMEI/KeymanEngine/Classes/Obsoletions.swift | 6 +++--- .../Classes/PackageWebViewController.swift | 13 +++++++------ .../Classes/Resource Data/FontManager.swift | 2 +- .../Classes/ResourceDownloadStatusToolbar.swift | 2 +- .../Settings/InstalledLanguagesViewController.swift | 2 +- .../KeymanEngine/Classes/kmp.json/KMPKeyboard.swift | 2 +- .../Classes/kmp.json/KMPLexicalModel.swift | 2 +- .../MainViewController/MainViewController.swift | 2 +- 12 files changed, 25 insertions(+), 21 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift b/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift index 345eeb9312..9d84fd1a2c 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift @@ -16,7 +16,7 @@ open class Alerts { public static func constructActivitySpinner() -> UIActivityIndicatorView { let activitySpinner: UIActivityIndicatorView - activitySpinner = UIActivityIndicatorView(style: .whiteLarge) + activitySpinner = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) activitySpinner.hidesWhenStopped = true activitySpinner.translatesAutoresizingMaskIntoConstraints = false activitySpinner.backgroundColor = Colors.spinnerBackground diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift index 390583510d..38848b316c 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift @@ -195,8 +195,8 @@ public class PackageInstallViewController: UIViewCon tabView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(tabVC.view) - tabView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true - tabView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true + tabView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true + tabView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true tabView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true tabView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift index 9a3ed80b9a..aaa6b82f9d 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift @@ -9,7 +9,7 @@ import WebKit /// Delegate receiving events from Keyman Web. -protocol KeymanWebDelegate: class { +protocol KeymanWebDelegate: AnyObject { /// Keyman Web has loaded (or reloaded). func keyboardLoaded(_ keymanWeb: KeymanWebViewController) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift index 4bd5375bc9..2eca96cf49 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift @@ -118,11 +118,14 @@ class KeymanWebViewController: UIViewController { override func loadView() { let config = WKWebViewConfiguration() let prefs = WKPreferences() - prefs.javaScriptEnabled = true config.preferences = prefs config.suppressesIncrementalRendering = false config.userContentController = self.userContentController + let webPagePrefs = WKWebpagePreferences.init() + webPagePrefs.allowsContentJavaScript = true + config.defaultWebpagePreferences = webPagePrefs + webView = KeymanWebView(frame: CGRect(origin: .zero, size: keyboardSize), configuration: config) webView!.isOpaque = false webView!.translatesAutoresizingMaskIntoConstraints = false @@ -253,7 +256,7 @@ extension KeymanWebViewController { self.currentText = String(jsonText) - var finalRange = range ?? self.currentCursorRange ?? nil + let finalRange = range ?? self.currentCursorRange ?? nil self.currentCursorRange = finalRange // diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift b/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift index 4587dd5c58..53b5879bfd 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift @@ -17,10 +17,10 @@ public enum APIKeyboardFetchError: Error { } public class APIKeyboardRepository { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APIKeyboardRepository and associated types have been obsoleted in favor of keyboard search and package-oriented queries.") -public protocol KeyboardRepository: class { } +public protocol KeyboardRepository: AnyObject { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APIKeyboardRepository and associated types have been obsoleted in favor of keyboard search and package-oriented queries.") -public protocol KeyboardRepositoryDelegate: class { } +public protocol KeyboardRepositoryDelegate: AnyObject { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APILexicalModelRepository and associated types have been obsoleted by `Queries.LexicalModel` and its `fetch` variants.") public protocol LexicalModelRepository { } @@ -32,7 +32,7 @@ public enum APILexicalModelFetchError: Error { } public class APILexicalModelRepository { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APILexicalModelRepository and associated types have been obsoleted by `Queries.LexicalModel` and its `fetch` variants.") -public protocol LexicalModelRepositoryDelegate: class { } +public protocol LexicalModelRepositoryDelegate: AnyObject { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "This type is no longer utilized by KeymanEngine, as the related API methods have all been obsoleted.") public struct Options: Codable { } diff --git a/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift index 0277065a7e..111a99fc98 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift @@ -40,17 +40,18 @@ class PackageWebViewController: UIViewController, WKNavigationDelegate { override func loadView() { let config = WKWebViewConfiguration() - let prefs = WKPreferences() - prefs.javaScriptEnabled = true + let webkitPrefs = WKPreferences() /** In iPadOS 16 and above WKWebView defaults to lying about its user-agent, telling the web server that it is a mac. We can avoid this with .mobile: */ - let pref = WKWebpagePreferences.init() - pref.preferredContentMode = .mobile - config.defaultWebpagePreferences = pref + let webPagePrefs = WKWebpagePreferences.init() + webPagePrefs.preferredContentMode = .mobile + webPagePrefs.allowsContentJavaScript = true + config.defaultWebpagePreferences = webPagePrefs + // Inject a meta viewport tag into the head of the file if it doesn't exist let metaViewportInjection = """ if(!document.querySelectorAll('meta[name=viewport]').length) { @@ -64,7 +65,7 @@ class PackageWebViewController: UIViewController, WKNavigationDelegate { let injection = WKUserScript(source: metaViewportInjection, injectionTime: .atDocumentStart, forMainFrameOnly: true) let controller = WKUserContentController() controller.addUserScript(injection) - config.preferences = prefs + config.preferences = webkitPrefs config.userContentController = controller webView = WKWebView(frame: CGRect.zero, configuration: config) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index 6070de2c96..32e938da4f 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -65,7 +65,7 @@ public class FontManager { // // Calls to `cachedFont` after the `.filter` below may be assumed to have // non-nil return values. - var fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } + let fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } // The prior line filters out any entries where cachedFont(at: $0) would be nil. // Batch-lookups all fonts lacking cache-confirmation of prior registration. diff --git a/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift b/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift index 4625aad046..5bc2421f95 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift @@ -72,7 +72,7 @@ public class ResourceDownloadStatusToolbar: UIToolbar { * Creates the classic spinning-wheel 'activity in progress' indicator. */ private func setupActivityIndicator() -> UIActivityIndicatorView { - let indicatorView = UIActivityIndicatorView(style: .gray) + let indicatorView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium) indicatorView.center = CGPoint(x: frame.width - indicatorView.frame.width, y: frame.height * 0.5) indicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin, .flexibleBottomMargin] diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift index 54eaa542f3..d213567e65 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift @@ -389,7 +389,7 @@ public class InstalledLanguagesViewController: UITableViewController, UIAlertVie func showActivityView() { view.isUserInteractionEnabled = false - let indicatorView = UIActivityIndicatorView(style: .whiteLarge) + let indicatorView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) let activityView = UIView(frame: indicatorView.bounds.insetBy(dx: -10.0, dy: -10.0)) activityView.backgroundColor = Colors.spinnerBackground activityView.layer.cornerRadius = 6.0 diff --git a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift index 7a735f5fd3..336b29d3a9 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift @@ -8,7 +8,7 @@ import Foundation -class KMPKeyboard: Codable, KMPResource { +final class KMPKeyboard: Codable, KMPResource { public var name: String public var keyboardId: String public var packageId: String? diff --git a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift index d63f451e56..63c7fba524 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift @@ -8,7 +8,7 @@ import Foundation -class KMPLexicalModel: Codable, KMPResource { +final class KMPLexicalModel: Codable, KMPResource { public var name: String public var lexicalModelId: String public var packageId: String? diff --git a/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift b/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift index 7c445a8fe4..a55055d389 100644 --- a/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift +++ b/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift @@ -781,7 +781,7 @@ class MainViewController: UIViewController, TextViewDelegate, UIActionSheetDeleg dismissGetStartedView(nil) overlayWindow.isHidden = false - let activityView = UIActivityIndicatorView(style: .whiteLarge) + let activityView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) let containerView = UIView(frame: activityView.bounds.insetBy(dx: -10.0, dy: -10.0)) containerView.backgroundColor = Colors.spinnerBackground containerView.layer.cornerRadius = 6.0 From 2237db95f612813413417cb58b24512ab5d03ee9 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 13 Feb 2026 18:25:59 +0100 Subject: [PATCH 13/17] test(core): add LDML baseline test with minimal keyboard This replaces and enables the commented `k_000_null_keyboard` test which didn't work because keys that are not on any layer don't produce output. This instead defines a minimal keyboard with just two keys and then tests typing a key that is on the keyboard followed by a key not on the keyboard. Test-bot: skip --- .../ldml/keyboards/k_000_minimal_keyboard.xml | 23 +++++++++++++++++++ .../ldml/keyboards/k_000_null_keyboard.xml | 10 -------- core/tests/unit/ldml/keyboards/meson.build | 3 +-- 3 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 core/tests/unit/ldml/keyboards/k_000_minimal_keyboard.xml delete mode 100644 core/tests/unit/ldml/keyboards/k_000_null_keyboard.xml diff --git a/core/tests/unit/ldml/keyboards/k_000_minimal_keyboard.xml b/core/tests/unit/ldml/keyboards/k_000_minimal_keyboard.xml new file mode 100644 index 0000000000..44c043f891 --- /dev/null +++ b/core/tests/unit/ldml/keyboards/k_000_minimal_keyboard.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/core/tests/unit/ldml/keyboards/k_000_null_keyboard.xml b/core/tests/unit/ldml/keyboards/k_000_null_keyboard.xml deleted file mode 100644 index 73dfce5dd9..0000000000 --- a/core/tests/unit/ldml/keyboards/k_000_null_keyboard.xml +++ /dev/null @@ -1,10 +0,0 @@ - - diff --git a/core/tests/unit/ldml/keyboards/meson.build b/core/tests/unit/ldml/keyboards/meson.build index 55004f78b8..29aa37541b 100644 --- a/core/tests/unit/ldml/keyboards/meson.build +++ b/core/tests/unit/ldml/keyboards/meson.build @@ -17,8 +17,7 @@ tests_from_cldr = [ # these have 'embedded' (@@) testdata instead of a separate file tests_without_testdata = [ -# disabling 000 until we have updates to core or to the keyboard so that it passes -# 'k_000_null_keyboard', + 'k_000_minimal_keyboard', 'k_002_tinyu32', 'k_003_transform', 'k_004_tinyshift', From 60e49fe2710636b0e5965d63c577e89a8fcad6b5 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Fri, 20 Feb 2026 12:01:18 -0600 Subject: [PATCH 14/17] auto: increment master version to 19.0.205 Test-bot: skip Build-bot: skip --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index a24f4ba447..05f975e397 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 19.0.204 alpha 2026-02-20 + +* maint(web): ensure Web build scripts handle paths with spaces properly (#15598) + ## 19.0.203 alpha 2026-02-16 * docs: Add status.keyman.com info to website readme (#15591) diff --git a/VERSION.md b/VERSION.md index 846c888483..8b71bafa00 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.204 \ No newline at end of file +19.0.205 \ No newline at end of file From 610ccc11c2726e2e615b9b868b07fdeebf9ca8dc Mon Sep 17 00:00:00 2001 From: Shawn Schantz Date: Mon, 23 Feb 2026 13:38:01 -0500 Subject: [PATCH 15/17] Revert "maint(ios): resolved warnings for Xcode 26" This reverts commit a91f098ed6ba9f9ac57122eea416696dc120658c. Apply these changes in a separate PR. --- ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift | 2 +- .../Installation/PackageInstallViewController.swift | 4 ++-- .../Classes/Keyboard/KeymanWebDelegate.swift | 2 +- .../Classes/Keyboard/KeymanWebViewController.swift | 7 ++----- .../KMEI/KeymanEngine/Classes/Obsoletions.swift | 6 +++--- .../Classes/PackageWebViewController.swift | 13 ++++++------- .../Classes/Resource Data/FontManager.swift | 2 +- .../Classes/ResourceDownloadStatusToolbar.swift | 2 +- .../Settings/InstalledLanguagesViewController.swift | 2 +- .../KeymanEngine/Classes/kmp.json/KMPKeyboard.swift | 2 +- .../Classes/kmp.json/KMPLexicalModel.swift | 2 +- .../MainViewController/MainViewController.swift | 2 +- 12 files changed, 21 insertions(+), 25 deletions(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift b/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift index 9d84fd1a2c..345eeb9312 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Alerts.swift @@ -16,7 +16,7 @@ open class Alerts { public static func constructActivitySpinner() -> UIActivityIndicatorView { let activitySpinner: UIActivityIndicatorView - activitySpinner = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) + activitySpinner = UIActivityIndicatorView(style: .whiteLarge) activitySpinner.hidesWhenStopped = true activitySpinner.translatesAutoresizingMaskIntoConstraints = false activitySpinner.backgroundColor = Colors.spinnerBackground diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift index 38848b316c..390583510d 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Installation/PackageInstallViewController.swift @@ -195,8 +195,8 @@ public class PackageInstallViewController: UIViewCon tabView.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(tabVC.view) - tabView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true - tabView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true + tabView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true + tabView.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true tabView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true tabView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift index aaa6b82f9d..9a3ed80b9a 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebDelegate.swift @@ -9,7 +9,7 @@ import WebKit /// Delegate receiving events from Keyman Web. -protocol KeymanWebDelegate: AnyObject { +protocol KeymanWebDelegate: class { /// Keyman Web has loaded (or reloaded). func keyboardLoaded(_ keymanWeb: KeymanWebViewController) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift index 2eca96cf49..4bd5375bc9 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/KeymanWebViewController.swift @@ -118,14 +118,11 @@ class KeymanWebViewController: UIViewController { override func loadView() { let config = WKWebViewConfiguration() let prefs = WKPreferences() + prefs.javaScriptEnabled = true config.preferences = prefs config.suppressesIncrementalRendering = false config.userContentController = self.userContentController - let webPagePrefs = WKWebpagePreferences.init() - webPagePrefs.allowsContentJavaScript = true - config.defaultWebpagePreferences = webPagePrefs - webView = KeymanWebView(frame: CGRect(origin: .zero, size: keyboardSize), configuration: config) webView!.isOpaque = false webView!.translatesAutoresizingMaskIntoConstraints = false @@ -256,7 +253,7 @@ extension KeymanWebViewController { self.currentText = String(jsonText) - let finalRange = range ?? self.currentCursorRange ?? nil + var finalRange = range ?? self.currentCursorRange ?? nil self.currentCursorRange = finalRange // diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift b/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift index 53b5879bfd..4587dd5c58 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Obsoletions.swift @@ -17,10 +17,10 @@ public enum APIKeyboardFetchError: Error { } public class APIKeyboardRepository { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APIKeyboardRepository and associated types have been obsoleted in favor of keyboard search and package-oriented queries.") -public protocol KeyboardRepository: AnyObject { } +public protocol KeyboardRepository: class { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APIKeyboardRepository and associated types have been obsoleted in favor of keyboard search and package-oriented queries.") -public protocol KeyboardRepositoryDelegate: AnyObject { } +public protocol KeyboardRepositoryDelegate: class { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APILexicalModelRepository and associated types have been obsoleted by `Queries.LexicalModel` and its `fetch` variants.") public protocol LexicalModelRepository { } @@ -32,7 +32,7 @@ public enum APILexicalModelFetchError: Error { } public class APILexicalModelRepository { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "APILexicalModelRepository and associated types have been obsoleted by `Queries.LexicalModel` and its `fetch` variants.") -public protocol LexicalModelRepositoryDelegate: AnyObject { } +public protocol LexicalModelRepositoryDelegate: class { } @available(swift, deprecated: 0.1, obsoleted: 0.1, message: "This type is no longer utilized by KeymanEngine, as the related API methods have all been obsoleted.") public struct Options: Codable { } diff --git a/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift index 111a99fc98..0277065a7e 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/PackageWebViewController.swift @@ -40,18 +40,17 @@ class PackageWebViewController: UIViewController, WKNavigationDelegate { override func loadView() { let config = WKWebViewConfiguration() - let webkitPrefs = WKPreferences() + let prefs = WKPreferences() + prefs.javaScriptEnabled = true /** In iPadOS 16 and above WKWebView defaults to lying about its user-agent, telling the web server that it is a mac. We can avoid this with .mobile: */ - let webPagePrefs = WKWebpagePreferences.init() - webPagePrefs.preferredContentMode = .mobile - webPagePrefs.allowsContentJavaScript = true - config.defaultWebpagePreferences = webPagePrefs + let pref = WKWebpagePreferences.init() + pref.preferredContentMode = .mobile + config.defaultWebpagePreferences = pref - // Inject a meta viewport tag into the head of the file if it doesn't exist let metaViewportInjection = """ if(!document.querySelectorAll('meta[name=viewport]').length) { @@ -65,7 +64,7 @@ class PackageWebViewController: UIViewController, WKNavigationDelegate { let injection = WKUserScript(source: metaViewportInjection, injectionTime: .atDocumentStart, forMainFrameOnly: true) let controller = WKUserContentController() controller.addUserScript(injection) - config.preferences = webkitPrefs + config.preferences = prefs config.userContentController = controller webView = WKWebView(frame: CGRect.zero, configuration: config) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift index 32e938da4f..6070de2c96 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Resource Data/FontManager.swift @@ -65,7 +65,7 @@ public class FontManager { // // Calls to `cachedFont` after the `.filter` below may be assumed to have // non-nil return values. - let fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } + var fontSet = initialFontSet.filter { !(cachedFont(at: $0)?.isRegistered ?? true) } // The prior line filters out any entries where cachedFont(at: $0) would be nil. // Batch-lookups all fonts lacking cache-confirmation of prior registration. diff --git a/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift b/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift index 5bc2421f95..4625aad046 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/ResourceDownloadStatusToolbar.swift @@ -72,7 +72,7 @@ public class ResourceDownloadStatusToolbar: UIToolbar { * Creates the classic spinning-wheel 'activity in progress' indicator. */ private func setupActivityIndicator() -> UIActivityIndicatorView { - let indicatorView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium) + let indicatorView = UIActivityIndicatorView(style: .gray) indicatorView.center = CGPoint(x: frame.width - indicatorView.frame.width, y: frame.height * 0.5) indicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin, .flexibleBottomMargin] diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift index d213567e65..54eaa542f3 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Settings/InstalledLanguagesViewController.swift @@ -389,7 +389,7 @@ public class InstalledLanguagesViewController: UITableViewController, UIAlertVie func showActivityView() { view.isUserInteractionEnabled = false - let indicatorView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) + let indicatorView = UIActivityIndicatorView(style: .whiteLarge) let activityView = UIView(frame: indicatorView.bounds.insetBy(dx: -10.0, dy: -10.0)) activityView.backgroundColor = Colors.spinnerBackground activityView.layer.cornerRadius = 6.0 diff --git a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift index 336b29d3a9..7a735f5fd3 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPKeyboard.swift @@ -8,7 +8,7 @@ import Foundation -final class KMPKeyboard: Codable, KMPResource { +class KMPKeyboard: Codable, KMPResource { public var name: String public var keyboardId: String public var packageId: String? diff --git a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift index 63c7fba524..d63f451e56 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/kmp.json/KMPLexicalModel.swift @@ -8,7 +8,7 @@ import Foundation -final class KMPLexicalModel: Codable, KMPResource { +class KMPLexicalModel: Codable, KMPResource { public var name: String public var lexicalModelId: String public var packageId: String? diff --git a/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift b/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift index a55055d389..7c445a8fe4 100644 --- a/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift +++ b/ios/keyman/Keyman/Keyman/Classes/MainViewController/MainViewController.swift @@ -781,7 +781,7 @@ class MainViewController: UIViewController, TextViewDelegate, UIActionSheetDeleg dismissGetStartedView(nil) overlayWindow.isHidden = false - let activityView = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.large) + let activityView = UIActivityIndicatorView(style: .whiteLarge) let containerView = UIView(frame: activityView.bounds.insetBy(dx: -10.0, dy: -10.0)) containerView.backgroundColor = Colors.spinnerBackground containerView.layer.cornerRadius = 6.0 From 464421a9ff3724f83c0b1de0d2234a2f55bcc312 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Tue, 24 Feb 2026 12:01:46 -0600 Subject: [PATCH 16/17] auto: increment master version to 19.0.206 Test-bot: skip Build-bot: skip --- HISTORY.md | 6 ++++++ VERSION.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 05f975e397..95455d540f 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ # Keyman Version History +## 19.0.205 alpha 2026-02-24 + +* fix(core): fix iterator in backspace handling (#15596) +* refactor(core): simplify loop for removing text (#15600) +* test(core): add LDML baseline test with minimal keyboard (#15608) + ## 19.0.204 alpha 2026-02-20 * maint(web): ensure Web build scripts handle paths with spaces properly (#15598) diff --git a/VERSION.md b/VERSION.md index 8b71bafa00..616f6c2126 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.205 \ No newline at end of file +19.0.206 \ No newline at end of file From 1cc1e972adbe596c04144fa0b5c3625dfbbd294f Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 25 Feb 2026 12:01:25 -0600 Subject: [PATCH 17/17] auto: increment master version to 19.0.207 Test-bot: skip Build-bot: skip --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 95455d540f..f42af6d60b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 19.0.206 alpha 2026-02-25 + +* maint(ios): upgrade to Xcode 26.2 (#15498) + ## 19.0.205 alpha 2026-02-24 * fix(core): fix iterator in backspace handling (#15596) diff --git a/VERSION.md b/VERSION.md index 616f6c2126..3027f050d0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -19.0.206 \ No newline at end of file +19.0.207 \ No newline at end of file