sillsdev / sillsdev/TheCombine

Evaluate KeymanWeb integration for data-entry fields (ref: Bloom POC)

Open
#4,329 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
22
Forks
10
Avg merge
2d 2h
Merged PRs (30d)
9

Description

Summary

Evaluation of whether Bloom's KeymanWeb integration can be reused to add
Keyman keyboard support to The Combine's data-entry fields.

Source reference: src/BloomBrowserUI/bookEdit/js/keymanWebIntegration.ts on the
Keyman branch of BloomDesktop
(an explicitly-labeled proof-of-concept).

Verdict

  • As a drop-in module: not usable. It's a POC — hard-coded to one Thai keyboard,
    any-typed throughout, CDN-coupled, and wired to Bloom's contenteditable DOM model.
  • As a reference implementation: valuable. The engine-loading and race-condition
    logic transfers directly, and The Combine already has the attach points it needs.

What the Bloom file does

Lazy-loads the KeymanWeb engine once from s.keyman.com, registers the thai_kedmanee
keyboard, waits for the keyboard code (not just its stub) to finish downloading, then on
each focus attaches the engine to the focused element, activates Thai, and shows the
on-screen keyboard (OSK). It is driven by a global focusin handler over Bloom's
bloom-editable divs.

What ports well to The Combine

  • Attach points already exist. KeymanWeb's attachToControl works on
    <input>/<textarea>, and VernWithSuggestions already exposes both a vernInput ref
    and an onFocus callback. Bloom's global focusin becomes a clean per-field
    onFocus={() => attachKeymanWebIfNeeded(vernInput.current)}.
  • The non-trivial engine logic is the real payload: single-instance load promise;
    the "keyboard stub registered ≠ keyboard code loaded" poll; attach-once-via-WeakSet /
    activate-on-every-focus split; and the root/resources/fonts pathing fix.
  • lang-based dispatch fits our model. We key everything on BCP47 tags, so the POC's
    isThai(lang) gate generalizes to "does this writing system have a configured keyboard."

Blockers specific to The Combine

  1. Controlled-input conflict (biggest risk). Our fields are MUI Autocomplete +
    controlled TextField that normalize via onInputChange/onChange. KeymanWeb writes
    directly into the DOM input and dispatches events; whether React's controlled state, the
    Autocomplete suggestion list, and NFC normalization stay in sync with Keyman's insertions
    must be verified empirically. Bloom edits uncontrolled contenteditable, so it never
    hit this.
  2. CDN dependency vs. offline deployment. We ship as a self-hostable stack (Docker/helm/
    ansible) for low-connectivity field sites. A hard s.keyman.com dependency undercuts
    that; the engine + keyboards would need to be bundled/served locally. (Keyman is on npm,
    which would also remove the pathing hacks and the any typing.)
  3. Hard-coded single language. We are multilingual by project. The WritingSystem model
    has bcp47/name/font/rtl but no keyboard field, and Keyman keyboard IDs are not
    1:1 with BCP47. Real use requires a data-model addition plus a per-writing-system keyboard
    picker.
  4. Repo style. window as any / keyman: any conflict with our strict-TS / no-any
    conventions; needs a typed wrapper.
  5. OSK ↔ Autocomplete focus. Clicking the floating on-screen keyboard can blur the input,
    firing onBlur and closing the suggestion dropdown. Needs testing; the OSK may be more
    friction than value versus relying on OS/browser IMEs.

Recommendation / next steps

Treat the Bloom file as a cookbook, not a component:

  • Lift the load-once promise, keyboard-loaded poll, and pathing fix into a typed
    keymanIntegration.ts (bundle Keyman from npm rather than CDN injection).
  • Drive it from field onFocus in VernWithSuggestions (and later GlossWithSuggestions).
  • Go/no-go gate: prove out one real writing system end-to-end and confirm the
    controlled-input sync (blocker #1) before generalizing.
  • If pursued, design the WritingSystem keyboard field + per-writing-system keyboard
    picker (blocker #3).

Findings generated during a code evaluation; details and file/line references available on request.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read src/BloomBrowserUI/bookEdit/js/keymanWebIntegration.ts on the BloomDesktop Keyman branch, then inspect VernWithSuggestions and its vernInput ref and onFocus callback. Run an end-to-end experiment with one writing system to verify controlled-input synchronization, Autocomplete focus behavior, and offline loading. The evaluation is done when there is a documented go/no-go decision and the remaining data-model and keyboard-picker requirements are clear.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend, internationalization
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.