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

ui/common: enable isolatedDeclarations #15700

Merged
merged 4 commits into from
Jul 12, 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
6 changes: 3 additions & 3 deletions ui/common/src/clock.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
export const formatMs = (msTime: number) => {
export const formatMs = (msTime: number): string => {
const date = new Date(Math.max(0, msTime + 500)),
hours = date.getUTCHours(),
minutes = date.getUTCMinutes(),
seconds = date.getUTCSeconds();
return hours > 0 ? hours + ':' + pad(minutes) + ':' + pad(seconds) : minutes + ':' + pad(seconds);
};

export const otbClockIsRunning = (fen: string) => !fen.includes('PPPPPPPP/RNBQKBNR');
export const otbClockIsRunning = (fen: string): boolean => !fen.includes('PPPPPPPP/RNBQKBNR');

export const lichessClockIsRunning = (fen: string, color: Color) =>
export const lichessClockIsRunning = (fen: string, color: Color): boolean =>
color == 'white' ? !fen.includes('PPPPPPPP/RNBQKBNR') : !fen.startsWith('rnbqkbnr/pppppppp');

const pad = (x: number) => (x < 10 ? '0' : '') + x;
44 changes: 23 additions & 21 deletions ui/common/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,32 @@ export const memoize = <A>(compute: () => A): (() => A) => {
};
};

export const scrollToInnerSelector = (el: HTMLElement, selector: string, horiz: boolean = false) =>
export const scrollToInnerSelector = (el: HTMLElement, selector: string, horiz: boolean = false): void =>
scrollTo(el, el.querySelector(selector), horiz);

export const scrollTo = (el: HTMLElement, target: HTMLElement | null, horiz: boolean = false) => {
export const scrollTo = (el: HTMLElement, target: HTMLElement | null, horiz: boolean = false): void => {
if (target)
horiz
? (el.scrollLeft = target.offsetLeft - el.offsetWidth / 2 + target.offsetWidth / 2)
: (el.scrollTop = target.offsetTop - el.offsetHeight / 2 + target.offsetHeight / 2);
};

export const onClickAway = (f: () => void) => (el: HTMLElement) => {
const listen: () => void = () =>
$(document).one('click', e => {
if (!document.contains(el)) {
return;
}
if (el.contains(e.target)) {
listen();
} else {
f();
}
});
setTimeout(listen, 300);
};
export const onClickAway =
(f: () => void) =>
(el: HTMLElement): void => {
const listen: () => void = () =>
$(document).one('click', e => {
if (!document.contains(el)) {
return;
}
if (el.contains(e.target)) {
listen();
} else {
f();
}
});
setTimeout(listen, 300);
};

export type SparseSet<T> = Set<T> | T;
export type SparseMap<V> = Map<string, SparseSet<V>>;
Expand All @@ -114,13 +116,13 @@ export function getSpread<T>(m: SparseMap<T>, key: string): T[] {
return spread(m.get(key));
}

export function remove<T>(m: SparseMap<T>, key: string, val: T) {
export function remove<T>(m: SparseMap<T>, key: string, val: T): void {
const v = m.get(key);
if (v === val) m.delete(key);
else if (v instanceof Set) v.delete(val);
}

export function pushMap<T>(m: SparseMap<T>, key: string, val: T) {
export function pushMap<T>(m: SparseMap<T>, key: string, val: T): void {
const v = m.get(key);
if (!v) m.set(key, val);
else {
Expand All @@ -129,16 +131,16 @@ export function pushMap<T>(m: SparseMap<T>, key: string, val: T) {
}
}

export function hyphenToCamel(str: string) {
export function hyphenToCamel(str: string): string {
return str.replace(/-([a-z])/g, g => g[1].toUpperCase());
}

export const requestIdleCallback = (f: () => void, timeout?: number) => {
export const requestIdleCallback = (f: () => void, timeout?: number): void => {
if (window.requestIdleCallback) window.requestIdleCallback(f, timeout ? { timeout } : undefined);
else requestAnimationFrame(f);
};

export const escapeHtml = (str: string) =>
export const escapeHtml = (str: string): string =>
/[&<>"']/.test(str)
? str
.replace(/&/g, '&amp;')
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface Opts<Result> {
regex?: RegExp;
}

export default function <Result>(opts: Opts<Result>) {
export default function <Result>(opts: Opts<Result>): void {
const minLength = opts.minLength || 3,
empty = opts.empty || (() => '<div class="complete-list__empty">No results.</div>'),
cache = new Map<string, Result[]>(),
Expand Down
6 changes: 3 additions & 3 deletions ui/common/src/controls.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { h, Hooks, VNode } from 'snabbdom';
import { bind } from './snabbdom';
import { toggle as baseToggle } from './common';
import { toggle as baseToggle, Toggle } from './common';
import * as xhr from './xhr';

export interface ToggleSettings {
Expand All @@ -13,7 +13,7 @@ export interface ToggleSettings {
change(v: boolean): void;
}

export function toggle(t: ToggleSettings, trans: Trans, redraw: () => void) {
export function toggle(t: ToggleSettings, trans: Trans, redraw: () => void): VNode {
const fullId = 'abset-' + t.id;
return h(
'div.setting.' + fullId + (t.cls ? '.' + t.cls : ''),
Expand Down Expand Up @@ -45,7 +45,7 @@ export function rangeConfig(read: () => number, write: (value: number) => void):
};
}

export const boolPrefXhrToggle = (prefKey: string, val: boolean, effect: () => void = site.reload) =>
export const boolPrefXhrToggle = (prefKey: string, val: boolean, effect: () => void = site.reload): Toggle =>
baseToggle(val, async v => {
await xhr.text(`/pref/${prefKey}`, { method: 'post', body: xhr.form({ [prefKey]: v ? '1' : '0' }) });
effect();
Expand Down
13 changes: 7 additions & 6 deletions ui/common/src/device.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Hooks } from 'snabbdom';
import { memoize } from './common';
import { bind } from './snabbdom';

const longPressDuration = 610;

export function bindMobileTapHold(el: HTMLElement, f: (e: Event) => unknown, redraw?: () => void) {
export function bindMobileTapHold(el: HTMLElement, f: (e: Event) => unknown, redraw?: () => void): void {
let longPressCountdown: number;

el.addEventListener('touchstart', e => {
Expand Down Expand Up @@ -36,7 +37,7 @@ export const bindMobileMousedown =
}
};

export const hookMobileMousedown = (f: (e: Event) => any) =>
export const hookMobileMousedown = (f: (e: Event) => any): Hooks =>
bind('ontouchstart' in window ? 'click' : 'mousedown', f);

export const isMobile = (): boolean => isAndroid() || isIOS();
Expand All @@ -45,7 +46,7 @@ export const isAndroid = (): boolean => /Android/.test(navigator.userAgent);

export const isSafari = (): boolean => /^((?!chrome|android).)*safari/i.test(navigator.userAgent);

export const isIOS = (constraint?: { below?: number; atLeast?: number }) => {
export const isIOS = (constraint?: { below?: number; atLeast?: number }): boolean => {
let answer = ios();
if (!constraint || !answer) return answer;
const version = parseFloat(navigator.userAgent.slice(navigator.userAgent.indexOf('Version/') + 8));
Expand All @@ -65,16 +66,16 @@ export const getFirefoxMajorVersion = (): number | undefined => {

export const isIOSChrome = (): boolean => /CriOS/.test(navigator.userAgent);

export const isTouchDevice = () => !hasMouse();
export const isTouchDevice = (): boolean => !hasMouse();

export const isIPad = (): boolean =>
navigator?.maxTouchPoints > 2 && /iPad|Macintosh/.test(navigator.userAgent);

export type Feature = 'wasm' | 'sharedMem' | 'simd';

export const hasFeature = (feat?: string) => !feat || features().includes(feat as Feature);
export const hasFeature = (feat?: string): boolean => !feat || features().includes(feat as Feature);

export const features = memoize<readonly Feature[]>(() => {
export const features: () => readonly Feature[] = memoize<readonly Feature[]>(() => {
const features: Feature[] = [];
if (
typeof WebAssembly === 'object' &&
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export type Action =
| { selector: string; event?: string | string[]; listener: ActionListener }
| { selector: string; event?: string | string[]; result: string };

export const ready = site.load.then(async () => {
export const ready: Promise<boolean> = site.load.then(async () => {
window.addEventListener('resize', onResize);
if (window.HTMLDialogElement) return true;
dialogPolyfill = (await import(site.asset.url('npm/dialog-polyfill.esm.js')).catch(() => undefined))
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/flairPicker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function flairPickerLoader(element: HTMLElement) {
export default function flairPickerLoader(element: HTMLElement): void {
const parent = $(element).parent();
const close = () => element.removeAttribute('open');
const onEmojiSelect = (i?: { id: string; src: string }) => {
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/linkPopup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { domDialog } from './dialog';

export const makeLinkPopups = (dom: HTMLElement | Cash, trans: Trans, selector = 'a[href^="http"]') => {
export const makeLinkPopups = (dom: HTMLElement | Cash, trans: Trans, selector = 'a[href^="http"]'): void => {
const $el = $(dom);
if (!$el.hasClass('link-popup-ready'))
$el.addClass('link-popup-ready').on('click', selector, function (this: HTMLLinkElement) {
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/menuHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type State = {
event?: string;
};

export default function () {
export default function (): void {
if ('ontouchstart' in window) return;

const interval = 200,
Expand Down
8 changes: 4 additions & 4 deletions ui/common/src/miniBoard.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { h } from 'snabbdom';
import { h, VNode } from 'snabbdom';
import * as domData from './data';
import { uciToMove } from 'chessground/util';

Expand All @@ -25,15 +25,15 @@ export const initWith = (node: HTMLElement, fen: string, orientation: Color, lm?
);
};

export const initAll = (parent?: HTMLElement) =>
export const initAll = (parent?: HTMLElement): void =>
Array.from((parent || document).getElementsByClassName('mini-board--init')).forEach((el: HTMLElement) => {
el.classList.remove('mini-board--init');
init(el);
});

export const fenColor = (fen: string) => (fen.includes(' w') ? 'white' : 'black');
export const fenColor = (fen: string): Color => (fen.includes(' w') ? 'white' : 'black');

export const renderClock = (color: Color, time: number) =>
export const renderClock = (color: Color, time: number): VNode =>
h(`span.mini-game__clock.mini-game__clock--${color}`, {
attrs: { 'data-time': time, 'data-managed': 1 },
});
2 changes: 1 addition & 1 deletion ui/common/src/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function notify(msg: string | (() => string)) {
listenToFocus();
}

export default function (msg: string | (() => string)) {
export default function (msg: string | (() => string)): void {
if (document.hasFocus() || !('Notification' in window)) return;
if (Notification.permission === 'granted') {
// increase chances that the first tab can put a local storage lock
Expand Down
4 changes: 2 additions & 2 deletions ui/common/src/number.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
let numberFormatter: false | Intl.NumberFormat | null = false;

export const numberFormat = (n: number) => {
export const numberFormat = (n: number): string => {
if (numberFormatter === false)
numberFormatter = window.Intl && Intl.NumberFormat ? new Intl.NumberFormat() : null;
if (numberFormatter === null) return '' + n;
Expand All @@ -17,7 +17,7 @@ export const numberSpread = (el: HTMLElement, nbSteps: number, duration: number,
}
};
let timeouts: Timeout[] = [];
return (nb: number, overrideNbSteps?: number) => {
return (nb: number, overrideNbSteps?: number): void => {
if (!el || (!nb && nb !== 0)) return;
if (overrideNbSteps) nbSteps = Math.abs(overrideNbSteps);
timeouts.forEach(clearTimeout);
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/password.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const addPasswordVisibilityToggleListener = () => {
export const addPasswordVisibilityToggleListener = (): void => {
$('.password-wrapper').each(function (this: HTMLElement) {
const $wrapper = $(this);
const $button = $wrapper.find('.password-reveal');
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/perfIcons.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as licon from './licon';

const perfIcons = {
const perfIcons: Record<Exclude<Perf, 'fromPosition'>, string> = {
ultraBullet: licon.UltraBullet,
bullet: licon.Bullet,
blitz: licon.FlameBlitz,
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/random.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const randomToken = () => {
export const randomToken = (): string => {
try {
const data = window.crypto.getRandomValues(new Uint8Array(9));
return btoa(String.fromCharCode(...data)).replace(/[/+]/g, '_');
Expand Down
2 changes: 1 addition & 1 deletion ui/common/src/resize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default function resizeHandle(
pref: Prefs.ShowResizeHandle,
ply: number,
visible?: Visible,
) {
): void {
if (pref === Prefs.ShowResizeHandle.Never) return;

const el = document.createElement('cg-resize');
Expand Down
16 changes: 8 additions & 8 deletions ui/common/src/richText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { VNode, Hooks } from 'snabbdom';
import { escapeHtml } from './common';

// from https://github.com/bryanwoods/autolink-js/blob/master/autolink.js
export const linkRegex =
export const linkRegex: RegExp =
/(^|[\s\n]|<[A-Za-z]*\/?>)((?:(?:https?|ftp):\/\/|lichess\.org)[\-A-Z0-9+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/gi;
export const newLineRegex = /\n/g;
export const userPattern = /(^|[^\w@#/])@([a-z0-9_-]{2,30})/gi;
export const newLineRegex: RegExp = /\n/g;
export const userPattern: RegExp = /(^|[^\w@#/])@([a-z0-9_-]{2,30})/gi;

// looks like it has a @mention or #gameid or a url.tld
export const isMoreThanText = (str: string) => /(\n|(@|#|\.)\w{2,}|(board|game) \d)/i.test(str);
export const isMoreThanText = (str: string): boolean => /(\n|(@|#|\.)\w{2,}|(board|game) \d)/i.test(str);

export function toLink(url: string): string {
if (!url.match(/^[A-Za-z]+:\/\//)) url = 'https://' + url;
Expand All @@ -36,17 +36,17 @@ export const innerHTML = <A>(a: A, toHtml: (a: A) => string): Hooks => ({
},
});

export function linkReplace(href: string, body?: string, cls?: string) {
export function linkReplace(href: string, body?: string, cls?: string): string {
if (href.includes('&quot;')) return href;
return `<a target="_blank" rel="noopener nofollow noreferrer" href="${
href.startsWith('/') || href.includes('://') ? href : '//' + href
}"${cls ? ` class="${cls}"` : ''}>${body ? body : href}</a>`;
}

export const userLinkReplace = (_: string, prefix: string, user: string) =>
export const userLinkReplace = (_: string, prefix: string, user: string): string =>
prefix + linkReplace('/@/' + user, '@' + user);

export const expandMentions = (html: string) => html.replace(userPattern, userLinkReplace);
export const expandMentions = (html: string): string => html.replace(userPattern, userLinkReplace);

export function enrichText(text: string, allowNewlines = true): string {
let html = autolink(escapeHtml(text), toLink);
Expand All @@ -60,7 +60,7 @@ export function richHTML(text: string, newLines = true): Hooks {

const linkPattern = /\b\b(?:https?:\/\/)?(lichess\.org\/[-–—\w+&'@#\/%?=()~|!:,.;]+[\w+&@#\/%=~|])/gi;
const pawnDropPattern = /^[a-h][2-7]$/;
export const movePattern =
export const movePattern: RegExp =
/\b(\d+)\s*(\.+)\s*(?:[o0-]+[o0]|[NBRQKP\u2654\u2655\u2656\u2657\u2658\u2659]?[a-h]?[1-8]?[x@]?[a-h][1-8](?:=[NBRQK\u2654\u2655\u2656\u2657\u2658\u2659])?)\+?#?[!\?=]{0,5}/gi;
const boardPattern = /\b(?:board|game)\s(\d{1,2})/gi;

Expand Down
10 changes: 5 additions & 5 deletions ui/common/src/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface Selectable<C = any> {
}

export class Selector<T extends Selectable, C = any> {
group = new Map<string, T>();
group: Map<string, T> = new Map<string, T>();
context?: C;
key: string | false = false;

Expand All @@ -22,7 +22,7 @@ export class Selector<T extends Selectable, C = any> {
return this.key ? this.group.get(this.key) : undefined;
}

select(key: string | false) {
select(key: string | false): void {
if (this.key) {
if (this.key === key) return;
this.selected?.deselect?.(this.context);
Expand All @@ -35,14 +35,14 @@ export class Selector<T extends Selectable, C = any> {
return this.group.get(key);
}

set(key: string, val: T) {
set(key: string, val: T): void {
const reselect = this.key === key;
this.close(key);
this.group.set(key, val);
if (reselect) this.select(key);
}

close(key?: string) {
close(key?: string): void {
if (key === undefined) {
for (const k of this.group.keys()) this.close(k);
return;
Expand All @@ -54,7 +54,7 @@ export class Selector<T extends Selectable, C = any> {
this.group.get(key)?.close?.(this.context);
}

delete(key?: string) {
delete(key?: string): void {
this.close(key);
key ? this.group.delete(key) : this.group.clear();
}
Expand Down
Loading
Loading