Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
25a40ab
fix(developer): resync model and keyboard after device switch in Server
mcdurdin Jun 23, 2026
d866049
chore(developer): consolidate api-extractor usage in Developer
mcdurdin Jun 24, 2026
77ad99e
feat(android): add keyman-version to package-version check
mcdurdin Jun 25, 2026
bbeb799
feat(ios): add keyman-version to package-version check
mcdurdin Jun 25, 2026
7155e9d
fix(android): refactor `KMLog` - simplification and added resilience
mcdurdin Jun 29, 2026
b535203
chore(developer): fix docs, api_extractor params in build.sh's
mcdurdin Jun 29, 2026
809a3ca
chore(android): address review comments
mcdurdin Jun 30, 2026
0fc869f
fix(web): define IME interfaces in `KeyboardInterfaceBase`
mcdurdin Jul 1, 2026
d527e37
docs(web): cleanup of index pages and page titles
mcdurdin Jul 1, 2026
e6d86d7
refactor(web): rename `keymanweb` to `keyman` in UI modules
mcdurdin Jul 1, 2026
cda7dc6
chore: remove deprecated "X-UA-Compatible" and "apple-mobile-web-app-…
mcdurdin Jul 1, 2026
a1bd098
Merge branch 'master' into fix/web/16144-define-interfaces-for-imes-i…
mcdurdin Jul 2, 2026
948c02c
chore(developer): Merge branch 'master' into fix/developer/15217-resy…
mcdurdin Jul 2, 2026
db88104
fix(developer): move osk banner resync from Server frontend to Web se…
mcdurdin Jul 2, 2026
1191e43
fix(android): fix setting font
ermshiperete Jul 2, 2026
1867a76
Apply suggestions from code review
ermshiperete Jul 3, 2026
70282bf
fix(android): rename method to `getKeyboardTextFontFilenameOnly`
ermshiperete Jul 3, 2026
81b0c0b
fix(web): fixes cookie unit-tests and path for OSK resources during t…
jahorton Jul 6, 2026
c6db29c
chore(linux): reorder buttons on kmp install window
kingsuper195 Jul 8, 2026
71aefb8
fix(android): address code review comments
ermshiperete Jul 8, 2026
e00304c
Merge pull request #16210 from kingsuper195/chore/linux/install-kmp-b…
mcdurdin Jul 8, 2026
c9bfc87
Merge pull request #16174 from keymanapp/refactor/web/16168-ui-remove…
mcdurdin Jul 8, 2026
34c6beb
Merge pull request #16176 from keymanapp/chore/16172-remove-deprecate…
mcdurdin Jul 8, 2026
1aae71e
Merge pull request #16152 from keymanapp/fix/android/16122-refactor-K…
mcdurdin Jul 8, 2026
fcf8988
Merge pull request #16188 from keymanapp/fix/android/16187_font
ermshiperete Jul 8, 2026
d0e1649
chore(android): cleanup font variable names, remove obsolete code
ermshiperete Jul 8, 2026
21c4345
Merge pull request #16209 from keymanapp/fix/auto-test-cookies-and-paths
jahorton Jul 8, 2026
3369ad8
auto: increment master version to 19.0.253
keyman-server Jul 8, 2026
d094af0
Merge pull request #16212 from keymanapp/auto/version-master-19.0.253
keyman-server Jul 8, 2026
c51657a
Merge branch 'master' into feat/ios/325-add-keyman-version-check-to-p…
mcdurdin Jul 9, 2026
41344ab
Merge branch 'master' into feat/android/325-add-keyman-version-check-…
mcdurdin Jul 9, 2026
4ab67f5
Merge pull request #16127 from keymanapp/fix/developer/15217-resync-m…
mcdurdin Jul 9, 2026
528876b
Merge pull request #16135 from keymanapp/chore/developer/14838-consol…
mcdurdin Jul 9, 2026
574e7f6
chore(android): address code review comments
ermshiperete Jul 9, 2026
2e3e347
auto: increment master version to 19.0.254
keyman-server Jul 9, 2026
00c213b
Merge pull request #16213 from keymanapp/auto/version-master-19.0.254
keyman-server Jul 9, 2026
b22798d
fix(android): add permissions for Sentry and set default keyboard
ermshiperete Jul 10, 2026
2b078ce
fix(android): handle blank keyboard tap properly
mcdurdin Jul 10, 2026
83328c9
fix(web): ensure onmouseleave does not crash if mouseEnterPromise is …
mcdurdin Jul 10, 2026
2b2339d
fix(android): restrict fallback tap to document element only
mcdurdin Jul 10, 2026
ab2d0a8
maint(android): use KEYMAN_TIER instead of TIER.md
mcdurdin Jul 10, 2026
96b0a4b
Merge pull request #16217 from keymanapp/fix/android/handle-blank-key…
mcdurdin Jul 10, 2026
07daf94
Merge pull request #16170 from keymanapp/fix/web/16144-define-interfa…
mcdurdin Jul 10, 2026
7cf6ed0
auto: increment master version to 19.0.255
keyman-server Jul 10, 2026
54705df
Merge pull request #16222 from keymanapp/auto/version-master-19.0.255
keyman-server Jul 10, 2026
bafc1f8
Merge pull request #16219 from keymanapp/maint/android/use-env-instea…
mcdurdin Jul 11, 2026
79bc1d8
Merge pull request #16138 from keymanapp/feat/ios/325-add-keyman-vers…
mcdurdin Jul 11, 2026
0d8e6ae
Merge pull request #16171 from keymanapp/docs/web/16169-cleanup
mcdurdin Jul 11, 2026
b25005b
docs(web): fix typos following #16170
mcdurdin Jul 11, 2026
c61734c
Merge pull request #16139 from keymanapp/feat/android/325-add-keyman-…
mcdurdin Jul 11, 2026
0e076d5
chore(web): declare scope for stubAndKeyboardCache members
mcdurdin Jul 10, 2026
e6fdecc
auto: increment master version to 19.0.256
keyman-server Jul 11, 2026
f500d0a
Merge pull request #16227 from keymanapp/auto/version-master-19.0.256
keyman-server Jul 11, 2026
7889d9a
Merge pull request #16216 from keymanapp/fix/android/16180_scriptError
ermshiperete Jul 13, 2026
cb8f958
fix(android): improve clarity of keyboard script error popup
mcdurdin Jul 13, 2026
ab2bfc9
maint(resources): add extra debug reporting for builder
mcdurdin Jul 13, 2026
a1c8e63
chore(android): cleanup Android build scripts and artifact filenames
mcdurdin Jul 13, 2026
d295e0f
maint(resources): add comment for debug printing
mcdurdin Jul 13, 2026
1639f1f
Merge pull request #16230 from keymanapp/maint/resources/builder-debu…
mcdurdin Jul 13, 2026
896387a
chore(linux): remove questing, add stonking
ermshiperete Jul 13, 2026
b04e28a
chore(android): log legacy cloud keyboards
ermshiperete Jul 13, 2026
82ab647
chore(android): keep handling of legacy keyboards
ermshiperete Jul 13, 2026
88731e5
chore(android): more cleanup
ermshiperete Jul 13, 2026
1174752
auto: increment master version to 19.0.257
keyman-server Jul 13, 2026
9a40db7
Merge pull request #16238 from keymanapp/auto/version-master-19.0.257
keyman-server Jul 13, 2026
6537d60
Merge pull request #16236 from keymanapp/chore/linux/16235_remove-que…
ermshiperete Jul 14, 2026
5c42897
Merge pull request #16234 from keymanapp/chore/android/16137-cleanup-…
mcdurdin Jul 14, 2026
3852d35
Merge pull request #16221 from keymanapp/chore/web/stubAndKeyboardCac…
mcdurdin Jul 14, 2026
3c38a4c
Merge pull request #16228 from keymanapp/fix/android/16145-error-popu…
mcdurdin Jul 14, 2026
9bdfe0e
chore(android): address code review comments
ermshiperete Jul 14, 2026
c03e63b
Merge pull request #16237 from keymanapp/chore/android/loglegacy
ermshiperete Jul 14, 2026
a93467a
chore(android): remove doc for non-existing deprecated functions
ermshiperete Jul 14, 2026
1581f7a
Merge pull request #16211 from keymanapp/chore/android/cleanup
ermshiperete Jul 14, 2026
b0a4b44
auto: increment master version to 19.0.258
keyman-server Jul 14, 2026
aa5e4a4
Merge pull request #16245 from keymanapp/auto/version-master-19.0.258
keyman-server Jul 14, 2026
edbdbfa
Merge pull request #16244 from keymanapp/chore/android/obsoletedeprec…
ermshiperete Jul 15, 2026
043e1ca
auto: increment master version to 19.0.259
keyman-server Jul 15, 2026
6800dcd
Merge pull request #16249 from keymanapp/auto/version-master-19.0.259
keyman-server Jul 15, 2026
8d533da
Merge pull request #16225 from keymanapp/docs/web/typos
mcdurdin Jul 20, 2026
0f16f39
chore: Merge branch 'epic/web-core' into auto/A19S33-merge-master-int…
ermshiperete Jul 20, 2026
e37989c
chore: Merge branch 'epic/web-core' into auto/A19S33-merge-master-int…
ermshiperete Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deb-packaging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ jobs:
strategy:
fail-fast: true
matrix:
dist: [jammy, noble, questing]
dist: [jammy, noble, resolute]

steps:
- name: Checkout
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,7 @@ lcov.info

# flag file for build script
.configured

# see common/tools/api-extractor/README.md
tsdoc.json
api-extractor.json
44 changes: 44 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Keyman Version History

## 19.0.258 alpha 2026-07-15

* chore(android): remove doc for non-existing deprecated functions (#16244)

## 19.0.257 alpha 2026-07-14

* chore(linux): remove questing, add stonking (#16236)
* chore(android): cleanup Android build scripts and artifact filenames (#16234)
* chore(web): declare scope for stubAndKeyboardCache members (#16221)
* fix(android): improve clarity of keyboard script error popup (#16228)
* chore(android): log legacy cloud keyboards (#16237)
* chore(android): cleanup font variable names, remove obsolete code (#16211)

## 19.0.256 alpha 2026-07-13

* fix(android): add permissions for Sentry and set default keyboard (#16216)
* maint(resources): add extra debug reporting for builder (#16230)

## 19.0.255 alpha 2026-07-11

* maint(android): use KEYMAN_TIER instead of TIER.md (#16219)
* feat(ios): add keyman-version to package-version check (#16138)
* docs(web): cleanup of index pages and page titles (#16171)
* feat(android): add keyman-version to package-version check (#16139)

## 19.0.254 alpha 2026-07-10

* fix(android): handle blank keyboard tap properly (#16217)
* fix(web): define IME interfaces in `KeyboardInterfaceBase` (#16170)

## 19.0.253 alpha 2026-07-09

* fix(web): resync model in `set osk()` (as used by Server) (#16127)
* chore(developer): consolidate api-extractor usage in Developer (#16135)

## 19.0.252 alpha 2026-07-08

* chore(linux): reorder buttons on kmp install window (#16210)
* refactor(web): rename `keymanweb` to `keyman` in UI modules (#16174)
* chore: remove deprecated "X-UA-Compatible" and "apple-mobile-web-app-capable" metas (#16176)
* fix(android): refactor `KMLog` - simplification and added resilience (#16152)
* fix(android): differentiate between fontPath and fontUrl in Keyman Engine for Android (#16188)
* fix(web): fixes cookie unit-tests and path for OSK resources during testing (#16209)

## 19.0.251 alpha 2026-07-02

* fix(android): skip test on Windows that triggers androidx WebKit bug (#16184)
Expand Down
2 changes: 1 addition & 1 deletion VERSION.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19.0.252
19.0.259
96 changes: 39 additions & 57 deletions android/KMAPro/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env bash
# Build Keyman for Android app (KMAPro)
# Keyman is copyright (C) SIL Global. MIT License.
#
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
Expand All @@ -9,111 +10,92 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "$KEYMAN_ROOT/resources/build/utils.inc.sh"
. "$KEYMAN_ROOT/resources/build/build-help.inc.sh"
. "$KEYMAN_ROOT/resources/build/build-download-resources.sh"

. "$KEYMAN_ROOT/android/KMAPro/build-play-store-notes.inc.sh"

# ################################ Main script ################################

# Definition of global compile constants

CONFIG="release"
BUILD_FLAGS="build -x lint -x test" # Gradle build w/o test
TEST_FLAGS="-x assembleRelease lintRelease testRelease" # Gradle test w/o build
DAEMON_FLAG=

builder_describe "Builds Keyman for Android app." \
"@/android/KMEA" \
"clean" \
"configure" \
"build" \
"test Runs lint and unit tests." \
"publish-symbols Publishes symbols to Sentry." \
"test Runs lint and unit tests." \
"publish-symbols Publishes symbols to Sentry." \
"publish-play-store Publishes the APK to the Play Store."

# parse before describe_outputs to check debug flags
builder_parse "$@"

if builder_is_debug_build; then
builder_heading "### Debug config ####"
CONFIG="debug"
BUILD_FLAGS="assembleDebug -x lintDebug -x testDebug"
TEST_FLAGS="-x assembleDebug lintDebug testDebug"
else
BUILD_FLAGS="build -x lint -x test" # Gradle build w/o test
TEST_FLAGS="-x assembleRelease lintRelease testRelease" # Gradle test w/o build
fi

if builder_is_ci_build; then
GRADLE_DAEMON=--no-daemon
else
GRADLE_DAEMON=
fi

# Locations for bundled keyboard and lexical model

KEYBOARD_PACKAGE_ID="sil_euro_latin"
KEYBOARDS_TARGET="android/KMAPro/kMAPro/src/main/assets/${KEYBOARD_PACKAGE_ID}.kmp"
MODEL_PACKAGE_ID="nrc.en.mtnt"
MODELS_TARGET="android/KMAPro/kMAPro/src/main/assets/${MODEL_PACKAGE_ID}.model.kmp"

builder_describe_outputs \
configure "/${MODELS_TARGET}" \
build /android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk

#### Build


# Parse args

if builder_is_ci_build; then
DAEMON_FLAG=--no-daemon
fi
build /android/KMAPro/kMAPro/build/outputs/apk/$BUILDER_CONFIGURATION/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk

#### Build action definitions ####

# Check about cleaning artifact paths
if builder_start_action clean; then
rm -rf "$KEYMAN_ROOT/android/KMAPro/kMAPro/build/outputs"
builder_finish_action success clean
fi

if builder_start_action configure; then

do_configure() {
downloadKeyboardPackage "$KEYBOARD_PACKAGE_ID" "${KEYMAN_ROOT}/$KEYBOARDS_TARGET"
downloadModelPackage "$MODEL_PACKAGE_ID" "${KEYMAN_ROOT}/$MODELS_TARGET"
}

builder_finish_action success configure
fi

if builder_start_action build; then

do_build() {
# Copy Keyman Engine for Android
cp "${KEYMAN_ROOT}/android/KMEA/app/build/outputs/aar/keyman-engine-${CONFIG}.aar" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/libs/keyman-engine.aar"
cp "${KEYMAN_ROOT}/android/KMEA/app/build/outputs/aar/keyman-engine-${BUILDER_CONFIGURATION}.aar" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/libs/keyman-engine.aar"

# Convert markdown to html for offline help
build_help_html android KMAPro/kMAPro/src/main/assets/info

echo "BUILD_FLAGS $BUILD_FLAGS"
./gradlew $DAEMON_FLAG clean $BUILD_FLAGS
builder_echo "BUILD_FLAGS $BUILD_FLAGS"
./gradlew $GRADLE_DAEMON $BUILD_FLAGS

mv "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION}.apk" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$CONFIG/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk"

builder_finish_action success build
fi

if builder_start_action test; then

echo "TEST_FLAGS $TEST_FLAGS"
./gradlew $DAEMON_FLAG $TEST_FLAGS
mv "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$BUILDER_CONFIGURATION/keyman-${KEYMAN_VERSION}.apk" "${KEYMAN_ROOT}/android/KMAPro/kMAPro/build/outputs/apk/$BUILDER_CONFIGURATION/keyman-${KEYMAN_VERSION_FOR_FILENAME}.apk"
}

builder_finish_action success test
fi
do_test() {
builder_echo "TEST_FLAGS $TEST_FLAGS"
./gradlew $GRADLE_DAEMON $TEST_FLAGS
}

publish_symbols() {
do_publish_symbols() {
if builder_is_ci_build && builder_is_ci_build_level_release; then
# TODO: what does publishSentry even do?
./gradlew $DAEMON_FLAG publishSentry
./gradlew $GRADLE_DAEMON publishSentry
builder_echo "Making a Sentry release for tag $KEYMAN_VERSION_GIT_TAG"
sentry-cli upload-dif -p keyman-android --include-sources
sentry-cli releases -p keyman-android files $KEYMAN_VERSION_GIT_TAG upload-sourcemaps ./
fi
}

publish_play_store() {
do_publish_play_store() {
if builder_is_ci_build && builder_is_ci_build_level_release; then
generateReleaseNotes
# Publish Keyman for Android to Play Store
./gradlew $DAEMON_FLAG publishReleaseApk
./gradlew $GRADLE_DAEMON publishReleaseApk
fi
}

builder_run_action publish-symbols publish_symbols
builder_run_action publish-play-store publish_play_store
builder_run_action clean rm -rf "$KEYMAN_ROOT/android/KMAPro/kMAPro/build"
builder_run_action configure do_configure
builder_run_action build do_build
builder_run_action test do_test
builder_run_action publish-symbols do_publish_symbols
builder_run_action publish-play-store do_publish_play_store
3 changes: 1 addition & 2 deletions android/KMAPro/kMAPro/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ plugins {

ext.rootPath = '../../'
apply from: "$rootPath/version.gradle"

String tier = new File('../../TIER.md').getText('UTF-8').trim();
String tier = System.getenv("KEYMAN_TIER");

java {
toolchain {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/**
* Copyright (C) 2017 SIL International. All rights reserved.
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/

package com.tavultesoft.kmapro;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
Expand Down Expand Up @@ -386,7 +387,7 @@ protected void onResume() {
super.onResume();
if (webView != null) {
if (didFinishLoading) {
String fontFilename = KMManager.getKeyboardTextFontFilename();
String fontFilename = getKeyboardTextFontFilenameOnly();
if (!loadedFont.equals(fontFilename)) {
webView.reload();
}
Expand Down Expand Up @@ -432,8 +433,19 @@ public void onBackPressed() {
}
}

/**
* Returns the filename without path of the display font of the current keyboard.
*/
private String getKeyboardTextFontFilenameOnly() {
String fontPath = KMManager.getKeyboardTextFontFilename();
if (fontPath == null || fontPath.isEmpty()) {
return "";
}
return new File(fontPath).getName();
}

private void loadFont() {
String font = KMManager.getKeyboardTextFontFilename();
String font = getKeyboardTextFontFilenameOnly();
if (!font.isEmpty()) {
loadedFont = font;
String fontUrl = String.format("%s%s", fontBaseUri, font);
Expand Down
2 changes: 1 addition & 1 deletion android/KMEA/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ext.rootPath = '../../'
apply from: "$rootPath/version.gradle"

base {
// Specify library filename keyman-engine-$CONFIG.aar
// Specify library filename keyman-engine-$BUILDER_CONFIGURATION.aar
archivesName = "keyman-engine"
}

Expand Down
18 changes: 13 additions & 5 deletions android/KMEA/app/src/main/assets/android-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ sentryManager.init();

window.addEventListener('load', init, false);

function loadDefaultKeyboard() {
notifyHost('reloadAfterError');
}

function init() {
//document.body.style.backgroundColor="transparent";
//window.console.log('Device type = '+device);
Expand Down Expand Up @@ -82,7 +78,19 @@ function init() {
keyman.addEventListener('keyboardchange', setIsChiral);
keyman.core.languageProcessor.on('statechange', onStateChange);

document.body.addEventListener('touchend', loadDefaultKeyboard);
// If the keyboard fails to display, this usually indicates that a Javascript
// error has occurred, perhaps in the active keyboard. So we have a last-gasp
// fallback in that situation; if the user touches the blank document, we will
// attempt to reload the default keyboard.
document.addEventListener('touchend', (event) => {
if(event.target == document.documentElement) {
// The error will be reported through to Sentry if the user has error
// reporting enabled; breadcrumbs can give us helpful details on possible
// root causes for the error
window.console.error('user touched the document body, which can only happen if the keyboard was not presented. This is usually caused by another error.');
notifyHost('reloadAfterError');
}
});

notifyHost('pageLoaded');
}
Expand Down
Loading