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

chore(web): enforce strict function types in web/ 🔩 #11463

Merged
merged 2 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions web/src/app/browser/src/keymanEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ 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), (engine: KeymanEngine) => {
super(worker, config, new ContextManager(config, () => this.legacyAPIEvents), (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),
keyboardInterface: new KeyboardInterface(window, engine as KeymanEngine),
defaultOutputRules: new DefaultBrowserRules(engine.contextManager)
};
});
Expand All @@ -73,8 +73,8 @@ export default class KeymanEngine extends KeymanEngineBase<BrowserConfiguration,
this.hardKeyboard = new HardwareEventKeyboard(config.hardDevice, this.core.keyboardProcessor, this.contextManager);

// Scrolls the document-body to ensure that a focused element remains visible after the OSK appears.
this.contextManager.on('targetchange', (target: OutputTarget<any>) => {
const e = target?.getElement();
this.contextManager.on('targetchange', (target) => {
const e = (target as OutputTarget<any>)?.getElement();
if(this.osk) {
(this.osk.activationModel as TwoStateActivator<HTMLElement>).activationTrigger = e;
}
Expand Down
10 changes: 6 additions & 4 deletions web/src/app/browser/src/languageMenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ export class LanguageMenu {
}

// Touchstart (or mspointerdown) event highlights the touched list item
const touchStart = function(this: HTMLElement & KeyboardTag, e: TouchEvent) {
const touchStart = function(this: HTMLElement, e: TouchEvent) {

e.stopPropagation();
if(this.className.indexOf('selected') <= 0) {
this.className=this.className+' selected';
Expand All @@ -495,7 +496,7 @@ export class LanguageMenu {

//TODO: Still drags Android background sometimes (not consistently)
// Touchmove drags the list and prevents release from selecting the language
const touchMove=function(this: HTMLElement & KeyboardTag, e: TouchEvent) {
const touchMove=function(this: HTMLElement, e: TouchEvent) {
e.stopImmediatePropagation();
var scroller=<HTMLElement>languageMenu.lgList.childNodes[0],
yMax=scroller.scrollHeight-scroller.offsetHeight,
Expand Down Expand Up @@ -539,7 +540,8 @@ export class LanguageMenu {
};

// Touch release (click) event selects touched list item
const touchEnd=function(this: HTMLElement & KeyboardTag, e: TouchEvent) {
const touchEnd=function(this: HTMLElement, e: TouchEvent) {
const entry = this as HTMLElement & KeyboardTag;
if(typeof(e.stopImmediatePropagation) != 'undefined') {
e.stopImmediatePropagation();
} else {
Expand All @@ -552,7 +554,7 @@ export class LanguageMenu {
languageMenu.keyman.contextManager.focusAssistant.setFocusTimer(); // #5946

languageMenu.lgList.style.display='none'; //still allows blank menu momentarily on selection
languageMenu.keyman.contextManager.activateKeyboard(this.kn,this.kc,true);
languageMenu.keyman.contextManager.activateKeyboard(entry.kn, entry.kc,true);
languageMenu.keyman.contextManager.restoreLastActiveTarget();
languageMenu.hide();
}
Expand Down
8 changes: 4 additions & 4 deletions web/src/app/browser/src/utils/alertHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class AlertHost {
bx.className='kmw-alert-close';

// Close alert if anywhere in box is touched, since close box is too small on mobiles
lb.onmousedown = lb.onclick = (e) => {
const lbClick = lb.onmousedown = lb.onclick = (e: MouseEvent | TouchEvent) => {
// Ignore if waiting, only handle for alert
if(bx.style.display == 'block') {
bg.style.display='none';
Expand All @@ -68,13 +68,13 @@ export class AlertHost {
}
};

lb.addEventListener('touchstart', lb.onclick, false);
bg.onmousedown = bg.onclick = (e) => {
lb.addEventListener('touchstart', lbClick, false);
const bgClick = bg.onmousedown = bg.onclick = (e: MouseEvent | TouchEvent) => {
e.preventDefault();
e.stopPropagation();

}
bg.addEventListener('touchstart', bg.onclick, false);
bg.addEventListener('touchstart', bgClick, false);
lb.appendChild(bx); // [0]
lb.appendChild(lt); // [1]
lb.appendChild(gr); // [2]
Expand Down
10 changes: 5 additions & 5 deletions web/src/app/ui/kmwuitoolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1187,7 +1187,7 @@ if(!keyman?.ui?.name) {
* @param {Object} p
**/
readonly onHideOSK = (p: {
HiddenByUser: boolean
HiddenByUser?: boolean
}) => {
if(this.init && p.HiddenByUser) {
this.oskButtonNode.className = 'kmw_button';
Expand Down Expand Up @@ -1264,7 +1264,7 @@ if(!keyman?.ui?.name) {
* A closure to be evaluated upon dismissal of a modal popup generated
* by this UI module.
*/
dismissalCallback: (event: Event) => any = null;
dismissalCallback: (event: MouseEvent) => any = null;

/**
* The root element associated with an active modal popup; related
Expand All @@ -1277,7 +1277,7 @@ if(!keyman?.ui?.name) {
* for the popup, we stash the old event listener here and restore
* it when we're done.
*/
lastDismissalCallback: (event: Event) => any = null;
lastDismissalCallback: (event: MouseEvent) => any = null;

/**
* Function PopupDismissal
Expand Down Expand Up @@ -1309,7 +1309,7 @@ if(!keyman?.ui?.name) {
* @param {function(Object)} callback
* Description Prepare for callback dismissal
**/
SetupPopupDismissal(element: HTMLElement, callback: (event: Event) => any) {
SetupPopupDismissal(element: HTMLElement, callback: (event: MouseEvent) => any) {
if(this.PopupDismissal == document.onclick) {
this.CancelPopupDismissal(this.dismissalCallback);
}
Expand All @@ -1325,7 +1325,7 @@ if(!keyman?.ui?.name) {
* @param {?function(Object)} callback
* Description Cancel callback dismissal
**/
CancelPopupDismissal(callback?: (event: Event) => void) {
CancelPopupDismissal(callback?: (event: MouseEvent) => void) {
if(this.PopupDismissal == document.onclick) {
document.onclick = this.lastDismissalCallback;
this.lastDismissalCallback = null;
Expand Down
5 changes: 2 additions & 3 deletions web/src/engine/dom-utils/src/cookieSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ type DecodedCookieFieldValue = string | number | boolean;

type FilteredRecordEncoder = (value: DecodedCookieFieldValue, key: string) => string;
type FilteredRecordDecoder = (value: string, key: string) => DecodedCookieFieldValue;
const no_change = (val: string) => val as string;

export default class CookieSerializer<Type extends Record<keyof Type, DecodedCookieFieldValue>> {
readonly name: string;
Expand All @@ -12,11 +11,11 @@ export default class CookieSerializer<Type extends Record<keyof Type, DecodedCoo
}

load(decoder?: FilteredRecordDecoder): Type {
return this.loadCookie(this.name, decoder || no_change) as Type;
return this.loadCookie(this.name, decoder || ((val: string) => val as DecodedCookieFieldValue)) as Type;
}

save(cookie: Type, encoder?: FilteredRecordEncoder) {
this.saveCookie(this.name, cookie, encoder || no_change);
this.saveCookie(this.name, cookie, encoder || ((val: DecodedCookieFieldValue) => val as string));
}

/**
Expand Down
4 changes: 3 additions & 1 deletion web/src/engine/events/src/legacyEventEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export class LegacyEventEmitter<EventTypes extends LegacyEventMap> {
func: EventListener<EventTypes, T>
): boolean {
this._removeEventListener(event, func);
this.events[event].push(func);
// TS gets hung up on the type info here because we can potentially store
// different types of listeners for different events.
this.events[event].push(func as unknown as any);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion web/src/engine/osk/src/banner/suggestionBanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ export class SuggestionBanner extends Banner {
maxRoamingBounds: safeBounds,
safeBounds: safeBounds,
// touchEventRoot: this.element, // is the default
itemIdentifier: (sample, target: HTMLElement) => {
itemIdentifier: (sample) => {
const selBounds = this.selectionBounds.getBoundingClientRect();

// Step 1: is the coordinate within the range we permit for selecting _anything_?
Expand Down
6 changes: 3 additions & 3 deletions web/src/engine/osk/src/input/gestures/browser/flick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,10 @@ export default class Flick implements GestureHandler {
coord: [NaN, 0]
}];

keys = keys.concat(Object.keys(flickSet).map((dir: (typeof OrderedFlickDirections[number])) => {
keys = keys.concat(Object.keys(flickSet).map((dir) => {
return {
spec: flickSet[dir] as ActiveSubKey,
coord: FlickNameCoordMap.get(dir)
spec: flickSet[dir as typeof OrderedFlickDirections[number]] as ActiveSubKey,
coord: FlickNameCoordMap.get(dir as typeof OrderedFlickDirections[number])
};
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,15 @@ export class GesturePreviewHost extends EventEmitter<EventMap> {
if(keySpec.flick) {
const flickSpec = keySpec.flick || {};

Object.keys(flickSpec).forEach((dir: typeof OrderedFlickDirections[number]) => {
Object.keys(flickSpec).forEach((dir) => {
const flickPreview = document.createElement('div');
flickPreview.className = 'kmw-flick-preview kmw-key-text';
flickPreview.textContent = flickSpec[dir].text;
flickPreview.textContent = flickSpec[dir as typeof OrderedFlickDirections[number]].text;

const ps /* preview style */ = flickPreview.style;

// is in polar coords, origin toward north, clockwise.
const coords = FlickNameCoordMap.get(dir);
const coords = FlickNameCoordMap.get(dir as typeof OrderedFlickDirections[number]);

const x = coerceZeroes(-Math.sin(coords[0])); // Put 'e' flick at left
const y = coerceZeroes(Math.cos(coords[0])); // Put 'n' flick at bottom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('PageContextAttachment', () => {
sut.listInputs();

const expected = ['email', 'search', 'text', 'url', 'textarea'];
const types = sut.sortedInputs.map((e: HTMLInputElement) => (e.type));
const types = sut.sortedInputs.map((e) => ((e as HTMLInputElement).type));
assert.equal(types.length, expected.length);
assert.deepEqual(types, expected, `Actual [${types}]`);
});
Expand All @@ -86,7 +86,7 @@ describe('PageContextAttachment', () => {
sut.listInputs();

const expected = ['1', '3'];
const types = sut.sortedInputs.map((e: HTMLInputElement) => (e.id));
const types = sut.sortedInputs.map((e) => (e as HTMLInputElement).id);
assert.equal(types.length, expected.length);
assert.deepEqual(types, expected, `Actual [${types}]`);
});
Expand Down
1 change: 0 additions & 1 deletion web/src/tsconfig.dom.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"lib": [ "DOM", "ES6"],
// TODO: These override ../tsconfig.base.json settings, and so should be removed if possible,
// but existing code in web/ breaks some of these settings
"strictFunctionTypes": false,
"noImplicitReturns": false,
"strictNullChecks": false,
}
Expand Down
Loading