Skip to content

Commit

Permalink
Merge pull request #12040 from keymanapp/change/web/cherry-pick/11962…
Browse files Browse the repository at this point in the history
…-revert-11174

change(web): revert #11174, which loads keyboards before initializing the OSK 🍒 🏠
  • Loading branch information
mcdurdin authored Jul 30, 2024
2 parents abfc5c2 + 8c87b55 commit faaf90a
Show file tree
Hide file tree
Showing 11 changed files with 31 additions and 118 deletions.
6 changes: 1 addition & 5 deletions android/KMEA/app/src/main/assets/android-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ function init() {
keyman.beepKeyboard = beepKeyboard;

// Readies the keyboard stub for instant loading during the init process.
try {
KeymanWeb.registerStub(JSON.parse(jsInterface.initialKeyboard()));
} catch(error) {
console.error(error);
}
KeymanWeb.registerStub(JSON.parse(jsInterface.initialKeyboard()));

keyman.init({
'embeddingApp':device,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ export default class PredictionContext extends EventEmitter<PredictionContextEve
this.connect();
}

public get modelState() {
return this.langProcessor.state;
}

private connect() {
this.langProcessor.addListener('invalidatesuggestions', this.invalidateSuggestions);
this.langProcessor.addListener('suggestionsready', this.updateSuggestions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,8 @@ function getOskWidth() {

function getOskHeight() {
var height = oskHeight;
if(keyman.osk && keyman.osk.banner._activeType != 'blank') {
if(keyman.osk.banner._activeType != 'blank') {
height = height - keyman.osk.banner.height;
} else {
height = height - (bannerHeight ? bannerHeight : 0);
}
return height;
}
Expand Down
4 changes: 1 addition & 3 deletions web/src/app/browser/src/contextManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -818,9 +818,7 @@ export default class ContextManager extends ContextManagerBase<BrowserConfigurat

// Sets the default stub (as specified with the `getSavedKeyboard` call) as active.
if(stub) {
return this.activateKeyboard(stub.id, stub.langId);
} else {
return null;
this.activateKeyboard(t[0], t[1]);
}
}

Expand Down
44 changes: 17 additions & 27 deletions web/src/app/browser/src/keymanEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
// or do anything that would mutate the value.
const savedKeyboardStr = this.contextManager.getSavedKeyboardRaw();

if(device.touchable) {
this.osk = new views.AnchoredOSKView(this);
} else {
this.osk = new views.FloatingOSKView(this);
}

setupOskListeners(this, this.osk, this.contextManager);

// Automatically performs related handler setup & maintains references
// needed for related cleanup / shutdown.
this.pageIntegration = new PageIntegrationHandlers(window, this);
Expand All @@ -213,34 +221,16 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
this._initialized = 2;

// Let any deferred, pre-init stubs complete registration
await this.config.deferForInitialization;

/*
Attempt to restore the user's last-used keyboard from their previous session.
The method auto-loads the default stub if one is available and the last-used keyboard
has no registered stub.
Note: any cloud stubs will probably not be available yet.
If we tracked cloud requests and awaited a Promise.all on pending queries,
we could handle that too.
*/
const loadingKbd: Promise<any> = this.contextManager.restoreSavedKeyboard(savedKeyboardStr);

// Wait for the initial keyboard to load before setting the OSK; this will avoid building an
// empty OSK that we'll instantly discard after.
try {
await loadingKbd;
} catch { /* in case of failed fetch due to network error or bad URI; we must still let the OSK init. */ };

const firstKbdConfig = {
keyboardToActivate: this.contextManager.activeKeyboard
};
const osk = device.touchable ? new views.AnchoredOSKView(this, firstKbdConfig) : new views.FloatingOSKView(this, firstKbdConfig);
await Promise.resolve();

// Attempt to restore the user's last-used keyboard from their previous session.
//
// Note: any cloud stubs will probably not be available yet.
// If we tracked cloud requests and awaited a Promise.all on pending queries,
// we could handle that too.
this.contextManager.restoreSavedKeyboard(savedKeyboardStr);

setupOskListeners(this, osk, this.contextManager);
// And, now that we have our loaded active keyboard - or failed, thus must use that default...
// Now we set the OSK in place, an act which triggers VisualKeyboard construction.
this.osk = osk;
await Promise.resolve();
}

get register(): (x: CloudQueryResult) => void {
Expand Down
6 changes: 3 additions & 3 deletions web/src/app/browser/src/viewsAnchorpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function buildBaseOskConfiguration(engine: KeymanEngine) {
};

class PublishedAnchoredOSKView extends AnchoredOSKView {
constructor(engine: KeymanEngine, config?: Partial<ViewConfiguration>) {
constructor(engine: KeymanEngine, config?: ViewConfiguration) {
let finalConfig = {
...buildBaseOskConfiguration(engine),
...(config || {})
Expand All @@ -28,7 +28,7 @@ class PublishedAnchoredOSKView extends AnchoredOSKView {
}

class PublishedFloatingOSKView extends FloatingOSKView {
constructor(engine: KeymanEngine, config?: Partial<FloatingOSKViewConfiguration>) {
constructor(engine: KeymanEngine, config?: FloatingOSKViewConfiguration) {
let finalConfig: FloatingOSKViewConfiguration = {
...buildBaseOskConfiguration(engine),
...(config || {})
Expand All @@ -39,7 +39,7 @@ class PublishedFloatingOSKView extends FloatingOSKView {
}

class PublishedInlineOSKView extends InlinedOSKView {
constructor(engine: KeymanEngine, config?: Partial<ViewConfiguration>) {
constructor(engine: KeymanEngine, config?: ViewConfiguration) {
let finalConfig: ViewConfiguration = {
...buildBaseOskConfiguration(engine),
...(config || {})
Expand Down
37 changes: 6 additions & 31 deletions web/src/app/webview/src/keymanEngine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultRules, DeviceSpec, RuleBehavior, isEmptyTransform, Keyboard } from '@keymanapp/keyboard-processor'
import { DefaultRules, DeviceSpec, RuleBehavior } 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';
Expand Down Expand Up @@ -71,32 +71,7 @@ export default class KeymanEngine extends KeymanEngineBase<WebviewConfiguration,
});

this.contextManager.initialize();
this.config.finalizeInit();

// Is triggered by the previous call.
// Defer to allow any pending stubs to be registered
await this.config.deferForInitialization;

// Was at least one stub pre-registered?
const kbdCache = this.keyboardRequisitioner.cache;
const firstStub = kbdCache.defaultStub;
let firstKeyboard: Keyboard;
if(firstStub) {
// If so, the common engine will have automatically started fetching it.
// Wait for the keyboard to load in order to avoid the high cost of building
// a stand-in we'll automatically replace.
try {
// Re-uses pre-existing fetch requests and fetched keyboards.
firstKeyboard = await kbdCache.fetchKeyboardForStub(firstStub);
} catch { /* in case of failed fetch due to network error or bad URI; we must still let the OSK init. */ };
}

const keyboardConfig: ViewConfiguration['keyboardToActivate'] = firstKeyboard ? {
keyboard: firstKeyboard,
metadata: firstStub
} : null;

// We construct the OSK now to avoid layout reflow thrashing from building a stand-in keyboard if possible.
const oskConfig: ViewConfiguration = {
hostDevice: this.config.hostDevice,
pathConfig: this.config.paths,
Expand All @@ -107,13 +82,13 @@ export default class KeymanEngine extends KeymanEngineBase<WebviewConfiguration,
predictionContextManager: this.contextManager.predictionContext,
heightOverride: this.getOskHeight,
widthOverride: this.getOskWidth,
isEmbedded: true,
keyboardToActivate: keyboardConfig
isEmbedded: true
};

const osk = new AnchoredOSKView(oskConfig);
setupEmbeddedListeners(this, osk);
this.osk = osk;
this.osk = new AnchoredOSKView(oskConfig);
setupEmbeddedListeners(this, this.osk);

this.config.finalizeInit();
}

// Functions that the old 'app/webview' equivalent had always provided to the WebView
Expand Down
2 changes: 0 additions & 2 deletions web/src/engine/main/src/keymanEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ export default class KeymanEngine<
// so we handle that here.
this.osk?.bannerController.selectBanner(state);
this.osk?.refreshLayout();

// If `this.osk` is not yet initialized, the OSK itself will check if the model is loaded
});

// The OSK does not possess a direct connection to the KeyboardProcessor's state-key
Expand Down
9 changes: 0 additions & 9 deletions web/src/engine/osk/src/config/viewConfiguration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { type PredictionContext } from "@keymanapp/input-processor";
import { Keyboard, KeyboardProperties } from "@keymanapp/keyboard-processor";
import type Activator from "../views/activator.js";
import CommonConfiguration from "./commonConfiguration.js";

Expand Down Expand Up @@ -41,12 +40,4 @@ export default interface Configuration extends CommonConfiguration {
* with the active context.
*/
predictionContextManager?: PredictionContext;

/**
* Can be set and specified during initialization to start with the specified keyboard activated.
*/
keyboardToActivate?: {
keyboard: Keyboard,
metadata: KeyboardProperties;
}
}
11 changes: 1 addition & 10 deletions web/src/engine/osk/src/views/floatingOskView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class FloatingOSKView extends OSKView {
dfltX: string;
dfltY: string;

private layoutSerializer = new FloatingOSKCookieSerializer();
layoutSerializer = new FloatingOSKCookieSerializer();

private titleBar: TitleBar;
private resizeBar: ResizeBar;
Expand Down Expand Up @@ -233,15 +233,6 @@ export default class FloatingOSKView extends OSKView {
* @return {boolean}
*/
private loadPersistedLayout(): void {
/*
If a keyboard is available during OSK construction, it is possible
for this field to be `undefined`. `loadPersistedLayout` will be called
later in construction, so it's safe to skip.
*/
if(!this.layoutSerializer) {
return;
}

let c = this.layoutSerializer.loadWithDefaults({
visible: 1,
userSet: 0,
Expand Down
22 changes: 1 addition & 21 deletions web/src/engine/osk/src/views/oskView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ export default abstract class OSKView
private _baseFontSize: ParsedLengthStyle;

private needsLayout: boolean = true;
private initialized: boolean;

private _animatedHideTimeout: number;

Expand Down Expand Up @@ -239,7 +238,7 @@ export default abstract class OSKView

this._bannerController = new BannerController(this.bannerView, this.hostDevice, this.config.predictionContextManager);

this.keyboardView = new EmptyView();
this.keyboardView = this._GenerateKeyboardView(null, null);
this._Box.appendChild(this.keyboardView.element);

// Install the default OSK stylesheets - but don't have it managed by the keyboard-specific stylesheet manager.
Expand All @@ -252,22 +251,10 @@ export default abstract class OSKView
this.uiStyleSheetManager.linkExternalSheet(sheetHref);
}

this.activeKeyboard = this.config.keyboardToActivate;

// Ensure the appropriate banner mode is activated; it's possible for a model to have either
// partially or fully loaded, especially if the prior line has a full Keyboard instance.
const modelState = this.config.predictionContextManager?.modelState;
if(modelState) {
this.bannerController.selectBanner(modelState);
}

this.setBaseMouseEventListeners();
if(this.hostDevice.touchable) {
this.setBaseTouchEventListeners();
}

this._Box.style.display = 'none';
this.initialized = true;
}

protected get configuration(): Configuration {
Expand Down Expand Up @@ -553,13 +540,6 @@ export default abstract class OSKView
keyboard: Keyboard,
metadata: KeyboardProperties
}) {
// Is the keyboard already loaded? If so, ignore the change command.
//
// Note: ensures that the _instances_ are the same; it's possible to make new instances
// to force a refresh. Does not perform a deep-equals.
if(this.initialized && this.keyboardData?.keyboard == keyboardData?.keyboard && this.keyboardData?.metadata == keyboardData?.metadata) {
return;
}
this.keyboardData = keyboardData;
this.loadActiveKeyboard();

Expand Down

0 comments on commit faaf90a

Please sign in to comment.