keymanapp / keyman

Keyman cross platform input methods system running on Android, iOS, Linux, macOS, Windows and mobile and desktop web
https://keyman.com/
Other
403 stars 112 forks source link

feat(common): cross-platform IMX (picker) support #7928

Open jahorton opened 1 year ago

jahorton commented 1 year ago

Is your feature request related to a problem? Please describe.

In our keyboards repository, we have a few old Web keyboards that implemented custom CJK-picker functionality. This functionality is only functional on desktop form-factor devices, and is thus not practical to use within Keyman for Android or Keyman for iPhone and iPad.

See:

We've had a few recent Community forum posts highly related to this functionality, with some users and/or communities seeking to implement their own versions of this as well.

See:

Note that at their core, picker keyboards like the three existing ones listed above tend to operate based upon the following pattern, expressed roughly in Keyman language syntax:

Describe the solution you'd like

Desired features:

Describe alternatives you've considered

No response

Keyman apps

jahorton commented 1 year ago

My current thoughts toward this: I believe that the both the motivating problem and our existing solutions for pickers / IMX-es are similar enough to predictive text that we could implement the majority of picker support as an alternative predictive-text model type, allowing re-use of existing model-handling code.

Notable Limitations

(Initial) inability to use pickers and predictive text together

Note that initially, this would prevent use of a picker/IMX with a predictive-text model; our predictive-text worker only supports a single loaded model at present, and even if it did support a second, we'd want to support a separate thread so that ongoing predictive text operations (for a previous keystroke) don't block the picker from providing its suggestions (for a newer one) due to lack of concurrency. There's no reason we can't remedy that down the road, especially once we properly convert KeymanWeb to use of ES modules, which will greatly simplify reuse of the relevant code and more easily allow us to construct a separate worker to handle IMX operations. The design work to clearly present 'suggestions' and interaction with the user... would require significant design work and is likely a larger problem to address.

Keyman's predictive-text is currently touch-device-only; It's not yet fully cross-platform

While this point is true, note that on our roadmap, we're moving in the direction of reusing Web's OSK across all the desktop platforms. The OSK is coded in TypeScript, as is our predictive text, and the current predictive-text banner is included in that.

This is work we're already planning to do, and so the suggestion is simply to leverage these existing plans to accomplish the extra goal of IMX support as well. The predictive text banner offers a very similar UI structure to that of our existing pickers, after all.

A later point in the roadmap also mentions our desire to support predictive text on the desktop platforms; ideally, we'll be able to "two birds, one stone" that problem alongside IMX support by taking this strategy.

General Design / Implementation Strategy

Our existing predictive text model template - the Trie-based dictionary/"word list" model - assumes the following details:

Picker "models" would reject both of those assumptions, but fortunately... these assumptions are not baked into the model design or its code interfaces. There isn't anything preventing us from mapping text in one script to output in a different script. One other notable distinction: for some cases (like with Chinese) it is possible for a one-to-many relationship to exist between source (input) text and destination (output) text. I believe that at least one of the picker keyboards above either once used or still uses a database backend to facilitate its operation.

I believe we could actually use a Trie structure similar to that for our wordlist models and adapt it for use with pickers; we'd just need to separate input and output mapping and allow leaf nodes to contain multiple possible outputs. We'd also drop the "frequency" aspect of wordlist models, providing a ordinal to keep the order of outputs deterministic.

The other interesting point of note; picker operation has its own distinct notion of 'context' that is markedly different from standard predictive-text operations; it assumes that the user will actively select entries for every "pick" made, with that acting as the "word break" our current predictive text system expects. The CJK languages don't use wordbreaking in the same way.

mcdurdin commented 1 year ago

Note also the existing Windows IMX keyboards (actually significantly older than web imx), such as:

Documentation:

jahorton commented 1 year ago

Sadly, it looks like we never really wrote decent documentation for Web's IMX support... but I do remember where a lot of the connectors are.

One major one:

https://github.com/keymanapp/keyman/blob/dc1c95298aa84427b2e8d0103d2ef717915b7799/common/web/keyboard-processor/src/keyboards/keyboard.ts#L337-L348

If a Web keyboard implements a KNS function, Web will call that to "awaken" the picker if it is in a currently-hidden state and reset its context to match that of the active text-insertion point.

I'd have to go digging a bit to be 100% clear on this part, but...

https://github.com/keymanapp/keyman/blob/dc1c95298aa84427b2e8d0103d2ef717915b7799/common/web/keyboard-processor/src/keyboards/keyboard.ts#L164-L182

I'm nigh-certain the Web picker keyboards utilize the "help text" field "hold" the picker UI in place, while the "script" one defines the picker's functionality and generates the picker UI when the keyboard is first loaded.

The 'KNS' function defined above should be defined within the "help file", which itself is set in Keyman keyboard language via the &kmw_helpfile store.

Correspondingly, "help text" is set via the &kmw_helptext store.

mcdurdin commented 1 year ago

Sadly, it looks like we never really wrote decent documentation for Web's IMX support...

Why, what's wrong with this?!?

image

🤣🤣🤣

mcdurdin commented 1 year ago

I don't want to pour cold water on your proposal, but I am not sure that the predictive text module will be sufficient:

  1. Predictive text may give us some of the functionality needed, but there's a whole lot of UI in, for instance, the Chinese IMX, that is specific to how it works and would not really fit into how the predictive text model and banner works.
  2. IMX UI on desktop follows the text caret, and is not part of the OSK.
  3. Predictive text models are written in TypeScript. This may be okay, but the desktop IMXs currently have database-backed data which we would need to re-engineer into a js runtime presumably in a browser instance, which is very heavy, and not very well suited to the task. The Chinese IMX has 65,000 words and currently loads instantly.
jahorton commented 1 year ago

I don't want to pour cold water on your proposal, but I am not sure that the predictive text module will be sufficient:

  1. Predictive text may give us some of the functionality needed, but there's a whole lot of UI in, for instance, the Chinese IMX, that is specific to how it works and would not really fit into how the predictive text model and banner works.

That particular keyboard is the one I've probably referenced the most when thinking about this.

Obviously, the "enter a number to select a picker option" is distinct from current predictive text, but that's something we could consider enabling just for picker models.

What else is "specific to how it works" that isn't directly analogous to existing predictive text / suggestion banner functionality? The "show more" is currently distinct, but we're looking at design for removing that limitation of the current predictive text system.

  1. IMX UI on desktop follows the text caret, and is not part of the OSK.

OK, that part's fair.

There is always the option of launching the banner without the rest of the OSK... kind of like your occasional push to have a separate WebView for popup keys on Android.

  1. Predictive text models are written in TypeScript. This may be okay, but the desktop IMXs currently have database-backed data which we would need to re-engineer into a js runtime presumably in a browser instance, which is very heavy, and not very well suited to the task. The Chinese IMX has 65,000 words and currently loads instantly.

I'd like to point out that some, if not all, of the picker keyboards listed above also have database-backed data which is retrieved via API query. The link below is one such query, as does occur when using the japanese keyboard:

https://r.keymanweb.com/kbd/japanese.php?kana=%E3%81%AB%E3%81%BB%E3%82%93&id=4

Thought experiment: is a WebWorker able to launch queries against such endpoints? If so, the "picker model" could use the very same technique internally to avoid embedding the database in JS-land. The pattern already exists.

Then, setting an option during model setup that notes "Hey, are we embedded in a desktop app? Just post a query to the app's database" should allow us to use the same general structure, but supply the data locally.

Side-note: I remember noting in the past that existing KeymanWeb picker keyboards with a database / API-query backend currently build a cache of things the user has typed and fetch from that if the same input is repeated again. Noticing that sort of code within the keyboard's embedded script was one of the clearer "tells" that a keyboard used the design, at least for me.


I don't see any blockers, though some of the concerns you raised are pretty valid, demonstrating that even this approach isn't exactly a "low-hanging fruit" on either side (embedding app or embedded KMW).

mcdurdin commented 1 year ago

For Chinese IMX, read Chinese CS-pinyin desktop IMX (Keyman for Windows), sorry wasn't clear on that before!

Thought also: the Japanese IMX has glosses also visible which is super helpful for language learners.

On Wed, 21 Dec 2022, 12:45 pm Joshua Horton, @.***> wrote:

I don't want to pour cold water on your proposal, but I am not sure that the predictive text module will be sufficient:

  1. Predictive text may give us some of the functionality needed, but there's a whole lot of UI in, for instance, the Chinese IMX, that is specific to how it works and would not really fit into how the predictive text model and banner works.

That particular keyboard is the one I've probably referenced the most when thinking about this.

Obviously, the "enter a number to select a picker option" is distinct from current predictive text, but that's something we could consider enabling just for picker models.

What else is "specific to how it works" that isn't directly analogous to existing predictive text / suggestion banner functionality? The "show more" is currently distinct, but we're looking at design for removing that limitation of the current predictive text system.

  1. IMX UI on desktop follows the text caret, and is not part of the OSK.

OK, that part's fair.

There is always the option of launching the banner without the rest of the OSK... kind of like your occasional push to have a separate WebView for popup keys on Android.

  1. Predictive text models are written in TypeScript. This may be okay, but the desktop IMXs currently have database-backed data which we would need to re-engineer into a js runtime presumably in a browser instance, which is very heavy, and not very well suited to the task. The Chinese IMX has 65,000 words and currently loads instantly.

I'd like to point out that some, if not all, of the picker keyboards listed above also have database-backed data which is retrieved via API query.

https://r.keymanweb.com/kbd/japanese.php?kana=%E3%81%AB%E3%81%BB%E3%82%93&id=4

Thought experiment: is a WebWorker unable to launch queries against such endpoints? If not, the "picker model" could use the very same technique internally. The pattern already exists.

Then, setting an option during model setup that notes "Hey, are we embedded in a desktop app? Just post a query to the app's database" should allow us to use the same general structure, but supply the data locally.

Side-note: I remember noting in the past that existing KeymanWeb picker keyboards with a database / API-query backend currently build a cache of things the user has typed and fetch from that if the same input is repeated again. Noticing that sort of code within the keyboard's embedded script was one of the clearer "tells" that a keyboard used the design, at least for me.

I don't see any blockers, though some of the concerns you raised are pretty valid, demonstrating that even this approach isn't exactly a "low-hanging fruit" on either side (embedding app or embedded KMW).

— Reply to this email directly, view it on GitHub https://github.com/keymanapp/keyman/issues/7928#issuecomment-1360663023, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABCKHPPYS7Q6J643BV3IDGTWOJOLXANCNFSM6AAAAAATC7DDO4 . You are receiving this because you commented.Message ID: @.***>

mcdurdin commented 2 months ago

https://github.com/keymanapp/keyboards/issues/3103

mcdurdin commented 1 month ago

Preliminary design documentation: https://docs.google.com/document/d/1Lp565RdfXOkyYMf20BfzszZ1e8Y9DUF744yox2M_w5A/edit