diff --git a/tools/cldr-apps/js/src/esm/cldrKeyboard.mjs b/tools/cldr-apps/js/src/esm/cldrKeyboard.mjs new file mode 100644 index 00000000000..c5188177e1a --- /dev/null +++ b/tools/cldr-apps/js/src/esm/cldrKeyboard.mjs @@ -0,0 +1,114 @@ +/** + * Operations around keyboard support + */ + +import * as cldrClient from "./cldrClient.mjs"; +import * as cldrStatus from "./cldrStatus.mjs"; + +// See https://keyman.com/developer/keymanweb/ for the latest version and scripts to use +const KEYMAN_VERSION = "17.0.333"; +const KEYMAN_SCRIPTS = ["keymanweb.js", "kmwuitoggle.js"]; +const KEYMAN_BASE = "https://s.keyman.com/kmw/engine/"; +const KEYMAN_ATTACH = `( + function(kmw) { + kmw.init({attachType:'auto'}); + } +)(keyman);`; + + +// are the scripts installed? +let installed = false; +let installing = false; +// is the option enabled? +let enabled = false; +// did we call init yet? +let initted = false; + + +function getRemoteScript(src) { + const e = document.createElement('script'); + e.setAttribute('src', src); + return e; +} + +function getInlineScript(body) { + const e = document.createElement('script'); + e.textContent = body; + return e; +} + +/** insert the script tags */ +async function installKeyboards() { + if (installing) return; + installing = true; + + if (!installed) { + const { body } = document; + for (const script of KEYMAN_SCRIPTS) { + const e = getRemoteScript(`${KEYMAN_BASE}${KEYMAN_VERSION}/${script}`); + body.appendChild(e); + await waitForLoad(e); // block here until loaded + } + const attach = getInlineScript(KEYMAN_ATTACH); + body.appendChild(attach); + installed = true; + installing = false; + updateKeyboardLocale(cldrStatus.getCurrentLocale()); + } + + function waitForLoad(e) { + return new Promise((resolve, reject) => { + try { + e.addEventListener('load', resolve); + } catch (err) { + reject(err); + } + }); + } +} + +/** + * Update whether user has requested web keyboards + * @param {boolean} enable true if keyboards are enabled + */ +export function setUseKeyboards(enable) { + if (enable != enabled) { + if (enable) { + installKeyboards().then(() => { enabled = true; }); + } else { + enabled = false; + } + } +} + +/** + * Update the keyboard locale + * @param {string} curLocale + */ +export function updateKeyboardLocale(curLocale) { + if (installed && enabled) { + // make sure keyman is loaded + for (const { InternalName } of keyman.getKeyboards()) { + keyman.removeKeyboards(InternalName); + console.log(`Removed kbd: ${InternalName}`); + } + console.log(`Adding kbd: @${curLocale}`); + keyman.addKeyboards(`@${curLocale}`); + // end keyboards + } +} + +export function isEnabled() { + return enabled; +} + +/** Note: may need to call reload() in order to unload keyboard. */ +export async function setEnabledPref(enable) { + const client = await cldrClient.getClient(); + setUseKeyboards(enable); + if (enable) { + await client.apis.user.setSetting({setting: 'webkeyboard'}); + } else { + await client.apis.user.removeSetting({setting: 'webkeyboard'}); + } +} diff --git a/tools/cldr-apps/js/src/esm/cldrMenu.mjs b/tools/cldr-apps/js/src/esm/cldrMenu.mjs index 0a40a49f9da..3a10adeee3c 100644 --- a/tools/cldr-apps/js/src/esm/cldrMenu.mjs +++ b/tools/cldr-apps/js/src/esm/cldrMenu.mjs @@ -8,6 +8,7 @@ import * as cldrCoverage from "./cldrCoverage.mjs"; import * as cldrDom from "./cldrDom.mjs"; import * as cldrEvent from "./cldrEvent.mjs"; import * as cldrGui from "./cldrGui.mjs"; +import * as cldrKeyboard from "./cldrKeyboard.mjs"; import * as cldrLoad from "./cldrLoad.mjs"; import { LocaleMap } from "./cldrLocaleMap.mjs"; import * as cldrStatus from "./cldrStatus.mjs"; @@ -418,6 +419,8 @@ function updateLocaleMenu() { const curLocale = cldrStatus.getCurrentLocale(); let prefixMessage = ""; if (curLocale != null && curLocale != "" && curLocale != "-") { + // hook to update the keyboard locale + cldrKeyboard.updateKeyboardLocale(curLocale); const locmap = cldrLoad.getTheLocaleMap(); cldrStatus.setCurrentLocaleName(locmap.getLocaleName(curLocale)); var bund = locmap.getLocaleInfo(curLocale); diff --git a/tools/cldr-apps/js/src/esm/cldrStatus.mjs b/tools/cldr-apps/js/src/esm/cldrStatus.mjs index 862b875c6ec..5c30742b0d9 100644 --- a/tools/cldr-apps/js/src/esm/cldrStatus.mjs +++ b/tools/cldr-apps/js/src/esm/cldrStatus.mjs @@ -3,6 +3,7 @@ */ import * as cldrGui from "./cldrGui.mjs"; import { ref } from "vue"; +import { setUseKeyboards } from "./cldrKeyboard.mjs"; const refs = { currentLocale: ref(null), @@ -44,6 +45,7 @@ function getStatusTarget() { * Events: * - sessionId: session ID changed * - surveyUser: survey user changed + * - update: any update changed */ function on(type, callback) { getStatusTarget().addEventListener(type, callback); @@ -94,6 +96,8 @@ function updateAll(status) { if (status.user) { setSurveyUser(status.user); } + setUseKeyboards(status?.settings?.user?.webkeyboard); + dispatchEvent(new Event('update')); } /** diff --git a/tools/cldr-apps/js/src/views/MainMenu.vue b/tools/cldr-apps/js/src/views/MainMenu.vue index ba2fe275e20..bd6864d7b86 100644 --- a/tools/cldr-apps/js/src/views/MainMenu.vue +++ b/tools/cldr-apps/js/src/views/MainMenu.vue @@ -134,11 +134,15 @@