mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-24 08:37:42 +00:00
feat(web): touch-layout layer spec processing now deferred until needed
This commit is contained in:
parent
fdd4c2a6a7
commit
bb0420109f
4 changed files with 44 additions and 26 deletions
|
|
@ -745,7 +745,11 @@ export class ActiveLayer implements LayoutLayer {
|
|||
}
|
||||
|
||||
export class ActiveLayout implements LayoutFormFactor{
|
||||
layer: ActiveLayer[];
|
||||
/**
|
||||
* Holds all layer specifications for the layout. There is no guarantee that they
|
||||
* have been fully preprocessed.
|
||||
*/
|
||||
layer: TouchLayerSpec[];
|
||||
font: string;
|
||||
keyLabels: boolean;
|
||||
isDefault?: boolean;
|
||||
|
|
@ -766,8 +770,25 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fully preprocessed version of the specified layer spec.
|
||||
* @param layerId
|
||||
* @returns
|
||||
*/
|
||||
@Enumerable
|
||||
getLayer(layerId: string): ActiveLayer {
|
||||
if(!this.layerMap[layerId]) {
|
||||
const spec = this.layer.find((layerSpec) => layerSpec.id == layerId);
|
||||
if(!spec) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prepare the layer-spec for actual use.
|
||||
ActiveLayer.sanitize(spec);
|
||||
ActiveLayer.polyfill(spec, this);
|
||||
this.layerMap[layerId] = spec as ActiveLayer;
|
||||
}
|
||||
|
||||
return this.layerMap[layerId];
|
||||
}
|
||||
|
||||
|
|
@ -786,10 +807,10 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
static correctLayerEmptyRowBug(layers: LayoutLayer[]) {
|
||||
for(let n=0; n<layers.length; n++) {
|
||||
let layer=layers[n];
|
||||
let rows=layer['row'];
|
||||
let rows=layer.row;
|
||||
let i: number;
|
||||
for(i=rows.length-1; i>=0; i--) {
|
||||
if(!Array.isArray(rows[i]['key']) || rows[i]['key'].length == 0) {
|
||||
if(!Array.isArray(rows[i].key) || rows[i].key.length == 0) {
|
||||
rows.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -798,10 +819,6 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
|
||||
static sanitize(rawLayout: TouchLayoutSpec) {
|
||||
ActiveLayout.correctLayerEmptyRowBug(rawLayout.layer);
|
||||
|
||||
for(const layer of rawLayout.layer) {
|
||||
ActiveLayer.sanitize(layer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -843,11 +860,8 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
}
|
||||
|
||||
// Create a separate OSK div for each OSK layer, only one of which will ever be visible
|
||||
var n: number;
|
||||
let layerMap: {[layerId: string]: ActiveLayer} = {};
|
||||
|
||||
let layers=layout.layer;
|
||||
|
||||
// Add class functions to the existing layout object, allowing it to act as an ActiveLayout.
|
||||
let dummy = new ActiveLayout();
|
||||
for(let key in dummy) {
|
||||
|
|
@ -856,24 +870,20 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
}
|
||||
}
|
||||
|
||||
let aLayout = layout as ActiveLayout;
|
||||
let aLayout = layout as unknown as ActiveLayout;
|
||||
aLayout.keyboard = keyboard;
|
||||
aLayout.formFactor = formFactor;
|
||||
|
||||
for(n=0; n<layers.length; n++) {
|
||||
ActiveLayer.polyfill(layers[n], aLayout);
|
||||
layerMap[layers[n].id] = layers[n] as ActiveLayer;
|
||||
}
|
||||
|
||||
// After all layers are preprocessed...
|
||||
aLayout.layerMap = layerMap;
|
||||
|
||||
// The default-layer shift key & shift-layer shift key on mobile platforms should have a
|
||||
// default multitap re: a 'caps' layer under select conditions.
|
||||
//
|
||||
// Note: whether or not any other keys have multitaps doesn't matter here. Just THESE.
|
||||
if(formFactor != 'desktop' && !!layout.layer.find((entry) => entry.id == 'caps')) {
|
||||
const defaultLayer = layout.layer.find((entry) => entry.id == 'default') as ActiveLayer;
|
||||
const shiftLayer = layout.layer.find((entry) => entry.id == 'shift') as ActiveLayer;
|
||||
// Triggers preprocessing for both default and shift layers. They're the
|
||||
// most-frequently referenced, at least.
|
||||
const defaultLayer = aLayout.getLayer('default') as ActiveLayer;
|
||||
const shiftLayer = aLayout.getLayer('shift') as ActiveLayer;
|
||||
|
||||
const defaultShift = defaultLayer.getKey('K_SHIFT');
|
||||
const shiftShift = shiftLayer ?.getKey('K_SHIFT');
|
||||
|
|
@ -898,7 +908,7 @@ export class ActiveLayout implements LayoutFormFactor{
|
|||
aLayout.hasLongpresses = analysisMetadata.hasLongpresses;
|
||||
aLayout.hasMultitaps = analysisMetadata.hasMultitaps;
|
||||
|
||||
aLayout.layerMap = layerMap;
|
||||
// All layers are lazy-processed, with the usual processing applied when first referenced.
|
||||
|
||||
return aLayout;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export interface LayoutLayer extends LayoutLayerBase {
|
|||
aligned?: boolean
|
||||
};
|
||||
|
||||
export interface LayoutFormFactor extends Omit<LayoutFormFactorSpec, 'layer'> {
|
||||
export interface LayoutFormFactor extends LayoutFormFactorSpec {
|
||||
};
|
||||
|
||||
export type LayoutSpec = {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { ActiveKey, ActiveLayout, ActiveSubKey } from "./activeLayout.js";
|
|||
import KeyEvent from "../text/keyEvent.js";
|
||||
import type OutputTarget from "../text/outputTarget.js";
|
||||
import { TouchLayout } from "@keymanapp/common-types";
|
||||
import TouchLayoutSpec = TouchLayout.TouchLayoutPlatform;
|
||||
type TouchLayoutSpec = TouchLayout.TouchLayoutPlatform & { isDefault?: boolean};
|
||||
|
||||
import type { ComplexKeyboardStore } from "../text/kbdInterface.js";
|
||||
|
||||
|
|
@ -403,7 +403,7 @@ export default class Keyboard {
|
|||
// Final check - do we construct a layout, or is this a case where helpText / insertHelpHTML should take over?
|
||||
if(rawSpecifications) {
|
||||
// Now to generate a layout from our raw specifications.
|
||||
let layout = this._layouts[formFactor] = Layouts.buildDefaultLayout(rawSpecifications, this, formFactor) as ActiveLayout;
|
||||
let layout: TouchLayoutSpec = this._layouts[formFactor] = Layouts.buildDefaultLayout(rawSpecifications, this, formFactor);
|
||||
layout.isDefault = true;
|
||||
return layout;
|
||||
} else {
|
||||
|
|
@ -425,11 +425,13 @@ export default class Keyboard {
|
|||
if(rawLayout) {
|
||||
// Prevents accidentally reprocessing layouts; it's a simple enough check.
|
||||
if(this.layoutStates[formFactor] == LayoutState.NOT_LOADED) {
|
||||
rawLayout = ActiveLayout.polyfill(rawLayout, this, formFactor);
|
||||
const layout = ActiveLayout.polyfill(rawLayout, this, formFactor);
|
||||
this.layoutStates[formFactor] = LayoutState.POLYFILLED;
|
||||
return layout;
|
||||
} else {
|
||||
return rawLayout as unknown as ActiveLayout;
|
||||
}
|
||||
|
||||
return rawLayout as ActiveLayout;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1294,6 +1294,12 @@ export default class VisualKeyboard extends EventEmitter<EventMap> implements Ke
|
|||
return allottedHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
Note: these may not be fully preprocessed yet!
|
||||
|
||||
However, any "empty row bug" preprocessing has been applied, and that's
|
||||
what we care about here.
|
||||
*/
|
||||
const layers = this.layerGroup.spec.layer;
|
||||
let oskHeight = 0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue