Skip to content

Commit

Permalink
Merge pull request #10909 from keymanapp/chore/b17s2-merge-beta-to-ma…
Browse files Browse the repository at this point in the history
…ster

chore: B17S2 merge beta to master
  • Loading branch information
ermshiperete authored Mar 5, 2024
2 parents 0a40c1a + af7b17f commit aa17142
Show file tree
Hide file tree
Showing 268 changed files with 7,184 additions and 2,290 deletions.
321 changes: 243 additions & 78 deletions CONTRIBUTING.md

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,98 @@
* chore(common): move to 18.0 alpha (#10713)
* chore: move to 18.0 alpha

## 17.0.279 beta 2024-02-29

* fix(linux): Fix libkeymancore-dev dependencies (#10880)
* chore(resources): update to latest ldml: xmlns, uset (#10865)

## 17.0.278 beta 2024-02-28

* docs(linux): Updated whatsnew for Keyman for Linux 17 (#10858)
* (#10869)
* chore(android/engine): Reduce toast notifications after installations (#10868)
* fix(android/engine): Check selection indexes (#10857)

## 17.0.277 beta 2024-02-27

* fix(developer): exit kmc test data if any failure messages occurred (#10805)
* docs(windows): add whats new Keyman for Windows 17.0 (#10783)
* feat(developer): add api-extractor and api-documenter, config, and build integration (#10839)
* feat(developer): publish api documentation to help.keyman.com (#10841)
* docs(developer): npm package readme files (#10842)
* refactor(developer): move osk module from common-types to developer-utils (#10845)
* chore(linux): Update debian changelog (#10828)
* fix(developer): repeated options in kmc must now be fully specified (#10821)
* docs(developer): add documentation for kmc-analyze (#10854)

## 17.0.276 beta 2024-02-26

* chore(linux): Fix autopkg tests (#10824)

## 17.0.275 beta 2024-02-23

* (#10791)
* fix(developer): publish keymancore-1.dll symbols (#10797)
* fix(developer): improve uploading of sourcemaps to sentry (#10798)
* fix(android/engine): Fix how keyboard picker menu exits (#10806)
* chore(linux): Fix `upload-to-debian.sh` script for beta releases (#10784)
* chore(linux): Fix API verification after adding SONAME (#10813)
* chore(linux): Address comments from Debian mailing list (#10800)
* docs(linux): Update how to build binary package with docker (#10814)
* chore(linux): Update debian changelog (#10785)

## 17.0.274 beta 2024-02-22

* fix(android/engine): Remove logs for uninitialized default keyboard (#10782)
* refactor(android/app): Allow SystemKeyboard to install default keyboard and dictionary (#10794)
* chore(android/app): Remove logging for install referrer details (#10795)
* docs(android/app): Update tablet screenshots (again) (#10796)
* docs(android): Update screenshots for help (#10808)
* chore(web): proper reporting of errors from es5 KMW (#10807)
* fix(android): first keystroke when context is empty (#10809)
* chore(linux): Update Debian `control` file (#10787)

## 17.0.273 beta 2024-02-21

* fix(developer): match kmc console formatting for messages in IDE (#10775)
* fix(developer): ensure fatal errors report message or made non-fatal (#10777)
* chore(developer): add LDML specific text to Project view (#10779)
* fix(developer): reset debugger after ldml keyboard compile (#10780)
* fix(developer): crash opening invalid project (#10781)
* docs(ios): document gestures (#10763)

## 17.0.272 beta 2024-02-20

* fix(core): fix output append logic in any_group::apply_transform (#10758)
* fix(android): Match phone suggestion banner styling on tablet (#10760)
* docs(mac): Document What's New for version 17.0 (#10764)
* (#10773)
* chore(developer): reduce WARN_TouchLayoutUsesUnsupportedGesturesDownlevel to HINT (#10766)
* fix(developer): prevent renaming of new project types in New Project dialog (#10767)
* fix(developer): return an error code if build-test-data fails (#10765)
* fix(developer): allow more parameters in kmc.cmd (#10759)
* chore(linux): Ignore missing .symbols file in stable branch (#10674)
* chore(linux): Update symbols file with current version (#10575)
* docs(linux): Update screenshots and FAQ (#10768)
* chore(linux): Fix `debian.sh` by removing quotes (#10772)

## 17.0.271 beta 2024-02-19

* chore(developer): add infrastructure messages tests (#10756)
* chore(windows): Update more PT strings (#10718)
* docs(android/app): Update tablet screenshots (#10726)
* fix(web): sticky special-key highlighting (#10729)
* fix(web): disables modipress for layer-switch keys with subkeys (#10745)
* fix(web): missing null-guard for hardware keystrokes without active Keyman keyboard (#10740)
* docs(ios): what's new in 17.0 (#10748)
* fix(web): handling of page-elements focused before engine initialization (#10744)
* fix(ios): multitap consistency after new-lines (#10728)
* docs(common): Update website README (#10738)

## 17.0.270 beta 2024-02-17

* (#10735)

## 17.0.269 beta 2024-02-15

* docs(android): Document using gestures on touch, and remove references to Browser (#10686)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public static void checkGooglePlayInstallReferrer(MainActivity mainActivity, Con
}

if (!installerInfo.equalsIgnoreCase(GOOGLE_PLAY)) {
KMLog.LogInfo(TAG, "Skipping install referrer. Installed from " + installerInfo);
// Don't log install referrer #10762
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
package com.keyman.android;

import com.tavultesoft.kmapro.BuildConfig;
import com.tavultesoft.kmapro.DefaultLanguageResource;
import com.tavultesoft.kmapro.KeymanSettingsActivity;
import com.keyman.android.BannerController;
import com.keyman.engine.KMManager;
import com.keyman.engine.KMManager.KeyboardType;
import com.keyman.engine.KMHardwareKeyboardInterpreter;
Expand Down Expand Up @@ -64,11 +64,13 @@ public void onCreate() {
KMManager.setDebugMode(true);
}
KMManager.addKeyboardEventListener(this);
KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);
interpreter = new KMHardwareKeyboardInterpreter(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_SYSTEM);
Context context = getApplicationContext();
KMManager.initialize(context, KeyboardType.KEYBOARD_TYPE_SYSTEM);
DefaultLanguageResource.install(context);
interpreter = new KMHardwareKeyboardInterpreter(context, KeyboardType.KEYBOARD_TYPE_SYSTEM);
KMManager.setInputMethodService(this); // for HW interface

SharedPreferences prefs = getApplicationContext().getSharedPreferences(getApplicationContext().getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
KMManager.SpacebarText spacebarText = KMManager.SpacebarText.fromString(prefs.getString(KeymanSettingsActivity.spacebarTextKey, KMManager.SpacebarText.LANGUAGE_KEYBOARD.toString()));
KMManager.setSpacebarText(spacebarText);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2024 SIL International. All rights reserved.
*/

package com.tavultesoft.kmapro;

import android.content.Context;
import android.content.SharedPreferences;

import com.keyman.engine.KMManager;
import com.keyman.engine.data.LexicalModel;

import java.util.HashMap;

public class DefaultLanguageResource {
private static final String defaultKeyboardInstalled = "DefaultKeyboardInstalled";
private static final String defaultDictionaryInstalled = "DefaultDictionaryInstalled";

/**
* Check if app has installed default keyboard and dictionary. If not, install them
* @param context
*/
public static void install(Context context) {
SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);

// Add default keyboard
boolean installDefaultKeyboard = prefs.getBoolean(defaultKeyboardInstalled, false);
if (!installDefaultKeyboard) {
if (!KMManager.keyboardExists(context, KMManager.KMDefault_PackageID, KMManager.KMDefault_KeyboardID,
KMManager.KMDefault_LanguageID)) {
KMManager.addKeyboard(context, KMManager.getDefaultKeyboard(context.getApplicationContext()));
}
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(defaultKeyboardInstalled, true);
editor.commit();
}

// Add default dictionary
boolean installDefaultDictionary = prefs.getBoolean(defaultDictionaryInstalled, false);
if (!installDefaultDictionary) {
LexicalModel defaultLexicalModel = LexicalModel.getDefaultLexicalModel(context);
HashMap<String, String> lexicalModelInfo = new HashMap<String, String>();
lexicalModelInfo.put(KMManager.KMKey_PackageID, defaultLexicalModel.getPackageID());
lexicalModelInfo.put(KMManager.KMKey_LanguageID, defaultLexicalModel.getLanguageID());
lexicalModelInfo.put(KMManager.KMKey_LanguageName, defaultLexicalModel.getLanguageName());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, defaultLexicalModel.getLexicalModelID());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelName, defaultLexicalModel.getLexicalModelName());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, defaultLexicalModel.getVersion());
/*
// If welcome.htm exists, add custom help link
welcomeFile = new File(KMManager.getLexicalModelsDir(), KMManager.KMDefault_DictionaryPackageID + File.separator + FileUtils.WELCOME_HTM);
lexicalModelInfo.put(KMManager.KMKey_CustomHelpLink, welcomeFile.getPath());
*/
KMManager.addLexicalModel(context, lexicalModelInfo);
KMManager.registerAssociatedLexicalModel(KMManager.KMDefault_LanguageID);

SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(defaultDictionaryInstalled, true);
editor.commit();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ public class MainActivity extends BaseActivity implements OnKeyboardEventListene
private final int maxTextSize = 72;
private int textSize = minTextSize;
private int lastOrientation = Configuration.ORIENTATION_UNDEFINED;
private static final String defaultKeyboardInstalled = "DefaultKeyboardInstalled";
private static final String defaultDictionaryInstalled = "DefaultDictionaryInstalled";
private static final String userTextKey = "UserText";
private static final String userTextSizeKey = "UserTextSize";
private Toolbar toolbar;
Expand Down Expand Up @@ -147,43 +145,9 @@ protected void onCreate(Bundle savedInstanceState) {
KMManager.initialize(getApplicationContext(), KeyboardType.KEYBOARD_TYPE_INAPP);
KMManager.executeResourceUpdate(this);

SharedPreferences prefs = getSharedPreferences(getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
// Add default keyboard
boolean installDefaultKeyboard = prefs.getBoolean(defaultKeyboardInstalled, false);
if (!installDefaultKeyboard) {
if (!KMManager.keyboardExists(context, KMManager.KMDefault_PackageID, KMManager.KMDefault_KeyboardID,
KMManager.KMDefault_LanguageID)) {
KMManager.addKeyboard(this, KMManager.getDefaultKeyboard(getApplicationContext()));
}
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(defaultKeyboardInstalled, true);
editor.commit();
}

// Add default dictionary
boolean installDefaultDictionary = prefs.getBoolean(defaultDictionaryInstalled, false);
if (!installDefaultDictionary) {
LexicalModel defaultLexicalModel = LexicalModel.getDefaultLexicalModel(context);
HashMap<String, String> lexicalModelInfo = new HashMap<String, String>();
lexicalModelInfo.put(KMManager.KMKey_PackageID, defaultLexicalModel.getPackageID());
lexicalModelInfo.put(KMManager.KMKey_LanguageID, defaultLexicalModel.getLanguageID());
lexicalModelInfo.put(KMManager.KMKey_LanguageName, defaultLexicalModel.getLanguageName());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelID, defaultLexicalModel.getLexicalModelID());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelName, defaultLexicalModel.getLexicalModelName());
lexicalModelInfo.put(KMManager.KMKey_LexicalModelVersion, defaultLexicalModel.getVersion());
/*
// If welcome.htm exists, add custom help link
welcomeFile = new File(KMManager.getLexicalModelsDir(), KMManager.KMDefault_DictionaryPackageID + File.separator + FileUtils.WELCOME_HTM);
lexicalModelInfo.put(KMManager.KMKey_CustomHelpLink, welcomeFile.getPath());
*/
KMManager.addLexicalModel(context, lexicalModelInfo);
KMManager.registerAssociatedLexicalModel(KMManager.KMDefault_LanguageID);

SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(defaultDictionaryInstalled, true);
editor.commit();
}
DefaultLanguageResource.install(context);

SharedPreferences prefs = getSharedPreferences(getString(R.string.kma_prefs_name), Context.MODE_PRIVATE);
KMManager.SpacebarText spacebarText = KMManager.SpacebarText.fromString(prefs.getString(KeymanSettingsActivity.spacebarTextKey, KMManager.SpacebarText.LANGUAGE_KEYBOARD.toString()));
KMManager.setSpacebarText(spacebarText);

Expand Down
25 changes: 20 additions & 5 deletions android/KMEA/app/src/main/assets/android-host.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var _debug = 0;
var _debug = false;

// Android harness attachment
if(window.parent && window.parent.jsInterface && !window.jsInterface) {
Expand Down Expand Up @@ -235,11 +235,16 @@ function updateKMText(text) {
text = '';
}

console_debug('updateKMText(text='+text+') context.value='+keyman.context.getText());
console_debug('updateKMText(text=' + text + ') with: \n' + build_context_string(keyman.context));

if(text != keyman.context.getText()) {
if(!text || text != keyman.context.getText()) {
keyman.context.setText(text);
keyman.resetContext();


console_debug('result: \n' + build_context_string(keyman.context));
} else {
console_debug('context unchanged');
}
}

Expand All @@ -249,11 +254,17 @@ function console_debug(s) {
}
}

function build_context_string(context) {
// Sadly, ES6-style "template strings" - strings with backticks - require Chrome 41+.
return 'preCaret: `' + context.getTextBeforeCaret() + '`\n' +
'selected: `' + context.getSelectedText() + '`\n' +
'postCaret: `' + context.getTextAfterCaret() + '`';
}

function updateKMSelectionRange(start, end) {
var context = keyman.context;

// console_debug('updateKMSelectionRange('+start+','+end+'): context.selStart='+ta.selectionStart+' '+
// '['+ta._KeymanWebSelectionStart+'] context.selEnd='+ta.selectionEnd+' '+ta._KeymanWebSelectionEnd);
console_debug('updateKMSelectionRange(' + start + ', ' + end + ') with: \n' + build_context_string(context));

if(start > end) {
var e0 = end;
Expand All @@ -264,6 +275,10 @@ function updateKMSelectionRange(start, end) {
if(context.selStart != start || context.selEnd != end) {
keyman.context.setSelection(start, end);
keyman.resetContext();

console_debug('result:\n' + build_context_string(context));
} else {
console.debug('range unchanged');
}
}

Expand Down
27 changes: 25 additions & 2 deletions android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.keyman.engine.KMManager.KeyboardType;
import com.keyman.engine.KeyboardEventHandler.EventType;
import com.keyman.engine.KeyboardEventHandler.OnKeyboardEventListener;
import com.keyman.engine.util.CharSequenceUtil;
import com.keyman.engine.util.DependencyUtil;
import com.keyman.engine.util.DependencyUtil.LibraryType;
import com.keyman.engine.util.FileUtils;
Expand Down Expand Up @@ -167,9 +168,31 @@ protected boolean updateSelectionRange(int selStart, int selEnd) {
InputConnection ic = KMManager.getInputConnection(this.keyboardType);
if (ic != null) {
ExtractedText icText = ic.getExtractedText(new ExtractedTextRequest(), 0);
if (icText != null) {
updateText(icText.text.toString());
if (icText == null) {
return false;
}

String rawText = icText.text.toString();
updateText(rawText.toString());

/*
The values of selStart & selEnd provided by the system are in code units,
not code-points. We need to account for surrogate pairs here.
Fortunately, it uses UCS-2 encoding... just like JS.
References:
- https://stackoverflow.com/a/23980211
- https://android.googlesource.com/platform/frameworks/base/+/152944f/core/java/android/view/inputmethod/InputConnection.java#326
*/

// Count the number of characters which are surrogate pairs.
int pairsAtStart = CharSequenceUtil.countSurrogatePairs(rawText.substring(0, selStart), rawText.length());
String selectedText = rawText.substring(selStart, selEnd);
int pairsSelected = CharSequenceUtil.countSurrogatePairs(selectedText, selectedText.length());

selStart -= pairsAtStart;
selEnd -= (pairsAtStart + pairsSelected);
}
this.loadJavascript(KMString.format("updateKMSelectionRange(%d,%d)", selStart, selEnd));
result = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.keyman.engine.data.Keyboard;
import com.keyman.engine.util.CharSequenceUtil;
import com.keyman.engine.util.KMLog;
import com.keyman.engine.util.KMString;

public class KMKeyboardJSHandler {
private Context context;
Expand Down Expand Up @@ -284,7 +285,17 @@ private static void performLeftDeletions(InputConnection ic, int dn) {

// Chop dn+numPairs code points from the end of charsBackup
// subSequence indices are start(inclusive) to end(exclusive)
CharSequence expectedChars = charsBackup.subSequence(0, charsBackup.length() - (dn + numPairs));
int start = 0;
int end = charsBackup.length() - (dn + numPairs);
CharSequence expectedChars;
try {
expectedChars = charsBackup.subSequence(start, end);
} catch (IndexOutOfBoundsException e) {
KMLog.LogException(TAG,
KMString.format("Bad subSequence of start %d, end is %d, length %d, dn %d, numPairs %d",
start, end, charsBackup.length(), dn, numPairs), e);
expectedChars = "";
}
ic.deleteSurroundingText(dn + numPairs, 0);
CharSequence newContext = getCharacterSequence(ic, originalBufferLength - 2*dn);

Expand Down Expand Up @@ -327,7 +338,15 @@ private static CharSequence getCharacterSequence(InputConnection ic, int length)
if (Character.isLowSurrogate(sequence.charAt(0))) {
// Adjust if the first char is also a split surrogate pair
// subSequence indices are start(inclusive) to end(exclusive)
sequence = sequence.subSequence(1, sequence.length());
int start = 1;
int end = sequence.length();
try {
sequence = sequence.subSequence(start, end);
} catch (IndexOutOfBoundsException e) {
KMLog.LogException(TAG,
KMString.format("Bad subSequence of start %d, end is %d",
start, end), e);
}
}

return sequence;
Expand Down
Loading

0 comments on commit aa17142

Please sign in to comment.