Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change(web): facilitates differentiated configuration objects for KMW variants 🧩 #8458

Merged
merged 12 commits into from
Mar 27, 2023

Conversation

jahorton
Copy link
Contributor

The eventual app/webview and app/browser variants of Keyman Engine for Web have many configuration aspects in common, but some of those aspects are quite specific to one variant or the other:

  • app/webview looks for a number of specialized hooks used in the KMW-embedding process to allow our mobile apps to better integrate with it.
  • app/browser looks to integrate itself into whatever websites / webpages utilize it.

While the full scope of app/browser's specialized needs haven't been fully determined at this time due to prioritizing app/webview, there's already sufficient cause to motivate tailored configuration classes for the two. These classes will likely serve as a central "settings" for other components that may be passed as needed, rather than exposing the entirety of top-level objects.

This PR also includes handling of a few configuration-related "loose ends".

@keymanapp-test-bot skip

@jahorton jahorton added this to the A17S8 milestone Mar 17, 2023
@keymanapp-test-bot
Copy link

keymanapp-test-bot bot commented Mar 17, 2023

User Test Results

Test specification and instructions

User tests are not required

Test Artifacts

Comment on lines +15 to +26
constructor(worker: Worker, sourceUri: string) {
const config = new WebviewConfiguration(sourceUri); // currently set to perform device auto-detect.
config.stubNamespacer = (stub) => {
// If the package has not yet been applied as namespacing...
if(stub.KP && stub.KI.indexOf(`${stub.KP}::`) == -1) {
// Apply namespacing. To make 100% sure that we don't muck up internal prefixing,
// we ensure it is applied consistently in the manner specified below.
stub.KI = toPrefixedKeyboardId(`${stub.KP}::${toUnprefixedKeyboardId(stub.KI)}`);
}
}

super(worker, config, new ContextManager());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block best showcases the main reason for the change in constructor parameter ordering: app/webview (and eventually app/browser) will construct their own Configuration object in their respective KeymanEngine constructor. Each derived-class constructor may take additional parameters, but the first parameter - for worker - will be consistent for both.

The reason: Worker can't be specified at this level if we wish to provide separate debug vs release build products. The non-minified + sourcemapped variant of the worker should be used for debug, while the minified + unsourcemapped variant would be used for release. These will be specified by the top-level entry point for both debug and release esbuild bundling configurations.

Copy link
Contributor Author

@jahorton jahorton Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that only path-related classes remain in this child project. A followup PR (#8459) will rename it accordingly.

As it's still utilized by more than one of the other child projects (engine/keyboard-cache and engine/main), it's still worth keeping around as a separate module of sorts.

There's a small part of me that thinks we could have the reduced paths interface used by engine/osk within this child project too, but then we'd might want to undo that when reusing the OSK in our other products;. The KMW-specific path fields defined by this child-project's objects wouldn't be of use to other platforms, after all, and wouldn't make much sense within a common space, unlike the OSK.

@@ -106,8 +108,9 @@ export class StylesheetManager {
// Modern browsers: use WOFF, TTF and fallback finally to SVG. Don't provide EOT
if(os == DeviceSpec.OperatingSystem.iOS) {
if(ttf != '') {
// once upon a time, we did a cache-prevention thing here... but that was removed long, long ago.
// ttf = this.unCached(ttf);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thing I checked - I was wrong! Fortunately, the kmwembedded.ts part I'd missed had not been removed yet, so I caught this mistake and remedied it here.

this._stubNamespacer = functor;
}

debugReport(): Record<string, any> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended for use with keyman.getDebugInfo().

As seen in the Sentry dashboard:
image

At this point, it may well implement most of the current report seen above, but we will likely add a few extra properties from other sources (like the engine object and/or the OSK) as well - so this isn't intended as the top-level call for said function.

private _defaultSpacebarText: SpacebarText;
private _stubNamespacer?: (KeyboardStub) => void;

public applyCacheBusting: boolean = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

app/webview: true
app/browser: false


this.hardKeyboard = new PassthroughKeyboard(config.hardDevice);
}

initialize() {
super.initialize();
init(options: Required<WebviewInitOptionSpec>) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay, a keyman.init for the modularized app/webview! Well, the start of one, anyway...

@jahorton jahorton marked this pull request as ready for review March 17, 2023 04:06
@mcdurdin mcdurdin modified the milestones: A17S8, A17S9 Mar 18, 2023
web/build.sh Outdated Show resolved Hide resolved
const config = new WebviewConfiguration(sourceUri); // currently set to perform device auto-detect.
config.stubNamespacer = (stub) => {
// If the package has not yet been applied as namespacing...
if(stub.KP && stub.KI.indexOf(`${stub.KP}::`) == -1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you just search for ::? Although wouldn't it be better for the namespace to be separated from KI rather than mutating input data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although wouldn't it be better for the namespace to be separated from KI rather than mutating input data?

I could see an argument for that, but the pre-modular namespacing system worked by prepending the package name as part of the ID. I opted to maintain that.

There's then the issue of Package_id::Keyboard_kbd_id vs Keyboard_Package_id::kbd_id due to the whole Keyboard_ ID-prefixing prepend bit that's been in KMW since forever. The function highlighted in the code block above is designed to ensure that it's always the former pattern and never the latter by detecting the latter and converting it over while leaving the former intact.

Though... I'm not 100% sure that Package-prepended keyboards actually use the Keyboard_ bit too in the existing implementation.

Copy link
Contributor Author

@jahorton jahorton Mar 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmation for that last point...

(from the current master)

// Skip on embedded which namespaces packageID::Keyboard_keyboardID

Contrast with...

(also from the current master)

// Establishes keyboard namespacing.
keymanweb.namespaceID = function(Pstub) {
if(typeof(Pstub['KP']) != 'undefined') {
// An embedded use case wants to utilize package-namespacing.
Pstub['KI'] = Pstub['KP'] + "::" + Pstub['KI'];
}
}

Any incoming keyboard IDs are already mutated to have a prepended package ID as part of the keyboard's ID itself.

We need to make sure that the Keyboard_ applies at the location we want, hence the if-condition seen above.

web/src/app/webview/src/keymanEngine.ts Outdated Show resolved Hide resolved
@@ -106,8 +108,9 @@ export class StylesheetManager {
// Modern browsers: use WOFF, TTF and fallback finally to SVG. Don't provide EOT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No SVG fonts! They're as dead as EOT.

Suggested change
// Modern browsers: use WOFF, TTF and fallback finally to SVG. Don't provide EOT
// Modern browsers: use WOFF2, WOFF, and fallback finally to TTF. SVG, EOT not supported.

See also lines 122-127. Perhaps should be done as a separate issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now tracked at #8500.

Comment on lines 38 to 42
if(typeof options.setActiveOnRegister == 'boolean') {
this._activateFirstKeyboard = options.setActiveOnRegister;
} else if (typeof options.setActiveOnRegister == 'string') {
let str = options.setActiveOnRegister.toLowerCase();
this._activateFirstKeyboard = str === 'true';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this option different types? Seems weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation at https://help.keyman.com/DEVELOPER/ENGINE/WEB/15.0/reference/core/init does suggest we could just go with string.

That said, from master:

// Defines default option values
options: OptionType = {
root: '',
resources: '',
keyboards: '',
fonts: '',
attachType: '',
ui: null,
setActiveOnRegister: 'true', // TODO: convert to boolean

I suppose that TODO can be deferred instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/search?q=org%3Akeymanapp%20setActiveOnRegister&type=code

Yuck! This is the type of thing where the string type should be marked as deprecated in 17.0 and replaced with a boolean in 18.0+. For now though, it is only documented as supporting string.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So given KM Developer Server passes a boolean, and keymanweb.com passes a string, I'd be really happy to just turn this into Boolean and mark it as a breaking change in the release notes, fixing keymanweb.com at the same time. It's a super simple fix for anyone using kmw on their own site, and they'll probably feel good about themselves when they convert "true" into true too!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #4304 for history of this

Copy link
Contributor Author

@jahorton jahorton Mar 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixing keymanweb.com at the same time

I'm not seeing a super-simple way to make an update for this right now for keymanweb.com without including lines 40-41 above. I suppose we'd need to make that update come beta instead?

I've gone ahead and removed those lines in my most recent commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For keymanweb.com we should do that when this merges into master, and then version-compare to determine which data type to use.

Copy link
Contributor Author

@jahorton jahorton Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as a TODO item on #8047 (the base feature branch's PR).

…r-configure-fix' into change/web/engine-configuration
@jahorton jahorton changed the base branch from feature-esmodule-web-engine to chore/web/update-feature-esmodule-for-configure-fix March 23, 2023 08:21
Base automatically changed from chore/web/update-feature-esmodule-for-configure-fix to feature-esmodule-web-engine March 26, 2023 15:48
@jahorton jahorton merged commit 40c6c14 into feature-esmodule-web-engine Mar 27, 2023
@jahorton jahorton deleted the change/web/engine-configuration branch March 27, 2023 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants