change(web): retools processor config init pattern

This commit is contained in:
Joshua A. Horton 2023-06-16 10:06:42 +07:00
parent 089f38f45e
commit 9884d6725d
3 changed files with 46 additions and 38 deletions

View file

@ -8,7 +8,7 @@ import {
VisualKeyboard
} from 'keyman/engine/osk';
import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/package-cache';
import { DeviceSpec, Keyboard, ProcessorInitOptions, extendString } from "@keymanapp/keyboard-processor";
import { DeviceSpec, Keyboard, extendString } from "@keymanapp/keyboard-processor";
import * as views from './viewsAnchorpoint.js';
import { BrowserConfiguration, BrowserInitOptionDefaults, BrowserInitOptionSpec } from './configuration.js';
@ -48,7 +48,15 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
constructor(worker: Worker, sourceUri: string) {
const config = new BrowserConfiguration(sourceUri); // currently set to perform device auto-detect.
super(worker, config, new ContextManager(config, () => this.legacyAPIEvents));
super(worker, config, new ContextManager(config, () => this.legacyAPIEvents), (engine: KeymanEngine) => {
return {
// The `engine` parameter cannot be supplied with the constructing instance before calling
// `super`, hence the 'fun' rigging to supply it _from_ `super` via this closure.
keyboardInterface: new KeyboardInterface(window, engine),
defaultOutputRules: new DefaultBrowserRules(engine.contextManager)
};
});
this._util = new UtilApiEndpoint(config);
this.beepHandler = new BeepHandler(this.core.keyboardInterface);
this.core.keyboardProcessor.beepHandler = () => this.beepHandler.beep(this.contextManager.activeTarget);
@ -111,15 +119,6 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
}
}
protected processorConfiguration(): ProcessorInitOptions {
return {
...super.processorConfiguration(),
keyboardInterface: this.interface || new KeyboardInterface(window, this),
// Overrides just this component of the configuration.
defaultOutputRules: new DefaultBrowserRules(this.contextManager)
};
};
async init(options: Required<BrowserInitOptionSpec>) {
let deviceDetector = new DeviceDetector();
let device = deviceDetector.detect();

View file

@ -1,5 +1,5 @@
import { DeviceSpec } from '@keymanapp/keyboard-processor'
import { KeymanEngine as KeymanEngineBase } from 'keyman/engine/main';
import { DefaultRules, DeviceSpec } from '@keymanapp/keyboard-processor'
import { KeymanEngine as KeymanEngineBase, KeyboardInterface } from 'keyman/engine/main';
import { AnchoredOSKView, ViewConfiguration, StaticActivator } from 'keyman/engine/osk';
import { getAbsoluteX, getAbsoluteY } from 'keyman/engine/dom-utils';
import { type KeyboardStub, toPrefixedKeyboardId, toUnprefixedKeyboardId } from 'keyman/engine/package-cache';
@ -25,7 +25,14 @@ export default class KeymanEngine extends KeymanEngineBase<WebviewConfiguration,
}
}
super(worker, config, new ContextManager(config));
super(worker, config, new ContextManager(config), (engine) => {
return {
// The `engine` parameter cannot be supplied with the constructing instance before calling
// `super`, hence the 'fun' rigging to supply it _from_ `super` via this closure.
keyboardInterface: new KeyboardInterface(window, engine, config.stubNamespacer),
defaultOutputRules: new DefaultRules()
};
});
this.hardKeyboard = new PassthroughKeyboard(config.hardDevice);
}

View file

@ -1,8 +1,8 @@
import { DefaultRules, type Keyboard, KeyboardKeymanGlobal, ProcessorInitOptions, OutputTarget } from "@keymanapp/keyboard-processor";
import { type Keyboard, KeyboardKeymanGlobal, ProcessorInitOptions } from "@keymanapp/keyboard-processor";
import { DOMKeyboardLoader as KeyboardLoader } from "@keymanapp/keyboard-processor/dom-keyboard-loader";
import { InputProcessor, PredictionContext } from "@keymanapp/input-processor";
import { OSKView } from "keyman/engine/osk";
import { KeyboardRequisitioner, type KeyboardStub, ModelCache, ModelSpec } from "keyman/engine/package-cache";
import { KeyboardRequisitioner, ModelCache, ModelSpec } from "keyman/engine/package-cache";
import { EngineConfiguration, InitOptionSpec } from "./engineConfiguration.js";
import KeyboardInterface from "./keyboardInterface.js";
@ -14,6 +14,19 @@ import { EventNames, EventListener, LegacyEventEmitter } from "keyman/engine/eve
import DOMCloudRequester from "keyman/engine/package-cache/dom-requester";
import KEYMAN_VERSION from "@keymanapp/keyman-version";
// From https://stackoverflow.com/a/69328045
type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
// Sets two parts non-optional at this level, while they were at lower levels.
type ProcessorConfiguration = WithRequired<WithRequired<ProcessorInitOptions, 'keyboardInterface'>, 'defaultOutputRules'>;
function determineBaseLayout(): string {
if(typeof(window['KeymanWeb_BaseLayout']) !== 'undefined') {
return window['KeymanWeb_BaseLayout'];
} else {
return 'us';
}
}
export default class KeymanEngine<
Configuration extends EngineConfiguration,
ContextManager extends ContextManagerBase<any>,
@ -73,26 +86,6 @@ export default class KeymanEngine<
// processing - silent failures are far harder to diagnose.
};
// Should be overwritten as needed by engine subclasses; `browser` should set its DefaultOutput subclass in place.
protected processorConfiguration(): ProcessorInitOptions {
// I732 START - Support for European underlying keyboards #1
let baseLayout: string;
if(typeof(window['KeymanWeb_BaseLayout']) !== 'undefined') {
baseLayout = window['KeymanWeb_BaseLayout'];
} else {
baseLayout = 'us';
}
return {
keyboardInterface: this.interface ||
new KeyboardInterface<ContextManager>(window, this, this.config.stubNamespacer),
baseLayout: baseLayout,
defaultOutputRules: new DefaultRules()
};
};
//
/**
* @param worker A configured WebWorker to serve as the predictive-text engine's main thread.
* Available in the following variants:
@ -100,12 +93,21 @@ export default class KeymanEngine<
* - non-sourcemapped + minified (release)
* @param config
* @param contextManager
* @param processorConfigInitializer A one-time use closure used to initialize certain critical components reliant
* upon the class instance, configured by the derived class, but needed during
* the superclass constructor.
*/
constructor(worker: Worker, config: Configuration, contextManager: ContextManager) {
constructor(
worker: Worker,
config: Configuration,
contextManager: ContextManager,
processorConfigInitializer: (engine: KeymanEngine<Configuration, ContextManager, HardKeyboard>) => ProcessorConfiguration
) {
this.config = config;
this.contextManager = contextManager;
const processorConfiguration = this.processorConfiguration();
const processorConfiguration = processorConfigInitializer(this);
processorConfiguration.baseLayout = determineBaseLayout();
this.interface = processorConfiguration.keyboardInterface as KeyboardInterface<ContextManager>;
this.core = new InputProcessor(config.hostDevice, worker, processorConfiguration);