diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java index 4deb03edf0..2071569fe6 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/MainActivity.java @@ -830,6 +830,14 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardEventLi } } + @Override + public void onLexicalModelInstalled(List> lexicalModelsInstalled) { + for(int i=0; ilexicalModelInfo = new HashMap<>(lexicalModelsInstalled.get(i)); + KMManager.addLexicalModel(this, lexicalModelInfo); + } + } + private void copyFile(FileInputStream inStream, File dstFile) throws IOException { OutputStream outStream = new FileOutputStream(dstFile); diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java index 9c30bb556a..47179ed6e2 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java @@ -182,26 +182,37 @@ public class PackageActivity extends AppCompatActivity { try { if (pkgTarget.equals(PackageProcessor.PP_TARGET_KEYBOARDS)) { // processKMP will remove currently installed package and install - installedPackageKeyboards = kmpProcessor.processKMP(kmpFile, tempPackagePath, PackageProcessor.PP_KEYBOARDS_KEY); + installedPackageKeyboards = kmpProcessor.processKMP(kmpFile, tempPackagePath, + PackageProcessor.PP_KEYBOARDS_KEY); // Do the notifications! boolean success = installedPackageKeyboards.size() != 0; if (success) { - notifyPackageInstallListeners(KeyboardEventHandler.EventType.PACKAGE_INSTALLED, installedPackageKeyboards, 1); + notifyPackageInstallListeners(KeyboardEventHandler.EventType.PACKAGE_INSTALLED, + installedPackageKeyboards, 1); if (installedPackageKeyboards != null) { - notifyPackageInstallListeners(KeyboardEventHandler.EventType.PACKAGE_INSTALLED, installedPackageKeyboards, 1); + notifyPackageInstallListeners(KeyboardEventHandler.EventType.PACKAGE_INSTALLED, + installedPackageKeyboards, 1); } cleanup(); } else { showErrorDialog(context, pkgId, getString(R.string.no_new_touch_keyboards_to_install)); } } else if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) { - installedLexicalModels = kmpProcessor.processKMP(kmpFile, tempPackagePath, PackageProcessor.PP_LEXICAL_MODELS_KEY); + installedLexicalModels = kmpProcessor.processKMP(kmpFile, tempPackagePath, + PackageProcessor.PP_LEXICAL_MODELS_KEY); // Do the notifications boolean success = installedLexicalModels.size() != 0; if (success) { - + notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, + installedLexicalModels, 1); + if (installedLexicalModels != null) { + notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, + installedLexicalModels, 1); + } + cleanup(); + } else { + showErrorDialog(context, pkgId, getString(R.string.no_new_predictive_text_to_install)); } - cleanup(); } } catch (Exception e) { Log.e("PackageActivity", "Error " + e); @@ -280,12 +291,20 @@ public class PackageActivity extends AppCompatActivity { alertDialog.show(); } - void notifyPackageInstallListeners(KeyboardEventHandler.EventType eventType, List> keyboards, int result) { + void notifyPackageInstallListeners(KeyboardEventHandler.EventType eventType, + List> keyboards, int result) { if (kbDownloadEventListeners != null) { KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, keyboards, result); } } + void notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType eventType, + List> models, int result) { + if (kbDownloadEventListeners != null) { + KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, models, result); + } + } + public static void addKeyboardDownloadEventListener(KeyboardEventHandler.OnKeyboardDownloadEventListener listener) { if (kbDownloadEventListeners == null) { kbDownloadEventListeners = new ArrayList(); diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index e1d33632f5..6750efd1af 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -49,6 +49,7 @@ Install Keyboard Package Install Predictive Text Package No new touch-optimized keyboards to install + No new predictive text to install No valid touch-optimized keyboards to install No keyboards or predictive text to install kmp.json does not exist diff --git a/android/KMEA/app/src/main/assets/keyboard.html b/android/KMEA/app/src/main/assets/keyboard.html index 88cccf60d0..cfcdb5aced 100644 --- a/android/KMEA/app/src/main/assets/keyboard.html +++ b/android/KMEA/app/src/main/assets/keyboard.html @@ -126,6 +126,12 @@ window.jsInterface.insertText(dn, s); } + function registerModel(model) { + var kmw=window['keyman']; + window.console.log('model: ' + model); + kmw.registerModel(model); + } + function resetContext() { var kmw=window['keyman']; kmw.resetContext(); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java index ca9def245a..d4f86f83c7 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboardDownloaderActivity.java @@ -367,10 +367,16 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { String pkgTarget = kmpProcessor.getPackageTarget(kmpFile); if (pkgTarget.equals(PackageProcessor.PP_TARGET_LEXICAL_MODELS)) { File unzipPath = kmpProcessor.unzipKMP(kmpFile); - // TODO: Propogate installedLexicalModels to KMW List> installedLexicalModels = kmpProcessor.processKMP(kmpFile, unzipPath, PackageProcessor.PP_LEXICAL_MODELS_KEY); + + boolean success = installedLexicalModels.size() != 0; + if (success) { + notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType.LEXICAL_MODEL_INSTALLED, + installedLexicalModels, 1); + } } + } if (result < 0) { if (FileUtils.hasFontExtension(url)) { @@ -407,6 +413,19 @@ public class KMKeyboardDownloaderActivity extends AppCompatActivity { KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, keyboardInfo, result); } } + + /** + * Notify listeners when a lexical model is installed + * @param eventType + * @param models + * @param result + */ + protected void notifyLexicalModelInstallListeners(KeyboardEventHandler.EventType eventType, + List> models, int result) { + if (kbDownloadEventListeners != null) { + KeyboardEventHandler.notifyListeners(kbDownloadEventListeners, eventType, models, result); + } + } } /** diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java index a6e03e3500..6b1bb0c7e5 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java @@ -57,6 +57,8 @@ import com.tavultesoft.kmea.packages.PackageProcessor; import com.tavultesoft.kmea.KMScanCodeMap; import com.tavultesoft.kmea.util.FileUtils; +import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; public final class KMManager { @@ -154,6 +156,7 @@ public final class KMManager { protected static final String KMFilename_Osk_Ttf_Font = "keymanweb-osk.ttf"; protected static final String KMFilename_Osk_Woff_Font = "keymanweb-osk.woff"; public static final String KMFilename_KeyboardsList = "keyboards_list.dat"; + public static final String KMFilename_LexicalModelsList = "lexical_models_list.dat"; private static Context appContext; @@ -647,6 +650,41 @@ public final class KMManager { return KeyboardPickerActivity.getKeyboardsList(context); } + public static boolean registerLexicalModel(HashMap lexicalModelInfo) { + String pkgID = lexicalModelInfo.get(KMKey_PackageID); + String modelID = lexicalModelInfo.get(KMKey_LexicalModelID); + String languageID = lexicalModelInfo.get(KMKey_LanguageID); + String path = "file://" + getLexicalModelsDir() + pkgID + File.separator + modelID + ".model.js"; + + JSONObject modelObj = new JSONObject(); + JSONArray languageJSONArray = new JSONArray(); + try { + modelObj.put("id", modelID); + languageJSONArray.put(languageID); + modelObj.put("languages", languageJSONArray); + modelObj.put("path", path); + } catch (JSONException e) { + Log.e(TAG, "Invalid lexical model to register"); + return false; + } + + // Use single quotes in JSONobject for javascript call + String model = String.valueOf(modelObj); + model = model.replaceAll("\"", "'"); + + if (InAppKeyboard != null && InAppKeyboardLoaded && !InAppKeyboardShouldIgnoreTextChange) { + InAppKeyboard.loadUrl(String.format("javascript:registerModel(%s)", model)); + } + if (SystemKeyboard != null && SystemKeyboardLoaded && !SystemKeyboardShouldIgnoreTextChange) { + SystemKeyboard.loadUrl(String.format("javascript:registerModel(%s)", model)); + } + return true; + } + + public static boolean addLexicalModel(Context context, HashMap lexicalModelInfo) { + return KeyboardPickerActivity.addLexicalModel(context, lexicalModelInfo); + } + public static boolean addKeyboard(Context context, HashMap keyboardInfo) { // Log Firebase analytic event. Bundle params = new Bundle(); diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardEventHandler.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardEventHandler.java index 3e19750b6b..a92e4d6c1c 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardEventHandler.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardEventHandler.java @@ -20,7 +20,8 @@ public final class KeyboardEventHandler { KEYBOARD_DISMISSED, KEYBOARD_DOWNLOAD_STARTED, KEYBOARD_DOWNLOAD_FINISHED, - PACKAGE_INSTALLED; + PACKAGE_INSTALLED, + LEXICAL_MODEL_INSTALLED; } public static void notifyListeners(ArrayList listeners, KeyboardType keyboardType, EventType event, String newValue) { @@ -44,11 +45,13 @@ public final class KeyboardEventHandler { } } - public static void notifyListeners(ArrayList listeners, EventType event, HashMap keyboardInfo, int result) { + public static void notifyListeners(ArrayList listeners, + EventType event, HashMap keyboardInfo, int result) { if (listeners != null) { @SuppressWarnings("unchecked") // make a copy of the list to avoid concurrent modification while iterating - ArrayList _listeners = (ArrayList) listeners.clone(); + ArrayList _listeners = + (ArrayList) listeners.clone(); if (event == EventType.KEYBOARD_DOWNLOAD_STARTED) { for (OnKeyboardDownloadEventListener listener : _listeners) listener.onKeyboardDownloadStarted(keyboardInfo); @@ -59,14 +62,22 @@ public final class KeyboardEventHandler { } } - public static void notifyListeners(ArrayList listeners, EventType event, List> keyboardsInfo, int result) { + public static void notifyListeners(ArrayList listeners, + EventType event, List> info, int result) { if (listeners != null) { @SuppressWarnings("unchecked") // make a copy of the list to avoid concurrent modification while iterating - ArrayList _listeners = (ArrayList) listeners.clone(); + ArrayList _listeners = + (ArrayList) listeners.clone(); if (event == EventType.PACKAGE_INSTALLED) { - for (OnKeyboardDownloadEventListener listener : _listeners) - listener.onPackageInstalled(keyboardsInfo); + for (OnKeyboardDownloadEventListener listener : _listeners) { + listener.onPackageInstalled(info); + } + } else if (event == EventType.LEXICAL_MODEL_INSTALLED) { + for (OnKeyboardDownloadEventListener listener : _listeners) { + listener.onLexicalModelInstalled(info); + } + } } } @@ -88,5 +99,7 @@ public final class KeyboardEventHandler { void onKeyboardDownloadFinished(HashMap keyboardInfo, int result); // result > 0 if successful, < 0 if failed void onPackageInstalled(List> keyboardsInstalled); + + void onLexicalModelInstalled(List> lexicalModelsInstalled); } } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardListActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardListActivity.java index 8259176eb3..937550131b 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardListActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardListActivity.java @@ -185,4 +185,9 @@ public final class KeyboardListActivity extends AppCompatActivity implements OnK public void onPackageInstalled(List> keyboardsInstalled) { // Do nothing. } -} \ No newline at end of file + + @Override + public void onLexicalModelInstalled(List> lexicalModelsInstalled) { + // Do nothing. + } +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java index db1dca3cf8..389e313258 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KeyboardPickerActivity.java @@ -58,6 +58,8 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O private static KMKeyboardPickerAdapter listAdapter = null; private static ArrayList> keyboardsList = null; private static HashMap keyboardVersions = null; + private static ArrayList> lexicalModelsList = null; + // private static HashMap lexicalModelsVersions = null; TODO private static boolean checkingUpdates = false; private static int updateCount = 0; private static int failedUpdateCount = 0; @@ -125,9 +127,22 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O keyboardsList.add(kbInfo); // We'd prefer not to overwrite a file if it exists - File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), KMManager.KMFilename_KeyboardsList); + File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), + KMManager.KMFilename_KeyboardsList); if (!file.exists()) { - saveKeyboardsList(context); + saveList(context, KMManager.KMFilename_KeyboardsList); + } + } + + lexicalModelsList = getLexicalModelsList(context); + if (lexicalModelsList == null) { + lexicalModelsList = new ArrayList>(); + + // We'd prefer not to overwrite a file if it exists + File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), + KMManager.KMFilename_LexicalModelsList); + if (!file.exists()) { + saveList(context, KMManager.KMFilename_LexicalModelsList); } } @@ -315,17 +330,21 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O return false; } - private static boolean saveKeyboardsList(Context context) { + private static boolean saveList(Context context, String listName) { boolean result; try { - File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), KMManager.KMFilename_KeyboardsList); + File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), listName); ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file)); - outputStream.writeObject(keyboardsList); + if (listName.equalsIgnoreCase(KMManager.KMFilename_KeyboardsList)) { + outputStream.writeObject(keyboardsList); + } else if (listName.equalsIgnoreCase(KMManager.KMFilename_LexicalModelsList)) { + outputStream.writeObject(lexicalModelsList); + } outputStream.flush(); outputStream.close(); result = true; } catch (Exception e) { - Log.e(TAG, "Failed to save keyboards list. Error: " + e); + Log.e(TAG, "Failed to save " + listName + ". Error: " + e); result = false; } @@ -335,7 +354,14 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O protected static boolean updateKeyboardsList(Context context, ArrayList> list) { boolean result; keyboardsList = list; - result = saveKeyboardsList(context); + result = saveList(context, KMManager.KMFilename_KeyboardsList); + return result; + } + + protected static boolean updateLexicalModelsList(Context context, ArrayList> list) { + boolean result; + lexicalModelsList = list; + result = saveList(context, KMManager.KMFilename_LexicalModelsList); return result; } @@ -359,6 +385,13 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O String kFont = kbInfo.get(KMManager.KMKey_Font); String kOskFont = kbInfo.get(KMManager.KMKey_OskFont); KMManager.setKeyboard(pkgId, kbId, langId, kbName, langName, kFont, kOskFont); + + // Register associated lexical model + HashMap lmInfo = getAssociatedLexicalModel(langId); + if (lmInfo != null) { + KMManager.registerLexicalModel(lmInfo); + } + } protected static boolean addKeyboard(Context context, HashMap keyboardInfo) { @@ -382,10 +415,10 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O int x = getKeyboardIndex(context, kbKey); if (x >= 0) { keyboardsList.set(x, keyboardInfo); - result = saveKeyboardsList(context); + result = saveList(context, KMManager.KMFilename_KeyboardsList); } else { keyboardsList.add(keyboardInfo); - result = saveKeyboardsList(context); + result = saveList(context, KMManager.KMFilename_KeyboardsList); if (!result) { keyboardsList.remove(keyboardsList.size() - 1); } @@ -397,6 +430,39 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O return result; } + protected static boolean addLexicalModel(Context context, HashMap lexicalModelInfo) { + boolean result = false; + + if (lexicalModelsList == null) { + lexicalModelsList = new ArrayList>(); + } + + if (lexicalModelInfo != null) { + String pkgID = lexicalModelInfo.get(KMManager.KMKey_PackageID); + String modelID = lexicalModelInfo.get(KMManager.KMKey_LexicalModelID); + String langID = lexicalModelInfo.get(KMManager.KMKey_LanguageID); + + if (pkgID != null && modelID != null && langID != null) { + String lmKey = String.format("%s_%s_%s", langID, pkgID, modelID); + if (lmKey.length() >= 3) { + int x = getLexicalModelIndex(context, lmKey); + if (x >= 0) { + lexicalModelsList.set(x, lexicalModelInfo); + result = saveList(context, KMManager.KMFilename_LexicalModelsList); + } else { + lexicalModelsList.add(lexicalModelInfo); + result = saveList(context, KMManager.KMFilename_LexicalModelsList); + if (!result) { + lexicalModelsList.remove(lexicalModelsList.size() - 1); + } + } + } + } + } + + return result; + } + protected static boolean removeKeyboard(Context context, int position) { boolean result = false; if (keyboardsList == null) { @@ -405,7 +471,7 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O if (keyboardsList != null && position >= 0 && position < keyboardsList.size()) { keyboardsList.remove(position); - result = saveKeyboardsList(context); + result = saveList(context, KMManager.KMFilename_KeyboardsList); } return result; @@ -430,17 +496,17 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O } @SuppressWarnings("unchecked") - protected static ArrayList> getKeyboardsList(Context context) { + private static ArrayList> getList(Context context, String filename) { ArrayList> list = null; - File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), KMManager.KMFilename_KeyboardsList); + File file = new File(context.getDir("userdata", Context.MODE_PRIVATE), filename); if (file.exists()) { try { ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file)); list = (ArrayList>) inputStream.readObject(); inputStream.close(); } catch (Exception e) { - Log.e(TAG, "Failed to read keyboards list. Error: " + e); + Log.e(TAG, "Failed to read " + filename + ". Error: " + e); list = null; } } @@ -448,6 +514,14 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O return list; } + protected static ArrayList> getKeyboardsList(Context context) { + return getList(context, KMManager.KMFilename_KeyboardsList); + } + + protected static ArrayList> getLexicalModelsList(Context context) { + return getList(context, KMManager.KMFilename_LexicalModelsList); + } + protected static boolean containsKeyboard(Context context, String keyboardKey) { if (keyboardsList == null) { keyboardsList = getKeyboardsList(context); @@ -524,6 +598,45 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O return index; } + protected static int getLexicalModelIndex(Context context, String lexicalModelKey) { + int index = -1; + + if (lexicalModelsList == null) { + lexicalModelsList = getLexicalModelsList(context); + } + + if (lexicalModelsList != null) { + int length = lexicalModelsList.size(); + for (int i=0; i < length; i++) { + HashMap lmInfo = lexicalModelsList.get(i); + String langId = lmInfo.get(KMManager.KMKey_LanguageID); + String pkgId = lmInfo.get(KMManager.KMKey_PackageID); + String lmId = lmInfo.get(KMManager.KMKey_LexicalModelID); + String lmKey = String.format("%s_%s_%s", langId, pkgId, lmId); + if (lmKey.equals(lexicalModelKey)) { + index = i; + break; + } + } + } + + return index; + } + + protected static HashMap getAssociatedLexicalModel(String langId) { + if (lexicalModelsList != null) { + int length = lexicalModelsList.size(); + for (int i = 0; i < length; i++) { + HashMap lmInfo = lexicalModelsList.get(i); + if (langId.equalsIgnoreCase(lmInfo.get(KMManager.KMKey_LanguageID))) { + return lmInfo; + } + } + } + + return null; + } + protected static HashMap getKeyboardInfo(Context context, int index) { if (index < 0) { return null; @@ -751,7 +864,7 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O index = getKeyboardIndex(this, kbKey); } keyboardsList.set(index, keyboardInfo); - saveKeyboardsList(this); + saveList(this, KMManager.KMFilename_KeyboardsList); } else if (result < 0) { failedUpdateCount++; } @@ -795,4 +908,9 @@ public final class KeyboardPickerActivity extends AppCompatActivity implements O public void onPackageInstalled(List> keyboardsInstalled) { // Do nothing } -} \ No newline at end of file + + @Override + public void onLexicalModelInstalled(List> lexicalModelsInstalled) { + // Do nothing + } +} diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java index 538c68e115..b14a6b1c40 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/LanguageListActivity.java @@ -164,6 +164,11 @@ public final class LanguageListActivity extends AppCompatActivity implements OnK // Do nothing. } + @Override + public void onLexicalModelInstalled(List> lexicalModelsInstalled) { + // Do nothing. + } + protected static HashMap getKeyboardInfo(int languageIndex, int keyboardIndex) { if (languages == null) return null; diff --git a/web/source/kmwembedded.ts b/web/source/kmwembedded.ts index 629216ff60..3e98bd613c 100644 --- a/web/source/kmwembedded.ts +++ b/web/source/kmwembedded.ts @@ -351,12 +351,21 @@ namespace com.keyman.text { } }; + /** + * Register a lexical model + * + * @param {com.keyman.text.prediction.ModelSpec} model Spec of the lexical model + */ + keymanweb['registerModel']=function(model: com.keyman.text.prediction.ModelSpec) { + keymanweb.modelManager.register(model); + } + /** * Function called by iOS when a device-implemented keyboard popup is displayed or hidden * * @param {boolean} isVisible * - **/ + **/ keymanweb['popupVisible'] = function(isVisible) { osk.vkbd.popupVisible = isVisible;