diff --git a/.prettierignore b/.prettierignore index dd2c75766784a..301e0fd52e650 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,5 +10,5 @@ !/ui/** dist/ readme -/ui/.build/pnpm-lock.yaml +pnpm-lock.yaml /ui/voice/@build/crowdv/*.json diff --git a/package.json b/package.json index 3c2f496471db8..20f4bbc9a8e2e 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@typescript-eslint/parser": "^8.13.0", "ab": "github:lichess-org/ab-stub", "chessground": "^9.1.1", + "chessops": "^0.14.2", "eslint": "^9.14.0", "lint-staged": "^15.2.10", "onchange": "^7.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb4c8417adfbf..bae786ba60880 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: chessground: specifier: ^9.1.1 version: 9.1.1 + chessops: + specifier: ^0.14.2 + version: 0.14.2 eslint: specifier: ^9.14.0 version: 9.14.0 @@ -97,9 +100,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -178,9 +178,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -226,9 +223,6 @@ importers: '@badrap/result': specifier: ^0.2.13 version: 0.2.13 - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -298,9 +292,6 @@ importers: ui/chess: dependencies: - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -350,17 +341,10 @@ importers: specifier: workspace:* version: link:../common - ui/dgt: - dependencies: - chessops: - specifier: ^0.14.2 - version: 0.14.2 + ui/dgt: {} ui/editor: dependencies: - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -400,9 +384,6 @@ importers: ui/learn: dependencies: - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -469,9 +450,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -514,9 +492,6 @@ importers: ui/puz: dependencies: - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -535,9 +510,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -559,9 +531,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common @@ -646,9 +615,6 @@ importers: chess: specifier: workspace:* version: link:../chess - chessops: - specifier: ^0.14.2 - version: 0.14.2 common: specifier: workspace:* version: link:../common diff --git a/ui/.build/src/build.ts b/ui/.build/src/build.ts index e2df6e3c0a751..13c066acb997f 100644 --- a/ui/.build/src/build.ts +++ b/ui/.build/src/build.ts @@ -12,7 +12,8 @@ import { type Package, env, errorMark, colors as c } from './main.ts'; import { i18n, stopI18n } from './i18n.ts'; export async function build(pkgs: string[]): Promise { - if (env.install) cps.execSync('pnpm install', { cwd: env.rootDir, stdio: 'inherit' }); + if (env.install) + cps.execSync('pnpm install --prefer-frozen-lockfile', { cwd: env.rootDir, stdio: 'inherit' }); if (!pkgs.length) env.log(`Parsing packages in '${c.cyan(env.uiDir)}'`); ps.chdir(env.uiDir); diff --git a/ui/@types/lichess/chessground.d.ts b/ui/@types/lichess/chessground.d.ts index fb722d3bdd4bd..b7ec4ae4e72f4 100644 --- a/ui/@types/lichess/chessground.d.ts +++ b/ui/@types/lichess/chessground.d.ts @@ -5,9 +5,12 @@ import * as cg from '../../../node_modules/chessground/dist/types'; declare global { type CgApi = Api; type CgConfig = Config; - namespace Cg { - type Role = cg.Role; - type Key = cg.Key; - type FEN = cg.FEN; - } + type Color = cg.Color; + type Role = cg.Role; + type Key = cg.Key; + type FEN = cg.FEN; + type Files = cg.File; + type Ranks = cg.Rank; + type Dests = cg.Dests; + type Piece = cg.Piece; } diff --git a/ui/@types/lichess/index.d.ts b/ui/@types/lichess/index.d.ts index 7df9bca97655c..b46e01beb3ef1 100644 --- a/ui/@types/lichess/index.d.ts +++ b/ui/@types/lichess/index.d.ts @@ -52,7 +52,7 @@ interface EsmModuleOpts extends AssetUrlOpts { type PairOf = [T, T]; type Flair = string; - +type Redraw = () => void; type RedirectTo = string | { url: string; cookie: Cookie }; interface LichessMousetrap { @@ -95,7 +95,6 @@ type SoundMoveOpts = { }; type SoundMove = (opts?: SoundMoveOpts) => void; - type SoundListener = (event: 'start' | 'stop', text?: string) => void; interface SoundI { @@ -113,7 +112,7 @@ interface SoundI { speech(v?: boolean): boolean; changeSet(s: string): void; say(text: string, cut?: boolean, force?: boolean, translated?: boolean): boolean; - saySan(san?: San, cut?: boolean): void; + saySan(san?: San, cut?: boolean, force?: boolean): void; sayOrPlay(name: string, text: string): void; preloadBoardSounds(): void; url(name: string): string; @@ -146,7 +145,7 @@ interface AssetUrlOpts { type Timeout = ReturnType; -declare type SocketSend = (type: string, data?: any, opts?: any, noRetry?: boolean) => void; +type SocketSend = (type: string, data?: any, opts?: any, noRetry?: boolean) => void; interface LichessAnnouncement { msg?: string; @@ -231,7 +230,7 @@ interface Navigator { deviceMemory?: number; // https://developer.mozilla.org/en-US/docs/Web/API/Navigator/deviceMemory } -declare type VariantKey = +type VariantKey = | 'standard' | 'chess960' | 'antichess' @@ -243,21 +242,16 @@ declare type VariantKey = | 'racingKings' | 'crazyhouse'; -declare type Speed = 'ultraBullet' | 'bullet' | 'blitz' | 'rapid' | 'classical' | 'correspondence'; - -declare type Perf = Exclude | Speed; +type Speed = 'ultraBullet' | 'bullet' | 'blitz' | 'rapid' | 'classical' | 'correspondence'; -declare type Color = 'white' | 'black'; +type Perf = Exclude | Speed; -declare type Files = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h'; -declare type Ranks = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'; -declare type Key = 'a0' | `${Files}${Ranks}`; -declare type Uci = string; -declare type San = string; -declare type Ply = number; -declare type Seconds = number; -declare type Centis = number; -declare type Millis = number; +type Uci = string; +type San = string; +type Ply = number; +type Seconds = number; +type Centis = number; +type Millis = number; interface Variant { key: VariantKey; diff --git a/ui/@types/lichess/tree.d.ts b/ui/@types/lichess/tree.d.ts index fe653d2733e49..a53855ae3a36b 100644 --- a/ui/@types/lichess/tree.d.ts +++ b/ui/@types/lichess/tree.d.ts @@ -4,7 +4,7 @@ declare namespace Tree { export type Path = string; interface ClientEvalBase extends EvalScore { - fen: Cg.FEN; + fen: FEN; depth: number; nodes: number; pvs: PvData[]; @@ -21,7 +21,7 @@ declare namespace Tree { export interface ServerEval extends EvalScore { best?: Uci; - fen: Cg.FEN; + fen: FEN; knodes: number; depth: number; pvs: PvDataServer[]; @@ -45,7 +45,7 @@ declare namespace Tree { id: string; ply: Ply; uci?: Uci; - fen: Cg.FEN; + fen: FEN; comments?: Comment[]; gamebook?: Gamebook; dests?: string; diff --git a/ui/analyse/package.json b/ui/analyse/package.json index 761ef84ed4235..fc28e1e911ef1 100644 --- a/ui/analyse/package.json +++ b/ui/analyse/package.json @@ -24,7 +24,6 @@ "chart": "workspace:*", "chat": "workspace:*", "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*", "debounce-promise": "^3.1.2", "editor": "workspace:*", diff --git a/ui/analyse/src/autoShape.ts b/ui/analyse/src/autoShape.ts index d6da56e9e0dc4..e7835f5ea860b 100644 --- a/ui/analyse/src/autoShape.ts +++ b/ui/analyse/src/autoShape.ts @@ -1,13 +1,12 @@ import { parseUci, makeSquare } from 'chessops/util'; import { isDrop } from 'chessops/types'; import { winningChances } from 'ceval'; -import * as cg from 'chessground/types'; import { opposite } from 'chessground/util'; -import { DrawModifiers, DrawShape } from 'chessground/draw'; +import type { DrawModifiers, DrawShape } from 'chessground/draw'; import { annotationShapes } from 'chess/glyphs'; -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; -const pieceDrop = (key: cg.Key, role: cg.Role, color: Color): DrawShape => ({ +const pieceDrop = (key: Key, role: Role, color: Color): DrawShape => ({ orig: key, piece: { color, diff --git a/ui/analyse/src/autoplay.ts b/ui/analyse/src/autoplay.ts index 7fae7202dd635..118fd8e091da3 100644 --- a/ui/analyse/src/autoplay.ts +++ b/ui/analyse/src/autoplay.ts @@ -1,4 +1,4 @@ -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; export type AutoplayDelay = number | 'realtime' | 'cpl'; diff --git a/ui/analyse/src/boot.ts b/ui/analyse/src/boot.ts index 1d1fd4d498408..dbf7c21905979 100644 --- a/ui/analyse/src/boot.ts +++ b/ui/analyse/src/boot.ts @@ -1,4 +1,4 @@ -import { AnalyseApi, AnalyseOpts } from './interfaces'; +import type { AnalyseApi, AnalyseOpts } from './interfaces'; import StrongSocket from 'common/socket'; export default function (start: (opts: AnalyseOpts) => AnalyseApi) { diff --git a/ui/analyse/src/control.ts b/ui/analyse/src/control.ts index 7a3958a20b50e..a4b0da173324e 100644 --- a/ui/analyse/src/control.ts +++ b/ui/analyse/src/control.ts @@ -1,4 +1,4 @@ -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; import { path as treePath } from 'tree'; diff --git a/ui/analyse/src/crazy/crazyCtrl.ts b/ui/analyse/src/crazy/crazyCtrl.ts index 2fa84f82e58de..750b26c083fc0 100644 --- a/ui/analyse/src/crazy/crazyCtrl.ts +++ b/ui/analyse/src/crazy/crazyCtrl.ts @@ -1,14 +1,13 @@ import { dragNewPiece } from 'chessground/drag'; import { readDrops } from 'chess'; -import AnalyseCtrl from '../ctrl'; -import * as cg from 'chessground/types'; -import { Api as ChessgroundApi } from 'chessground/api'; +import type AnalyseCtrl from '../ctrl'; +import type { MouchEvent } from 'chessground/types'; -export function drag(ctrl: AnalyseCtrl, color: Color, e: cg.MouchEvent): void { +export function drag(ctrl: AnalyseCtrl, color: Color, e: MouchEvent): void { if (e.button !== undefined && e.button !== 0) return; // only touch or left click if (ctrl.chessground.state.movable.color !== color) return; const el = e.target as HTMLElement; - const role = el.getAttribute('data-role') as cg.Role, + const role = el.getAttribute('data-role') as Role, number = el.getAttribute('data-nb'); if (!role || !color || number === '0') return; e.stopPropagation(); @@ -17,9 +16,9 @@ export function drag(ctrl: AnalyseCtrl, color: Color, e: cg.MouchEvent): void { } export function valid( - chessground: ChessgroundApi, + chessground: CgApi, possibleDrops: string | undefined | null, - piece: cg.Piece, + piece: Piece, pos: Key, ): boolean { if (piece.color !== chessground.state.movable.color) return false; diff --git a/ui/analyse/src/crazy/crazyView.ts b/ui/analyse/src/crazy/crazyView.ts index b407a552014e5..fd783e0b3cba8 100644 --- a/ui/analyse/src/crazy/crazyView.ts +++ b/ui/analyse/src/crazy/crazyView.ts @@ -1,8 +1,8 @@ import { drag } from './crazyCtrl'; import { h } from 'snabbdom'; -import { MouchEvent } from 'chessground/types'; +import type { MouchEvent } from 'chessground/types'; import { onInsert } from 'common/snabbdom'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; const eventNames = ['mousedown', 'touchstart']; const oKeys = ['pawn', 'knight', 'bishop', 'rook', 'queen']; diff --git a/ui/analyse/src/ctrl.ts b/ui/analyse/src/ctrl.ts index 8e348b2e3a478..60db5e2af416d 100644 --- a/ui/analyse/src/ctrl.ts +++ b/ui/analyse/src/ctrl.ts @@ -1,59 +1,50 @@ -import * as cg from 'chessground/types'; -import * as chessUtil from 'chess'; -import * as game from 'game'; +import { readDests, readDrops } from 'chess'; +import { playable, playedTurns } from 'game'; import * as keyboard from './keyboard'; -import * as util from './util'; +import { treeReconstruct, plyColor } from './util'; import { plural } from './view/util'; import { debounce, throttle } from 'common/timing'; -import GamebookPlayCtrl from './study/gamebook/gamebookPlayCtrl'; -import StudyCtrl from './study/studyCtrl'; +import type GamebookPlayCtrl from './study/gamebook/gamebookPlayCtrl'; +import type StudyCtrl from './study/studyCtrl'; import { isTouchDevice } from 'common/device'; -import { - AnalyseOpts, - AnalyseData, - ServerEvalData, - Key, - JustCaptured, - NvuiPlugin, - Redraw, -} from './interfaces'; -import { Api as ChessgroundApi } from 'chessground/api'; +import type { AnalyseOpts, AnalyseData, ServerEvalData, JustCaptured, NvuiPlugin } from './interfaces'; +import type { Api as ChessgroundApi } from 'chessground/api'; import { Autoplay, AutoplayDelay } from './autoplay'; -import { build as makeTree, path as treePath, ops as treeOps, TreeWrapper } from 'tree'; +import { build as makeTree, path as treePath, ops as treeOps, type TreeWrapper } from 'tree'; import { compute as computeAutoShapes } from './autoShape'; -import { Config as ChessgroundConfig } from 'chessground/config'; -import { CevalCtrl, isEvalBetter, sanIrreversible, EvalMeta } from 'ceval'; +import type { Config as ChessgroundConfig } from 'chessground/config'; +import { CevalCtrl, isEvalBetter, sanIrreversible, type EvalMeta } from 'ceval'; import { TreeView } from './treeView/treeView'; -import { defined, prop, Prop, toggle, Toggle, requestIdleCallback } from 'common'; +import { defined, prop, type Prop, toggle, type Toggle, requestIdleCallback } from 'common'; import { pubsub } from 'common/pubsub'; -import { DrawShape } from 'chessground/draw'; +import type { DrawShape } from 'chessground/draw'; import { lichessRules } from 'chessops/compat'; import EvalCache from './evalCache'; -import { make as makeFork, ForkCtrl } from './fork'; -import { make as makePractice, PracticeCtrl } from './practice/practiceCtrl'; -import { make as makeRetro, RetroCtrl } from './retrospect/retroCtrl'; -import { make as makeSocket, Socket } from './socket'; +import { make as makeFork, type ForkCtrl } from './fork'; +import { make as makePractice, type PracticeCtrl } from './practice/practiceCtrl'; +import { make as makeRetro, type RetroCtrl } from './retrospect/retroCtrl'; +import { make as makeSocket, type Socket } from './socket'; import { nextGlyphSymbol, add3or5FoldGlyphs } from './nodeFinder'; import { opposite, parseUci, makeSquare, roleToChar } from 'chessops/util'; -import { Outcome, isNormal } from 'chessops/types'; +import { type Outcome, isNormal } from 'chessops/types'; import { parseFen } from 'chessops/fen'; -import { Position, PositionError } from 'chessops/chess'; -import { Result } from '@badrap/result'; +import type { Position, PositionError } from 'chessops/chess'; +import type { Result } from '@badrap/result'; import { setupPosition } from 'chessops/variant'; import { storedBooleanProp } from 'common/storage'; -import { AnaMove } from './study/interfaces'; -import StudyPracticeCtrl from './study/practice/studyPracticeCtrl'; +import type { AnaMove } from './study/interfaces'; +import type StudyPracticeCtrl from './study/practice/studyPracticeCtrl'; import { valid as crazyValid } from './crazy/crazyCtrl'; import { PromotionCtrl } from 'chess/promotion'; -import wikiTheory, { wikiClear, WikiTheory } from './wiki'; +import wikiTheory, { wikiClear, type WikiTheory } from './wiki'; import ExplorerCtrl from './explorer/explorerCtrl'; import { uciToMove } from 'chessground/util'; import Persistence from './persistence'; import pgnImport from './pgnImport'; import ForecastCtrl from './forecast/forecastCtrl'; -import { ArrowKey, KeyboardMove, ctrl as makeKeyboardMove } from 'keyboardMove'; +import { type ArrowKey, type KeyboardMove, ctrl as makeKeyboardMove } from 'keyboardMove'; import * as control from './control'; -import { PgnError } from 'chessops/pgn'; +import type { PgnError } from 'chessops/pgn'; import { confirm } from 'common/dialog'; export default class AnalyseCtrl { @@ -208,10 +199,10 @@ export default class AnalyseCtrl { initialize(data: AnalyseData, merge: boolean): void { this.data = data; this.synthetic = data.game.id === 'synthetic'; - this.ongoing = !this.synthetic && game.playable(data); + this.ongoing = !this.synthetic && playable(data); const prevTree = merge && this.tree.root; - this.tree = makeTree(util.treeReconstruct(this.data.treeParts, this.data.sidelines)); + this.tree = makeTree(treeReconstruct(this.data.treeParts, this.data.sidelines)); if (prevTree) this.tree.merge(prevTree); const mainline = treeOps.mainlineNodeList(this.tree.root); if (this.data.game.status.name == 'draw') add3or5FoldGlyphs(mainline); @@ -301,7 +292,7 @@ export default class AnalyseCtrl { } turnColor(): Color { - return util.plyColor(this.node.ply); + return plyColor(this.node.ply); } togglePlay(delay: AutoplayDelay): void { @@ -328,13 +319,13 @@ export default class AnalyseCtrl { }); }); - serverMainline = () => this.mainline.slice(0, game.playedTurns(this.data) + 1); + serverMainline = () => this.mainline.slice(0, playedTurns(this.data) + 1); makeCgOpts(): ChessgroundConfig { const node = this.node, color = this.turnColor(), - dests = chessUtil.readDests(this.node.dests), - drops = chessUtil.readDrops(this.node.drops), + dests = readDests(this.node.dests), + drops = readDrops(this.node.drops), gamebookPlay = this.gamebookPlay(), movableColor = gamebookPlay ? gamebookPlay.movableColor() @@ -497,7 +488,7 @@ export default class AnalyseCtrl { return undefined; } - changeFen(fen: cg.FEN): void { + changeFen(fen: FEN): void { this.redirecting = true; window.location.href = '/analysis/' + @@ -506,7 +497,7 @@ export default class AnalyseCtrl { encodeURIComponent(fen).replace(/%20/g, '_').replace(/%2F/g, '/'); } - crazyValid = (role: cg.Role, key: cg.Key): boolean => { + crazyValid = (role: Role, key: Key): boolean => { const color = this.chessground.state.movable.color; return ( (color === 'white' || color === 'black') && @@ -516,12 +507,12 @@ export default class AnalyseCtrl { getCrazyhousePockets = () => this.node.crazy?.pockets; - sendNewPiece = (role: cg.Role, key: cg.Key): void => { + sendNewPiece = (role: Role, key: Key): void => { const color = this.chessground.state.movable.color; if (color === 'white' || color === 'black') this.userNewPiece({ color, role }, key); }; - userNewPiece = (piece: cg.Piece, pos: Key): void => { + userNewPiece = (piece: Piece, pos: Key): void => { if (crazyValid(this.chessground, this.node.drops, piece, pos)) { this.justPlayed = roleToChar(piece.role).toUpperCase() + '@' + pos; this.justDropped = piece.role; @@ -552,7 +543,7 @@ export default class AnalyseCtrl { } }; - sendMove = (orig: Key, dest: Key, capture?: JustCaptured, prom?: cg.Role): void => { + sendMove = (orig: Key, dest: Key, capture?: JustCaptured, prom?: Role): void => { const move: AnaMove = { orig, dest, @@ -570,9 +561,9 @@ export default class AnalyseCtrl { private preparePremoving(): void { this.chessground.set({ - turnColor: this.chessground.state.movable.color as cg.Color, + turnColor: this.chessground.state.movable.color as Color, movable: { - color: opposite(this.chessground.state.movable.color as cg.Color), + color: opposite(this.chessground.state.movable.color as Color), }, premovable: { enabled: true, @@ -664,7 +655,7 @@ export default class AnalyseCtrl { this.redraw(); } - encodeNodeFen(): cg.FEN { + encodeNodeFen(): FEN { return this.node.fen.replace(/\s/g, '_'); } @@ -712,7 +703,7 @@ export default class AnalyseCtrl { const opts = { variant: this.data.game.variant, initialFen: this.data.game.initialFen, - possible: (this.synthetic || !game.playable(this.data)) && !location.search.includes('evals=0'), + possible: (this.synthetic || !playable(this.data)) && !location.search.includes('evals=0'), emit: (ev: Tree.ClientEval, work: EvalMeta) => { this.onNewCeval(ev, work.path, work.threatMode); }, @@ -1025,7 +1016,7 @@ export default class AnalyseCtrl { this.redraw(); }; - pluginMove = (orig: cg.Key, dest: cg.Key, prom: cg.Role | undefined) => { + pluginMove = (orig: Key, dest: Key, prom: Role | undefined) => { const capture = this.chessground.state.pieces.get(dest); this.sendMove(orig, dest, capture, prom); }; diff --git a/ui/analyse/src/evalCache.ts b/ui/analyse/src/evalCache.ts index 22e4560835dc8..f86a0efa0ef2d 100644 --- a/ui/analyse/src/evalCache.ts +++ b/ui/analyse/src/evalCache.ts @@ -1,8 +1,7 @@ import { defined, prop } from 'common'; import { throttle } from 'common/timing'; -import { EvalHit, EvalGetData, EvalPutData } from './interfaces'; -import { AnalyseSocketSend } from './socket'; -import { FEN } from 'chessground/types'; +import type { EvalHit, EvalGetData, EvalPutData } from './interfaces'; +import type { AnalyseSocketSend } from './socket'; import { pubsub } from 'common/pubsub'; export interface EvalCacheOpts { diff --git a/ui/analyse/src/explorer/explorerConfig.ts b/ui/analyse/src/explorer/explorerConfig.ts index b651ca8d15b5b..76fee98055f75 100644 --- a/ui/analyse/src/explorer/explorerConfig.ts +++ b/ui/analyse/src/explorer/explorerConfig.ts @@ -1,16 +1,14 @@ import { h, VNode } from 'snabbdom'; -import { myUserId, Prop, prop } from 'common'; +import { myUserId, type Prop, prop } from 'common'; import * as licon from 'common/licon'; import { snabDialog } from 'common/dialog'; import { bind, dataIcon, iconTag, onInsert } from 'common/snabbdom'; -import { storedProp, storedJsonProp, StoredJsonProp, StoredProp, storedStringProp } from 'common/storage'; +import { storedProp, storedJsonProp, type StoredProp, storedStringProp } from 'common/storage'; import { ExplorerDb, ExplorerSpeed, ExplorerMode } from './interfaces'; import AnalyseCtrl from '../ctrl'; import perfIcons from 'common/perfIcons'; import { ucfirst } from './explorerUtil'; -import { Color } from 'chessground/types'; import { opposite } from 'chessground/util'; -import { Redraw } from '../interfaces'; import { userComplete } from 'common/userComplete'; const allSpeeds: ExplorerSpeed[] = ['ultraBullet', 'bullet', 'blitz', 'rapid', 'classical', 'correspondence']; @@ -30,14 +28,14 @@ type ByDbSettings = { export interface ExplorerConfigData { open: Prop; db: StoredProp; - rating: StoredJsonProp; - speed: StoredJsonProp; - mode: StoredJsonProp; + rating: Prop; + speed: Prop; + mode: Prop; byDbData: ByDbSettings; playerName: { open: Prop; value: StoredProp; - previous: StoredJsonProp; + previous: Prop; }; color: Prop; byDb(): ByDbSetting; @@ -116,7 +114,7 @@ export class ExplorerConfigCtrl { }; toggleMany = - (c: StoredJsonProp) => + (c: Prop) => (value: T) => { if (!c().includes(value)) c(c().concat([value])); else if (c().length > 1) c(c().filter(v => v !== value)); @@ -206,7 +204,7 @@ const masterDb = (ctrl: ExplorerConfigCtrl) => ]); const radioButton = - (ctrl: ExplorerConfigCtrl, storage: StoredJsonProp, render?: (t: T) => VNode) => + (ctrl: ExplorerConfigCtrl, storage: Prop, render?: (t: T) => VNode) => (v: T) => h( 'button', diff --git a/ui/analyse/src/explorer/explorerCtrl.ts b/ui/analyse/src/explorer/explorerCtrl.ts index 5febac546eead..ff4bbfc29d19f 100644 --- a/ui/analyse/src/explorer/explorerCtrl.ts +++ b/ui/analyse/src/explorer/explorerCtrl.ts @@ -1,18 +1,17 @@ -import { Prop, prop, defined } from 'common'; +import { type Prop, prop, defined } from 'common'; import { storedBooleanProp } from 'common/storage'; import { defer } from 'common/defer'; import { fenColor } from 'common/miniBoard'; import { debounce } from 'common/timing'; -import { sync, Sync } from 'common/promise'; +import { sync, type Sync } from 'common/promise'; import { opposite } from 'chessground/util'; import * as xhr from './explorerXhr'; import { winnerOf } from './explorerUtil'; -import * as gameUtil from 'game'; -import AnalyseCtrl from '../ctrl'; -import { Hovering, ExplorerData, OpeningData, SimpleTablebaseHit, ExplorerOpts } from './interfaces'; +import { replayable } from 'game'; +import type AnalyseCtrl from '../ctrl'; +import type { Hovering, ExplorerData, OpeningData, SimpleTablebaseHit, ExplorerOpts } from './interfaces'; import { ExplorerConfigCtrl } from './explorerConfig'; import { clearLastShow } from './explorerView'; -import { FEN } from 'chessground/types'; export const MAX_DEPTH = 50; @@ -61,7 +60,7 @@ export default class ExplorerCtrl { ) { this.allowed = prop(previous ? previous.allowed() : true); this.enabled = storedBooleanProp('analyse.explorer.enabled', false); - this.withGames = root.synthetic || gameUtil.replayable(root.data) || !!root.data.opponent.ai; + this.withGames = root.synthetic || replayable(root.data) || !!root.data.opponent.ai; this.effectiveVariant = root.data.game.variant.key === 'fromPosition' ? 'standard' : root.data.game.variant.key; this.config = new ExplorerConfigCtrl(root, this.effectiveVariant, this.reload, previous?.config); diff --git a/ui/analyse/src/explorer/explorerUtil.ts b/ui/analyse/src/explorer/explorerUtil.ts index 880dbf44d5d38..79a517150fdbe 100644 --- a/ui/analyse/src/explorer/explorerUtil.ts +++ b/ui/analyse/src/explorer/explorerUtil.ts @@ -1,9 +1,8 @@ -import { TablebaseMoveStats } from './interfaces'; +import type { TablebaseMoveStats } from './interfaces'; import { opposite } from 'chessops/util'; import { fenColor } from 'common/miniBoard'; -import { VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; -import { FEN } from 'chessground/types'; +import type { VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; export function winnerOf(fen: FEN, move: TablebaseMoveStats): Color | undefined { const stm = fenColor(fen); diff --git a/ui/analyse/src/explorer/explorerView.ts b/ui/analyse/src/explorer/explorerView.ts index f6f4dd5bbba2f..86b7727dc545f 100644 --- a/ui/analyse/src/explorer/explorerView.ts +++ b/ui/analyse/src/explorer/explorerView.ts @@ -1,23 +1,22 @@ -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { numberFormat } from 'common/number'; import perfIcons from 'common/perfIcons'; -import { bind, dataIcon, MaybeVNode, LooseVNodes, looseH as h } from 'common/snabbdom'; +import { bind, dataIcon, type MaybeVNode, type LooseVNodes, looseH as h } from 'common/snabbdom'; import { view as renderConfig } from './explorerConfig'; import { moveArrowAttributes, ucfirst } from './explorerUtil'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import { isOpening, isTablebase, - TablebaseCategory, - OpeningData, - OpeningMoveStats, - OpeningGame, - ExplorerDb, + type TablebaseCategory, + type OpeningData, + type OpeningMoveStats, + type OpeningGame, + type ExplorerDb, } from './interfaces'; import ExplorerCtrl, { MAX_DEPTH } from './explorerCtrl'; import { showTablebase } from './tablebaseView'; -import { FEN } from 'chessground/types'; function resultBar(move: OpeningMoveStats): VNode { const sum = move.white + move.draws + move.black; diff --git a/ui/analyse/src/explorer/explorerXhr.ts b/ui/analyse/src/explorer/explorerXhr.ts index 746a271a3818a..31c70f5a929fe 100644 --- a/ui/analyse/src/explorer/explorerXhr.ts +++ b/ui/analyse/src/explorer/explorerXhr.ts @@ -1,8 +1,7 @@ -import { ExplorerDb, OpeningData, TablebaseData } from './interfaces'; +import type { ExplorerDb, OpeningData, TablebaseData } from './interfaces'; import * as xhr from 'common/xhr'; import { readNdJson } from 'common/xhr'; -import { ExplorerConfigData } from './explorerConfig'; -import { FEN } from 'chessground/types'; +import type { ExplorerConfigData } from './explorerConfig'; interface OpeningXhrOpts { endpoint: string; diff --git a/ui/analyse/src/explorer/interfaces.ts b/ui/analyse/src/explorer/interfaces.ts index ed61aa35f9c9e..85010ebd5c938 100644 --- a/ui/analyse/src/explorer/interfaces.ts +++ b/ui/analyse/src/explorer/interfaces.ts @@ -1,5 +1,3 @@ -import { FEN } from 'chessground/types'; - export interface Hovering { fen: FEN; uci: Uci; diff --git a/ui/analyse/src/explorer/tablebaseView.ts b/ui/analyse/src/explorer/tablebaseView.ts index 5c33a9b1ea882..4ef3e43f64343 100644 --- a/ui/analyse/src/explorer/tablebaseView.ts +++ b/ui/analyse/src/explorer/tablebaseView.ts @@ -1,8 +1,7 @@ -import { h, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; import { moveArrowAttributes, winnerOf } from './explorerUtil'; -import { TablebaseMoveStats } from './interfaces'; -import { FEN } from 'chessground/types'; +import type { TablebaseMoveStats } from './interfaces'; export function showTablebase( ctrl: AnalyseCtrl, diff --git a/ui/analyse/src/forecast/forecastCtrl.ts b/ui/analyse/src/forecast/forecastCtrl.ts index 3865f0a3b65de..39335fc75cc19 100644 --- a/ui/analyse/src/forecast/forecastCtrl.ts +++ b/ui/analyse/src/forecast/forecastCtrl.ts @@ -1,10 +1,10 @@ import { prop, notEmpty, Prop } from 'common'; -import * as xhr from 'common/xhr'; -import { ForecastData, ForecastList, ForecastStep } from './interfaces'; -import { AnalyseData } from '../interfaces'; +import { json as xhrJson } from 'common/xhr'; +import type { ForecastData, ForecastList, ForecastStep } from './interfaces'; +import type { AnalyseData } from '../interfaces'; import { scalachessCharPair } from 'chessops/compat'; import { parseUci } from 'chessops'; -import { TreeWrapper } from 'tree'; +import type { TreeWrapper } from 'tree'; export default class ForecastCtrl { forecasts: Prop = prop([]); @@ -76,44 +76,40 @@ export default class ForecastCtrl { if (this.cfg.onMyTurn) return; this.loading(true); this.redraw(); - xhr - .json(this.saveUrl(), { - method: 'POST', - body: JSON.stringify(this.forecasts()), - headers: { 'Content-Type': 'application/json' }, - }) - .then(data => { - if (data.reload) this.reloadToLastPly(); - else { - this.loading(false); - this.forecasts(data.steps || []); - } - this.redraw(); - }); + xhrJson(this.saveUrl(), { + method: 'POST', + body: JSON.stringify(this.forecasts()), + headers: { 'Content-Type': 'application/json' }, + }).then(data => { + if (data.reload) this.reloadToLastPly(); + else { + this.loading(false); + this.forecasts(data.steps || []); + } + this.redraw(); + }); }; playAndSave = (node: ForecastStep) => { if (!this.cfg.onMyTurn) return; this.loading(true); this.redraw(); - xhr - .json(`${this.saveUrl()}/${node.uci}`, { - method: 'POST', - body: JSON.stringify( - this.findStartingWithNode(node) - .filter(notEmpty) - .map(fc => fc.slice(1)), - ), - headers: { 'Content-Type': 'application/json' }, - }) - .then(data => { - if (data.reload) this.reloadToLastPly(); - else { - this.loading(false); - this.forecasts(data.steps || []); - } - this.redraw(); - }); + xhrJson(`${this.saveUrl()}/${node.uci}`, { + method: 'POST', + body: JSON.stringify( + this.findStartingWithNode(node) + .filter(notEmpty) + .map(fc => fc.slice(1)), + ), + headers: { 'Content-Type': 'application/json' }, + }).then(data => { + if (data.reload) this.reloadToLastPly(); + else { + this.loading(false); + this.forecasts(data.steps || []); + } + this.redraw(); + }); }; showForecast = (path: string, tree: TreeWrapper, nodes: ForecastStep[]) => { diff --git a/ui/analyse/src/forecast/forecastView.ts b/ui/analyse/src/forecast/forecastView.ts index 3b63d6aea955d..597b5f36b6703 100644 --- a/ui/analyse/src/forecast/forecastView.ts +++ b/ui/analyse/src/forecast/forecastView.ts @@ -1,13 +1,13 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind, dataIcon } from 'common/snabbdom'; -import { ForecastStep } from './interfaces'; -import AnalyseCtrl from '../ctrl'; +import type { ForecastStep } from './interfaces'; +import type AnalyseCtrl from '../ctrl'; import { renderNodesHtml } from '../pgnExport'; import { spinnerVdom as spinner } from 'common/spinner'; import { fixCrazySan } from 'chess'; import { findCurrentPath } from '../treeView/common'; -import ForecastCtrl from './forecastCtrl'; +import type ForecastCtrl from './forecastCtrl'; function onMyTurn(fctrl: ForecastCtrl, cNodes: ForecastStep[]): VNode | undefined { const firstNode = cNodes[0]; diff --git a/ui/analyse/src/forecast/interfaces.ts b/ui/analyse/src/forecast/interfaces.ts index 2ad02252a0658..aa2bacfaa80f7 100644 --- a/ui/analyse/src/forecast/interfaces.ts +++ b/ui/analyse/src/forecast/interfaces.ts @@ -1,5 +1,3 @@ -import { FEN } from 'chessground/types'; - export interface ForecastData { onMyTurn?: boolean; steps?: ForecastStep[][]; diff --git a/ui/analyse/src/fork.ts b/ui/analyse/src/fork.ts index 586a04f96f54f..af828d3ec879b 100644 --- a/ui/analyse/src/fork.ts +++ b/ui/analyse/src/fork.ts @@ -1,8 +1,8 @@ import { defined } from 'common'; import { onInsert } from 'common/snabbdom'; import { h } from 'snabbdom'; -import AnalyseCtrl from './ctrl'; -import { ConcealOf } from './interfaces'; +import type AnalyseCtrl from './ctrl'; +import type { ConcealOf } from './interfaces'; import { renderIndexAndMove } from './view/moveView'; export interface ForkCtrl { diff --git a/ui/analyse/src/ground.ts b/ui/analyse/src/ground.ts index 6831ef9405810..cea2d37e544ab 100644 --- a/ui/analyse/src/ground.ts +++ b/ui/analyse/src/ground.ts @@ -1,10 +1,8 @@ -import { h, VNode } from 'snabbdom'; -import { Api as CgApi } from 'chessground/api'; -import { Config as CgConfig } from 'chessground/config'; -import * as cg from 'chessground/types'; +import { h, type VNode } from 'snabbdom'; +import type { Elements } from 'chessground/types'; import resizeHandle from 'common/resize'; import { storage } from 'common/storage'; -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; import * as Prefs from 'common/prefs'; import { Chessground as makeChessground } from 'chessground'; @@ -16,7 +14,7 @@ export const render = (ctrl: AnalyseCtrl): VNode => }, }); -export function promote(ground: CgApi, key: Key, role: cg.Role) { +export function promote(ground: CgApi, key: Key, role: Role) { const piece = ground.state.pieces.get(key); if (piece && piece.role == 'pawn') { ground.setPieces(new Map([[key, { color: piece.color, role, promoted: true }]])); @@ -48,7 +46,7 @@ export function makeConfig(ctrl: AnalyseCtrl): CgConfig { events: { move: ctrl.userMove, dropNewPiece: ctrl.userNewPiece, - insert(elements: cg.Elements) { + insert(elements: Elements) { resizeHandle(elements, Prefs.ShowResizeHandle.Always, ctrl.node.ply); }, }, diff --git a/ui/analyse/src/interfaces.ts b/ui/analyse/src/interfaces.ts index 2102bf461c096..94eb304a0abc6 100644 --- a/ui/analyse/src/interfaces.ts +++ b/ui/analyse/src/interfaces.ts @@ -1,20 +1,15 @@ -import { VNode } from 'snabbdom'; -import { Player, Status, Source, Clock } from 'game'; -import * as cg from 'chessground/types'; -import { ForecastData } from './forecast/interfaces'; -import { StudyPracticeData, Goal as PracticeGoal } from './study/practice/interfaces'; -import { RelayData } from './study/relay/interfaces'; -import { ChatCtrl } from 'chat'; -import { ExplorerOpts } from './explorer/interfaces'; -import { StudyDataFromServer } from './study/interfaces'; -import { AnalyseSocketSend } from './socket'; -import { ExternalEngineInfo } from 'ceval'; -import * as Prefs from 'common/prefs'; -import { EnhanceOpts } from 'common/richText'; - -export type Seconds = number; - -export type { Key, Piece } from 'chessground/types'; +import type { VNode } from 'snabbdom'; +import type { Player, Status, Source, Clock } from 'game'; +import type { ForecastData } from './forecast/interfaces'; +import type { StudyPracticeData, Goal as PracticeGoal } from './study/practice/interfaces'; +import type { RelayData } from './study/relay/interfaces'; +import type { ChatCtrl } from 'chat'; +import type { ExplorerOpts } from './explorer/interfaces'; +import type { StudyDataFromServer } from './study/interfaces'; +import type { AnalyseSocketSend } from './socket'; +import type { ExternalEngineInfo } from 'ceval'; +import type { Coords, MoveEvent } from 'common/prefs'; +import type { EnhanceOpts } from 'common/richText'; export interface NvuiPlugin { render(): VNode; @@ -57,7 +52,7 @@ export interface AnalyseData { } export interface AnalysePref { - coords: Prefs.Coords; + coords: Coords; is3d?: boolean; showDests?: boolean; rookCastle?: boolean; @@ -66,7 +61,7 @@ export interface AnalysePref { showCaptured?: boolean; animationDuration?: number; keyboardMove: boolean; - moveEvent: Prefs.MoveEvent; + moveEvent: MoveEvent; } export interface ServerEvalData { @@ -77,7 +72,7 @@ export interface ServerEvalData { } export interface EvalHit { - fen: cg.FEN; + fen: FEN; knodes: number; depth: number; pvs: Tree.PvDataServer[]; @@ -85,7 +80,7 @@ export interface EvalHit { } export interface EvalHitMulti extends EvalScore { - fen: cg.FEN; + fen: FEN; depth: number; } @@ -99,7 +94,7 @@ export interface Game { status: Status; player: Color; turns: number; - fen: cg.FEN; + fen: FEN; startedAtTurn?: number; source: Source; speed: Speed; @@ -163,12 +158,12 @@ export interface AnalyseOpts { embed?: boolean; } -export interface JustCaptured extends cg.Piece { +export interface JustCaptured extends Piece { promoted?: boolean; } export interface EvalGetData { - fen: cg.FEN; + fen: FEN; path: string; variant?: VariantKey; mpv?: number; @@ -187,5 +182,3 @@ export interface AnalyseState { path: Tree.Path | undefined; flipped: boolean; } - -export type Redraw = () => void; diff --git a/ui/analyse/src/keyboard.ts b/ui/analyse/src/keyboard.ts index 01e06731ba6db..c1d08160dbfd6 100644 --- a/ui/analyse/src/keyboard.ts +++ b/ui/analyse/src/keyboard.ts @@ -1,8 +1,8 @@ import * as control from './control'; -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; import * as xhr from 'common/xhr'; import { snabDialog } from 'common/dialog'; -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import { pubsub } from 'common/pubsub'; export const bind = (ctrl: AnalyseCtrl) => { diff --git a/ui/analyse/src/nodeFinder.ts b/ui/analyse/src/nodeFinder.ts index 3551ef5ddbff5..3b14c008e5c13 100644 --- a/ui/analyse/src/nodeFinder.ts +++ b/ui/analyse/src/nodeFinder.ts @@ -1,5 +1,4 @@ import { winningChances } from 'ceval'; -import { FEN } from 'chessground/types'; import { defined } from 'common'; import { zip } from 'common/algo'; diff --git a/ui/analyse/src/persistence.ts b/ui/analyse/src/persistence.ts index 7da211e548c1b..a808f5807acfa 100644 --- a/ui/analyse/src/persistence.ts +++ b/ui/analyse/src/persistence.ts @@ -1,6 +1,6 @@ -import AnalyseCtrl from './ctrl'; -import { AnalyseState } from './interfaces'; -import { objectStorage, ObjectStorage } from 'common/objectStorage'; +import type AnalyseCtrl from './ctrl'; +import type { AnalyseState } from './interfaces'; +import { objectStorage, type ObjectStorage } from 'common/objectStorage'; export default class Persistence { isDirty = false; // there are persisted user moves diff --git a/ui/analyse/src/pgnExport.ts b/ui/analyse/src/pgnExport.ts index f2fd6764f60cc..481d740730a1c 100644 --- a/ui/analyse/src/pgnExport.ts +++ b/ui/analyse/src/pgnExport.ts @@ -1,7 +1,7 @@ -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; import { h } from 'snabbdom'; import { initialFen, fixCrazySan } from 'chess'; -import { MaybeVNodes } from 'common/snabbdom'; +import { type MaybeVNodes } from 'common/snabbdom'; import { plyToTurn } from './util'; interface PgnNode { diff --git a/ui/analyse/src/pgnImport.ts b/ui/analyse/src/pgnImport.ts index 1bd8d60dae313..c1b2e2594591e 100644 --- a/ui/analyse/src/pgnImport.ts +++ b/ui/analyse/src/pgnImport.ts @@ -1,10 +1,17 @@ -import { AnalyseData, Game } from './interfaces'; +import type { AnalyseData, Game } from './interfaces'; import { makeFen } from 'chessops/fen'; import { makeSanAndPlay, parseSan } from 'chessops/san'; import { makeUci, Rules } from 'chessops'; -import { makeVariant, parsePgn, parseVariant, startingPosition, ChildNode, PgnNodeData } from 'chessops/pgn'; -import { IllegalSetup, Position } from 'chessops/chess'; -import { Player } from 'game'; +import { + makeVariant, + parsePgn, + parseVariant, + startingPosition, + type ChildNode, + type PgnNodeData, +} from 'chessops/pgn'; +import { IllegalSetup, type Position } from 'chessops/chess'; +import type { Player } from 'game'; import { scalachessCharPair } from 'chessops/compat'; import { makeSquare } from 'chessops/util'; diff --git a/ui/analyse/src/plugins/analyse.nvui.ts b/ui/analyse/src/plugins/analyse.nvui.ts index 6d0b027030eda..5469f0d0e1c22 100644 --- a/ui/analyse/src/plugins/analyse.nvui.ts +++ b/ui/analyse/src/plugins/analyse.nvui.ts @@ -1,12 +1,13 @@ -import { h, VNode } from 'snabbdom'; -import { defined, prop, Prop } from 'common'; -import * as xhr from 'common/xhr'; -import AnalyseController from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import { defined, prop, type Prop } from 'common'; +import { text as xhrText } from 'common/xhr'; +import type AnalyseController from '../ctrl'; import { makeConfig as makeCgConfig } from '../ground'; -import { AnalyseData } from '../interfaces'; -import { Player } from 'game'; +import type { AnalyseData } from '../interfaces'; +import type { Player } from 'game'; import viewStatus from 'game/view/status'; import { + type Style, renderSan, renderPieces, renderBoard, @@ -22,7 +23,6 @@ import { arrowKeyHandler, positionJumpHandler, pieceJumpingHandler, - Style, castlingFlavours, inputToLegalUci, namePiece, @@ -31,13 +31,12 @@ import { import { renderSetting } from 'nvui/setting'; import { Notify } from 'nvui/notify'; import { commands } from 'nvui/command'; -import { bind, MaybeVNodes } from 'common/snabbdom'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; import { throttle } from 'common/timing'; -import { Role } from 'chessground/types'; import explorerView from '../explorer/explorerView'; import { ops, path as treePath } from 'tree'; import { view as cevalView, renderEval } from 'ceval'; -import * as control from '../control'; +import { next, prev } from '../control'; import { lichessRules } from 'chessops/compat'; import { makeSan } from 'chessops/san'; import { opposite, parseUci } from 'chessops/util'; @@ -393,10 +392,10 @@ function isShortCommand(input: string): boolean { function onCommand(ctrl: AnalyseController, notify: (txt: string) => void, c: string, style: Style) { const lowered = c.toLowerCase(); if (lowered === 'next') { - control.next(ctrl); + next(ctrl); ctrl.redraw(); } else if (lowered === 'prev') { - control.prev(ctrl); + prev(ctrl); ctrl.redraw(); } else if (lowered === 'next line') { jumpNextLine(ctrl); @@ -466,7 +465,7 @@ function requestAnalysisButton( 'button', { hook: bind('click', _ => - xhr.text(`/${ctrl.data.game.id}/request-analysis`, { method: 'post' }).then( + xhrText(`/${ctrl.data.game.id}/request-analysis`, { method: 'post' }).then( () => { inProgress(true); notify('Server-side analysis in progress'); diff --git a/ui/analyse/src/plugins/analyse.study.topic.form.ts b/ui/analyse/src/plugins/analyse.study.topic.form.ts index 47aa470e8794c..5ed0abefe1329 100644 --- a/ui/analyse/src/plugins/analyse.study.topic.form.ts +++ b/ui/analyse/src/plugins/analyse.study.topic.form.ts @@ -1,5 +1,5 @@ import debounce from 'debounce-promise'; -import * as xhr from 'common/xhr'; +import { json as xhrJson, url as xhrUrl } from 'common/xhr'; import Tagify from '@yaireo/tagify'; site.load.then(() => { @@ -9,7 +9,7 @@ site.load.then(() => { maxTags: parseInt(input?.dataset['max'] ?? '64'), }); const doFetch: (term: string) => Promise = debounce( - (term: string) => xhr.json(xhr.url('/study/topic/autocomplete', { term })), + (term: string) => xhrJson(xhrUrl('/study/topic/autocomplete', { term })), 300, ); let clickDebounce: Timeout | undefined; // https://yaireo.github.io/tagify/#section-advance-options diff --git a/ui/analyse/src/plugins/analyse.study.tour.ts b/ui/analyse/src/plugins/analyse.study.tour.ts index d8d5676d5846f..ef56ab292b673 100644 --- a/ui/analyse/src/plugins/analyse.study.tour.ts +++ b/ui/analyse/src/plugins/analyse.study.tour.ts @@ -1,6 +1,6 @@ -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import Shepherd from 'shepherd.js'; -import { ChapterTab, StudyTour, Tab } from '../study/interfaces'; +import type { ChapterTab, StudyTour, Tab } from '../study/interfaces'; import { pubsub } from 'common/pubsub'; export function initModule(): StudyTour { diff --git a/ui/analyse/src/practice/practiceCtrl.ts b/ui/analyse/src/practice/practiceCtrl.ts index 2cbf9d4c868c2..1d47c67a2a799 100644 --- a/ui/analyse/src/practice/practiceCtrl.ts +++ b/ui/analyse/src/practice/practiceCtrl.ts @@ -1,11 +1,9 @@ -import { winningChances, Search } from 'ceval'; +import { winningChances, type Search } from 'ceval'; import { path as treePath } from 'tree'; import { detectThreefold } from '../nodeFinder'; import { tablebaseGuaranteed } from '../explorer/explorerCtrl'; -import AnalyseCtrl from '../ctrl'; -import { Redraw } from '../interfaces'; -import { defined, prop, Prop, requestIdleCallback } from 'common'; -import { altCastles } from 'chess'; +import type AnalyseCtrl from '../ctrl'; +import { defined, prop, type Prop, requestIdleCallback } from 'common'; import { parseUci } from 'chessops/util'; import { makeSan } from 'chessops/san'; @@ -56,7 +54,13 @@ export function make(root: AnalyseCtrl, playableDepth: () => number): PracticeCt comment = prop(null), hovering = prop<{ uci: string } | null>(null), hinting = prop(null), - played = prop(false); + played = prop(false), + altCastles = { + e1a1: 'e1c1', + e1h1: 'e1g1', + e8a8: 'e8c8', + e8h8: 'e8g8', + }; function commentable(node: Tree.Node, bonus = 0): boolean { if (node.tbhit || root.outcome(node)) return true; diff --git a/ui/analyse/src/practice/practiceView.ts b/ui/analyse/src/practice/practiceView.ts index 769dcc74e42e6..ad3d0759ac894 100644 --- a/ui/analyse/src/practice/practiceView.ts +++ b/ui/analyse/src/practice/practiceView.ts @@ -1,8 +1,8 @@ -import { Outcome } from 'chessops/types'; -import { h, VNode } from 'snabbdom'; -import { bind, MaybeVNodes } from 'common/snabbdom'; -import { PracticeCtrl, Comment } from './practiceCtrl'; -import AnalyseCtrl from '../ctrl'; +import type { Outcome } from 'chessops/types'; +import { h, type VNode } from 'snabbdom'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; +import type { PracticeCtrl, Comment } from './practiceCtrl'; +import type AnalyseCtrl from '../ctrl'; import { renderNextChapter } from '../study/nextChapter'; function commentBest(c: Comment, ctrl: PracticeCtrl): MaybeVNodes { diff --git a/ui/analyse/src/retrospect/retroCtrl.ts b/ui/analyse/src/retrospect/retroCtrl.ts index 6679a6e8e1388..894bb75172157 100644 --- a/ui/analyse/src/retrospect/retroCtrl.ts +++ b/ui/analyse/src/retrospect/retroCtrl.ts @@ -2,10 +2,9 @@ import { opposite } from 'chessground/util'; import { evalSwings } from '../nodeFinder'; import { winningChances } from 'ceval'; import { path as treePath } from 'tree'; -import { isEmpty, Prop, prop } from 'common'; -import { OpeningData } from '../explorer/interfaces'; -import AnalyseCtrl from '../ctrl'; -import { Redraw } from '../interfaces'; +import { isEmpty, type Prop, prop } from 'common'; +import type { OpeningData } from '../explorer/interfaces'; +import type AnalyseCtrl from '../ctrl'; export interface RetroCtrl { isSolving(): boolean; diff --git a/ui/analyse/src/retrospect/retroView.ts b/ui/analyse/src/retrospect/retroView.ts index 438c5de8807be..9961cd3ec7f54 100644 --- a/ui/analyse/src/retrospect/retroView.ts +++ b/ui/analyse/src/retrospect/retroView.ts @@ -1,10 +1,10 @@ import { renderIndexAndMove } from '../view/moveView'; -import { RetroCtrl } from './retroCtrl'; -import AnalyseCtrl from '../ctrl'; +import type { RetroCtrl } from './retroCtrl'; +import type AnalyseCtrl from '../ctrl'; import * as licon from 'common/licon'; import { bind, dataIcon } from 'common/snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; function skipOrViewSolution(ctrl: RetroCtrl) { return h('div.choices', [ diff --git a/ui/analyse/src/serverSideUnderboard.ts b/ui/analyse/src/serverSideUnderboard.ts index 2399ded3d3916..8c8ce8a69ae29 100644 --- a/ui/analyse/src/serverSideUnderboard.ts +++ b/ui/analyse/src/serverSideUnderboard.ts @@ -1,12 +1,11 @@ -import AnalyseCtrl from './ctrl'; +import type AnalyseCtrl from './ctrl'; import { baseUrl } from './view/util'; import * as licon from 'common/licon'; import { url as xhrUrl, textRaw as xhrTextRaw } from 'common/xhr'; -import { AnalyseData } from './interfaces'; -import { ChartGame, AcplChart } from 'chart'; +import type { AnalyseData } from './interfaces'; +import type { ChartGame, AcplChart } from 'chart'; import { stockfishName, spinnerHtml } from 'common/spinner'; import { alert, confirm, domDialog } from 'common/dialog'; -import { FEN } from 'chessground/types'; import { escapeHtml } from 'common'; import { storage } from 'common/storage'; import { pubsub } from 'common/pubsub'; diff --git a/ui/analyse/src/socket.ts b/ui/analyse/src/socket.ts index 1ada700e57a41..0ebfa8425d9d9 100644 --- a/ui/analyse/src/socket.ts +++ b/ui/analyse/src/socket.ts @@ -1,10 +1,9 @@ import { initial as initialBoardFEN } from 'chessground/fen'; import { ops as treeOps } from 'tree'; -import AnalyseCtrl from './ctrl'; -import { EvalGetData, EvalPutData, ServerEvalData } from './interfaces'; -import { AnaDests, AnaDrop, AnaMove, ChapterData, EditChapterData } from './study/interfaces'; -import { FormData as StudyFormData } from './study/studyForm'; -import { FEN } from 'chessground/types'; +import type AnalyseCtrl from './ctrl'; +import type { EvalGetData, EvalPutData, ServerEvalData } from './interfaces'; +import type { AnaDests, AnaDrop, AnaMove, ChapterData, EditChapterData } from './study/interfaces'; +import type { FormData as StudyFormData } from './study/studyForm'; interface DestsCache { [fen: string]: AnaDests; diff --git a/ui/analyse/src/start.ts b/ui/analyse/src/start.ts index 5e2f06a09b11c..8bcd26bc21452 100644 --- a/ui/analyse/src/start.ts +++ b/ui/analyse/src/start.ts @@ -1,8 +1,8 @@ import makeCtrl from './ctrl'; import menuHover from 'common/menuHover'; import makeView from './view/main'; -import { AnalyseApi, AnalyseOpts } from './interfaces'; -import { VNode } from 'snabbdom'; +import type { AnalyseApi, AnalyseOpts } from './interfaces'; +import type { VNode } from 'snabbdom'; import type * as studyDeps from './study/studyDeps'; export default function ( diff --git a/ui/analyse/src/study/chapterEditForm.ts b/ui/analyse/src/study/chapterEditForm.ts index 53731ebeecbcb..e622342a438ad 100644 --- a/ui/analyse/src/study/chapterEditForm.ts +++ b/ui/analyse/src/study/chapterEditForm.ts @@ -1,13 +1,18 @@ -import * as chapterForm from './chapterNewForm'; +import { fieldValue, modeChoices } from './chapterNewForm'; import { bind, bindSubmit, onInsert } from 'common/snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; import { option, emptyRedButton } from '../view/util'; -import { ChapterMode, EditChapterData, Orientation, StudyChapterConfig, ChapterPreview } from './interfaces'; +import type { + ChapterMode, + EditChapterData, + Orientation, + StudyChapterConfig, + ChapterPreview, +} from './interfaces'; import { defined, prop } from 'common'; import { confirm, snabDialog } from 'common/dialog'; import { h, VNode } from 'snabbdom'; -import { Redraw } from '../interfaces'; -import { StudySocketSend } from '../socket'; +import type { StudySocketSend } from '../socket'; export class StudyChapterEditForm { current = prop(null); @@ -70,10 +75,10 @@ export function view(ctrl: StudyChapterEditForm): VNode | undefined { { hook: bindSubmit(e => { ctrl.submit({ - name: chapterForm.fieldValue(e, 'name'), - mode: chapterForm.fieldValue(e, 'mode') as ChapterMode, - orientation: chapterForm.fieldValue(e, 'orientation') as Orientation, - description: chapterForm.fieldValue(e, 'description'), + name: fieldValue(e, 'name'), + mode: fieldValue(e, 'mode') as ChapterMode, + orientation: fieldValue(e, 'orientation') as Orientation, + description: fieldValue(e, 'description'), }); }, ctrl.redraw), }, @@ -123,7 +128,7 @@ function viewLoaded(ctrl: StudyChapterEditForm, data: StudyChapterConfig): VNode h('label.form-label', { attrs: { for: 'chapter-mode' } }, i18n.study.analysisMode), h( 'select#chapter-mode.form-control', - chapterForm.modeChoices.map(c => option(c[0], mode, c[1])), + modeChoices.map(c => option(c[0], mode, c[1])), ), ]), ]), diff --git a/ui/analyse/src/study/chapterNewForm.ts b/ui/analyse/src/study/chapterNewForm.ts index 7a2497dec7b17..3fbb5a5200d69 100644 --- a/ui/analyse/src/study/chapterNewForm.ts +++ b/ui/analyse/src/study/chapterNewForm.ts @@ -1,19 +1,17 @@ import { parseFen } from 'chessops/fen'; -import { defined, prop, Prop, toggle } from 'common'; +import { defined, prop, type Prop, toggle } from 'common'; import { snabDialog } from 'common/dialog'; import * as licon from 'common/licon'; -import { bind, bindSubmit, onInsert, looseH as h, dataIcon } from 'common/snabbdom'; +import { bind, bindSubmit, onInsert, looseH as h, dataIcon, type VNode } from 'common/snabbdom'; import { storedProp } from 'common/storage'; -import * as xhr from 'common/xhr'; -import { VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; -import { StudySocketSend } from '../socket'; +import { json as xhrJson, text as xhrText } from 'common/xhr'; +import type AnalyseCtrl from '../ctrl'; +import type { StudySocketSend } from '../socket'; import { spinnerVdom as spinner } from 'common/spinner'; import { option } from '../view/util'; -import { ChapterData, ChapterMode, ChapterTab, Orientation, StudyTour } from './interfaces'; +import type { ChapterData, ChapterMode, ChapterTab, Orientation, StudyTour } from './interfaces'; import { importPgn, variants as xhrVariants } from './studyXhr'; -import { StudyChapters } from './studyChapters'; -import { FEN } from 'chessground/types'; +import type { StudyChapters } from './studyChapters'; import type { LichessEditor } from 'editor'; import { pubsub } from 'common/pubsub'; @@ -198,7 +196,7 @@ export function view(ctrl: StudyChapterNewForm): VNode { { hook: { insert(vnode) { - xhr.json('/editor.json').then(async data => { + xhrJson('/editor.json').then(async data => { data.el = vnode.elm; data.fen = ctrl.root.node.fen; data.embed = true; @@ -286,9 +284,9 @@ export function view(ctrl: StudyChapterNewForm): VNode { hook: bind( 'click', () => { - xhr - .text(`/study/${study.data.id}/${study.vm.chapterId}.pgn`) - .then(pgnData => $('#chapter-pgn').val(pgnData)); + xhrText(`/study/${study.data.id}/${study.vm.chapterId}.pgn`).then(pgnData => + $('#chapter-pgn').val(pgnData), + ); return false; }, undefined, diff --git a/ui/analyse/src/study/commentForm.ts b/ui/analyse/src/study/commentForm.ts index 059baa27c9503..c811631e2a1ea 100644 --- a/ui/analyse/src/study/commentForm.ts +++ b/ui/analyse/src/study/commentForm.ts @@ -1,8 +1,8 @@ import { prop } from 'common'; import { onInsert } from 'common/snabbdom'; import { throttle } from 'common/timing'; -import { h, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; import { currentComments, isAuthorObj } from './studyComments'; import { storage } from 'common/storage'; diff --git a/ui/analyse/src/study/description.ts b/ui/analyse/src/study/description.ts index d70c33a477c60..128c3e5243ab1 100644 --- a/ui/analyse/src/study/description.ts +++ b/ui/analyse/src/study/description.ts @@ -1,8 +1,7 @@ -import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, onInsert, looseH as h } from 'common/snabbdom'; +import { type VNode, bind, onInsert, looseH as h } from 'common/snabbdom'; import { richHTML } from 'common/richText'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; import { confirm } from 'common/dialog'; export type Save = (t: string) => void; diff --git a/ui/analyse/src/study/gamebook/gamebookButtons.ts b/ui/analyse/src/study/gamebook/gamebookButtons.ts index 7f5d2c1edd648..03c2b6df05d5a 100644 --- a/ui/analyse/src/study/gamebook/gamebookButtons.ts +++ b/ui/analyse/src/study/gamebook/gamebookButtons.ts @@ -1,8 +1,7 @@ -import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, dataIcon, looseH as h } from 'common/snabbdom'; -import AnalyseCtrl from '../../ctrl'; -import StudyCtrl from '../studyCtrl'; +import { bind, dataIcon, type VNode, looseH as h } from 'common/snabbdom'; +import type AnalyseCtrl from '../../ctrl'; +import type StudyCtrl from '../studyCtrl'; export function playButtons(root: AnalyseCtrl): VNode | undefined { const study = root.study!, diff --git a/ui/analyse/src/study/gamebook/gamebookEdit.ts b/ui/analyse/src/study/gamebook/gamebookEdit.ts index d46adec3d9f1c..ae7e0be56da5d 100644 --- a/ui/analyse/src/study/gamebook/gamebookEdit.ts +++ b/ui/analyse/src/study/gamebook/gamebookEdit.ts @@ -1,10 +1,10 @@ -import * as control from '../../control'; -import AnalyseCtrl from '../../ctrl'; +import { prev } from '../../control'; +import type AnalyseCtrl from '../../ctrl'; import { requestIdleCallback } from 'common'; import * as licon from 'common/licon'; import { throttle } from 'common/timing'; -import { iconTag, bind, MaybeVNodes } from 'common/snabbdom'; -import { h, Hooks, VNode } from 'snabbdom'; +import { iconTag, bind, type MaybeVNodes } from 'common/snabbdom'; +import { h, type Hooks, type VNode } from 'snabbdom'; export function running(ctrl: AnalyseCtrl): boolean { return ( @@ -79,7 +79,7 @@ export function render(ctrl: AnalyseCtrl): VNode { ]), hasVariation ? null - : h('div.legend.clickable', { hook: bind('click', () => control.prev(ctrl), ctrl.redraw) }, [ + : h('div.legend.clickable', { hook: bind('click', () => prev(ctrl), ctrl.redraw) }, [ iconTag(licon.PlayTriangle), h('p', 'Add variation moves to explain why specific other moves are wrong.'), ]), diff --git a/ui/analyse/src/study/gamebook/gamebookPlayCtrl.ts b/ui/analyse/src/study/gamebook/gamebookPlayCtrl.ts index 3d49b88b190d3..0b9ec0d5e5a72 100644 --- a/ui/analyse/src/study/gamebook/gamebookPlayCtrl.ts +++ b/ui/analyse/src/study/gamebook/gamebookPlayCtrl.ts @@ -1,4 +1,4 @@ -import AnalyseCtrl from '../../ctrl'; +import type AnalyseCtrl from '../../ctrl'; import { path as treePath } from 'tree'; import { makeShapesFromUci } from '../../autoShape'; diff --git a/ui/analyse/src/study/gamebook/gamebookPlayView.ts b/ui/analyse/src/study/gamebook/gamebookPlayView.ts index ff9b60822cef8..73d3dd01237af 100644 --- a/ui/analyse/src/study/gamebook/gamebookPlayView.ts +++ b/ui/analyse/src/study/gamebook/gamebookPlayView.ts @@ -1,7 +1,6 @@ -import { VNode } from 'snabbdom'; -import GamebookPlayCtrl, { State } from './gamebookPlayCtrl'; +import GamebookPlayCtrl, { type State } from './gamebookPlayCtrl'; import * as licon from 'common/licon'; -import { iconTag, bind, dataIcon, looseH as h } from 'common/snabbdom'; +import { type VNode, iconTag, bind, dataIcon, looseH as h } from 'common/snabbdom'; import { richHTML } from 'common/richText'; export function render(ctrl: GamebookPlayCtrl): VNode { diff --git a/ui/analyse/src/study/interfaces.ts b/ui/analyse/src/study/interfaces.ts index 849e37f083e78..5d15a72dc4996 100644 --- a/ui/analyse/src/study/interfaces.ts +++ b/ui/analyse/src/study/interfaces.ts @@ -1,9 +1,8 @@ -import * as cg from 'chessground/types'; -import { Prop } from 'common'; -import { AnalyseData } from '../interfaces'; -import { GamebookOverride } from './gamebook/interfaces'; -import { Opening } from '../explorer/interfaces'; -import AnalyseCtrl from '../ctrl'; +import type { Prop } from 'common'; +import type { AnalyseData } from '../interfaces'; +import type { GamebookOverride } from './gamebook/interfaces'; +import type { Opening } from '../explorer/interfaces'; +import type AnalyseCtrl from '../ctrl'; export type Tab = 'intro' | 'members' | 'chapters'; export type ChapterTab = 'init' | 'edit' | 'game' | 'fen' | 'pgn'; @@ -235,7 +234,7 @@ export interface ChapterData { name: string; game?: string; variant?: VariantKey; - fen?: cg.FEN | null; + fen?: FEN | null; pgn?: string; orientation: Orientation; mode: ChapterMode; @@ -261,18 +260,18 @@ export interface AnaDests { export interface AnaMove { orig: string; dest: string; - fen: cg.FEN; + fen: FEN; path: string; variant?: VariantKey; ch?: string; - promotion?: cg.Role; + promotion?: Role; } export interface AnaDrop { - role: cg.Role; + role: Role; pos: Key; variant?: VariantKey; - fen: cg.FEN; + fen: FEN; path: string; ch?: string; } diff --git a/ui/analyse/src/study/inviteForm.ts b/ui/analyse/src/study/inviteForm.ts index 870cba224a9ed..57b78ed0c656b 100644 --- a/ui/analyse/src/study/inviteForm.ts +++ b/ui/analyse/src/study/inviteForm.ts @@ -1,11 +1,11 @@ import * as licon from 'common/licon'; import { bind, onInsert } from 'common/snabbdom'; import { titleNameToId } from '../view/util'; -import { h, VNode } from 'snabbdom'; -import { prop, Prop } from 'common'; -import { StudyMemberMap } from './interfaces'; -import { AnalyseSocketSend } from '../socket'; -import { storedSet, StoredSet } from 'common/storage'; +import { h, type VNode } from 'snabbdom'; +import { prop, type Prop } from 'common'; +import type { StudyMemberMap } from './interfaces'; +import type { AnalyseSocketSend } from '../socket'; +import { storedSet, type StoredSet } from 'common/storage'; import { snabDialog } from 'common/dialog'; import { userComplete } from 'common/userComplete'; import { pubsub } from 'common/pubsub'; diff --git a/ui/analyse/src/study/multiBoard.ts b/ui/analyse/src/study/multiBoard.ts index 43b5354437a1e..053d90aa529b6 100644 --- a/ui/analyse/src/study/multiBoard.ts +++ b/ui/analyse/src/study/multiBoard.ts @@ -1,14 +1,14 @@ import * as licon from 'common/licon'; import { otbClockIsRunning, formatMs } from 'common/clock'; import { fenColor } from 'common/miniBoard'; -import { MaybeVNode, VNode, bind, onInsert } from 'common/snabbdom'; +import { type MaybeVNode, type VNode, bind, onInsert } from 'common/snabbdom'; import { opposite as CgOpposite, uciToMove } from 'chessground/util'; -import { ChapterId, ChapterPreview, StudyPlayer } from './interfaces'; -import StudyCtrl from './studyCtrl'; -import { CloudEval, MultiCloudEval, renderEvalToggle, renderScoreAtDepth } from './multiCloudEval'; -import { Prop, Toggle, defined, notNull, prop, toggle } from 'common'; -import { Color } from 'chessops'; -import { StudyChapters, gameLinkAttrs, gameLinksListener } from './studyChapters'; +import type { ChapterId, ChapterPreview, StudyPlayer } from './interfaces'; +import type StudyCtrl from './studyCtrl'; +import { type CloudEval, type MultiCloudEval, renderEvalToggle, renderScoreAtDepth } from './multiCloudEval'; +import { type Prop, type Toggle, defined, notNull, prop, toggle } from 'common'; +import type { Color } from 'chessops'; +import { type StudyChapters, gameLinkAttrs, gameLinksListener } from './studyChapters'; import { playerFed } from './playerBars'; import { userTitle } from 'common/userLink'; import { h } from 'snabbdom'; diff --git a/ui/analyse/src/study/multiCloudEval.ts b/ui/analyse/src/study/multiCloudEval.ts index 28fa2876ffbe8..49e55ced2cc5b 100644 --- a/ui/analyse/src/study/multiCloudEval.ts +++ b/ui/analyse/src/study/multiCloudEval.ts @@ -1,13 +1,11 @@ -import { Prop, defined } from 'common'; -import { EvalHitMulti } from '../interfaces'; +import { type Prop, defined } from 'common'; +import type { EvalHitMulti } from '../interfaces'; import { storedBooleanPropWithEffect } from 'common/storage'; import { povChances } from 'ceval/src/winningChances'; -import { bind, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; -import { FEN } from 'chessground/types'; -import { StudyChapters } from './studyChapters'; +import { type VNode, bind, looseH as h } from 'common/snabbdom'; +import type { StudyChapters } from './studyChapters'; import { debounce } from 'common/timing'; -import { ServerNodeMsg } from './interfaces'; +import type { ServerNodeMsg } from './interfaces'; export interface CloudEval extends EvalHitMulti { chances: number; diff --git a/ui/analyse/src/study/nextChapter.ts b/ui/analyse/src/study/nextChapter.ts index 186dd69a68539..8c8106b50e920 100644 --- a/ui/analyse/src/study/nextChapter.ts +++ b/ui/analyse/src/study/nextChapter.ts @@ -1,7 +1,7 @@ import { h } from 'snabbdom'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import { ops as treeOps } from 'tree'; export const renderNextChapter = (ctrl: AnalyseCtrl) => diff --git a/ui/analyse/src/study/notif.ts b/ui/analyse/src/study/notif.ts index b984b49e7de90..013444e60d576 100644 --- a/ui/analyse/src/study/notif.ts +++ b/ui/analyse/src/study/notif.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; interface Notif { duration: number; diff --git a/ui/analyse/src/study/playerBars.ts b/ui/analyse/src/study/playerBars.ts index 6bcf664b2e71c..5c6ac428dc4e9 100644 --- a/ui/analyse/src/study/playerBars.ts +++ b/ui/analyse/src/study/playerBars.ts @@ -1,9 +1,9 @@ -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import { looseH as h } from 'common/snabbdom'; import renderClocks from '../view/clocks'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import { renderMaterialDiffs } from '../view/components'; -import { StudyPlayers, Federation, TagArray } from './interfaces'; +import type { StudyPlayers, Federation, TagArray } from './interfaces'; import { findTag, isFinished, looksLikeLichessGame, resultOf } from './studyChapters'; import { userTitle } from 'common/userLink'; import RelayPlayers, { fidePageLinkAttrs } from './relay/relayPlayers'; diff --git a/ui/analyse/src/study/practice/studyPracticeCtrl.ts b/ui/analyse/src/study/practice/studyPracticeCtrl.ts index 867d2d24d6d63..a92ec7d431dc5 100644 --- a/ui/analyse/src/study/practice/studyPracticeCtrl.ts +++ b/ui/analyse/src/study/practice/studyPracticeCtrl.ts @@ -1,11 +1,11 @@ -import * as xhr from '../studyXhr'; -import { Prop, prop } from 'common'; +import { practiceComplete } from '../studyXhr'; +import { type Prop, prop } from 'common'; import { storedBooleanProp } from 'common/storage'; import makeSuccess from './studyPracticeSuccess'; import { readOnlyProp } from '../../util'; -import { StudyPracticeData, Goal } from './interfaces'; -import { StudyData } from '../interfaces'; -import AnalyseCtrl from '../../ctrl'; +import type { StudyPracticeData, Goal } from './interfaces'; +import type { StudyData } from '../interfaces'; +import type AnalyseCtrl from '../../ctrl'; export default class StudyPracticeCtrl { goal: Prop; @@ -70,7 +70,7 @@ export default class StudyPracticeCtrl { former = this.data.completion[chapterId]; if (typeof former === 'undefined' || this.nbMoves() < former) { this.data.completion[chapterId] = this.nbMoves(); - xhr.practiceComplete(chapterId, this.nbMoves()); + practiceComplete(chapterId, this.nbMoves()); } }; diff --git a/ui/analyse/src/study/practice/studyPracticeSuccess.ts b/ui/analyse/src/study/practice/studyPracticeSuccess.ts index c450d450832d1..22c1a3165e621 100644 --- a/ui/analyse/src/study/practice/studyPracticeSuccess.ts +++ b/ui/analyse/src/study/practice/studyPracticeSuccess.ts @@ -1,6 +1,6 @@ -import AnalyseCtrl from '../../ctrl'; -import { Goal } from './interfaces'; -import { Comment } from '../../practice/practiceCtrl'; +import type AnalyseCtrl from '../../ctrl'; +import type { Goal } from './interfaces'; +import type { Comment } from '../../practice/practiceCtrl'; // returns null if not deep enough to know const isDrawish = (node: Tree.Node): boolean | null => diff --git a/ui/analyse/src/study/practice/studyPracticeView.ts b/ui/analyse/src/study/practice/studyPracticeView.ts index bed9e04922f48..a11b18423e0cf 100644 --- a/ui/analyse/src/study/practice/studyPracticeView.ts +++ b/ui/analyse/src/study/practice/studyPracticeView.ts @@ -1,14 +1,14 @@ import * as licon from 'common/licon'; -import { bind, bindNonPassive, MaybeVNodes } from 'common/snabbdom'; +import { bind, bindNonPassive, type MaybeVNodes } from 'common/snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; -import { h, thunk, VNode } from 'snabbdom'; +import { h, thunk, type VNode } from 'snabbdom'; import { toggle } from 'common/controls'; import { richHTML } from 'common/richText'; import { option, plural } from '../../view/util'; import { view as descView } from '../description'; -import { StudyPracticeData } from './interfaces'; -import StudyCtrl from '../studyCtrl'; -import StudyPracticeCtrl from './studyPracticeCtrl'; +import type { StudyPracticeData } from './interfaces'; +import type StudyCtrl from '../studyCtrl'; +import type StudyPracticeCtrl from './studyPracticeCtrl'; const selector = (data: StudyPracticeData) => h( diff --git a/ui/analyse/src/study/relay/relayCtrl.ts b/ui/analyse/src/study/relay/relayCtrl.ts index 4006775b7bf25..26b99861ae87e 100644 --- a/ui/analyse/src/study/relay/relayCtrl.ts +++ b/ui/analyse/src/study/relay/relayCtrl.ts @@ -1,12 +1,12 @@ -import { RelayData, LogEvent, RelaySync, RelayRound, RoundId } from './interfaces'; -import { BothClocks, ChapterId, ChapterSelect, Federations, ServerClockMsg } from '../interfaces'; -import { StudyMemberCtrl } from '../studyMembers'; -import { AnalyseSocketSend } from '../../socket'; -import { Prop, Toggle, defined, myUserId, notNull, prop, toggle } from 'common'; +import type { RelayData, LogEvent, RelaySync, RelayRound, RoundId } from './interfaces'; +import type { BothClocks, ChapterId, ChapterSelect, Federations, ServerClockMsg } from '../interfaces'; +import type { StudyMemberCtrl } from '../studyMembers'; +import type { AnalyseSocketSend } from '../../socket'; +import { type Prop, type Toggle, defined, myUserId, notNull, prop, toggle } from 'common'; import RelayTeams from './relayTeams'; import RelayPlayers from './relayPlayers'; -import { StudyChapters } from '../studyChapters'; -import { MultiCloudEval } from '../multiCloudEval'; +import type { StudyChapters } from '../studyChapters'; +import type { MultiCloudEval } from '../multiCloudEval'; import { VideoPlayer } from './videoPlayer'; import RelayStats from './relayStats'; import { pubsub } from 'common/pubsub'; diff --git a/ui/analyse/src/study/relay/relayGames.ts b/ui/analyse/src/study/relay/relayGames.ts index b6403a8477367..a0a0d03bf6ce2 100644 --- a/ui/analyse/src/study/relay/relayGames.ts +++ b/ui/analyse/src/study/relay/relayGames.ts @@ -1,9 +1,9 @@ -import { StudyCtrl } from '../studyDeps'; -import RelayCtrl from './relayCtrl'; +import type { StudyCtrl } from '../studyDeps'; +import type RelayCtrl from './relayCtrl'; import { userTitle } from 'common/userLink'; import { defined, scrollToInnerSelector } from 'common'; import { renderClock, verticalEvalGauge } from '../multiBoard'; -import { ChapterPreview } from '../interfaces'; +import type { ChapterPreview } from '../interfaces'; import { gameLinkAttrs } from '../studyChapters'; import { playerFed } from '../playerBars'; import { h } from 'snabbdom'; diff --git a/ui/analyse/src/study/relay/relayManagerView.ts b/ui/analyse/src/study/relay/relayManagerView.ts index b63498473a459..c69a64b189216 100644 --- a/ui/analyse/src/study/relay/relayManagerView.ts +++ b/ui/analyse/src/study/relay/relayManagerView.ts @@ -1,10 +1,10 @@ import * as licon from 'common/licon'; -import { looseH as h, bind, onInsert, dataIcon, MaybeVNode } from 'common/snabbdom'; -import { LogEvent } from './interfaces'; -import RelayCtrl from './relayCtrl'; +import { looseH as h, bind, onInsert, dataIcon, type MaybeVNode } from 'common/snabbdom'; +import type { LogEvent } from './interfaces'; +import type RelayCtrl from './relayCtrl'; import { memoize } from 'common'; import { side as studyViewSide } from '../studyView'; -import StudyCtrl from '../studyCtrl'; +import type StudyCtrl from '../studyCtrl'; export default function (ctrl: RelayCtrl, study: StudyCtrl): MaybeVNode { const contributor = ctrl.members.canContribute(), diff --git a/ui/analyse/src/study/relay/relayPlayers.ts b/ui/analyse/src/study/relay/relayPlayers.ts index a1d40293a8709..937b1f5c8b3ff 100644 --- a/ui/analyse/src/study/relay/relayPlayers.ts +++ b/ui/analyse/src/study/relay/relayPlayers.ts @@ -1,15 +1,22 @@ -import { Redraw, VNode, dataIcon, looseH as h, onInsert } from 'common/snabbdom'; -import * as xhr from 'common/xhr'; +import { type Redraw, type VNode, dataIcon, looseH as h, onInsert } from 'common/snabbdom'; +import { json as xhrJson } from 'common/xhr'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; -import { RelayTour, RoundId, TourId } from './interfaces'; +import type { RelayTour, RoundId, TourId } from './interfaces'; import { playerFed } from '../playerBars'; import { userTitle } from 'common/userLink'; -import { ChapterId, Federations, FideId, PointsStr, StudyPlayer, StudyPlayerFromServer } from '../interfaces'; +import type { + ChapterId, + Federations, + FideId, + PointsStr, + StudyPlayer, + StudyPlayerFromServer, +} from '../interfaces'; import tablesort from 'tablesort'; import extendTablesortNumber from 'common/tablesortNumber'; import { defined } from 'common'; -import { Attrs, Hooks, init as initSnabbdom, attributesModule, VNodeData } from 'snabbdom'; +import { type Attrs, type Hooks, init as initSnabbdom, attributesModule, type VNodeData } from 'snabbdom'; import { convertPlayerFromServer } from '../studyChapters'; import { isTouchDevice } from 'common/device'; @@ -90,7 +97,7 @@ export default class RelayPlayers { this.loading = true; this.redraw(); } - const players: (RelayPlayer & StudyPlayerFromServer)[] = await xhr.json( + const players: (RelayPlayer & StudyPlayerFromServer)[] = await xhrJson( `/broadcast/${this.tourId}/players`, ); this.players = players.map(p => convertPlayerFromServer(p, this.federations())); @@ -99,9 +106,9 @@ export default class RelayPlayers { loadPlayerWithGames = async (id: RelayPlayerId) => { const feds = this.federations(); - const full: RelayPlayerWithGames = await xhr - .json(`/broadcast/${this.tourId}/players/${encodeURIComponent(id)}`) - .then(p => convertPlayerFromServer(p, feds)); + const full: RelayPlayerWithGames = await xhrJson( + `/broadcast/${this.tourId}/players/${encodeURIComponent(id)}`, + ).then(p => convertPlayerFromServer(p, feds)); full.games.forEach((g: RelayPlayerGame) => { g.opponent = convertPlayerFromServer(g.opponent as RelayPlayer & StudyPlayerFromServer, feds); }); diff --git a/ui/analyse/src/study/relay/relayStats.ts b/ui/analyse/src/study/relay/relayStats.ts index bbaa05e3e0b37..07f0d4128d14f 100644 --- a/ui/analyse/src/study/relay/relayStats.ts +++ b/ui/analyse/src/study/relay/relayStats.ts @@ -1,7 +1,7 @@ -import { Redraw } from 'common/snabbdom'; +import type { Redraw } from 'common/snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; -import { RelayRound } from './interfaces'; -import * as xhr from 'common/xhr'; +import type { RelayRound } from './interfaces'; +import { json as xhrJson } from 'common/xhr'; import { h } from 'snabbdom'; export default class RelayStats { @@ -13,7 +13,7 @@ export default class RelayStats { ) {} loadFromXhr = async () => { - this.data = await xhr.json(`/broadcast/round/${this.round.id}/stats`); + this.data = await xhrJson(`/broadcast/round/${this.round.id}/stats`); this.redraw(); await site.asset.loadEsm('chart.relayStats', { init: { diff --git a/ui/analyse/src/study/relay/relayTeams.ts b/ui/analyse/src/study/relay/relayTeams.ts index 3979acca2038f..3dbf79926d1bd 100644 --- a/ui/analyse/src/study/relay/relayTeams.ts +++ b/ui/analyse/src/study/relay/relayTeams.ts @@ -1,13 +1,13 @@ -import { MaybeVNodes, Redraw, VNode, onInsert, looseH as h } from 'common/snabbdom'; -import * as xhr from 'common/xhr'; -import { RoundId } from './interfaces'; -import { ChapterId, ChapterPreview, StudyPlayer, ChapterSelect, StatusStr } from '../interfaces'; -import { MultiCloudEval, renderScoreAtDepth } from '../multiCloudEval'; +import { type MaybeVNodes, type Redraw, type VNode, onInsert, looseH as h } from 'common/snabbdom'; +import { json as xhrJson } from 'common/xhr'; +import type { RoundId } from './interfaces'; +import type { ChapterId, ChapterPreview, StudyPlayer, ChapterSelect, StatusStr } from '../interfaces'; +import { type MultiCloudEval, renderScoreAtDepth } from '../multiCloudEval'; import { spinnerVdom as spinner } from 'common/spinner'; import { playerFed } from '../playerBars'; import { gameLinkAttrs, gameLinksListener, StudyChapters } from '../studyChapters'; import { userTitle } from 'common/userLink'; -import RelayPlayers from './relayPlayers'; +import type RelayPlayers from './relayPlayers'; interface TeamWithPoints { name: string; @@ -42,7 +42,7 @@ export default class RelayTeams { this.loading = true; this.redraw(); } - this.teams = await xhr.json(`/broadcast/${this.roundId}/teams`); + this.teams = await xhrJson(`/broadcast/${this.roundId}/teams`); this.redraw(); }; } diff --git a/ui/analyse/src/study/relay/relayTourView.ts b/ui/analyse/src/study/relay/relayTourView.ts index eea0850ef5a48..2f08c7695dd56 100644 --- a/ui/analyse/src/study/relay/relayTourView.ts +++ b/ui/analyse/src/study/relay/relayTourView.ts @@ -1,15 +1,15 @@ -import AnalyseCtrl from '../../ctrl'; -import RelayCtrl, { RelayTab } from './relayCtrl'; +import type AnalyseCtrl from '../../ctrl'; +import RelayCtrl, { type RelayTab } from './relayCtrl'; import * as licon from 'common/licon'; import { bind, dataIcon, onInsert, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import { innerHTML, richHTML } from 'common/richText'; -import { RelayData, RelayGroup, RelayRound, RelayTourDates, RelayTourInfo } from './interfaces'; +import type { RelayData, RelayGroup, RelayRound, RelayTourDates, RelayTourInfo } from './interfaces'; import { view as multiBoardView } from '../multiBoard'; import { defined, memoize } from 'common'; -import StudyCtrl from '../studyCtrl'; +import type StudyCtrl from '../studyCtrl'; import { toggle } from 'common/controls'; -import * as xhr from 'common/xhr'; +import { text as xhrText } from 'common/xhr'; import { teamsView } from './relayTeams'; import { statsView } from './relayStats'; import { makeChatEl, type RelayViewContext } from '../../view/components'; @@ -404,7 +404,7 @@ const subscribe = (relay: RelayCtrl, ctrl: AnalyseCtrl) => cls: 'relay-tour__subscribe', checked: relay.data.isSubscribed, change: (v: boolean) => { - xhr.text(`/broadcast/${relay.data.tour.id}/subscribe?set=${v}`, { method: 'post' }); + xhrText(`/broadcast/${relay.data.tour.id}/subscribe?set=${v}`, { method: 'post' }); relay.data.isSubscribed = v; ctrl.redraw(); }, diff --git a/ui/analyse/src/study/relay/relayView.ts b/ui/analyse/src/study/relay/relayView.ts index da6d25e966dcb..e12d67c84fb40 100644 --- a/ui/analyse/src/study/relay/relayView.ts +++ b/ui/analyse/src/study/relay/relayView.ts @@ -1,8 +1,8 @@ import { view as cevalView } from 'ceval'; import { onClickAway } from 'common'; -import { looseH as h, onInsert, VNode } from 'common/snabbdom'; +import { looseH as h, onInsert, type VNode } from 'common/snabbdom'; import * as licon from 'common/licon'; -import AnalyseCtrl from '../../ctrl'; +import type AnalyseCtrl from '../../ctrl'; import { view as keyboardView } from '../../keyboard'; import type * as studyDeps from '../studyDeps'; import { tourSide, renderRelayTour } from './relayTourView'; @@ -16,7 +16,7 @@ import { renderTools, renderUnderboard, } from '../../view/components'; -import RelayCtrl from './relayCtrl'; +import type RelayCtrl from './relayCtrl'; export function relayView( ctrl: AnalyseCtrl, diff --git a/ui/analyse/src/study/relay/videoPlayer.ts b/ui/analyse/src/study/relay/videoPlayer.ts index 6b53ca2f4dcd8..dc4e636bac5d3 100644 --- a/ui/analyse/src/study/relay/videoPlayer.ts +++ b/ui/analyse/src/study/relay/videoPlayer.ts @@ -1,5 +1,5 @@ -import { looseH as h, Redraw, VNode } from 'common/snabbdom'; -import RelayCtrl from './relayCtrl'; +import { looseH as h, type Redraw, type VNode } from 'common/snabbdom'; +import type RelayCtrl from './relayCtrl'; import { allowVideo } from './relayView'; export class VideoPlayer { diff --git a/ui/analyse/src/study/serverEval.ts b/ui/analyse/src/study/serverEval.ts index 13936529c30dd..4fd57f70ffc6e 100644 --- a/ui/analyse/src/study/serverEval.ts +++ b/ui/analyse/src/study/serverEval.ts @@ -2,10 +2,10 @@ import * as licon from 'common/licon'; import { bind, onInsert } from 'common/snabbdom'; import { spinnerVdom, chartSpinner } from 'common/spinner'; import { requestIdleCallback } from 'common'; -import { h, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; -import { ChartGame, AcplChart } from 'chart'; -import { AnalyseData } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; +import type { ChartGame, AcplChart } from 'chart'; +import type { AnalyseData } from '../interfaces'; import { pubsub } from 'common/pubsub'; export default class ServerEval { diff --git a/ui/analyse/src/study/studyChapters.ts b/ui/analyse/src/study/studyChapters.ts index fc1bd16bf2b2a..d509ebcc45bb6 100644 --- a/ui/analyse/src/study/studyChapters.ts +++ b/ui/analyse/src/study/studyChapters.ts @@ -1,12 +1,11 @@ import { defined, prop, Prop, scrollToInnerSelector } from 'common'; import * as licon from 'common/licon'; -import { bind, dataIcon, iconTag, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; -import { StudySocketSend } from '../socket'; +import { type VNode, bind, dataIcon, iconTag, looseH as h } from 'common/snabbdom'; +import type AnalyseCtrl from '../ctrl'; +import type { StudySocketSend } from '../socket'; import { StudyChapterEditForm } from './chapterEditForm'; import { StudyChapterNewForm } from './chapterNewForm'; -import { +import type { LocalPaths, StudyChapter, StudyChapterConfig, @@ -21,7 +20,7 @@ import { ChapterSelect, StatusStr, } from './interfaces'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; import { opposite } from 'chessops/util'; import { fenColor } from 'common/miniBoard'; import { initialFen } from 'chess'; diff --git a/ui/analyse/src/study/studyComments.ts b/ui/analyse/src/study/studyComments.ts index ba38f5fbf5d2e..ffa3725a9b526 100644 --- a/ui/analyse/src/study/studyComments.ts +++ b/ui/analyse/src/study/studyComments.ts @@ -1,10 +1,10 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; import { richHTML } from 'common/richText'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import { nodeFullName } from '../view/util'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; import { confirm } from 'common/dialog'; export type AuthorObj = { diff --git a/ui/analyse/src/study/studyCtrl.ts b/ui/analyse/src/study/studyCtrl.ts index cfd64551955c1..8f05ea57fe04a 100644 --- a/ui/analyse/src/study/studyCtrl.ts +++ b/ui/analyse/src/study/studyCtrl.ts @@ -1,11 +1,10 @@ -import { Config as CgConfig } from 'chessground/config'; -import { DrawShape } from 'chessground/draw'; +import type { DrawShape } from 'chessground/draw'; import { prop, defined } from 'common'; import { debounce, throttle, throttlePromise } from 'common/timing'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import { StudyMemberCtrl } from './studyMembers'; import StudyPracticeCtrl from './practice/studyPracticeCtrl'; -import { StudyPracticeData } from './practice/interfaces'; +import type { StudyPracticeData } from './practice/interfaces'; import { CommentForm } from './commentForm'; import { GlyphForm } from './studyGlyph'; import { StudyForm } from './studyForm'; @@ -16,7 +15,7 @@ import { TagsForm } from './studyTags'; import ServerEval from './serverEval'; import * as xhr from './studyXhr'; import { path as treePath, ops as treeOps } from 'tree'; -import { +import type { StudyVm, Tab, ToolTab, @@ -40,15 +39,15 @@ import { import GamebookPlayCtrl from './gamebook/gamebookPlayCtrl'; import { DescriptionCtrl } from './description'; import RelayCtrl from './relay/relayCtrl'; -import { RelayData } from './relay/interfaces'; +import type { RelayData } from './relay/interfaces'; import { MultiBoardCtrl } from './multiBoard'; -import { StudySocketSendParams } from '../socket'; +import type { StudySocketSendParams } from '../socket'; import { storedMap } from 'common/storage'; import { opposite } from 'chessops/util'; import StudyChaptersCtrl from './studyChapters'; import { SearchCtrl } from './studySearch'; -import { GamebookOverride } from './gamebook/interfaces'; -import { EvalHitMulti, EvalHitMultiArray } from '../interfaces'; +import type { GamebookOverride } from './gamebook/interfaces'; +import type { EvalHitMulti, EvalHitMultiArray } from '../interfaces'; import { MultiCloudEval } from './multiCloudEval'; import { pubsub } from 'common/pubsub'; import { alert } from 'common/dialog'; diff --git a/ui/analyse/src/study/studyForm.ts b/ui/analyse/src/study/studyForm.ts index fcf97c246d0d0..bde7640eee15c 100644 --- a/ui/analyse/src/study/studyForm.ts +++ b/ui/analyse/src/study/studyForm.ts @@ -1,13 +1,11 @@ -import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { prop } from 'common'; import { confirm, prompt, snabDialog } from 'common/dialog'; import flairPickerLoader from 'bits/flairPicker'; -import { bindSubmit, bindNonPassive, onInsert, looseH as h } from 'common/snabbdom'; +import { type VNode, bindSubmit, bindNonPassive, onInsert, looseH as h } from 'common/snabbdom'; import { emptyRedButton } from '../view/util'; -import { StudyData } from './interfaces'; -import { Redraw } from '../interfaces'; -import RelayCtrl from './relay/relayCtrl'; +import type { StudyData } from './interfaces'; +import type RelayCtrl from './relay/relayCtrl'; export interface FormData { name: string; diff --git a/ui/analyse/src/study/studyGlyph.ts b/ui/analyse/src/study/studyGlyph.ts index 884d879d328e8..980a521865e71 100644 --- a/ui/analyse/src/study/studyGlyph.ts +++ b/ui/analyse/src/study/studyGlyph.ts @@ -2,9 +2,9 @@ import { prop } from 'common'; import { bind } from 'common/snabbdom'; import { throttle } from 'common/timing'; import { spinnerVdom as spinner } from 'common/spinner'; -import { h, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; -import * as xhr from './studyXhr'; +import { h, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; +import { glyphs as xhrGlyphs } from './studyXhr'; interface AllGlyphs { move: Tree.Glyph[]; @@ -30,7 +30,7 @@ export class GlyphForm { loadGlyphs = () => { if (!this.all()) - xhr.glyphs().then(gs => { + xhrGlyphs().then(gs => { this.all(gs); this.root.redraw(); }); diff --git a/ui/analyse/src/study/studyMembers.ts b/ui/analyse/src/study/studyMembers.ts index da81585e803c2..bd9424e55de0e 100644 --- a/ui/analyse/src/study/studyMembers.ts +++ b/ui/analyse/src/study/studyMembers.ts @@ -1,15 +1,14 @@ -import { AnalyseSocketSend } from '../socket'; -import { VNode } from 'snabbdom'; +import type { AnalyseSocketSend } from '../socket'; import * as licon from 'common/licon'; -import { iconTag, bind, onInsert, dataIcon, bindNonPassive, looseH as h } from 'common/snabbdom'; -import { makeCtrl as inviteFormCtrl, StudyInviteFormCtrl } from './inviteForm'; -import { NotifCtrl } from './notif'; +import { type VNode, iconTag, bind, onInsert, dataIcon, bindNonPassive, looseH as h } from 'common/snabbdom'; +import { makeCtrl as inviteFormCtrl, type StudyInviteFormCtrl } from './inviteForm'; +import type { NotifCtrl } from './notif'; import { prop, Prop, scrollTo } from 'common'; import { titleNameToId } from '../view/util'; -import { StudyMember, StudyMemberMap, Tab } from './interfaces'; +import type { StudyMember, StudyMemberMap, Tab } from './interfaces'; import { textRaw as xhrTextRaw } from 'common/xhr'; import { userLink } from 'common/userLink'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; import { once } from 'common/storage'; import { pubsub } from 'common/pubsub'; diff --git a/ui/analyse/src/study/studySearch.ts b/ui/analyse/src/study/studySearch.ts index ce46c3b99edf3..be6d9dd768b5e 100644 --- a/ui/analyse/src/study/studySearch.ts +++ b/ui/analyse/src/study/studySearch.ts @@ -1,11 +1,10 @@ -import { Prop, Toggle, propWithEffect, toggle } from 'common'; +import { type Prop, type Toggle, propWithEffect, toggle } from 'common'; import * as licon from 'common/licon'; import { bind, dataIcon, onInsert } from 'common/snabbdom'; import { snabDialog } from 'common/dialog'; -import { h, VNode } from 'snabbdom'; -import { Redraw } from '../interfaces'; -import { ChapterPreview } from './interfaces'; -import { StudyChapters } from './studyChapters'; +import { h, type VNode } from 'snabbdom'; +import type { ChapterPreview } from './interfaces'; +import type { StudyChapters } from './studyChapters'; import { pubsub } from 'common/pubsub'; export class SearchCtrl { diff --git a/ui/analyse/src/study/studyShare.ts b/ui/analyse/src/study/studyShare.ts index 10ba9df9b1f63..f68f107fd542c 100644 --- a/ui/analyse/src/study/studyShare.ts +++ b/ui/analyse/src/study/studyShare.ts @@ -1,13 +1,12 @@ import { prop } from 'common'; import * as licon from 'common/licon'; -import { bind, dataIcon, looseH as h } from 'common/snabbdom'; +import { type VNode, bind, dataIcon, looseH as h } from 'common/snabbdom'; import { copyMeInput } from 'common/copyMe'; import { text as xhrText, url as xhrUrl } from 'common/xhr'; -import { VNode } from 'snabbdom'; import { renderIndexAndMove } from '../view/moveView'; import { baseUrl } from '../view/util'; -import { ChapterPreview, StudyData } from './interfaces'; -import RelayCtrl from './relay/relayCtrl'; +import type { ChapterPreview, StudyData } from './interfaces'; +import type RelayCtrl from './relay/relayCtrl'; function fromPly(ctrl: StudyShare): VNode { const renderedMove = renderIndexAndMove({ withDots: true, showEval: false }, ctrl.currentNode()); diff --git a/ui/analyse/src/study/studyTags.ts b/ui/analyse/src/study/studyTags.ts index 5ae6693bf4bcc..8cb5f6959417b 100644 --- a/ui/analyse/src/study/studyTags.ts +++ b/ui/analyse/src/study/studyTags.ts @@ -1,10 +1,10 @@ import { onInsert } from 'common/snabbdom'; import { throttle } from 'common/timing'; -import { h, thunk, VNode } from 'snabbdom'; +import { h, thunk, type VNode } from 'snabbdom'; import { option } from '../view/util'; import { looksLikeLichessGame } from './studyChapters'; import { prop } from 'common'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; export class TagsForm { selectedType = prop(undefined); diff --git a/ui/analyse/src/study/studyView.ts b/ui/analyse/src/study/studyView.ts index 308a1db10e419..2ffc7021212df 100644 --- a/ui/analyse/src/study/studyView.ts +++ b/ui/analyse/src/study/studyView.ts @@ -1,12 +1,11 @@ import * as commentForm from './commentForm'; import * as glyphForm from './studyGlyph'; import * as practiceView from './practice/studyPracticeView'; -import AnalyseCtrl from '../ctrl'; -import { VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; import * as licon from 'common/licon'; -import { iconTag, bind, dataIcon, MaybeVNodes, looseH as h } from 'common/snabbdom'; +import { type VNode, iconTag, bind, dataIcon, type MaybeVNodes, looseH as h } from 'common/snabbdom'; import { playButtons as gbPlayButtons, overrideButton as gbOverrideButton } from './gamebook/gamebookButtons'; -import { Tab, ToolTab } from './interfaces'; +import type { Tab, ToolTab } from './interfaces'; import { view as chapterEditFormView } from './chapterEditForm'; import { view as chapterNewFormView } from './chapterNewForm'; import { view as chapterView } from './studyChapters'; @@ -22,7 +21,7 @@ import { view as tagsView } from './studyTags'; import { view as topicsView, formView as topicsFormView } from './topics'; import { view as searchView } from './studySearch'; import { render as renderTrainingView } from '../view/roundTraining'; -import StudyCtrl from './studyCtrl'; +import type StudyCtrl from './studyCtrl'; interface ToolButtonOpts { ctrl: StudyCtrl; diff --git a/ui/analyse/src/study/studyXhr.ts b/ui/analyse/src/study/studyXhr.ts index 6edebb6f1d554..bb6d644b9bda1 100644 --- a/ui/analyse/src/study/studyXhr.ts +++ b/ui/analyse/src/study/studyXhr.ts @@ -1,5 +1,5 @@ -import { StudyChapterConfig, ReloadData } from './interfaces'; -import * as xhr from 'common/xhr'; +import type { StudyChapterConfig, ReloadData } from './interfaces'; +import { text as xhrText, json as xhrJson, form as xhrForm } from 'common/xhr'; export const reload = ( baseUrl: string, @@ -10,24 +10,24 @@ export const reload = ( let url = `/${baseUrl}/${id}`; if (chapterId) url += '/' + chapterId; if (withChapters) url += '?chapters=1'; - return xhr.json(url); + return xhrJson(url); }; -export const variants = () => xhr.json('/variant', { cache: 'default' }); +export const variants = () => xhrJson('/variant', { cache: 'default' }); export const glyphs = () => - xhr.json(`/study/glyphs/${document.documentElement.lang}.json`, { cache: 'default' }); + xhrJson(`/study/glyphs/${document.documentElement.lang}.json`, { cache: 'default' }); export const chapterConfig = (studyId: string, chapterId: string): Promise => - xhr.json(`/study/${studyId}/${chapterId}/config`); + xhrJson(`/study/${studyId}/${chapterId}/config`); export const practiceComplete = (chapterId: string, nbMoves: number) => - xhr.text(`/practice/complete/${chapterId}/${nbMoves}`, { + xhrText(`/practice/complete/${chapterId}/${nbMoves}`, { method: 'POST', }); export const importPgn = (studyId: string, data: any) => - xhr.text(`/study/${studyId}/import-pgn?sri=${site.sri}`, { + xhrText(`/study/${studyId}/import-pgn?sri=${site.sri}`, { method: 'POST', - body: xhr.form(data), + body: xhrForm(data), }); diff --git a/ui/analyse/src/study/topics.ts b/ui/analyse/src/study/topics.ts index 774b1b355fd49..3a3b887c5902e 100644 --- a/ui/analyse/src/study/topics.ts +++ b/ui/analyse/src/study/topics.ts @@ -1,11 +1,10 @@ import { prop } from 'common'; import { bind, bindSubmit, onInsert } from 'common/snabbdom'; -import * as xhr from 'common/xhr'; +import { json as xhrJson, url as xhrUrl } from 'common/xhr'; import { snabDialog } from 'common/dialog'; -import { h, VNode } from 'snabbdom'; -import { Redraw } from '../interfaces'; -import { Topic } from './interfaces'; -import StudyCtrl from './studyCtrl'; +import { h, type VNode } from 'snabbdom'; +import type { Topic } from './interfaces'; +import type StudyCtrl from './studyCtrl'; export default class TopicsCtrl { open = prop(false); @@ -84,12 +83,12 @@ function setupTagify(elm: HTMLInputElement | HTMLTextAreaElement, userId?: strin abortCtrl = new AbortController(); // show loading animation and hide the suggestions dropdown tagi.loading(true).dropdown.hide.call(tagi); - xhr - .json(xhr.url('/study/topic/autocomplete', { term, user: userId }), { signal: abortCtrl.signal }) - .then(list => { + xhrJson(xhrUrl('/study/topic/autocomplete', { term, user: userId }), { signal: abortCtrl.signal }).then( + list => { tagi.settings.whitelist.splice(0, list.length, ...list); // update whitelist Array in-place tagi.loading(false).dropdown.show.call(tagi, term); // render the suggestions dropdown - }); + }, + ); }); $('.tagify__input').each(function (this: HTMLInputElement) { this.focus(); diff --git a/ui/analyse/src/treeView/columnView.ts b/ui/analyse/src/treeView/columnView.ts index 1f3f2fa58fd9d..a7271b1772d55 100644 --- a/ui/analyse/src/treeView/columnView.ts +++ b/ui/analyse/src/treeView/columnView.ts @@ -1,20 +1,19 @@ -import { VNode } from 'snabbdom'; import { isEmpty } from 'common'; import * as licon from 'common/licon'; -import { LooseVNodes, looseH as h } from 'common/snabbdom'; +import { type VNode, type LooseVNodes, looseH as h } from 'common/snabbdom'; import { fixCrazySan } from 'chess'; import { path as treePath, ops as treeOps } from 'tree'; import * as moveView from '../view/moveView'; -import AnalyseCtrl from '../ctrl'; -import { ConcealOf, Conceal } from '../interfaces'; +import type AnalyseCtrl from '../ctrl'; +import type { ConcealOf, Conceal } from '../interfaces'; import { + type Ctx as BaseCtx, + type Opts as BaseOpts, nonEmpty, mainHook, nodeClasses, renderInlineCommentsOf, retroLine, - Ctx as BaseCtx, - Opts as BaseOpts, renderComment, renderingCtx, } from './common'; diff --git a/ui/analyse/src/treeView/common.ts b/ui/analyse/src/treeView/common.ts index e3808643f4ba4..e8a85c5f413a4 100644 --- a/ui/analyse/src/treeView/common.ts +++ b/ui/analyse/src/treeView/common.ts @@ -1,12 +1,12 @@ -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import contextMenu from './contextMenu'; import { throttle } from 'common/timing'; import { enrichText, innerHTML } from 'common/richText'; import { authorText as commentAuthorText } from '../study/studyComments'; import { bindMobileTapHold } from 'common/device'; -import { h, Hooks, VNode } from 'snabbdom'; +import { h, type Hooks, type VNode } from 'snabbdom'; import { isEmpty, defined } from 'common'; -import { MaybeVNodes } from 'common/snabbdom'; +import { type MaybeVNodes } from 'common/snabbdom'; import { path as treePath } from 'tree'; import { playable } from 'game'; diff --git a/ui/analyse/src/treeView/contextMenu.ts b/ui/analyse/src/treeView/contextMenu.ts index 4712d11dc3393..2676b4f1a0144 100644 --- a/ui/analyse/src/treeView/contextMenu.ts +++ b/ui/analyse/src/treeView/contextMenu.ts @@ -1,7 +1,6 @@ import * as licon from 'common/licon'; -import { bind, onInsert, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; +import { type VNode, bind, onInsert, looseH as h } from 'common/snabbdom'; +import type AnalyseCtrl from '../ctrl'; import * as studyView from '../study/studyView'; import { patch, nodeFullName } from '../view/util'; import { renderVariationPgn } from '../pgnExport'; diff --git a/ui/analyse/src/treeView/inlineView.ts b/ui/analyse/src/treeView/inlineView.ts index dbba4ce3efa09..68abfb112cc9d 100644 --- a/ui/analyse/src/treeView/inlineView.ts +++ b/ui/analyse/src/treeView/inlineView.ts @@ -1,10 +1,10 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { fixCrazySan } from 'chess'; import { path as treePath, ops as treeOps } from 'tree'; import * as moveView from '../view/moveView'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import * as licon from 'common/licon'; -import { MaybeVNodes } from 'common/snabbdom'; +import type { MaybeVNodes } from 'common/snabbdom'; import { mainHook, nodeClasses, renderInlineCommentsOf, retroLine, Ctx, Opts, renderingCtx } from './common'; function renderChildrenOf(ctx: Ctx, node: Tree.Node, opts: Opts): MaybeVNodes | undefined { diff --git a/ui/analyse/src/treeView/treeView.ts b/ui/analyse/src/treeView/treeView.ts index f66f08fa019eb..4eb80cf64069e 100644 --- a/ui/analyse/src/treeView/treeView.ts +++ b/ui/analyse/src/treeView/treeView.ts @@ -1,10 +1,10 @@ -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import column from './columnView'; import inline from './inlineView'; import { isCol1 } from 'common/device'; -import { VNode } from 'snabbdom'; -import { ConcealOf } from '../interfaces'; -import { storedProp, StoredProp } from 'common/storage'; +import type { VNode } from 'snabbdom'; +import type { ConcealOf } from '../interfaces'; +import { storedProp, type StoredProp } from 'common/storage'; export type TreeViewKey = 'column' | 'inline'; diff --git a/ui/analyse/src/view/actionMenu.ts b/ui/analyse/src/view/actionMenu.ts index ee00f7eb51883..07ff0688ae0ff 100644 --- a/ui/analyse/src/view/actionMenu.ts +++ b/ui/analyse/src/view/actionMenu.ts @@ -2,11 +2,10 @@ import { isEmpty } from 'common'; import * as licon from 'common/licon'; import { isTouchDevice } from 'common/device'; import { domDialog } from 'common/dialog'; -import { bind, dataIcon, MaybeVNodes, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; -import { AutoplayDelay } from '../autoplay'; -import { toggle, ToggleSettings } from 'common/controls'; -import AnalyseCtrl from '../ctrl'; +import { type VNode, bind, dataIcon, type MaybeVNodes, looseH as h } from 'common/snabbdom'; +import type { AutoplayDelay } from '../autoplay'; +import { toggle, type ToggleSettings } from 'common/controls'; +import type AnalyseCtrl from '../ctrl'; import { cont as contRoute } from 'game/router'; import * as pgnExport from '../pgnExport'; diff --git a/ui/analyse/src/view/clocks.ts b/ui/analyse/src/view/clocks.ts index 20dc62710e2f0..bd0cf6581cb6c 100644 --- a/ui/analyse/src/view/clocks.ts +++ b/ui/analyse/src/view/clocks.ts @@ -1,5 +1,5 @@ -import { h, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; import { isFinished } from '../study/studyChapters'; import { notNull } from 'common'; diff --git a/ui/analyse/src/view/components.ts b/ui/analyse/src/view/components.ts index 9807973a0bba1..82eaaa5517652 100644 --- a/ui/analyse/src/view/components.ts +++ b/ui/analyse/src/view/components.ts @@ -1,16 +1,16 @@ import { view as cevalView } from 'ceval'; -import { VNode } from 'snabbdom'; import { parseFen } from 'chessops/fen'; import { defined } from 'common'; import * as licon from 'common/licon'; import { + type VNode, + type VNodeKids, + type MaybeVNode, bind, bindNonPassive, onInsert, dataIcon, - VNodeKids, looseH as h, - MaybeVNode, } from 'common/snabbdom'; import { playable } from 'game'; import { bindMobileMousedown, isMobile } from 'common/device'; @@ -24,8 +24,8 @@ import { view as forkView } from '../fork'; import renderClocks from './clocks'; import * as control from '../control'; import * as chessground from '../ground'; -import AnalyseCtrl from '../ctrl'; -import { ConcealOf } from '../interfaces'; +import type AnalyseCtrl from '../ctrl'; +import type { ConcealOf } from '../interfaces'; import * as pgnExport from '../pgnExport'; import { spinnerVdom as spinner } from 'common/spinner'; import * as Prefs from 'common/prefs'; @@ -36,8 +36,8 @@ import { render as renderTreeView } from '../treeView/treeView'; import * as gridHacks from './gridHacks'; import { dispatchChessgroundResize } from 'common/resize'; import serverSideUnderboard from '../serverSideUnderboard'; -import StudyCtrl from '../study/studyCtrl'; -import RelayCtrl from '../study/relay/relayCtrl'; +import type StudyCtrl from '../study/studyCtrl'; +import type RelayCtrl from '../study/relay/relayCtrl'; import type * as studyDeps from '../study/studyDeps'; import { renderPgnError } from '../pgnImport'; import { storage } from 'common/storage'; diff --git a/ui/analyse/src/view/main.ts b/ui/analyse/src/view/main.ts index 64d4b2c6a0397..d911afbf346a2 100644 --- a/ui/analyse/src/view/main.ts +++ b/ui/analyse/src/view/main.ts @@ -1,12 +1,11 @@ import { view as cevalView } from 'ceval'; import * as licon from 'common/licon'; -import { onInsert, looseH as h } from 'common/snabbdom'; +import { type VNode, onInsert, looseH as h } from 'common/snabbdom'; import { playable } from 'game'; import * as router from 'game/router'; -import { VNode } from 'snabbdom'; import { render as trainingView } from './roundTraining'; import crazyView from '../crazy/crazyView'; -import AnalyseCtrl from '../ctrl'; +import type AnalyseCtrl from '../ctrl'; import forecastView from '../forecast/forecastView'; import { view as keyboardView } from '../keyboard'; import { render as renderKeyboardMove } from 'keyboardMove'; diff --git a/ui/analyse/src/view/moveView.ts b/ui/analyse/src/view/moveView.ts index 49dab721ead25..d3681cf489620 100644 --- a/ui/analyse/src/view/moveView.ts +++ b/ui/analyse/src/view/moveView.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { fixCrazySan } from 'chess'; import { defined } from 'common'; import { view as cevalView, renderEval as normalizeEval } from 'ceval'; diff --git a/ui/analyse/src/view/roundTraining.ts b/ui/analyse/src/view/roundTraining.ts index 1a4f73b8dd59c..d39119698f06a 100644 --- a/ui/analyse/src/view/roundTraining.ts +++ b/ui/analyse/src/view/roundTraining.ts @@ -1,7 +1,7 @@ -import { h, thunk, VNode } from 'snabbdom'; -import AnalyseCtrl from '../ctrl'; +import { h, thunk, type VNode } from 'snabbdom'; +import type AnalyseCtrl from '../ctrl'; import { findTag } from '../study/studyChapters'; -import * as game from 'game'; +import { getPlayer } from 'game'; import * as licon from 'common/licon'; import { bind, dataIcon } from 'common/snabbdom'; import { ratingDiff } from 'common/userLink'; @@ -15,7 +15,7 @@ interface Advice { } const renderPlayer = (ctrl: AnalyseCtrl, color: Color): VNode => { - const p = game.getPlayer(ctrl.data, color); + const p = getPlayer(ctrl.data, color); if (p.user) return h('a.user-link.ulpt', { attrs: { href: '/@/' + p.user.username } }, [ p.user.username, diff --git a/ui/bits/package.json b/ui/bits/package.json index 54e3e159a0e16..9d8a9e2779280 100644 --- a/ui/bits/package.json +++ b/ui/bits/package.json @@ -30,7 +30,6 @@ "canvas-confetti": "^1.9.3", "chat": "workspace:*", "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*", "cropperjs": "^1.6.2", "debounce-promise": "^3.1.2", diff --git a/ui/bits/src/bits.captcha.ts b/ui/bits/src/bits.captcha.ts index 7547f5a9e772b..90874563e2f63 100644 --- a/ui/bits/src/bits.captcha.ts +++ b/ui/bits/src/bits.captcha.ts @@ -1,7 +1,5 @@ import * as xhr from 'common/xhr'; import * as domData from 'common/data'; -import type { Api as ChessgroundApi } from 'chessground/api'; -import type { Key } from 'chessground/types'; function init() { let failed = false; @@ -12,7 +10,7 @@ function init() { const $captcha = $(this), $board = $captcha.find('.mini-board'), $input = $captcha.find('input').val(''), - cg = domData.get($board[0]!, 'chessground') as ChessgroundApi; + cg = domData.get($board[0]!, 'chessground') as CgApi; if (!cg) { failed = true; return; diff --git a/ui/bits/src/bits.cms.ts b/ui/bits/src/bits.cms.ts index 5f0dd4c24647d..077be62c69398 100644 --- a/ui/bits/src/bits.cms.ts +++ b/ui/bits/src/bits.cms.ts @@ -3,7 +3,7 @@ import { throttle } from 'common/timing'; import { currentTheme } from 'common/theme'; import tablesort from 'tablesort'; import { storedJsonProp } from 'common/storage'; -import { Editor, EditorType } from '@toast-ui/editor'; +import { Editor, type EditorType } from '@toast-ui/editor'; site.load.then(() => { $('.markdown-editor').each(function (this: HTMLTextAreaElement) { diff --git a/ui/bits/src/bits.flatpickr.ts b/ui/bits/src/bits.flatpickr.ts index 051476b9b2e1e..3087e930477e7 100644 --- a/ui/bits/src/bits.flatpickr.ts +++ b/ui/bits/src/bits.flatpickr.ts @@ -1,6 +1,6 @@ import flatpickr from 'flatpickr'; import { use24h } from 'common/i18n'; -import { Options } from 'flatpickr/dist/types/options'; +import type { Options } from 'flatpickr/dist/types/options'; site.load.then(() => { $('.flatpickr').each(function (this: HTMLInputElement) { diff --git a/ui/bits/src/bits.lpv.ts b/ui/bits/src/bits.lpv.ts index d17be9a43d96e..bc8d21ec615ee 100644 --- a/ui/bits/src/bits.lpv.ts +++ b/ui/bits/src/bits.lpv.ts @@ -1,6 +1,6 @@ import Lpv from 'lichess-pgn-viewer'; -import PgnViewer from 'lichess-pgn-viewer/pgnViewer'; -import { Opts as LpvOpts } from 'lichess-pgn-viewer/interfaces'; +import type PgnViewer from 'lichess-pgn-viewer/pgnViewer'; +import type { Opts as LpvOpts } from 'lichess-pgn-viewer/interfaces'; import { text as xhrText } from 'common/xhr'; export default async function (opts?: { diff --git a/ui/bits/src/bits.ublogForm.ts b/ui/bits/src/bits.ublogForm.ts index 1dee3751a1652..7767eb3dd7f1a 100644 --- a/ui/bits/src/bits.ublogForm.ts +++ b/ui/bits/src/bits.ublogForm.ts @@ -1,6 +1,6 @@ -import * as xhr from 'common/xhr'; +import { json as xhrJson } from 'common/xhr'; import { throttle } from 'common/timing'; -import { Editor, EditorType } from '@toast-ui/editor'; +import { Editor, type EditorType } from '@toast-ui/editor'; import Tagify from '@yaireo/tagify'; import { currentTheme } from 'common/theme'; import { wireCropDialog } from './exports/crop'; @@ -64,8 +64,7 @@ const setupMarkdownEditor = (el: HTMLTextAreaElement) => { addImageBlobHook: (blob, cb) => { const formData = new FormData(); formData.append('image', blob); - xhr - .json(el.getAttribute('data-image-upload-url')!, { method: 'POST', body: formData }) + xhrJson(el.getAttribute('data-image-upload-url')!, { method: 'POST', body: formData }) .then(data => cb(data.imageUrl, '')) .catch(e => { cb(''); diff --git a/ui/board/src/menu.ts b/ui/board/src/menu.ts index a1437ad056bf4..c2e2f715d3e60 100644 --- a/ui/board/src/menu.ts +++ b/ui/board/src/menu.ts @@ -1,10 +1,9 @@ -import { h, VNode } from 'snabbdom'; -import { Toggle, myUserId, onClickAway } from 'common/common'; +import { h, type VNode } from 'snabbdom'; +import { type Toggle, myUserId, onClickAway } from 'common/common'; import { bindMobileMousedown } from 'common/device'; import * as licon from 'common/licon'; -import { MaybeVNode, MaybeVNodes, dataIcon, onInsert } from 'common/snabbdom'; -import { Redraw } from 'chessground/types'; -import * as controls from 'common/controls'; +import { type MaybeVNode, type MaybeVNodes, dataIcon, onInsert } from 'common/snabbdom'; +import { type ToggleSettings, toggle } from 'common/controls'; import { pubsub } from 'common/pubsub'; export const toggleButton = (toggle: Toggle, title: string): VNode => @@ -90,5 +89,5 @@ export class BoardMenu { disabled: !enabled, }); - private cmnToggle = (t: controls.ToggleSettings) => controls.toggle(t, this.redraw); + private cmnToggle = (t: ToggleSettings) => toggle(t, this.redraw); } diff --git a/ui/build b/ui/build index 43fb9ee26ff2c..5381e7c2684dc 100755 --- a/ui/build +++ b/ui/build @@ -9,6 +9,6 @@ if ! command -v pnpm &> /dev/null; then exit 1 fi -pnpm install --silent --ignore-workspace +pnpm install --silent --ignore-workspace --prefer-frozen-lockfile node --experimental-strip-types --no-warnings src/main.ts "$@" diff --git a/ui/ceval/package.json b/ui/ceval/package.json index 371668ed10c5e..434e8ed0965ba 100644 --- a/ui/ceval/package.json +++ b/ui/ceval/package.json @@ -16,7 +16,6 @@ "license": "AGPL-3.0-or-later", "dependencies": { "@badrap/result": "^0.2.13", - "chessops": "^0.14.2", "common": "workspace:*", "idb-keyval": "^6.2.1", "lila-stockfish-web": "0.0.7", diff --git a/ui/ceval/src/cache.ts b/ui/ceval/src/cache.ts index d08f78c9c65ff..d9e0ee5ffbde5 100644 --- a/ui/ceval/src/cache.ts +++ b/ui/ceval/src/cache.ts @@ -1,28 +1,28 @@ -import * as idb from 'idb-keyval'; +import { createStore, get, set, del } from 'idb-keyval'; export class Cache { private store; constructor(name: string) { - this.store = idb.createStore(`${name}--db`, `${name}--store`); + this.store = createStore(`${name}--db`, `${name}--store`); } async get(key: string, version: string): Promise<[boolean, any]> { - const cachedVersion = await idb.get(`${key}--version`, this.store); + const cachedVersion = await get(`${key}--version`, this.store); if (cachedVersion !== version) { return [false, undefined]; } - const data = await idb.get(`${key}--data`, this.store); + const data = await get(`${key}--data`, this.store); return [true, data]; } async set(key: string, version: string, data: any): Promise { - const cachedVersion = await idb.get(`${key}--version`, this.store); + const cachedVersion = await get(`${key}--version`, this.store); if (cachedVersion === version) { return; } - await idb.del(`${key}--version`, this.store); - await idb.set(`${key}--data`, data, this.store); - await idb.set(`${key}--version`, version, this.store); + await del(`${key}--version`, this.store); + await set(`${key}--data`, data, this.store); + await set(`${key}--version`, version, this.store); } } diff --git a/ui/ceval/src/ctrl.ts b/ui/ceval/src/ctrl.ts index ecb8ba6186c4d..8c6c8e36cd87a 100644 --- a/ui/ceval/src/ctrl.ts +++ b/ui/ceval/src/ctrl.ts @@ -1,6 +1,16 @@ import { throttle } from 'common/timing'; import { Engines } from './engines/engines'; -import { CevalOpts, CevalState, CevalEngine, Work, Step, Hovering, PvBoard, Started, Search } from './types'; +import { + type CevalOpts, + type CevalEngine, + type Work, + type Step, + type Hovering, + type PvBoard, + type Started, + type Search, + CevalState, +} from './types'; import { sanIrreversible, showEngineError, fewerCores } from './util'; import { defaultPosition, setupPosition } from 'chessops/variant'; import { parseFen } from 'chessops/fen'; @@ -10,8 +20,7 @@ import { prop, Prop, Toggle, toggle } from 'common'; import { clamp } from 'common/algo'; import { Result } from '@badrap/result'; import { storedIntProp, storage, tempStorage } from 'common/storage'; -import { Rules } from 'chessops'; -import { FEN } from 'chessground/types'; +import type { Rules } from 'chessops'; const cevalDisabledSentinel = '1'; diff --git a/ui/ceval/src/engines/engines.ts b/ui/ceval/src/engines/engines.ts index e56d0a234bb7d..c4d876724ebff 100644 --- a/ui/ceval/src/engines/engines.ts +++ b/ui/ceval/src/engines/engines.ts @@ -1,11 +1,11 @@ -import { BrowserEngineInfo, ExternalEngineInfo, EngineInfo, CevalEngine, Requires } from '../types'; -import CevalCtrl from '../ctrl'; +import type { BrowserEngineInfo, ExternalEngineInfo, EngineInfo, CevalEngine, Requires } from '../types'; +import type CevalCtrl from '../ctrl'; import { SimpleEngine } from './simpleEngine'; import { StockfishWebEngine } from './stockfishWebEngine'; import { ThreadedEngine } from './threadedEngine'; import { ExternalEngine } from './externalEngine'; import { storedStringProp, StoredProp } from 'common/storage'; -import { isAndroid, isIOS, isIPad, getFirefoxMajorVersion, features, Feature } from 'common/device'; +import { isAndroid, isIOS, isIPad, getFirefoxMajorVersion, features, type Feature } from 'common/device'; import { xhrHeader } from 'common/xhr'; import { lichessRules } from 'chessops/compat'; import { log } from 'common/permalog'; diff --git a/ui/ceval/src/engines/externalEngine.ts b/ui/ceval/src/engines/externalEngine.ts index d37dd1def978f..a16a278229d14 100644 --- a/ui/ceval/src/engines/externalEngine.ts +++ b/ui/ceval/src/engines/externalEngine.ts @@ -1,4 +1,10 @@ -import { Work, ExternalEngineInfo, CevalEngine, CevalState, EngineNotifier } from '../types'; +import { + type Work, + type ExternalEngineInfo, + type CevalEngine, + type EngineNotifier, + CevalState, +} from '../types'; import { randomToken } from 'common/algo'; import { readNdJson } from 'common/xhr'; import { throttle } from 'common/timing'; diff --git a/ui/ceval/src/engines/simpleEngine.ts b/ui/ceval/src/engines/simpleEngine.ts index 0778ca2ef5f3c..fd2fe861d3297 100644 --- a/ui/ceval/src/engines/simpleEngine.ts +++ b/ui/ceval/src/engines/simpleEngine.ts @@ -1,5 +1,5 @@ import { Protocol } from '../protocol'; -import { Work, CevalState, CevalEngine, BrowserEngineInfo } from '../types'; +import { CevalState, type Work, type CevalEngine, type BrowserEngineInfo } from '../types'; export class SimpleEngine implements CevalEngine { private failed: Error; diff --git a/ui/ceval/src/engines/stockfishWebEngine.ts b/ui/ceval/src/engines/stockfishWebEngine.ts index 30e6f13c2abcf..5ee0b0fbe2ce1 100644 --- a/ui/ceval/src/engines/stockfishWebEngine.ts +++ b/ui/ceval/src/engines/stockfishWebEngine.ts @@ -1,6 +1,12 @@ -import { Work, CevalEngine, CevalState, BrowserEngineInfo, EngineNotifier } from '../types'; +import { + CevalState, + type Work, + type CevalEngine, + type BrowserEngineInfo, + type EngineNotifier, +} from '../types'; import { Protocol } from '../protocol'; -import { objectStorage, ObjectStorage } from 'common/objectStorage'; +import { objectStorage, type ObjectStorage } from 'common/objectStorage'; import { sharedWasmMemory } from '../util'; import type StockfishWeb from 'lila-stockfish-web'; diff --git a/ui/ceval/src/engines/threadedEngine.ts b/ui/ceval/src/engines/threadedEngine.ts index a195915f33a25..a80370c71f28a 100644 --- a/ui/ceval/src/engines/threadedEngine.ts +++ b/ui/ceval/src/engines/threadedEngine.ts @@ -1,5 +1,11 @@ import { Protocol } from '../protocol'; -import { Work, CevalEngine, CevalState, BrowserEngineInfo, EngineNotifier } from '../types'; +import { + CevalState, + type Work, + type CevalEngine, + type BrowserEngineInfo, + type EngineNotifier, +} from '../types'; import { sharedWasmMemory } from '../util'; import { Cache } from '../cache'; diff --git a/ui/ceval/src/protocol.ts b/ui/ceval/src/protocol.ts index e49d323e784f8..e62212ad2ab8a 100644 --- a/ui/ceval/src/protocol.ts +++ b/ui/ceval/src/protocol.ts @@ -1,5 +1,5 @@ import { defined } from 'common'; -import { Work } from './types'; +import type { Work } from './types'; export class Protocol { public engineName: string | undefined; diff --git a/ui/ceval/src/types.ts b/ui/ceval/src/types.ts index afeb9670f717a..bfd85f1d34ca4 100644 --- a/ui/ceval/src/types.ts +++ b/ui/ceval/src/types.ts @@ -1,6 +1,6 @@ -import { Outcome } from 'chessops/types'; -import { Prop } from 'common'; -import { Feature } from 'common/device'; +import type { Outcome } from 'chessops/types'; +import type { Prop } from 'common'; +import type { Feature } from 'common/device'; import type CevalCtrl from './ctrl'; export type WinningChances = number; diff --git a/ui/ceval/src/view/main.ts b/ui/ceval/src/view/main.ts index 14325fc30ea7a..5b4ddaa049bbc 100644 --- a/ui/ceval/src/view/main.ts +++ b/ui/ceval/src/view/main.ts @@ -1,11 +1,10 @@ -import * as winningChances from '../winningChances'; +import { povChances } from '../winningChances'; import * as licon from 'common/licon'; import { stepwiseScroll } from 'common/controls'; -import { onInsert, bind, LooseVNodes, looseH as h } from 'common/snabbdom'; +import { type VNode, type LooseVNodes, onInsert, bind, looseH as h } from 'common/snabbdom'; import { defined, notNull, requestIdleCallback } from 'common'; -import { ParentCtrl, NodeEvals, CevalState } from '../types'; -import { VNode } from 'snabbdom'; -import { Position } from 'chessops/chess'; +import { type ParentCtrl, type NodeEvals, CevalState } from '../types'; +import type { Position } from 'chessops/chess'; import { lichessRules } from 'chessops/compat'; import { makeSanAndPlay } from 'chessops/san'; import { opposite, parseUci } from 'chessops/util'; @@ -14,7 +13,7 @@ import { renderEval } from '../util'; import { setupPosition } from 'chessops/variant'; import { uciToMove } from 'chessground/util'; import { renderCevalSettings } from './settings'; -import CevalCtrl from '../ctrl'; +import type CevalCtrl from '../ctrl'; import { Chessground as makeChessground } from 'chessground'; type EvalInfo = { knps: number; npsText: string; depthText: string }; @@ -143,7 +142,7 @@ export function renderGauge(ctrl: ParentCtrl): VNode | undefined { const bestEv = getBestEval(ctrl.currentEvals()); let ev; if (bestEv) { - ev = winningChances.povChances('white', bestEv); + ev = povChances('white', bestEv); gaugeLast = ev; } else ev = gaugeLast; return h( diff --git a/ui/ceval/src/view/settings.ts b/ui/ceval/src/view/settings.ts index 6db320b25651b..5fc783c50c806 100644 --- a/ui/ceval/src/view/settings.ts +++ b/ui/ceval/src/view/settings.ts @@ -1,10 +1,9 @@ -import { VNode } from 'snabbdom'; -import { ParentCtrl } from '../types'; -import CevalCtrl from '../ctrl'; +import type { ParentCtrl } from '../types'; +import type CevalCtrl from '../ctrl'; import { fewerCores } from '../util'; import { rangeConfig } from 'common/controls'; import { isChrome } from 'common/device'; -import { onInsert, bind, dataIcon, looseH as h } from 'common/snabbdom'; +import { type VNode, onInsert, bind, dataIcon, looseH as h } from 'common/snabbdom'; import * as Licon from 'common/licon'; import { onClickAway } from 'common'; import { clamp } from 'common/algo'; diff --git a/ui/ceval/src/winningChances.ts b/ui/ceval/src/winningChances.ts index 5b332a6fcd5c2..783b268bc266c 100644 --- a/ui/ceval/src/winningChances.ts +++ b/ui/ceval/src/winningChances.ts @@ -1,4 +1,4 @@ -import { WinningChances } from './types'; +import type { WinningChances } from './types'; const toPov = (color: Color, diff: number): number => (color === 'white' ? diff : -diff); diff --git a/ui/challenge/src/challenge.ts b/ui/challenge/src/challenge.ts index a9bcbefa47640..76e7a1e4d03df 100644 --- a/ui/challenge/src/challenge.ts +++ b/ui/challenge/src/challenge.ts @@ -2,7 +2,7 @@ import { init, VNode, classModule, attributesModule } from 'snabbdom'; import ChallengeCtrl from './ctrl'; import { loaded, loading } from './view'; import { json } from 'common/xhr'; -import { ChallengeOpts, ChallengeData } from './interfaces'; +import type { ChallengeOpts, ChallengeData } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/challenge/src/ctrl.ts b/ui/challenge/src/ctrl.ts index 03dcd9a1c12c5..d20a403015667 100644 --- a/ui/challenge/src/ctrl.ts +++ b/ui/challenge/src/ctrl.ts @@ -1,6 +1,6 @@ -import * as xhr from 'common/xhr'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; import { once } from 'common/storage'; -import { ChallengeOpts, ChallengeData, Reasons } from './interfaces'; +import type { ChallengeOpts, ChallengeData, Reasons } from './interfaces'; export default class ChallengeCtrl { data: ChallengeData; @@ -41,18 +41,18 @@ export default class ChallengeCtrl { this.data.in.forEach(c => { if (c.id === id) { c.declined = true; - xhr - .text(`/challenge/${id}/decline`, { method: 'post', body: xhr.form({ reason }) }) - .catch(() => site.announce({ msg: 'Failed to send challenge decline' })); + xhrText(`/challenge/${id}/decline`, { method: 'post', body: xhrForm({ reason }) }).catch(() => + site.announce({ msg: 'Failed to send challenge decline' }), + ); } }); cancel = (id: string) => this.data.out.forEach(c => { if (c.id === id) { c.declined = true; - xhr - .text(`/challenge/${id}/cancel`, { method: 'post' }) - .catch(() => site.announce({ msg: 'Failed to send challenge cancellation' })); + xhrText(`/challenge/${id}/cancel`, { method: 'post' }).catch(() => + site.announce({ msg: 'Failed to send challenge cancellation' }), + ); } }); onRedirect = () => { diff --git a/ui/challenge/src/interfaces.ts b/ui/challenge/src/interfaces.ts index a8a963248064b..b411ca2a9bcb8 100644 --- a/ui/challenge/src/interfaces.ts +++ b/ui/challenge/src/interfaces.ts @@ -1,5 +1,3 @@ -import { FEN } from 'chessground/types'; - export interface ChallengeOpts { el: Element; data?: ChallengeData; diff --git a/ui/challenge/src/view.ts b/ui/challenge/src/view.ts index 60a0f1153fc9c..ddae0641edf04 100644 --- a/ui/challenge/src/view.ts +++ b/ui/challenge/src/view.ts @@ -1,11 +1,11 @@ -import { Challenge, ChallengeData, ChallengeDirection, ChallengeUser, TimeControl } from './interfaces'; +import type { Challenge, ChallengeData, ChallengeDirection, ChallengeUser, TimeControl } from './interfaces'; import { h, VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import { userLink } from 'common/userLink'; import { initMiniBoard } from 'common/miniBoard'; import { opposite } from 'chessground/util'; -import ChallengeCtrl from './ctrl'; +import type ChallengeCtrl from './ctrl'; export const loaded = (ctrl: ChallengeCtrl): VNode => ctrl.redirecting diff --git a/ui/chart/src/acpl.ts b/ui/chart/src/acpl.ts index 50eb2c29ed469..aaa338ed7e2c9 100644 --- a/ui/chart/src/acpl.ts +++ b/ui/chart/src/acpl.ts @@ -1,14 +1,14 @@ import { winningChances } from 'ceval'; import { + type ChartConfiguration, + type ChartDataset, + type PointStyle, Chart, - ChartConfiguration, - ChartDataset, Filler, LineController, LineElement, LinearScale, PointElement, - PointStyle, Tooltip, } from 'chart.js'; import { @@ -26,7 +26,7 @@ import { resizePolyfill, } from './common'; import division from './division'; -import { AcplChart, AnalyseData, Player } from './interface'; +import type { AcplChart, AnalyseData, Player } from './interface'; import ChartDataLabels from 'chartjs-plugin-datalabels'; import { pubsub } from 'common/pubsub'; diff --git a/ui/chart/src/chart.game.ts b/ui/chart/src/chart.game.ts index 2548fef632714..7a23bdd6b2779 100644 --- a/ui/chart/src/chart.game.ts +++ b/ui/chart/src/chart.game.ts @@ -1,4 +1,4 @@ -import { ChartGame, AcplChart } from './interface'; +import type { ChartGame, AcplChart } from './interface'; import movetime from './movetime'; import acpl from './acpl'; import { gridColor, tooltipBgColor, fontFamily, maybeChart, resizePolyfill, colorSeries } from './common'; diff --git a/ui/chart/src/chart.lag.ts b/ui/chart/src/chart.lag.ts index 0f687e5d58b7e..06442ca2db286 100644 --- a/ui/chart/src/chart.lag.ts +++ b/ui/chart/src/chart.lag.ts @@ -1,9 +1,9 @@ import { + type ChartConfiguration, + type ChartDataset, + type ChartType, ArcElement, Chart, - ChartConfiguration, - ChartDataset, - ChartType, DoughnutController, Title, } from 'chart.js'; diff --git a/ui/chart/src/chart.ratingDistribution.ts b/ui/chart/src/chart.ratingDistribution.ts index f332ae7f81a0c..7400753220ae5 100644 --- a/ui/chart/src/chart.ratingDistribution.ts +++ b/ui/chart/src/chart.ratingDistribution.ts @@ -1,11 +1,11 @@ -import { Point } from 'chart.js/dist/core/core.controller'; +import type { Point } from 'chart.js/dist/core/core.controller'; import { animation, fontFamily, gridColor, hoverBorderColor, resizePolyfill } from './common'; -import { DistributionData } from './interface'; +import type { DistributionData } from './interface'; import { + type ChartConfiguration, + type ChartData, + type ChartDataset, Chart, - ChartConfiguration, - ChartData, - ChartDataset, Filler, LineController, LineElement, diff --git a/ui/chart/src/chart.ratingHistory.ts b/ui/chart/src/chart.ratingHistory.ts index 2e5a53cee272d..989a7eb59de39 100644 --- a/ui/chart/src/chart.ratingHistory.ts +++ b/ui/chart/src/chart.ratingHistory.ts @@ -1,4 +1,8 @@ import { + type ChartDataset, + type Point, + type ChartConfiguration, + type PointStyle, Chart, PointElement, LinearScale, @@ -6,16 +10,12 @@ import { LineController, Tooltip, LineElement, - ChartDataset, - Point, - ChartConfiguration, - PointStyle, } from 'chart.js'; -import { PerfRatingHistory } from './interface'; +import type { PerfRatingHistory } from './interface'; import { fontColor, fontFamily, gridColor, hoverBorderColor, tooltipBgColor, resizePolyfill } from './common'; import 'chartjs-adapter-dayjs-4'; import zoomPlugin from 'chartjs-plugin-zoom'; -import noUiSlider, { Options, PipsMode } from 'nouislider'; +import noUiSlider, { type Options, PipsMode } from 'nouislider'; import dayjs from 'dayjs'; import duration from 'dayjs/plugin/duration'; import dayOfYear from 'dayjs/plugin/dayOfYear'; diff --git a/ui/chart/src/chart.relayStats.ts b/ui/chart/src/chart.relayStats.ts index 97ff9fdce27f7..da91f23b68aa7 100644 --- a/ui/chart/src/chart.relayStats.ts +++ b/ui/chart/src/chart.relayStats.ts @@ -1,4 +1,4 @@ -import { RoundStats } from './interface'; +import type { RoundStats } from './interface'; import * as chart from 'chart.js'; import 'chartjs-adapter-dayjs-4'; import { hoverBorderColor, gridColor, tooltipBgColor, fontColor, fontFamily, animation } from './common'; diff --git a/ui/chart/src/common.ts b/ui/chart/src/common.ts index 63552b4ca1681..7f5b739c11c63 100644 --- a/ui/chart/src/common.ts +++ b/ui/chart/src/common.ts @@ -1,4 +1,4 @@ -import { Chart, ChartDataset, ChartOptions } from 'chart.js'; +import { Chart, type ChartDataset, type ChartOptions } from 'chart.js'; import { currentTheme } from 'common/theme'; export interface MovePoint { diff --git a/ui/chart/src/division.ts b/ui/chart/src/division.ts index 474e0fec602d7..85d9baacf94bb 100644 --- a/ui/chart/src/division.ts +++ b/ui/chart/src/division.ts @@ -1,6 +1,6 @@ import { chartYMax, chartYMin } from './common'; -import { Division } from './interface'; -import { ChartDataset, Point } from 'chart.js'; +import type { Division } from './interface'; +import type { ChartDataset, Point } from 'chart.js'; export default function (div?: Division): ChartDataset<'line'>[] { const lines: { div: string; loc: number }[] = []; diff --git a/ui/chart/src/interface.ts b/ui/chart/src/interface.ts index d9a122bfe8907..06f1507b924d2 100644 --- a/ui/chart/src/interface.ts +++ b/ui/chart/src/interface.ts @@ -1,4 +1,4 @@ -import { Chart } from 'chart.js'; +import type { Chart } from 'chart.js'; export interface PlyChart extends Chart<'line'> { selectPly(ply: number, isMainline: boolean): void; diff --git a/ui/chart/src/movetime.ts b/ui/chart/src/movetime.ts index cfde791aadfb6..1374515c49576 100644 --- a/ui/chart/src/movetime.ts +++ b/ui/chart/src/movetime.ts @@ -2,16 +2,16 @@ import { BarController, BarElement, Chart, - ChartDataset, + type ChartDataset, LineController, LineElement, LinearScale, PointElement, - PointStyle, + type PointStyle, Tooltip, } from 'chart.js'; import { - MovePoint, + type MovePoint, animation, blackFill, fontColor, @@ -25,7 +25,7 @@ import { axisOpts, resizePolyfill, } from './common'; -import { AnalyseData, Player, PlyChart } from './interface'; +import type { AnalyseData, Player, PlyChart } from './interface'; import division from './division'; import { pubsub } from 'common/pubsub'; diff --git a/ui/chat/src/chat.ts b/ui/chat/src/chat.ts index 92592b6f47c83..392d1d626e4d9 100644 --- a/ui/chat/src/chat.ts +++ b/ui/chat/src/chat.ts @@ -1,7 +1,7 @@ import { init, attributesModule, classModule } from 'snabbdom'; import view from './view'; -import { ChatOpts } from './interfaces'; +import type { ChatOpts } from './interfaces'; import ChatCtrl from './ctrl'; export type { ChatPlugin } from './interfaces'; diff --git a/ui/chat/src/ctrl.ts b/ui/chat/src/ctrl.ts index a735d5fdf745e..dae8b51caf116 100644 --- a/ui/chat/src/ctrl.ts +++ b/ui/chat/src/ctrl.ts @@ -1,4 +1,4 @@ -import { +import type { ChatOpts, Line, Tab, @@ -11,12 +11,12 @@ import { ChatPalantir, ChatPlugin, } from './interfaces'; -import { PresetCtrl, presetCtrl } from './preset'; +import { type PresetCtrl, presetCtrl } from './preset'; import { noteCtrl } from './note'; import { moderationCtrl } from './moderation'; import { prop } from 'common'; import { storage, type LichessStorage } from 'common/storage'; -import { pubsub, PubsubEvent, PubsubCallback } from 'common/pubsub'; +import { pubsub, type PubsubEvent, type PubsubCallback } from 'common/pubsub'; import { alert } from 'common/dialog'; export default class ChatCtrl { diff --git a/ui/chat/src/discussion.ts b/ui/chat/src/discussion.ts index 538c04f287dc6..9b2c47a700ab9 100644 --- a/ui/chat/src/discussion.ts +++ b/ui/chat/src/discussion.ts @@ -2,11 +2,11 @@ import * as licon from 'common/licon'; import * as enhance from 'common/richText'; import { userLink } from 'common/userLink'; import * as spam from './spam'; -import { Line } from './interfaces'; -import { h, thunk, VNode, VNodeData } from 'snabbdom'; +import type { Line } from './interfaces'; +import { h, thunk, type VNode, type VNodeData } from 'snabbdom'; import { lineAction as modLineAction, report } from './moderation'; import { presetView } from './preset'; -import ChatCtrl from './ctrl'; +import type ChatCtrl from './ctrl'; import { tempStorage } from 'common/storage'; import { pubsub } from 'common/pubsub'; import { alert } from 'common/dialog'; diff --git a/ui/chat/src/interfaces.ts b/ui/chat/src/interfaces.ts index 90533aba83461..e9af0f7925f08 100644 --- a/ui/chat/src/interfaces.ts +++ b/ui/chat/src/interfaces.ts @@ -1,8 +1,8 @@ -import { VNode } from 'snabbdom'; -import { Prop } from 'common'; +import type { VNode } from 'snabbdom'; +import type { Prop } from 'common'; import type { Palantir } from 'palantir'; -import { EnhanceOpts } from 'common/richText'; +import type { EnhanceOpts } from 'common/richText'; export interface ChatOpts { el: HTMLElement; diff --git a/ui/chat/src/moderation.ts b/ui/chat/src/moderation.ts index c55e98a660807..d05a177e0c76b 100644 --- a/ui/chat/src/moderation.ts +++ b/ui/chat/src/moderation.ts @@ -1,11 +1,11 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; import { userLink } from 'common/userLink'; -import { ModerationCtrl, ModerationOpts, ModerationData, ModerationReason } from './interfaces'; +import type { ModerationCtrl, ModerationOpts, ModerationData, ModerationReason } from './interfaces'; import { numberFormat } from 'common/number'; import { userModInfo, flag, timeout } from './xhr'; -import ChatCtrl from './ctrl'; +import type ChatCtrl from './ctrl'; import { pubsub } from 'common/pubsub'; import { confirm } from 'common/dialog'; diff --git a/ui/chat/src/note.ts b/ui/chat/src/note.ts index 430d3532708ca..41b78bd86c3a6 100644 --- a/ui/chat/src/note.ts +++ b/ui/chat/src/note.ts @@ -1,5 +1,5 @@ -import { h, VNode } from 'snabbdom'; -import { NoteCtrl, NoteOpts } from './interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { NoteCtrl, NoteOpts } from './interfaces'; import * as xhr from './xhr'; import { debounce } from 'common/timing'; diff --git a/ui/chat/src/preset.ts b/ui/chat/src/preset.ts index f62669c8e36a0..7cc7d4a0428ed 100644 --- a/ui/chat/src/preset.ts +++ b/ui/chat/src/preset.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { bind } from 'common/snabbdom'; -import { Redraw } from './interfaces'; +import type { Redraw } from './interfaces'; export interface PresetCtrl { group(): string | undefined; diff --git a/ui/chat/src/view.ts b/ui/chat/src/view.ts index 5a856e3ecf95c..c42a8ec502860 100644 --- a/ui/chat/src/view.ts +++ b/ui/chat/src/view.ts @@ -1,13 +1,13 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; -import { Tab } from './interfaces'; +import type { Tab } from './interfaces'; import discussionView from './discussion'; import { noteView } from './note'; import { moderationView } from './moderation'; import type * as palantir from 'palantir'; -import ChatCtrl from './ctrl'; +import type ChatCtrl from './ctrl'; export default function (ctrl: ChatCtrl): VNode { return h( diff --git a/ui/chess/package.json b/ui/chess/package.json index ee0ea1ce88ad9..93b880ba6f093 100644 --- a/ui/chess/package.json +++ b/ui/chess/package.json @@ -24,7 +24,6 @@ "author": "Thibault Duplessis", "license": "AGPL-3.0-or-later", "dependencies": { - "common": "workspace:*", - "chessops": "^0.14.2" + "common": "workspace:*" } } diff --git a/ui/chess/src/chess.ts b/ui/chess/src/chess.ts index 40fbf88024e08..5c418e7f4ae75 100644 --- a/ui/chess/src/chess.ts +++ b/ui/chess/src/chess.ts @@ -1,6 +1,5 @@ -import { FEN } from 'chessground/types'; import { uciChar } from './uciChar'; -import { NormalMove, Chess, parseUci, makeUci } from 'chessops'; +import { type NormalMove, type Chess, parseUci, makeUci } from 'chessops'; import { normalizeMove } from 'chessops/chess'; export * from './sanWriter'; @@ -10,8 +9,6 @@ export function fixCrazySan(san: San): San { return san[0] === 'P' ? san.slice(1) : san; } -export type Dests = Map; - export function destsToUcis(dests: Dests): Uci[] { const ucis: string[] = []; for (const [orig, d] of dests) { @@ -48,40 +45,3 @@ export function normalMove(chess: Chess, unsafeUci: Uci): { uci: Uci; move: Norm const move = unsafe && 'from' in unsafe ? { ...unsafe, ...normalizeMove(chess, unsafe) } : undefined; return move && chess.isLegal(move) ? { uci: makeUci(move), move } : undefined; } - -export const altCastles = { - e1a1: 'e1c1', - e1h1: 'e1g1', - e8a8: 'e8c8', - e8h8: 'e8g8', -}; - -// we must strive to redefine roles and promotions in each and every module -export const from = (uci: Uci) => uci.slice(0, 2) as Key; -export const to = (uci: Uci) => uci.slice(2, 4) as Key; - -export const Roles = ['king', 'queen', 'rook', 'bishop', 'knight', 'pawn'] as const; -export type Role = (typeof Roles)[number]; - -export const RoleChars = ['K', 'Q', 'R', 'B', 'N', 'P'] as const; -export type RoleChar = (typeof RoleChars)[number]; - -export const roleChar = (role: string) => - ({ - king: 'K', - queen: 'Q', - rook: 'R', - bishop: 'B', - knight: 'N', - pawn: 'P', - })[role] as RoleChar; -export const charRole = (char: string) => - ({ - P: 'pawn', - N: 'knight', - B: 'bishop', - R: 'rook', - Q: 'queen', - K: 'king', - })[char] as Role; -export const promo = (uci: Uci): Role => charRole(uci.slice(4, 5).toUpperCase() as RoleChar); diff --git a/ui/chess/src/glyphs.ts b/ui/chess/src/glyphs.ts index d35126b499ff8..4c2e9b846ca20 100644 --- a/ui/chess/src/glyphs.ts +++ b/ui/chess/src/glyphs.ts @@ -1,5 +1,5 @@ import { parseUci, makeSquare, squareRank } from 'chessops/util'; -import { DrawShape } from 'chessground/draw'; +import type { DrawShape } from 'chessground/draw'; export function annotationShapes(node: Tree.Node): DrawShape[] { const { uci, glyphs, san } = node; diff --git a/ui/chess/src/moveRootCtrl.ts b/ui/chess/src/moveRootCtrl.ts index d01ef94d3084a..b81684610d024 100644 --- a/ui/chess/src/moveRootCtrl.ts +++ b/ui/chess/src/moveRootCtrl.ts @@ -1,7 +1,5 @@ -import * as cg from 'chessground/types'; - export interface MoveRootCtrl { - pluginMove: (orig: cg.Key, dest: cg.Key, prom: cg.Role | undefined) => void; + pluginMove: (orig: Key, dest: Key, prom: Role | undefined) => void; redraw: () => void; flipNow: () => void; offerDraw?: (v: boolean, immediately?: boolean) => void; diff --git a/ui/chess/src/promotion.ts b/ui/chess/src/promotion.ts index 9827c110a5737..a9dad531a2c43 100644 --- a/ui/chess/src/promotion.ts +++ b/ui/chess/src/promotion.ts @@ -1,14 +1,13 @@ import { h } from 'snabbdom'; -import * as Prefs from 'common/prefs'; -import { MaybeVNode, bind, onInsert } from 'common/snabbdom'; -import { Api as CgApi } from 'chessground/api'; -import { DrawShape } from 'chessground/draw'; -import * as cgUtil from 'chessground/util'; -import * as cg from 'chessground/types'; +import { AutoQueen } from 'common/prefs'; +import { type MaybeVNode, bind, onInsert } from 'common/snabbdom'; +import type { DrawShape } from 'chessground/draw'; +import { opposite, key2pos } from 'chessground/util'; +import type { MoveMetadata } from 'chessground/types'; export type Hooks = { - submit: (orig: Key, dest: Key, role: cg.Role) => void; - show?: (ctrl: PromotionCtrl, roles: cg.Role[] | false) => void; + submit: (orig: Key, dest: Key, role: Role) => void; + show?: (ctrl: PromotionCtrl, roles: Role[] | false) => void; }; interface Promoting { @@ -18,9 +17,9 @@ interface Promoting { hooks: Hooks; } -const PROMOTABLE_ROLES: cg.Role[] = ['queen', 'knight', 'rook', 'bishop']; +const PROMOTABLE_ROLES: Role[] = ['queen', 'knight', 'rook', 'bishop']; -export function promote(g: CgApi, key: Key, role: cg.Role): void { +export function promote(g: CgApi, key: Key, role: Role): void { const piece = g.state.pieces.get(key); if (piece && piece.role == 'pawn') { g.setPieces(new Map([[key, { color: piece.color, role, promoted: true }]])); @@ -29,16 +28,16 @@ export function promote(g: CgApi, key: Key, role: cg.Role): void { export class PromotionCtrl { private promoting?: Promoting; - private prePromotionRole?: cg.Role; + private prePromotionRole?: Role; constructor( private withGround: (f: (cg: CgApi) => A) => A | false | undefined, private onCancel: () => void, private redraw: () => void, - private autoQueenPref: Prefs.AutoQueen = Prefs.AutoQueen.Never, + private autoQueenPref: AutoQueen = AutoQueen.Never, ) {} - start = (orig: Key, dest: Key, hooks: Hooks, meta?: cg.MoveMetadata, forceAutoQueen = false): boolean => + start = (orig: Key, dest: Key, hooks: Hooks, meta?: MoveMetadata, forceAutoQueen = false): boolean => this.withGround(g => { const premovePiece = g.state.pieces.get(orig); const piece = premovePiece || g.state.pieces.get(dest); @@ -53,8 +52,8 @@ export class PromotionCtrl { if ( !meta?.ctrlKey && !this.promoting && - (this.autoQueenPref === Prefs.AutoQueen.Always || - (this.autoQueenPref === Prefs.AutoQueen.OnPremove && premovePiece) || + (this.autoQueenPref === AutoQueen.Always || + (this.autoQueenPref === AutoQueen.OnPremove && premovePiece) || forceAutoQueen) ) { if (premovePiece) this.setPrePromotion(dest, 'queen'); @@ -96,14 +95,14 @@ export class PromotionCtrl { this.renderPromotion( promoting.dest, antichess ? PROMOTABLE_ROLES.concat('king') : PROMOTABLE_ROLES, - cgUtil.opposite(g.state.turnColor), + opposite(g.state.turnColor), g.state.orientation, ), ) || null ); }; - finish(role: cg.Role): void { + finish(role: Role): void { const promoting = this.promoting; if (promoting) { this.promoting = undefined; @@ -114,26 +113,26 @@ export class PromotionCtrl { } } - private doPromote(promoting: Omit, role: cg.Role): void { + private doPromote(promoting: Omit, role: Role): void { this.withGround(g => promote(g, promoting.dest, role)); promoting.hooks.submit(promoting.orig, promoting.dest, role); } - private setPrePromotion(dest: cg.Key, role: cg.Role): void { + private setPrePromotion(dest: Key, role: Role): void { this.prePromotionRole = role; this.withGround(g => g.setAutoShapes([ { orig: dest, - piece: { color: cgUtil.opposite(g.state.turnColor), role, opacity: 0.8 }, + piece: { color: opposite(g.state.turnColor), role, opacity: 0.8 }, brush: '', } as DrawShape, ]), ); } - private renderPromotion(dest: Key, pieces: cg.Role[], color: Color, orientation: Color): MaybeVNode { - let left = (7 - cgUtil.key2pos(dest)[0]) * 12.5; + private renderPromotion(dest: Key, pieces: Role[], color: Color, orientation: Color): MaybeVNode { + let left = (7 - key2pos(dest)[0]) * 12.5; if (orientation === 'white') left = 87.5 - left; const vertical = color === orientation ? 'top' : 'bottom'; diff --git a/ui/chess/src/sanWriter.ts b/ui/chess/src/sanWriter.ts index bed6fe0ae269a..245dbb77f2cde 100644 --- a/ui/chess/src/sanWriter.ts +++ b/ui/chess/src/sanWriter.ts @@ -1,4 +1,4 @@ -import { Square } from 'chessops'; +import type { Square } from 'chessops'; export type Board = { pieces: { [key: number]: string }; turn: boolean }; export type SanToUci = { [key: string]: Uci }; diff --git a/ui/common/src/common.ts b/ui/common/src/common.ts index adb68eca6047c..c4c1c404607ba 100644 --- a/ui/common/src/common.ts +++ b/ui/common/src/common.ts @@ -129,3 +129,13 @@ export function $as(cashOrHtml: Cash | string): T { export function myUserId(): string | undefined { return document.body.dataset.user; } + +export const charToRole = (char: string) => + ({ + P: 'pawn', + N: 'knight', + B: 'bishop', + R: 'rook', + Q: 'queen', + K: 'king', + })[char.toUpperCase()] as Role; diff --git a/ui/common/src/controls.ts b/ui/common/src/controls.ts index a6cc15f2c50af..5c44023670f06 100644 --- a/ui/common/src/controls.ts +++ b/ui/common/src/controls.ts @@ -1,6 +1,6 @@ -import { h, Hooks, VNode } from 'snabbdom'; +import { h, type Hooks, type VNode } from 'snabbdom'; import { bind } from './snabbdom'; -import { toggle as baseToggle, Toggle } from './common'; +import { toggle as baseToggle, type Toggle } from './common'; import * as xhr from './xhr'; export interface ToggleSettings { diff --git a/ui/common/src/copyMe.ts b/ui/common/src/copyMe.ts index e22d0bb8357ca..32909e747eee3 100644 --- a/ui/common/src/copyMe.ts +++ b/ui/common/src/copyMe.ts @@ -1,4 +1,4 @@ -import { Attrs, VNode, h } from 'snabbdom'; +import { type Attrs, type VNode, h } from 'snabbdom'; import * as licon from './licon'; export function copyMeInput(content: string, inputAttrs: Attrs = {}): VNode { diff --git a/ui/common/src/device.ts b/ui/common/src/device.ts index db51dafd57ebe..340fbba1aef9f 100644 --- a/ui/common/src/device.ts +++ b/ui/common/src/device.ts @@ -1,4 +1,4 @@ -import { Hooks } from 'snabbdom'; +import { type Hooks } from 'snabbdom'; import { memoize } from './common'; import { bind } from './snabbdom'; diff --git a/ui/common/src/dialog.ts b/ui/common/src/dialog.ts index 6bd243d73e431..649fbce17996b 100644 --- a/ui/common/src/dialog.ts +++ b/ui/common/src/dialog.ts @@ -1,4 +1,4 @@ -import { onInsert, looseH as h, VNode, Attrs, LooseVNodes } from './snabbdom'; +import { onInsert, looseH as h, type VNode, type Attrs, type LooseVNodes } from './snabbdom'; import { isTouchDevice } from './device'; import { escapeHtml, frag, $as } from './common'; import { eventJanitor } from './event'; diff --git a/ui/common/src/miniBoard.ts b/ui/common/src/miniBoard.ts index 6373356018414..fbb6efa4dd0cf 100644 --- a/ui/common/src/miniBoard.ts +++ b/ui/common/src/miniBoard.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as domData from './data'; import { lichessClockIsRunning, setClockWidget } from './clock'; import { uciToMove } from 'chessground/util'; @@ -110,7 +110,7 @@ export const finishMiniGame = (node: HTMLElement, win?: 'black' | 'white'): void }); interface MiniGameUpdateData { - fen: Cg.FEN; + fen: FEN; lm: Uci; wc?: number; bc?: number; diff --git a/ui/common/src/permalog.ts b/ui/common/src/permalog.ts index 8a2a401b80d20..0035a7ac66d8c 100644 --- a/ui/common/src/permalog.ts +++ b/ui/common/src/permalog.ts @@ -1,4 +1,4 @@ -import { objectStorage, ObjectStorage, DbInfo } from './objectStorage'; +import { objectStorage, type ObjectStorage, type DbInfo } from './objectStorage'; export const log: LichessLog = makeLog(); diff --git a/ui/common/src/resize.ts b/ui/common/src/resize.ts index b738f2988dc66..e11c14848a299 100644 --- a/ui/common/src/resize.ts +++ b/ui/common/src/resize.ts @@ -1,7 +1,7 @@ -import * as cg from 'chessground/types'; +import type { Elements } from 'chessground/types'; import * as xhr from './xhr'; import { debounce } from './timing'; -import * as Prefs from './prefs'; +import { ShowResizeHandle } from './prefs'; import { pubsub } from './pubsub'; type MouchEvent = Event & Partial; @@ -15,12 +15,12 @@ export const bindChessgroundResize = (f: () => void): void => document.body.addEventListener('chessground.resize', f); export default function resizeHandle( - els: cg.Elements, - pref: Prefs.ShowResizeHandle, + els: Elements, + pref: ShowResizeHandle, ply: number, visible?: Visible, ): void { - if (pref === Prefs.ShowResizeHandle.Never) return; + if (pref === ShowResizeHandle.Never) return; const el = document.createElement('cg-resize'); els.container.appendChild(el); @@ -65,7 +65,7 @@ export default function resizeHandle( el.addEventListener('touchstart', startResize, { passive: false }); el.addEventListener('mousedown', startResize, { passive: false }); - if (pref === Prefs.ShowResizeHandle.OnlyAtStart) { + if (pref === ShowResizeHandle.OnlyAtStart) { const toggle = (ply: number) => el.classList.toggle('none', visible ? !visible(ply) : ply >= 2); toggle(ply); pubsub.on('ply', toggle); diff --git a/ui/common/src/richText.ts b/ui/common/src/richText.ts index fdfbf68a8fb3b..df252c8c76f7a 100644 --- a/ui/common/src/richText.ts +++ b/ui/common/src/richText.ts @@ -1,6 +1,6 @@ // Rich Text helper functions // Refactored for https://github.com/lichess-org/lila/issues/7342 request -import { VNode, Hooks } from 'snabbdom'; +import type { VNode, Hooks } from 'snabbdom'; import { escapeHtml } from './common'; // from https://github.com/bryanwoods/autolink-js/blob/master/autolink.js diff --git a/ui/common/src/snabbdom.ts b/ui/common/src/snabbdom.ts index 7ffd84ef376f9..e0948f0c3372b 100644 --- a/ui/common/src/snabbdom.ts +++ b/ui/common/src/snabbdom.ts @@ -1,4 +1,11 @@ -import { h as snabH, VNode, VNodeData, VNodeChildElement, Hooks, Attrs } from 'snabbdom'; +import { + type VNode, + type VNodeData, + type VNodeChildElement, + type Hooks, + type Attrs, + h as snabH, +} from 'snabbdom'; export type { Attrs, VNode }; export type Redraw = () => void; diff --git a/ui/common/src/spinner.ts b/ui/common/src/spinner.ts index 91dcd542584e2..5c85bc2ed38ff 100644 --- a/ui/common/src/spinner.ts +++ b/ui/common/src/spinner.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; export const spinnerHtml = '
'; diff --git a/ui/common/src/storage.ts b/ui/common/src/storage.ts index ed4e983a43fc2..3b98871435b2d 100644 --- a/ui/common/src/storage.ts +++ b/ui/common/src/storage.ts @@ -1,4 +1,4 @@ -import { defined, notNull, Prop, Toggle, withEffect } from './common'; +import { defined, notNull, type Prop, type Toggle, withEffect } from './common'; export const storage: LichessStorageHelper = builder(window.localStorage); export const tempStorage: LichessStorageHelper = builder(window.sessionStorage); @@ -74,10 +74,8 @@ export const storedIntPropWithEffect = ( effect: (v: number) => void, ): Prop => withEffect(storedIntProp(k, defaultValue), effect); -export type StoredJsonProp = Prop; - export const storedJsonProp = - (key: string, defaultValue: () => V): StoredJsonProp => + (key: string, defaultValue: () => V): Prop => (v?: V) => { if (defined(v)) { storage.set(key, JSON.stringify(v)); diff --git a/ui/common/src/userLink.ts b/ui/common/src/userLink.ts index 96bc6c3a28e57..bea6a06860109 100644 --- a/ui/common/src/userLink.ts +++ b/ui/common/src/userLink.ts @@ -1,5 +1,5 @@ -import { Attrs, h, VNode } from 'snabbdom'; -import { MaybeVNode } from './snabbdom'; +import { type Attrs, h, type VNode } from 'snabbdom'; +import { type MaybeVNode } from './snabbdom'; export interface HasRating { rating?: number; diff --git a/ui/coordinateTrainer/src/chessground.ts b/ui/coordinateTrainer/src/chessground.ts index 8ed50012ae546..eb9df0e5d2f0a 100644 --- a/ui/coordinateTrainer/src/chessground.ts +++ b/ui/coordinateTrainer/src/chessground.ts @@ -1,8 +1,7 @@ -import { h, VNode } from 'snabbdom'; -import { Config as CgConfig } from 'chessground/config'; -import * as cg from 'chessground/types'; +import { h, type VNode } from 'snabbdom'; +import type { Elements } from 'chessground/types'; import resizeHandle from 'common/resize'; -import CoordinateTrainerCtrl from './ctrl'; +import type CoordinateTrainerCtrl from './ctrl'; import { Chessground as makeChessground } from 'chessground'; import { pubsub } from 'common/pubsub'; @@ -35,7 +34,7 @@ function makeConfig(ctrl: CoordinateTrainerCtrl): CgConfig { draggable: { enabled: false }, selectable: { enabled: false }, events: { - insert(elements: cg.Elements) { + insert(elements: Elements) { resizeHandle(elements, ctrl.config.resizePref, ctrl.playing ? 2 : 0); }, select: ctrl.onChessgroundSelect, diff --git a/ui/coordinateTrainer/src/coordinateTrainer.ts b/ui/coordinateTrainer/src/coordinateTrainer.ts index b62f36eb9e0a0..6f25a57747491 100644 --- a/ui/coordinateTrainer/src/coordinateTrainer.ts +++ b/ui/coordinateTrainer/src/coordinateTrainer.ts @@ -8,7 +8,7 @@ import { } from 'snabbdom'; import menuHover from 'common/menuHover'; import view from './view'; -import { CoordinateTrainerConfig } from './interfaces'; +import type { CoordinateTrainerConfig } from './interfaces'; import CoordinateTrainerCtrl from './ctrl'; const patch = init([classModule, attributesModule, propsModule, eventListenersModule, styleModule]); diff --git a/ui/coordinateTrainer/src/ctrl.ts b/ui/coordinateTrainer/src/ctrl.ts index e915211c056ac..4c81fff2cc6a8 100644 --- a/ui/coordinateTrainer/src/ctrl.ts +++ b/ui/coordinateTrainer/src/ctrl.ts @@ -1,11 +1,11 @@ import { sparkline } from '@fnando/sparkline'; -import * as xhr from 'common/xhr'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; import { throttlePromiseDelay } from 'common/timing'; import { myUserId, withEffect } from 'common'; -import { makeVoice, VoiceCtrl } from 'voice'; +import { makeVoice, type VoiceCtrl } from 'voice'; import { storedBooleanProp, storedProp } from 'common/storage'; -import { Api as CgApi } from 'chessground/api'; -import { +import type { Api as CgApi } from 'chessground/api'; +import type { ColorChoice, TimeControl, CoordinateTrainerConfig, @@ -83,9 +83,9 @@ export default class CoordinateTrainerCtrl { const setZen = throttlePromiseDelay( () => 1000, zen => - xhr.text('/pref/zen', { + xhrText('/pref/zen', { method: 'post', - body: xhr.form({ zen: zen ? 1 : 0 }), + body: xhrForm({ zen: zen ? 1 : 0 }), }), ); @@ -281,9 +281,9 @@ export default class CoordinateTrainerCtrl { if (this.timeControl() === 'thirtySeconds') { this.updateScoreList(); if (this.isAuth) - xhr.text('/training/coordinate/score', { + xhrText('/training/coordinate/score', { method: 'post', - body: xhr.form({ mode: this.mode(), color: this.orientation, score: this.score }), + body: xhrForm({ mode: this.mode(), color: this.orientation, score: this.score }), }); } diff --git a/ui/coordinateTrainer/src/side.ts b/ui/coordinateTrainer/src/side.ts index b629ced2c5ff7..714d2916cd84b 100644 --- a/ui/coordinateTrainer/src/side.ts +++ b/ui/coordinateTrainer/src/side.ts @@ -1,7 +1,7 @@ -import { h, VNode, VNodes } from 'snabbdom'; +import { h, type VNode, type VNodes } from 'snabbdom'; import { bind } from 'common/snabbdom'; -import CoordinateTrainerCtrl from './ctrl'; -import { ColorChoice, TimeControl, Mode } from './interfaces'; +import type CoordinateTrainerCtrl from './ctrl'; +import type { ColorChoice, TimeControl, Mode } from './interfaces'; import { toggle } from 'common/controls'; const colors: [ColorChoice, string][] = [ diff --git a/ui/coordinateTrainer/src/view.ts b/ui/coordinateTrainer/src/view.ts index a7502176fb84d..f057f974bef74 100644 --- a/ui/coordinateTrainer/src/view.ts +++ b/ui/coordinateTrainer/src/view.ts @@ -1,9 +1,9 @@ -import { VNode, VNodeStyle } from 'snabbdom'; +import type { VNode, VNodeStyle } from 'snabbdom'; import { bind, looseH as h } from 'common/snabbdom'; import { renderVoiceBar } from 'voice'; import chessground from './chessground'; import CoordinateTrainerCtrl, { DURATION } from './ctrl'; -import { CoordModifier } from './interfaces'; +import type { CoordModifier } from './interfaces'; import side from './side'; const textOverlay = (ctrl: CoordinateTrainerCtrl): VNode | false => { diff --git a/ui/dasher/src/background.ts b/ui/dasher/src/background.ts index be28513a4908c..6d4672a8c98ea 100644 --- a/ui/dasher/src/background.ts +++ b/ui/dasher/src/background.ts @@ -1,11 +1,11 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { elementScrollBarWidthSlowGuess, header } from './util'; import { debounce, throttlePromiseDelay } from 'common/timing'; import { prefersLight } from 'common/theme'; import * as licon from 'common/licon'; import { bind, onInsert } from 'common/snabbdom'; -import * as xhr from 'common/xhr'; -import { DasherCtrl, PaneCtrl } from './interfaces'; +import { text as xhrText, form as xhrForm, textRaw as xhrTextRaw } from 'common/xhr'; +import { type DasherCtrl, PaneCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; export interface BackgroundData { @@ -65,9 +65,10 @@ export class BackgroundCtrl extends PaneCtrl { this.data.current = c; this.apply(); this.redraw(); - return xhr - .text('/pref/bg', { body: xhr.form({ bg: c }), method: 'post' }) - .then(this.reloadAllTheThings, this.announceFail); + return xhrText('/pref/bg', { body: xhrForm({ bg: c }), method: 'post' }).then( + this.reloadAllTheThings, + this.announceFail, + ); }, ); @@ -86,8 +87,7 @@ export class BackgroundCtrl extends PaneCtrl { private getImage = () => this.data.image; private setImage = (i: string) => { this.data.image = i; - xhr - .textRaw('/pref/bgImg', { body: xhr.form({ bgImg: i }), method: 'post' }) + xhrTextRaw('/pref/bgImg', { body: xhrForm({ bgImg: i }), method: 'post' }) .then(res => (res.ok ? res.text() : Promise.reject(res.text()))) .then(this.reloadAllTheThings, err => err.then(this.announceFail)); this.apply(); diff --git a/ui/dasher/src/board.ts b/ui/dasher/src/board.ts index f6e984796ae3c..c2769e192f104 100644 --- a/ui/dasher/src/board.ts +++ b/ui/dasher/src/board.ts @@ -2,9 +2,9 @@ import { header } from './util'; import { hyphenToCamel, toggle } from 'common'; import { debounce } from 'common/timing'; import * as licon from 'common/licon'; -import * as xhr from 'common/xhr'; -import { bind, looseH as h, VNode } from 'common/snabbdom'; -import { DasherCtrl, PaneCtrl } from './interfaces'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; +import { bind, looseH as h, type VNode } from 'common/snabbdom'; +import { type DasherCtrl, PaneCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; type Board = string; @@ -88,9 +88,9 @@ export class BoardCtrl extends PaneCtrl { private setBoard = (t: Board) => { this.apply(t); const field = `theme${this.is3d ? '3d' : ''}`; - xhr - .text(`/pref/${field}`, { body: xhr.form({ [field]: t }), method: 'post' }) - .catch(() => site.announce({ msg: 'Failed to save theme preference' })); + xhrText(`/pref/${field}`, { body: xhrForm({ [field]: t }), method: 'post' }).catch(() => + site.announce({ msg: 'Failed to save theme preference' }), + ); this.redraw(); }; @@ -121,15 +121,15 @@ export class BoardCtrl extends PaneCtrl { const body = new FormData(); body.set(hyphenToCamel(prop), this.getVar(prop).toString()); const path = prop === 'zoom' ? `/pref/zoom?v=${this.getVar(prop)}` : `/pref/${hyphenToCamel(prop)}`; - xhr.text(path, { body, method: 'post' }).catch(() => site.announce({ msg: `Failed to save ${prop}` })); + xhrText(path, { body, method: 'post' }).catch(() => site.announce({ msg: `Failed to save ${prop}` })); }, 1000); private set3d = async (v: boolean) => { if (this.is3d === v) return; this.data.is3d = v; - xhr - .text('/pref/is3d', { body: xhr.form({ is3d: v }), method: 'post' }) - .catch(() => site.announce({ msg: 'Failed to save preference' })); + xhrText('/pref/is3d', { body: xhrForm({ is3d: v }), method: 'post' }).catch(() => + site.announce({ msg: 'Failed to save preference' }), + ); if (v) await site.asset.loadCssPath('common.board-3d'); else site.asset.removeCssPath('common.board-3d'); diff --git a/ui/dasher/src/ctrl.ts b/ui/dasher/src/ctrl.ts index 7a1db8e585a37..86b42ee572aa2 100644 --- a/ui/dasher/src/ctrl.ts +++ b/ui/dasher/src/ctrl.ts @@ -5,9 +5,9 @@ import { BackgroundCtrl } from './background'; import { BoardCtrl } from './board'; import { PieceCtrl } from './piece'; import { LinksCtrl } from './links'; -import { MaybeVNode, Redraw } from 'common/snabbdom'; -import { DasherData, Mode, PaneCtrl } from './interfaces'; -import { Prop, prop } from 'common'; +import type { MaybeVNode, Redraw } from 'common/snabbdom'; +import type { DasherData, Mode, PaneCtrl } from './interfaces'; +import { type Prop, prop } from 'common'; import { pubsub } from 'common/pubsub'; const defaultMode = 'links'; diff --git a/ui/dasher/src/dasher.ts b/ui/dasher/src/dasher.ts index b9174e9d60282..4b24c9b4ad1df 100644 --- a/ui/dasher/src/dasher.ts +++ b/ui/dasher/src/dasher.ts @@ -1,8 +1,8 @@ -import { Redraw } from 'common/snabbdom'; +import type { Redraw } from 'common/snabbdom'; import { DasherCtrl } from './ctrl'; -import * as xhr from 'common/xhr'; +import { json as xhrJson } from 'common/xhr'; import { spinnerVdom, spinnerHtml } from 'common/spinner'; -import { init as initSnabbdom, VNode, classModule, attributesModule, h } from 'snabbdom'; +import { init as initSnabbdom, type VNode, classModule, attributesModule, h } from 'snabbdom'; const patch = initSnabbdom([classModule, attributesModule]); @@ -26,7 +26,7 @@ export default async function initModule(): Promise { redraw(); - const data = await xhr.json('/dasher'); + const data = await xhrJson('/dasher'); ctrl = new DasherCtrl(data, redraw); redraw(); diff --git a/ui/dasher/src/interfaces.ts b/ui/dasher/src/interfaces.ts index 3f4c6c30aafef..d394b536c2aaf 100644 --- a/ui/dasher/src/interfaces.ts +++ b/ui/dasher/src/interfaces.ts @@ -1,9 +1,9 @@ -import { LangsData } from './langs'; -import { BackgroundData } from './background'; -import { BoardData } from './board'; -import { PieceData } from './piece'; -import { DasherCtrl } from './ctrl'; -import { Redraw, VNode } from 'common/snabbdom'; +import type { LangsData } from './langs'; +import type { BackgroundData } from './background'; +import type { BoardData } from './board'; +import type { PieceData } from './piece'; +import type { DasherCtrl } from './ctrl'; +import type { Redraw, VNode } from 'common/snabbdom'; export { DasherCtrl }; diff --git a/ui/dasher/src/langs.ts b/ui/dasher/src/langs.ts index 6a038eda4902d..70f3708c9dc65 100644 --- a/ui/dasher/src/langs.ts +++ b/ui/dasher/src/langs.ts @@ -1,7 +1,7 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { header } from './util'; -import { DasherCtrl, PaneCtrl } from './interfaces'; +import { type DasherCtrl, PaneCtrl } from './interfaces'; type Code = string; type Name = string; diff --git a/ui/dasher/src/links.ts b/ui/dasher/src/links.ts index 1f668e5975bfb..a8f2df34d2470 100644 --- a/ui/dasher/src/links.ts +++ b/ui/dasher/src/links.ts @@ -1,6 +1,6 @@ -import { Attrs, looseH as h, VNode, bind } from 'common/snabbdom'; +import { type Attrs, looseH as h, type VNode, bind } from 'common/snabbdom'; import * as licon from 'common/licon'; -import { Mode, DasherCtrl, PaneCtrl } from './interfaces'; +import { type Mode, type DasherCtrl, PaneCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; export class LinksCtrl extends PaneCtrl { diff --git a/ui/dasher/src/piece.ts b/ui/dasher/src/piece.ts index 2bc4c99fca130..2d49f588d6406 100644 --- a/ui/dasher/src/piece.ts +++ b/ui/dasher/src/piece.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; -import * as xhr from 'common/xhr'; +import { h, type VNode } from 'snabbdom'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; import { header, elementScrollBarWidthSlowGuess } from './util'; import { bind } from 'common/snabbdom'; -import { DasherCtrl, PaneCtrl } from './interfaces'; +import { type DasherCtrl, PaneCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; type Piece = string; @@ -63,9 +63,9 @@ export class PieceCtrl extends PaneCtrl { private set = (t: Piece) => { this.apply(t); const field = `pieceSet${this.is3d ? '3d' : ''}`; - xhr - .text(`/pref/${field}`, { body: xhr.form({ [field]: t }), method: 'post' }) - .catch(() => site.announce({ msg: 'Failed to save piece set preference' })); + xhrText(`/pref/${field}`, { body: xhrForm({ [field]: t }), method: 'post' }).catch(() => + site.announce({ msg: 'Failed to save piece set preference' }), + ); this.redraw(); }; } diff --git a/ui/dasher/src/ping.ts b/ui/dasher/src/ping.ts index 3ac97fe1ca05f..08ebddfb9af62 100644 --- a/ui/dasher/src/ping.ts +++ b/ui/dasher/src/ping.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { defined } from 'common'; -import { DasherCtrl } from './interfaces'; +import type { DasherCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; export class PingCtrl { diff --git a/ui/dasher/src/sound.ts b/ui/dasher/src/sound.ts index d03ebd346ff60..1d96766147c21 100644 --- a/ui/dasher/src/sound.ts +++ b/ui/dasher/src/sound.ts @@ -1,10 +1,10 @@ import * as licon from 'common/licon'; -import * as xhr from 'common/xhr'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; import { throttle, throttlePromiseDelay } from 'common/timing'; -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { header } from './util'; import { bind } from 'common/snabbdom'; -import { DasherCtrl, PaneCtrl } from './interfaces'; +import { type DasherCtrl, PaneCtrl } from './interfaces'; import { pubsub } from 'common/pubsub'; type Key = string; @@ -77,9 +77,9 @@ export class SoundCtrl extends PaneCtrl { private postSet = throttlePromiseDelay( () => 1000, (soundSet: string) => - xhr - .text('/pref/soundSet', { body: xhr.form({ soundSet }), method: 'post' }) - .catch(() => site.announce({ msg: 'Failed to save sound preference' })), + xhrText('/pref/soundSet', { body: xhrForm({ soundSet }), method: 'post' }).catch(() => + site.announce({ msg: 'Failed to save sound preference' }), + ), ); private makeList = () => { diff --git a/ui/dasher/src/util.ts b/ui/dasher/src/util.ts index 4ad5f83cdfa69..bbfa0d48b31da 100644 --- a/ui/dasher/src/util.ts +++ b/ui/dasher/src/util.ts @@ -1,5 +1,5 @@ import * as licon from 'common/licon'; -import { bind, looseH as h, VNode } from 'common/snabbdom'; +import { bind, looseH as h, type VNode } from 'common/snabbdom'; import { memoize } from 'common'; export const header = (name: string, close: () => void): VNode => diff --git a/ui/dgt/package.json b/ui/dgt/package.json index 7e218b0274bcb..77c278ac8967c 100644 --- a/ui/dgt/package.json +++ b/ui/dgt/package.json @@ -5,9 +5,6 @@ "description": "lichess.org dgt", "author": "Thibault Duplessis", "license": "AGPL-3.0-or-later", - "dependencies": { - "chessops": "^0.14.2" - }, "lichess": { "bundles": "src/dgt.ts" } diff --git a/ui/dgt/src/play.ts b/ui/dgt/src/play.ts index 3969d90408105..f46c49d33b02b 100644 --- a/ui/dgt/src/play.ts +++ b/ui/dgt/src/play.ts @@ -1,7 +1,7 @@ import { Chess, normalizeMove, castlingSide } from 'chessops/chess'; import { INITIAL_FEN, makeFen, parseFen } from 'chessops/fen'; import { makeSan, parseSan } from 'chessops/san'; -import { NormalMove } from 'chessops/types'; +import type { NormalMove } from 'chessops/types'; import { board } from 'chessops/debug'; import { defaultSetup, fen, makeUci, parseUci } from 'chessops'; diff --git a/ui/editor/package.json b/ui/editor/package.json index d775c708e07be..e48b2f6f7730d 100644 --- a/ui/editor/package.json +++ b/ui/editor/package.json @@ -13,7 +13,6 @@ "license": "AGPL-3.0-or-later", "types": "dist/editor.d.ts", "dependencies": { - "chessops": "^0.14.2", "common": "workspace:*" }, "lichess": { diff --git a/ui/editor/src/chessground.ts b/ui/editor/src/chessground.ts index 37e56d31f6d51..6801d8360998a 100644 --- a/ui/editor/src/chessground.ts +++ b/ui/editor/src/chessground.ts @@ -1,8 +1,7 @@ -import { h, VNode } from 'snabbdom'; -import { Config as CgConfig } from 'chessground/config'; -import { MouchEvent } from 'chessground/types'; -import * as util from 'chessground/util'; -import EditorCtrl from './ctrl'; +import { h, type VNode } from 'snabbdom'; +import type { MouchEvent } from 'chessground/types'; +import { eventPosition, opposite } from 'chessground/util'; +import type EditorCtrl from './ctrl'; import { storage } from 'common/storage'; import { Chessground as makeChessground } from 'chessground'; import { pubsub } from 'common/pubsub'; @@ -64,7 +63,7 @@ function onMouseEvent(ctrl: EditorCtrl): (e: MouchEvent) => void { ctrl.chessground.state.draggable.current.newPiece) ) return; - const pos = util.eventPosition(e); + const pos = eventPosition(e); if (!pos) return; const key = ctrl.chessground!.getKeyAtDomPos(pos); if (!key) return; @@ -98,7 +97,7 @@ function onMouseEvent(ctrl: EditorCtrl): (e: MouchEvent) => void { if (e.type === 'contextmenu' && sel != 'trash') { ctrl.chessground!.cancelMove(); - sel[0] = util.opposite(sel[0]); + sel[0] = opposite(sel[0]); ctrl.redraw(); } } diff --git a/ui/editor/src/ctrl.ts b/ui/editor/src/ctrl.ts index 85a3dbf7ffe46..859add7593f00 100644 --- a/ui/editor/src/ctrl.ts +++ b/ui/editor/src/ctrl.ts @@ -1,22 +1,22 @@ import { - EditorState, - Selected, - Redraw, - Options, - Config, - CastlingToggle, - CastlingToggles, + type EditorState, + type Selected, + type Redraw, + type Options, + type Config, + type CastlingToggle, + type CastlingToggles, CASTLING_TOGGLES, } from './interfaces'; -import { Api as CgApi } from 'chessground/api'; -import { Rules, Square } from 'chessops/types'; -import { SquareSet } from 'chessops/squareSet'; +import type { Api as CgApi } from 'chessground/api'; +import type { Rules, Square } from 'chessops/types'; +import type { SquareSet } from 'chessops/squareSet'; import { Board } from 'chessops/board'; -import { Setup, Material, RemainingChecks, defaultSetup } from 'chessops/setup'; +import { type Setup, Material, RemainingChecks, defaultSetup } from 'chessops/setup'; import { Castles, defaultPosition, setupPosition } from 'chessops/variant'; import { makeFen, parseFen, parseCastlingFen, INITIAL_FEN, EMPTY_FEN } from 'chessops/fen'; import { lichessVariant, lichessRules } from 'chessops/compat'; -import { defined, prop, Prop } from 'common'; +import { defined, prop, type Prop } from 'common'; import { prompt } from 'common/dialog'; export default class EditorCtrl { diff --git a/ui/editor/src/editor.ts b/ui/editor/src/editor.ts index 977a148357490..4c3978f614997 100644 --- a/ui/editor/src/editor.ts +++ b/ui/editor/src/editor.ts @@ -1,5 +1,5 @@ import EditorCtrl from './ctrl'; -import { LichessEditor, Config } from './interfaces'; +import type { LichessEditor, Config } from './interfaces'; import menuHover from 'common/menuHover'; import view from './view'; import { init, attributesModule, eventListenersModule, classModule, propsModule } from 'snabbdom'; diff --git a/ui/editor/src/interfaces.ts b/ui/editor/src/interfaces.ts index 0be4f4edb6dd4..f723cb5068537 100644 --- a/ui/editor/src/interfaces.ts +++ b/ui/editor/src/interfaces.ts @@ -1,5 +1,3 @@ -import { Role } from 'chessground/types'; - export type CastlingToggle = 'K' | 'Q' | 'k' | 'q'; export const CASTLING_TOGGLES: CastlingToggle[] = ['K', 'Q', 'k', 'q']; @@ -20,7 +18,7 @@ export type Redraw = () => void; export type Selected = 'pointer' | 'trash' | [Color, Role]; export interface LichessEditor { - getFen(): Cg.FEN; + getFen(): FEN; setOrientation(o: Color): void; } diff --git a/ui/editor/src/view.ts b/ui/editor/src/view.ts index e833537cf7f50..277f32de0e874 100644 --- a/ui/editor/src/view.ts +++ b/ui/editor/src/view.ts @@ -1,15 +1,15 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { copyMeInput } from 'common/copyMe'; -import { MouchEvent, NumberPair } from 'chessground/types'; +import type { MouchEvent, NumberPair } from 'chessground/types'; import { dragNewPiece } from 'chessground/drag'; import { eventPosition, opposite } from 'chessground/util'; -import { Rules } from 'chessops/types'; +import type { Rules } from 'chessops/types'; import { parseFen } from 'chessops/fen'; import { parseSquare, makeSquare } from 'chessops/util'; -import EditorCtrl from './ctrl'; +import type EditorCtrl from './ctrl'; import chessground from './chessground'; -import { Selected, CastlingToggle, EditorState, EndgamePosition, OpeningPosition } from './interfaces'; +import type { Selected, CastlingToggle, EditorState, EndgamePosition, OpeningPosition } from './interfaces'; import { dataIcon } from 'common/snabbdom'; import { domDialog } from 'common/dialog'; diff --git a/ui/game/src/game.ts b/ui/game/src/game.ts index 4527deed48edf..5e989fabfc534 100644 --- a/ui/game/src/game.ts +++ b/ui/game/src/game.ts @@ -1,10 +1,9 @@ -import { GameData, Player } from './interfaces'; -import * as status from './status'; +import type { GameData, Player } from './interfaces'; +import { finished, aborted, ids } from './status'; export * from './interfaces'; -export const playable = (data: GameData): boolean => - data.game.status.id < status.ids.aborted && !imported(data); +export const playable = (data: GameData): boolean => data.game.status.id < ids.aborted && !imported(data); export const isPlayerPlaying = (data: GameData): boolean => playable(data) && !data.player.spectator; @@ -50,7 +49,7 @@ export const moretimeable = (data: GameData): boolean => const imported = (data: GameData): boolean => data.game.source === 'import'; export const replayable = (data: GameData): boolean => - imported(data) || status.finished(data) || (status.aborted(data) && bothPlayersHavePlayed(data)); + imported(data) || finished(data) || (aborted(data) && bothPlayersHavePlayed(data)); export function getPlayer(data: GameData, color: Color): Player; export function getPlayer(data: GameData, color?: Color): Player | null { @@ -62,7 +61,7 @@ export function getPlayer(data: GameData, color?: Color): Player | null { export const hasAi = (data: GameData): boolean => !!(data.player.ai || data.opponent.ai); export const userAnalysable = (data: GameData): boolean => - status.finished(data) || (playable(data) && (!data.clock || !isPlayerPlaying(data))); + finished(data) || (playable(data) && (!data.clock || !isPlayerPlaying(data))); export const isCorrespondence = (data: GameData): boolean => data.game.speed === 'correspondence'; diff --git a/ui/game/src/interfaces.ts b/ui/game/src/interfaces.ts index 8b7310f50aeaf..8f646a57ba048 100644 --- a/ui/game/src/interfaces.ts +++ b/ui/game/src/interfaces.ts @@ -1,5 +1,3 @@ -import * as cg from 'chessground/types'; - export interface GameData { game: Game; player: Player; @@ -18,7 +16,7 @@ export interface Game { status: Status; player: Color; turns: number; - fen: cg.FEN; + fen: FEN; startedAtTurn?: number; source: Source; speed: Speed; @@ -193,7 +191,7 @@ export interface CheckCount { } export type MaterialDiffSide = { - [role in cg.Role]: number; + [role in Role]: number; }; export interface MaterialDiff { diff --git a/ui/game/src/material.ts b/ui/game/src/material.ts index 1f77f00b3bff9..d0e046f869ab9 100644 --- a/ui/game/src/material.ts +++ b/ui/game/src/material.ts @@ -1,8 +1,7 @@ -import * as cg from 'chessground/types'; import { opposite } from 'chessground/util'; -import { CheckCount, CheckState, MaterialDiff } from './interfaces'; +import type { CheckCount, CheckState, MaterialDiff } from './interfaces'; -const ROLES: { [key: string]: cg.Role | undefined } = { +const ROLES: { [key: string]: Role | undefined } = { p: 'pawn', n: 'knight', b: 'bishop', diff --git a/ui/game/src/router.ts b/ui/game/src/router.ts index 668fd257c58d7..0ebd4264dffb6 100644 --- a/ui/game/src/router.ts +++ b/ui/game/src/router.ts @@ -1,4 +1,4 @@ -import { GameData, ContinueMode } from './interfaces'; +import type { GameData, ContinueMode } from './interfaces'; export function game(data: GameData, color?: Color, embed?: boolean): string; export function game(data: string, color?: Color, embed?: boolean): string; diff --git a/ui/game/src/status.ts b/ui/game/src/status.ts index 85643cc441cd0..7ea74db4cefd7 100644 --- a/ui/game/src/status.ts +++ b/ui/game/src/status.ts @@ -1,4 +1,4 @@ -import { GameData, StatusName, Status } from './interfaces'; +import type { GameData, StatusName, Status } from './interfaces'; // https://github.com/lichess-org/scalachess/blob/master/core/src/main/scala/Status.scala diff --git a/ui/game/src/view/material.ts b/ui/game/src/view/material.ts index d9d8f781e4dcb..b45bec32d8ea9 100644 --- a/ui/game/src/view/material.ts +++ b/ui/game/src/view/material.ts @@ -1,6 +1,5 @@ -import * as cg from 'chessground/types'; -import { h, VNode } from 'snabbdom'; -import { CheckCount, CheckState, MaterialDiffSide } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { CheckCount, CheckState, MaterialDiffSide } from '../interfaces'; import { countChecks, getMaterialDiff, getScore, NO_CHECKS } from '../material'; import { opposite } from 'chessground/util'; @@ -11,7 +10,7 @@ function renderMaterialDiff( checks?: number, ): VNode { const children: VNode[] = []; - let role: cg.Role; + let role: Role; for (role in material) { if (material[role] > 0) { const content: VNode[] = []; @@ -27,7 +26,7 @@ function renderMaterialDiff( export function renderMaterialDiffs( showCaptured: boolean, bottomColor: Color, - fen: cg.FEN, + fen: FEN, showChecks: boolean, checkStates: CheckState[], ply: Ply, diff --git a/ui/game/src/view/status.ts b/ui/game/src/view/status.ts index e4a6403a5214e..7ce705e9ec94e 100644 --- a/ui/game/src/view/status.ts +++ b/ui/game/src/view/status.ts @@ -1,5 +1,4 @@ -import { FEN } from 'chessground/types'; -import { Ctrl } from '../interfaces'; +import type { Ctrl } from '../interfaces'; export function bishopOnColor(expandedFen: string, offset: 0 | 1): boolean { if (expandedFen.length !== 64) throw new Error('Expanded FEN expected to be 64 characters'); diff --git a/ui/insight/src/axis.ts b/ui/insight/src/axis.ts index 617a1b57b0b9c..9e9ae214a71de 100644 --- a/ui/insight/src/axis.ts +++ b/ui/insight/src/axis.ts @@ -1,7 +1,7 @@ -import Ctrl from './ctrl'; -import { MaybeVNode } from 'common/snabbdom'; -import { h, VNodeData } from 'snabbdom'; -import { Categ, Dimension, Metric } from './interfaces'; +import type Ctrl from './ctrl'; +import type { MaybeVNode } from 'common/snabbdom'; +import { h, type VNodeData } from 'snabbdom'; +import type { Categ, Dimension, Metric } from './interfaces'; const selectData = (onClick: (v: { value: string }) => void, getValue: () => string): VNodeData => ({ hook: { diff --git a/ui/insight/src/boards.ts b/ui/insight/src/boards.ts index 3e34359216f49..b8232aa6699e4 100644 --- a/ui/insight/src/boards.ts +++ b/ui/insight/src/boards.ts @@ -1,6 +1,6 @@ -import Ctrl from './ctrl'; +import type Ctrl from './ctrl'; import { h } from 'snabbdom'; -import { Game } from './interfaces'; +import type { Game } from './interfaces'; import { initMiniBoard } from 'common/miniBoard'; const miniGame = (game: Game) => diff --git a/ui/insight/src/chart.ts b/ui/insight/src/chart.ts index b859b9a5cd657..c297e27c2cbd8 100644 --- a/ui/insight/src/chart.ts +++ b/ui/insight/src/chart.ts @@ -1,18 +1,18 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import Ctrl from './ctrl'; -import { InsightChart, InsightData } from './interfaces'; +import type Ctrl from './ctrl'; +import type { InsightChart, InsightData } from './interfaces'; import { Chart, - ChartDataset, - ChartConfiguration, + type ChartDataset, + type ChartConfiguration, BarController, BarElement, CategoryScale, Legend, LinearScale, Tooltip, - ChartOptions, + type ChartOptions, } from 'chart.js'; import { currentTheme } from 'common/theme'; import { gridColor, tooltipBgColor, fontFamily, maybeChart, resizePolyfill, colorSeries } from 'chart'; diff --git a/ui/insight/src/ctrl.ts b/ui/insight/src/ctrl.ts index d84f4ba7b7eaf..e84724656cb5e 100644 --- a/ui/insight/src/ctrl.ts +++ b/ui/insight/src/ctrl.ts @@ -1,6 +1,6 @@ import { throttlePromiseDelay } from 'common/timing'; -import * as xhr from 'common/xhr'; -import { +import { json as xhrJson } from 'common/xhr'; +import type { InsightData, Dimension, Env, @@ -88,16 +88,15 @@ export default class { return new Promise(resolve => { setTimeout( () => - xhr - .json(this.env.postUrl, { - method: 'post', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - metric: this.vm.metric.key, - dimension: this.vm.dimension.key, - filters: this.vm.filters, - }), - }) + xhrJson(this.env.postUrl, { + method: 'post', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + metric: this.vm.metric.key, + dimension: this.vm.dimension.key, + filters: this.vm.filters, + }), + }) .then( (answer: InsightData) => { this.vm.answer = answer; diff --git a/ui/insight/src/filters.ts b/ui/insight/src/filters.ts index 7f8f33930fdca..9c1009d403b76 100644 --- a/ui/insight/src/filters.ts +++ b/ui/insight/src/filters.ts @@ -1,6 +1,6 @@ import { h } from 'snabbdom'; -import Ctrl from './ctrl'; -import { Dimension } from './interfaces'; +import type Ctrl from './ctrl'; +import type { Dimension } from './interfaces'; const select = (ctrl: Ctrl) => (dimension: Dimension) => { if (dimension.key === 'date') return; diff --git a/ui/insight/src/help.ts b/ui/insight/src/help.ts index 091fa295024ce..f7bcd07340921 100644 --- a/ui/insight/src/help.ts +++ b/ui/insight/src/help.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import Ctrl from './ctrl'; +import type Ctrl from './ctrl'; export default function (ctrl: Ctrl) { return h('div.help.box', [ diff --git a/ui/insight/src/info.ts b/ui/insight/src/info.ts index 445e14704a30c..36b5ad9a787d0 100644 --- a/ui/insight/src/info.ts +++ b/ui/insight/src/info.ts @@ -3,7 +3,7 @@ import { onInsert } from 'common/snabbdom'; import { numberFormat } from 'common/number'; import { userLink } from 'common/userLink'; import { h } from 'snabbdom'; -import Ctrl from './ctrl'; +import type Ctrl from './ctrl'; import { registerFormHandler } from './insight'; import { spinnerHtml } from 'common/spinner'; diff --git a/ui/insight/src/insight.ts b/ui/insight/src/insight.ts index 148765c2cae8c..ed69d1903e543 100644 --- a/ui/insight/src/insight.ts +++ b/ui/insight/src/insight.ts @@ -1,7 +1,7 @@ import { attributesModule, classModule, init } from 'snabbdom'; import Ctrl from './ctrl'; -import { Env } from './interfaces'; +import type { Env } from './interfaces'; import { view } from './view'; import { registerMultipleSelect } from './multipleSelect'; diff --git a/ui/insight/src/interfaces.ts b/ui/insight/src/interfaces.ts index 7913e8364d126..c63b88efbd703 100644 --- a/ui/insight/src/interfaces.ts +++ b/ui/insight/src/interfaces.ts @@ -1,4 +1,4 @@ -import { Chart } from 'chart.js'; +import type { Chart } from 'chart.js'; export interface Vm { metric: Metric; diff --git a/ui/insight/src/presets.ts b/ui/insight/src/presets.ts index dfeafa8f940b7..ba210cc58127a 100644 --- a/ui/insight/src/presets.ts +++ b/ui/insight/src/presets.ts @@ -1,8 +1,8 @@ import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; import { h } from 'snabbdom'; -import Ctrl from './ctrl'; -import { Preset } from './interfaces'; +import type Ctrl from './ctrl'; +import type { Preset } from './interfaces'; export default function (ctrl: Ctrl) { return h( diff --git a/ui/insight/src/table.ts b/ui/insight/src/table.ts index 6ef068a615811..c980530194740 100644 --- a/ui/insight/src/table.ts +++ b/ui/insight/src/table.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import Ctrl from './ctrl'; +import type Ctrl from './ctrl'; export function formatNumber(dt: string, n: number) { const percent = dt == 'percent'; diff --git a/ui/insight/src/view.ts b/ui/insight/src/view.ts index 1e3f87ccd33c7..296a13dbe9b1e 100644 --- a/ui/insight/src/view.ts +++ b/ui/insight/src/view.ts @@ -9,8 +9,8 @@ import { vert } from './table'; import help from './help'; import info from './info'; import boards from './boards'; -import Ctrl from './ctrl'; -import { ViewTab } from './interfaces'; +import type Ctrl from './ctrl'; +import type { ViewTab } from './interfaces'; import { bind, looseH as h } from 'common/snabbdom'; let forceRender = false; diff --git a/ui/keyboardMove/src/ctrl.ts b/ui/keyboardMove/src/ctrl.ts index 01811a0715a90..95ce7530ca0b4 100644 --- a/ui/keyboardMove/src/ctrl.ts +++ b/ui/keyboardMove/src/ctrl.ts @@ -1,29 +1,28 @@ -import * as cg from 'chessground/types'; -import { SanToUci } from 'chess'; -import { h, VNode } from 'snabbdom'; +import type { SanToUci } from 'chess'; +import { h, type VNode } from 'snabbdom'; import { onInsert } from 'common/snabbdom'; import { promote } from 'chess/promotion'; -import { propWithEffect, Prop } from 'common'; +import { propWithEffect, type Prop } from 'common'; import { snabDialog } from 'common/dialog'; -import { MoveRootCtrl, MoveUpdate } from 'chess/moveRootCtrl'; +import type { MoveRootCtrl, MoveUpdate } from 'chess/moveRootCtrl'; import { load as loadKeyboardMove } from './keyboardMove'; import KeyboardChecker from './keyboardChecker'; -export type KeyboardMoveHandler = (fen: cg.FEN, dests?: cg.Dests, yourMove?: boolean) => void; +export type KeyboardMoveHandler = (fen: FEN, dests?: Dests, yourMove?: boolean) => void; export const arrowKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'] as const; export type ArrowKey = (typeof arrowKeys)[number]; export const isArrowKey = (v: string): v is ArrowKey => arrowKeys.includes(v as ArrowKey); export interface KeyboardMove { - drop(key: cg.Key, piece: string): void; - promote(orig: cg.Key, dest: cg.Key, piece: string): void; + drop(key: Key, piece: string): void; + promote(orig: Key, dest: Key, piece: string): void; update(up: MoveUpdate): void; registerHandler(h: KeyboardMoveHandler): void; isFocused: Prop; - san(orig: cg.Key, dest: cg.Key): void; - select(key: cg.Key): void; - hasSelected(): cg.Key | undefined; + san(orig: Key, dest: Key): void; + select(key: Key): void; + hasSelected(): Key | undefined; confirmMove(): void; usedSan: boolean; legalSans: SanToUci | null; @@ -40,7 +39,7 @@ export interface KeyboardMove { goBerserk?: () => void; } -const sanToRole: { [key: string]: cg.Role } = { +const sanToRole: { [key: string]: Role } = { P: 'pawn', N: 'knight', B: 'bishop', @@ -60,11 +59,11 @@ export interface RootData { } export interface KeyboardMoveRootCtrl extends MoveRootCtrl { - sendNewPiece?: (role: cg.Role, key: cg.Key, isPredrop: boolean) => void; + sendNewPiece?: (role: Role, key: Key, isPredrop: boolean) => void; userJumpPlyDelta?: (plyDelta: Ply) => void; handleArrowKey?: (arrowKey: ArrowKey) => void; submitMove?: (v: boolean) => void; - crazyValid?: (role: cg.Role, key: cg.Key) => boolean; + crazyValid?: (role: Role, key: Key) => boolean; getCrazyhousePockets?: () => [CrazyPocket, CrazyPocket] | undefined; data: RootData; } @@ -76,7 +75,7 @@ export function ctrl(root: KeyboardMoveRootCtrl): KeyboardMove { let preHandlerBuffer: string | undefined; let lastSelect = performance.now(); let cg: CgApi; - const select = (key: cg.Key): void => { + const select = (key: Key): void => { if (cg.state.selected === key) cg.cancelMove(); else { cg.selectSquare(key, true); diff --git a/ui/keyboardMove/src/keyboardMove.ts b/ui/keyboardMove/src/keyboardMove.ts index 030078d42d8ad..1018a611b928d 100644 --- a/ui/keyboardMove/src/keyboardMove.ts +++ b/ui/keyboardMove/src/keyboardMove.ts @@ -1,7 +1,6 @@ -import { Dests } from 'chessground/types'; import { sanWriter, destsToUcis } from 'chess'; -import { KeyboardMoveHandler, KeyboardMove, isArrowKey } from './ctrl'; -import { Submit, makeSubmit } from './keyboardSubmit'; +import { type KeyboardMoveHandler, type KeyboardMove, isArrowKey } from './ctrl'; +import { type Submit, makeSubmit } from './keyboardSubmit'; export interface Opts { input: HTMLInputElement; diff --git a/ui/keyboardMove/tests/keyboardSubmit.test.ts b/ui/keyboardMove/tests/keyboardSubmit.test.ts index 16de93bf5a79d..4c21bdab42597 100644 --- a/ui/keyboardMove/tests/keyboardSubmit.test.ts +++ b/ui/keyboardMove/tests/keyboardSubmit.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test, vi } from 'vitest'; -import { Prop, propWithEffect } from 'common'; +import { type Prop, propWithEffect } from 'common'; import { makeSubmit } from '../src/keyboardSubmit'; -import { Dests, destsToUcis, sanWriter } from 'chess'; +import { destsToUcis, sanWriter } from 'chess'; // Tips for working with this file: // - tests will often require a FEN position and a map of legal moves, e.g.: diff --git a/ui/learn/package.json b/ui/learn/package.json index 3db591ba031bd..171526f263576 100644 --- a/ui/learn/package.json +++ b/ui/learn/package.json @@ -11,8 +11,7 @@ "author": "ornicar", "license": "AGPL-3.0-or-later", "dependencies": { - "common": "workspace:*", - "chessops": "^0.14.2" + "common": "workspace:*" }, "lichess": { "bundles": "src/learn.ts" diff --git a/ui/learn/src/apple.ts b/ui/learn/src/apple.ts index 4cda9da9cdc5f..cad93274f5300 100644 --- a/ui/learn/src/apple.ts +++ b/ui/learn/src/apple.ts @@ -1,4 +1,4 @@ -import { DrawShape } from 'chessground/draw'; +import type { DrawShape } from 'chessground/draw'; // Safari specifically requires globally unique IDs for SVG elements, even between different SVGs, // so we concatenate a unique key to every ID for each SVG. diff --git a/ui/learn/src/assert.ts b/ui/learn/src/assert.ts index be7c84fcf2559..c83410c6dfd7f 100644 --- a/ui/learn/src/assert.ts +++ b/ui/learn/src/assert.ts @@ -1,5 +1,5 @@ -import { charToRole, SquareName as Key, Piece } from 'chessops'; -import { AssertData } from './levelCtrl'; +import { charToRole, type SquareName } from 'chessops'; +import type { AssertData } from './levelCtrl'; import { readKeys } from './util'; type Assert = (level: AssertData) => boolean; @@ -10,7 +10,7 @@ const pieceMatch = (piece: Piece | undefined, matcher: Piece): boolean => piece?.role === matcher.role && piece.color === matcher.color; const pieceOnAnyOf = - (matcher: Piece, keys: Key[]): Assert => + (matcher: Piece, keys: SquareName[]): Assert => (level: AssertData) => keys.some(key => pieceMatch(level.chess.get(key), matcher)); @@ -20,21 +20,21 @@ const fenToMatcher = (fenPiece: FenPiece): Piece => ({ }); export const pieceOn = - (fenPiece: FenPiece, key: Key): Assert => + (fenPiece: FenPiece, key: SquareName): Assert => (level: AssertData) => pieceMatch(level.chess.get(key), fenToMatcher(fenPiece)); export const pieceNotOn = - (fenPiece: FenPiece, key: Key): Assert => + (fenPiece: FenPiece, key: SquareName): Assert => (level: AssertData) => !pieceMatch(level.chess.get(key), fenToMatcher(fenPiece)); -export const noPieceOn = (keys: string | Key[]): Assert => { +export const noPieceOn = (keys: string | SquareName[]): Assert => { const keyArr = readKeys(keys); return (level: AssertData) => level.chess.occupiedKeys().some(sq => !keyArr.includes(sq)); }; -export const whitePawnOnAnyOf = (keys: string | Key[]): Assert => +export const whitePawnOnAnyOf = (keys: string | SquareName[]): Assert => pieceOnAnyOf(fenToMatcher('P'), readKeys(keys)); export const extinct = diff --git a/ui/learn/src/chess.ts b/ui/learn/src/chess.ts index bd4462dcad830..2a0b17f09d18d 100644 --- a/ui/learn/src/chess.ts +++ b/ui/learn/src/chess.ts @@ -1,42 +1,33 @@ -import * as cg from 'chessground/types'; import { parseFen, makeBoardFen } from 'chessops/fen'; -import { - parseSquare, - makeSquare, - Piece, - Chess, - NormalMove as Move, - SquareName as Key, - charToRole, -} from 'chessops'; -import { Antichess, Context } from 'chessops/variant'; +import { parseSquare, makeSquare, Chess, type NormalMove, type SquareName, charToRole } from 'chessops'; +import { Antichess, type Context } from 'chessops/variant'; import { chessgroundDests } from 'chessops/compat'; -import { CgMove } from './chessground'; +import type { CgMove } from './chessground'; import { makeSan } from 'chessops/san'; -import { isRole, oppColor, PromotionChar, PromotionRole } from './util'; +import { isRole, oppColor, type PromotionChar, type PromotionRole } from './util'; type LearnVariant = Chess | Antichess; export interface ChessCtrl { - dests(pos: LearnVariant, opts?: { illegal?: boolean }): cg.Dests; + dests(pos: LearnVariant, opts?: { illegal?: boolean }): Dests; setColor(c: Color): void; getColor(): Color; fen(): string; - move(orig: Key, dest: Key, prom?: PromotionRole | PromotionChar | ''): Move | null; - moves(pos: LearnVariant): Move[]; - occupiedKeys(): Key[]; - kingKey(color: Color): Key | undefined; + move(orig: SquareName, dest: SquareName, prom?: PromotionRole | PromotionChar | ''): NormalMove | null; + moves(pos: LearnVariant): NormalMove[]; + occupiedKeys(): SquareName[]; + kingKey(color: Color): SquareName | undefined; findCapture(): CgMove | undefined; findUnprotectedCapture(): CgMove | undefined; checks(): CgMove[] | undefined; playRandomMove(): CgMove | undefined; - get(square: Key): Piece | undefined; + get(square: SquareName): Piece | undefined; instance: LearnVariant; sanHistory(): string[]; defaultChessMate(): boolean; } -export default function (fen: string, appleKeys: Key[]): ChessCtrl { +export default function (fen: string, appleKeys: SquareName[]): ChessCtrl { const setup = parseFen(fen).unwrap(); const chess = Chess.fromSetup(setup); // Use antichess when there are less than 2 kings @@ -96,20 +87,23 @@ export default function (fen: string, appleKeys: Key[]): ChessCtrl { const history: string[] = []; - const moves = (pos: LearnVariant): Move[] => - Array.from(dests(pos)).reduce( + const moves = (pos: LearnVariant): NormalMove[] => + Array.from(dests(pos)).reduce( (prev, [orig, dests]) => - prev.concat(dests.map((dest): Move => ({ from: parseSquare(orig), to: parseSquare(dest) }))), + prev.concat(dests.map((dest): NormalMove => ({ from: parseSquare(orig), to: parseSquare(dest) }))), [], ); - const findCaptures = (pos: LearnVariant): Move[] => moves(pos).filter(move => pos.board.get(move.to)); + const findCaptures = (pos: LearnVariant): NormalMove[] => moves(pos).filter(move => pos.board.get(move.to)); const setColor = (c: Color): void => { pos.turn = c; }; - const moveToCgMove = (move: Move): CgMove => ({ orig: makeSquare(move.from), dest: makeSquare(move.to) }); + const moveToCgMove = (move: NormalMove): CgMove => ({ + orig: makeSquare(move.from), + dest: makeSquare(move.to), + }); const kingKey = (color: Color) => { const kingSq = pos.board.kingOf(color); @@ -127,8 +121,8 @@ export default function (fen: string, appleKeys: Key[]): ChessCtrl { setColor: setColor, fen: () => makeBoardFen(pos.board), moves: moves, - move: (orig: Key, dest: Key, prom?: PromotionChar | PromotionRole | '') => { - const move: Move = { + move: (orig: SquareName, dest: SquareName, prom?: PromotionChar | PromotionRole | '') => { + const move: NormalMove = { from: parseSquare(orig), to: parseSquare(dest), promotion: prom ? (isRole(prom) ? prom : charToRole(prom)) : undefined, @@ -173,7 +167,7 @@ export default function (fen: string, appleKeys: Key[]): ChessCtrl { } return undefined; }, - get: (key: Key) => pos.board.get(parseSquare(key)), + get: (key: SquareName) => pos.board.get(parseSquare(key)), instance: pos, sanHistory: () => history, defaultChessMate: (): boolean => cloneWithChessDests(pos).isCheckmate(), diff --git a/ui/learn/src/chessground.ts b/ui/learn/src/chessground.ts index 4322fdad709d1..ae5353731c81c 100644 --- a/ui/learn/src/chessground.ts +++ b/ui/learn/src/chessground.ts @@ -1,7 +1,6 @@ -import { Config as CgConfig } from 'chessground/config'; -import { h, VNode } from 'snabbdom'; -import { RunCtrl } from './run/runCtrl'; -import * as Prefs from 'common/prefs'; +import { h, type VNode } from 'snabbdom'; +import type { RunCtrl } from './run/runCtrl'; +import { Coords } from 'common/prefs'; import { Chessground as makeChessground } from 'chessground'; export interface Shape { @@ -32,7 +31,7 @@ const makeConfig = (ctrl: RunCtrl): CgConfig => ({ fen: '8/8/8/8/8/8/8/8', blockTouchScroll: true, coordinates: true, - coordinatesOnSquares: ctrl.pref.coords === Prefs.Coords.All, + coordinatesOnSquares: ctrl.pref.coords === Coords.All, movable: { free: false, color: undefined, showDests: ctrl.pref.destination }, drawable: { enabled: false }, draggable: { enabled: true }, diff --git a/ui/learn/src/ctrl.ts b/ui/learn/src/ctrl.ts index f2f9f9a7e5746..ab1eb7428cd71 100644 --- a/ui/learn/src/ctrl.ts +++ b/ui/learn/src/ctrl.ts @@ -1,7 +1,6 @@ -import { LearnProgress, LearnOpts } from './learn'; -import { Stage } from './stage/list'; -import * as stages from './stage/list'; -import * as scoring from './score'; +import type { LearnProgress, LearnOpts } from './learn'; +import { type Stage, byId as stageById } from './stage/list'; +import { gtz } from './score'; import { SideCtrl } from './sideCtrl'; import { clearTimeouts } from './timeouts'; import { extractHashParameters } from './hashRouting'; @@ -41,7 +40,7 @@ export class LearnCtrl { // otherwise find a level id based on the last completed level (() => { if (!stageId) return; - const stage = stages.byId[stageId]; + const stage = stageById[stageId]; if (!stage) return; const result = this.data.stages[stage.key]; let it = 0; @@ -58,16 +57,16 @@ export class LearnCtrl { inStage = () => this.opts.stageId !== null; isStageIdComplete = (stageId: number) => { - const stage = stages.byId[stageId]; + const stage = stageById[stageId]; if (!stage) return true; const result = this.data.stages[stage.key]; if (!result) return false; - return result.scores.filter(scoring.gtz).length >= stage.levels.length; + return result.scores.filter(gtz).length >= stage.levels.length; }; stageProgress = (stage: Stage) => { const result = this.data.stages[stage.key]; - const complete = result ? result.scores.filter(scoring.gtz).length : 0; + const complete = result ? result.scores.filter(gtz).length : 0; return [complete, stage.levels.length]; }; } diff --git a/ui/learn/src/item.ts b/ui/learn/src/item.ts index d221b83ce9a91..c01e702a3b5bc 100644 --- a/ui/learn/src/item.ts +++ b/ui/learn/src/item.ts @@ -1,19 +1,19 @@ -import type { SquareName as Key } from 'chessops'; -import * as util from './util'; +import type { SquareName } from 'chessops'; +import { readKeys } from './util'; export interface Items { - doIfKeyExists(key: Key, f: () => U): U | undefined; - remove(key: Key): void; + doIfKeyExists(key: SquareName, f: () => U): U | undefined; + remove(key: SquareName): void; isEmpty(): boolean; - appleKeys(): Key[]; + appleKeys(): SquareName[]; } -export function ctrl(blueprint: { apples: string | Key[] }): Items { - const items: Set = new Set(util.readKeys(blueprint.apples)); +export function ctrl(blueprint: { apples: string | SquareName[] }): Items { + const items: Set = new Set(readKeys(blueprint.apples)); return { - doIfKeyExists: (key: Key, f: () => U) => (items.has(key) ? f() : undefined), - remove: (key: Key) => items.delete(key), + doIfKeyExists: (key: SquareName, f: () => U) => (items.has(key) ? f() : undefined), + remove: (key: SquareName) => items.delete(key), isEmpty: () => items.size == 0, appleKeys: () => Array.from(items), }; diff --git a/ui/learn/src/learn.ts b/ui/learn/src/learn.ts index 5d1a70d4af4a8..f6d71b8c60f73 100644 --- a/ui/learn/src/learn.ts +++ b/ui/learn/src/learn.ts @@ -8,10 +8,10 @@ import { } from 'snabbdom'; import { LearnCtrl } from './ctrl'; import { view } from './view'; -import * as Prefs from 'common/prefs'; +import { Coords } from 'common/prefs'; import { pubsub } from 'common/pubsub'; -import storage, { Storage } from './storage'; +import storage, { type Storage } from './storage'; const patch = init([classModule, attributesModule, propsModule, eventListenersModule, styleModule]); @@ -33,7 +33,7 @@ export interface LearnOpts { } export interface LearnPrefs { - coords: Prefs.Coords; + coords: Coords; destination: boolean; } diff --git a/ui/learn/src/levelCtrl.ts b/ui/learn/src/levelCtrl.ts index 59636b019aad9..12775a1ec0b4e 100644 --- a/ui/learn/src/levelCtrl.ts +++ b/ui/learn/src/levelCtrl.ts @@ -1,17 +1,16 @@ -import { PromotionRole, WithGround, arrow, oppColor } from './util'; -import { Items, ctrl as makeItems } from './item'; -import { Level } from './stage/list'; -import * as scoring from './score'; +import { type PromotionRole, type WithGround, arrow, oppColor } from './util'; +import { type Items, ctrl as makeItems } from './item'; +import type { Level } from './stage/list'; +import { scenario as scoreScenario, pieceValue, capture, apple, getLevelBonus } from './score'; import * as timeouts from './timeouts'; -import * as sound from './sound'; -import makeChess, { ChessCtrl } from './chess'; -import makeScenario, { Scenario } from './scenario'; -import { SquareName as Key, makeSquare, makeUci } from 'chessops'; -import { CgMove } from './chessground'; -import * as cg from 'chessground/types'; +import { failure, levelStart, levelEnd, take, move as moveSound } from './sound'; +import makeChess, { type ChessCtrl } from './chess'; +import makeScenario, { type Scenario } from './scenario'; +import { type SquareName, makeSquare, makeUci } from 'chessops'; +import type { CgMove } from './chessground'; import { PromotionCtrl } from './promotionCtrl'; -import { Prop, prop } from 'common'; -import { DrawShape } from 'chessground/draw'; +import { type Prop, prop } from 'common'; +import type { DrawShape } from 'chessground/draw'; import { makeAppleShape } from './apple'; export interface LevelVm { @@ -95,7 +94,7 @@ export class LevelCtrl { rookCastle: false, }, events: { - move: (orig: Key, dest: Key) => { + move: (orig: SquareName, dest: SquareName) => { const piece = ground.state.pieces.get(dest); if (!piece || piece.color !== blueprint.color) return; if (!this.promotionCtrl.start(orig, dest, sendMove)) sendMove(orig, dest); @@ -120,7 +119,7 @@ export class LevelCtrl { const assertData = (): AssertData => ({ scenario, chess, vm }); const detectFailure = () => { const failed = !!blueprint.failure?.(assertData()); - if (failed) sound.failure(); + if (failed) failure(); return failed; }; const detectSuccess = () => (blueprint.success ? blueprint.success(assertData()) : items.isEmpty()); @@ -132,11 +131,11 @@ export class LevelCtrl { vm.failed = true; ground.stop(); this.showCapture(move); - sound.failure(); + failure(); return true; }; - return (orig: Key, dest: Key, prom?: PromotionRole) => { + return (orig: SquareName, dest: SquareName, prom?: PromotionRole) => { vm.nbMoves++; const move = chess.move(orig, dest, prom); if (move) this.setFen(chess.fen(), blueprint.color, new Map()); @@ -144,7 +143,7 @@ export class LevelCtrl { // moving into check vm.failed = true; this.showKingAttackers(); - sound.failure(); + failure(); redraw(); return; } @@ -152,18 +151,18 @@ export class LevelCtrl { inScenario, captured = false; items.doIfKeyExists(makeSquare(move.to), () => { - vm.score += scoring.apple; + vm.score += apple; items.remove(makeSquare(move.to)); took = true; }); const pieceAtKey = chess.instance.board.get(move.to); if (!took && pieceAtKey && blueprint.pointsForCapture && pieceAtKey.role != 'king') { - vm.score += blueprint.showPieceValues ? scoring.pieceValue(pieceAtKey.role) : scoring.capture; + vm.score += blueprint.showPieceValues ? pieceValue(pieceAtKey.role) : capture; took = true; } this.setCheck(); if (scenario.player(makeUci(move))) { - vm.score += scoring.scenario; + vm.score += scoreScenario; inScenario = true; } else { captured = detectCapture(); @@ -172,15 +171,18 @@ export class LevelCtrl { if (this.isAppleLevel()) this.setShapes(); if (!vm.failed && detectSuccess()) this.complete(); if (vm.willComplete) return; - if (took) sound.take(); - else if (inScenario) sound.take(); - else sound.move(); + if (took) take(); + else if (inScenario) take(); + else moveSound(); if (vm.failed) { if (blueprint.showFailureFollowUp && !captured) timeouts.setTimeout(() => { const rm = chess.playRandomMove(); if (!rm) return; - this.setFen(chess.fen(), blueprint.color, new Map(), [rm.orig, rm.dest] as [Key, Key]); + this.setFen(chess.fen(), blueprint.color, new Map(), [rm.orig, rm.dest] as [ + SquareName, + SquareName, + ]); }, 600); } else { ground.selectSquare(dest); @@ -193,7 +195,7 @@ export class LevelCtrl { }; }; - setFen = (fen: string, color: Color, dests: cg.Dests, lastMove?: [Key, Key]) => + setFen = (fen: string, color: Color, dests: Dests, lastMove?: [SquareName, SquareName]) => this.withGround(g => g.set({ turnColor: color, @@ -239,7 +241,7 @@ export class LevelCtrl { if (checks) this.setShapes(checks.map(move => arrow(move.orig + move.dest, 'yellow'))); }); - setColorDests = (color: Color, dests: cg.Dests) => + setColorDests = (color: Color, dests: Dests) => this.withGround(ground => ground.set({ turnColor: color, @@ -248,20 +250,20 @@ export class LevelCtrl { ); start = () => { - sound.levelStart(); + levelStart(); if (this.chess.getColor() !== this.blueprint.color) timeouts.setTimeout(this.scenario.opponent, 1000); }; complete = () => { this.vm.willComplete = true; - this.vm.score += scoring.getLevelBonus(this.blueprint, this.vm.nbMoves); + this.vm.score += getLevelBonus(this.blueprint, this.vm.nbMoves); this.opts.onCompleteImmediate(); this.withGround(g => timeouts.setTimeout( () => { this.vm.lastStep = false; this.vm.completed = true; - sound.levelEnd(); + levelEnd(); this.withGround(g => g.stop()); this.redraw(); if (!this.blueprint.nextButton) timeouts.setTimeout(this.opts.onComplete, 1200); diff --git a/ui/learn/src/mapSideView.ts b/ui/learn/src/mapSideView.ts index 9e180e048e117..b7b521efa610e 100644 --- a/ui/learn/src/mapSideView.ts +++ b/ui/learn/src/mapSideView.ts @@ -1,10 +1,10 @@ -import * as util from './util'; -import * as stages from './stage/list'; -import { SideCtrl } from './sideCtrl'; +import { assetUrl } from './util'; +import { categs } from './stage/list'; +import type { SideCtrl } from './sideCtrl'; import { h } from 'snabbdom'; import { bind } from 'common/snabbdom'; import { BASE_LEARN_PATH, hashHref } from './hashRouting'; -import { LearnCtrl } from './ctrl'; +import type { LearnCtrl } from './ctrl'; import { confirm } from 'common/dialog'; export function mapSideView(ctrl: LearnCtrl) { @@ -20,9 +20,9 @@ function renderInStage(ctrl: SideCtrl) { { attrs: { href: BASE_LEARN_PATH }, }, - [h('img', { attrs: { src: util.assetUrl + 'images/learn/brutal-helm.svg' } }), i18n.site.menu], + [h('img', { attrs: { src: assetUrl + 'images/learn/brutal-helm.svg' } }), i18n.site.menu], ), - ...stages.categs.map((categ, categId) => + ...categs.map((categ, categId) => h( 'div.categ', { diff --git a/ui/learn/src/progressView.ts b/ui/learn/src/progressView.ts index cce30a413860c..52f33421d5ebb 100644 --- a/ui/learn/src/progressView.ts +++ b/ui/learn/src/progressView.ts @@ -1,14 +1,14 @@ -import * as scoring from './score'; -import { Level } from './stage/list'; +import { getLevelRank } from './score'; +import type { Level } from './stage/list'; import { h } from 'snabbdom'; import { hashHref } from './hashRouting'; -import { RunCtrl } from './run/runCtrl'; +import type { RunCtrl } from './run/runCtrl'; import * as licon from 'common/licon'; const star = h('i', { attrs: { 'data-icon': licon.Star } }); export function makeStars(level: Level, score: number) { - const rank = scoring.getLevelRank(level, score); + const rank = getLevelRank(level, score); const stars = []; for (let i = 3; i >= rank; i--) stars.push(star); return h('span.stars.st' + stars.length, stars); diff --git a/ui/learn/src/promotionCtrl.ts b/ui/learn/src/promotionCtrl.ts index e977ca95e7cbb..338a559cfca2e 100644 --- a/ui/learn/src/promotionCtrl.ts +++ b/ui/learn/src/promotionCtrl.ts @@ -1,5 +1,5 @@ -import { PiecesDiff } from 'chessground/types'; -import { PromotionRole, WithGround } from './util'; +import type { PiecesDiff } from 'chessground/types'; +import type { PromotionRole, WithGround } from './util'; type PromotionCallback = (orig: Key, dest: Key, role: PromotionRole) => void; diff --git a/ui/learn/src/promotionView.ts b/ui/learn/src/promotionView.ts index 010e83034f2f0..28f69a01c4607 100644 --- a/ui/learn/src/promotionView.ts +++ b/ui/learn/src/promotionView.ts @@ -1,5 +1,5 @@ -import { RunCtrl } from './run/runCtrl'; -import { PromotionRole } from './util'; +import type { RunCtrl } from './run/runCtrl'; +import type { PromotionRole } from './util'; import { h } from 'snabbdom'; import { bind } from 'common/snabbdom'; import { opposite, key2pos } from 'chessground/util'; diff --git a/ui/learn/src/run/congrats.ts b/ui/learn/src/run/congrats.ts index aa0410c45489e..825b6d8161952 100644 --- a/ui/learn/src/run/congrats.ts +++ b/ui/learn/src/run/congrats.ts @@ -1,11 +1,4 @@ -function shuffle(a: T[]) { - for (let i = a.length; i; i -= 1) { - const j = Math.floor(Math.random() * i); - const x = a[i - 1]; - a[i - 1] = a[j]; - a[j] = x; - } -} +import { shuffle } from 'common/algo'; const list: string[] = [ i18n.learn.awesome, diff --git a/ui/learn/src/run/runCtrl.ts b/ui/learn/src/run/runCtrl.ts index ae14f80b8e140..9ad5316081ca1 100644 --- a/ui/learn/src/run/runCtrl.ts +++ b/ui/learn/src/run/runCtrl.ts @@ -1,12 +1,11 @@ -import * as sound from '../sound'; -import * as stages from '../stage/list'; -import { Prop, prop } from 'common'; -import { LearnProgress, LearnOpts } from '../learn'; -import { Stage } from '../stage/list'; +import { stageStart, stageEnd } from '../sound'; +import { type Prop, prop } from 'common'; +import type { LearnProgress, LearnOpts } from '../learn'; +import { type Stage, type Level, byId as stageById } from '../stage/list'; import { clearTimeouts } from '../timeouts'; import { LevelCtrl } from '../levelCtrl'; import { hashNavigate } from '../hashRouting'; -import { WithGround } from '../util'; +import type { WithGround } from '../util'; export class RunCtrl { data: LearnProgress = this.opts.storage.data; @@ -18,7 +17,7 @@ export class RunCtrl { stageCompleted: Prop = prop(false); get stage(): Stage { - return stages.byId[this.opts.stageId ?? 1]!; + return stageById[this.opts.stageId ?? 1]!; } constructor( @@ -47,7 +46,7 @@ export class RunCtrl { } else if (this.stageCompleted()) return; else { this.stageCompleted(true); - sound.stageEnd(); + stageEnd(); } this.redraw(); }, @@ -59,7 +58,7 @@ export class RunCtrl { this.stageCompleted(false); if (!this.opts.stageId) return; - if (this.stageStarting()) sound.stageStart(); + if (this.stageStarting()) stageStart(); else this.levelCtrl.start(); }; @@ -74,9 +73,9 @@ export class RunCtrl { stageScore = () => this.data.stages[this.stage.key]?.scores.reduce((a, b) => a + b) ?? 0; - score = (level: stages.Level) => this.data.stages[this.stage.key]?.scores[level.id - 1] ?? 0; + score = (level: Level) => this.data.stages[this.stage.key]?.scores[level.id - 1] ?? 0; - getNext = () => stages.byId[this.stage.id + 1]; + getNext = () => stageById[this.stage.id + 1]; hideStartingPane = () => { if (!this.stageStarting()) return; diff --git a/ui/learn/src/run/runView.ts b/ui/learn/src/run/runView.ts index 0fb6c5de80b3e..978fc2d9076e0 100644 --- a/ui/learn/src/run/runView.ts +++ b/ui/learn/src/run/runView.ts @@ -1,12 +1,12 @@ -import * as util from '../util'; +import { withLinebreaks } from '../util'; import chessground from '../chessground'; import congrats from './congrats'; import stageStarting from './stageStarting'; import stageComplete from './stageComplete'; -import { LevelCtrl } from '../levelCtrl'; -import { RunCtrl } from './runCtrl'; +import type { LevelCtrl } from '../levelCtrl'; +import type { RunCtrl } from './runCtrl'; import { mapSideView } from '../mapSideView'; -import { LearnCtrl } from '../ctrl'; +import type { LearnCtrl } from '../ctrl'; import { h, VNode } from 'snabbdom'; import { bind } from 'common/snabbdom'; import { makeStars, progressView } from '../progressView'; @@ -62,7 +62,7 @@ export const runView = (ctrl: LearnCtrl) => { ? renderFailed(runCtrl) : levelCtrl.vm.completed ? renderCompleted(levelCtrl) - : h('div.goal', util.withLinebreaks(levelCtrl.blueprint.goal)), + : h('div.goal', withLinebreaks(levelCtrl.blueprint.goal)), progressView(runCtrl), ]), ]), diff --git a/ui/learn/src/run/stageComplete.ts b/ui/learn/src/run/stageComplete.ts index 718d016178979..043c124aa1bd1 100644 --- a/ui/learn/src/run/stageComplete.ts +++ b/ui/learn/src/run/stageComplete.ts @@ -1,7 +1,7 @@ -import * as util from '../util'; -import * as scoring from '../score'; +import { withLinebreaks } from '../util'; +import { getStageRank } from '../score'; import { numberSpread } from 'common/number'; -import { RunCtrl } from './runCtrl'; +import type { RunCtrl } from './runCtrl'; import { h } from 'snabbdom'; import { bind } from 'common/snabbdom'; import { hashNavigate } from '../hashRouting'; @@ -26,7 +26,7 @@ export default function (ctrl: RunCtrl) { ), }, h('div.learn__screen', [ - h('div.stars', makeStars(scoring.getStageRank(stage, score))), + h('div.stars', makeStars(getStageRank(stage, score))), h('h1', i18n.learn.stageXComplete(stage.id)), h( 'span.score', @@ -45,7 +45,7 @@ export default function (ctrl: RunCtrl) { ), ), ), - h('p', util.withLinebreaks(stage.complete)), + h('p', withLinebreaks(stage.complete)), h('div.buttons', [ next ? h('a.next', { hook: bind('click', () => hashNavigate(next.id)) }, [ diff --git a/ui/learn/src/run/stageStarting.ts b/ui/learn/src/run/stageStarting.ts index 2b38c565898cc..754b98eefda13 100644 --- a/ui/learn/src/run/stageStarting.ts +++ b/ui/learn/src/run/stageStarting.ts @@ -1,5 +1,5 @@ -import * as util from '../util'; -import { RunCtrl } from './runCtrl'; +import { withLinebreaks } from '../util'; +import type { RunCtrl } from './runCtrl'; import { h } from 'snabbdom'; import { bind } from 'common/snabbdom'; @@ -10,7 +10,7 @@ export default function (ctrl: RunCtrl) { h('div.learn__screen', [ h('h1', i18n.learn.stageX(ctrl.stage.id) + ': ' + ctrl.stage.title), ctrl.stage.illustration, - h('p', util.withLinebreaks(ctrl.stage.intro)), + h('p', withLinebreaks(ctrl.stage.intro)), h( 'div.buttons', h( diff --git a/ui/learn/src/scenario.ts b/ui/learn/src/scenario.ts index 010db99ee5e36..a48c392354e43 100644 --- a/ui/learn/src/scenario.ts +++ b/ui/learn/src/scenario.ts @@ -1,6 +1,5 @@ -import * as cg from 'chessground/types'; import * as timeouts from './timeouts'; -import { ChessCtrl } from './chess'; +import type { ChessCtrl } from './chess'; import { decomposeUci } from './util'; import { Shape } from './chessground'; @@ -21,8 +20,8 @@ export type ScenarioLevel = ( interface ScenarioOpts { chess: ChessCtrl; - makeChessDests(): cg.Dests; - setFen(fen: string, color: Color, dests: cg.Dests, lastMove?: [Key, Key]): void; + makeChessDests(): Dests; + setFen(fen: string, color: Color, dests: Dests, lastMove?: [Key, Key]): void; setShapes(shapes: Shape[]): void; } diff --git a/ui/learn/src/score.ts b/ui/learn/src/score.ts index 5603bed0dba96..eaeeef09000ef 100644 --- a/ui/learn/src/score.ts +++ b/ui/learn/src/score.ts @@ -1,6 +1,5 @@ -import { Level, Stage } from './stage/list'; -import * as util from './util'; -import { Role } from 'chessops'; +import type { Level, Stage } from './stage/list'; +import { readKeys } from './util'; export const apple = 50; export const capture = 50; @@ -20,9 +19,7 @@ export const getLevelBonus = (l: Level, nbMoves: number) => { }; const getLevelMaxScore = (l: Level): number => - util.readKeys(l.apples).length * apple + - (l.pointsForCapture ? (l.captures || 0) * capture : 0) + - levelBonus[1]; + readKeys(l.apples).length * apple + (l.pointsForCapture ? (l.captures || 0) * capture : 0) + levelBonus[1]; export const getLevelRank = (l: Level, score: number): Rank => { const max = getLevelMaxScore(l); diff --git a/ui/learn/src/sideCtrl.ts b/ui/learn/src/sideCtrl.ts index 2bd6550fe42e8..2881de3f97e41 100644 --- a/ui/learn/src/sideCtrl.ts +++ b/ui/learn/src/sideCtrl.ts @@ -1,4 +1,4 @@ -import * as stages from './stage/list'; +import { stageIdToCategId, byKey as stageByKey, list as stageList } from './stage/list'; import * as scoring from './score'; import { Prop, propWithEffect } from 'common'; import { LearnProgress, LearnOpts } from './learn'; @@ -20,14 +20,14 @@ export class SideCtrl { reset = () => this.opts.storage.reset(); activeStageId = () => this.opts.stageId || 1; - getCategIdFromStageId = () => stages.stageIdToCategId(this.activeStageId()); + getCategIdFromStageId = () => stageIdToCategId(this.activeStageId()); updateCategId = () => this.categId(this.getCategIdFromStageId() || this.categId()); progress = () => { - const max = stages.list.length * 10; + const max = stageList.length * 10; const data = this.data.stages; const total = Object.keys(data).reduce((t, key) => { - const rank = scoring.getStageRank(stages.byKey[key], data[key].scores); + const rank = scoring.getStageRank(stageByKey[key], data[key].scores); if (rank === 1) return t + 10; if (rank === 2) return t + 8; return t + 5; diff --git a/ui/learn/src/stage/bishop.ts b/ui/learn/src/stage/bishop.ts index b6ee581accec5..b2803919d3874 100644 --- a/ui/learn/src/stage/bishop.ts +++ b/ui/learn/src/stage/bishop.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, pieceImg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const stage: StageNoID = { key: 'bishop', diff --git a/ui/learn/src/stage/capture.ts b/ui/learn/src/stage/capture.ts index 34cbd343397be..cc32ed22ccc63 100644 --- a/ui/learn/src/stage/capture.ts +++ b/ui/learn/src/stage/capture.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { LevelPartial, StageNoID } from './list'; +import type { LevelPartial, StageNoID } from './list'; import { extinct } from '../assert'; const imgUrl = assetUrl + 'images/learn/bowman.svg'; diff --git a/ui/learn/src/stage/castling.ts b/ui/learn/src/stage/castling.ts index aad73e58ea650..022ef7a20bbda 100644 --- a/ui/learn/src/stage/castling.ts +++ b/ui/learn/src/stage/castling.ts @@ -1,6 +1,6 @@ import { and, lastMoveSan, not, or, pieceNotOn, mate } from '../assert'; import { arrow, assetUrl, circle, roundSvg, toLevel } from '../util'; -import { LevelPartial, StageNoID } from './list'; +import type { LevelPartial, StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/castle.svg'; diff --git a/ui/learn/src/stage/check1.ts b/ui/learn/src/stage/check1.ts index f99219dfa2ea9..aeeaaa9e95faa 100644 --- a/ui/learn/src/stage/check1.ts +++ b/ui/learn/src/stage/check1.ts @@ -1,6 +1,6 @@ import { check, not } from '../assert'; import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/winged-sword.svg'; diff --git a/ui/learn/src/stage/check2.ts b/ui/learn/src/stage/check2.ts index 719b9389aa3c1..7257190cc7f5c 100644 --- a/ui/learn/src/stage/check2.ts +++ b/ui/learn/src/stage/check2.ts @@ -1,6 +1,6 @@ import { checkIn, noCheckIn } from '../assert'; import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/crossed-swords.svg'; diff --git a/ui/learn/src/stage/checkmate1.ts b/ui/learn/src/stage/checkmate1.ts index 4974fe4a05cc4..0b4599983e1ff 100644 --- a/ui/learn/src/stage/checkmate1.ts +++ b/ui/learn/src/stage/checkmate1.ts @@ -1,6 +1,6 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; import { mate, not } from '../assert'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/guillotine.svg'; diff --git a/ui/learn/src/stage/combat.ts b/ui/learn/src/stage/combat.ts index 9337ba8990440..b44baff66b48a 100644 --- a/ui/learn/src/stage/combat.ts +++ b/ui/learn/src/stage/combat.ts @@ -1,6 +1,6 @@ import { extinct } from '../assert'; import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { LevelPartial, StageNoID } from './list'; +import type { LevelPartial, StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/battle-gear.svg'; diff --git a/ui/learn/src/stage/enpassant.ts b/ui/learn/src/stage/enpassant.ts index dfb5eb2172211..bd6b4b9206257 100644 --- a/ui/learn/src/stage/enpassant.ts +++ b/ui/learn/src/stage/enpassant.ts @@ -1,6 +1,6 @@ import { scenarioComplete, scenarioFailed } from '../assert'; import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/spinning-blades.svg'; diff --git a/ui/learn/src/stage/fork.ts b/ui/learn/src/stage/fork.ts index 91951244631bd..888a826018deb 100644 --- a/ui/learn/src/stage/fork.ts +++ b/ui/learn/src/stage/fork.ts @@ -1,6 +1,6 @@ import { checkIn, noCheckIn } from '../assert'; import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/crossed-swords.svg'; diff --git a/ui/learn/src/stage/king.ts b/ui/learn/src/stage/king.ts index 9d7d4ec229d1a..041f4f5c26ad4 100644 --- a/ui/learn/src/stage/king.ts +++ b/ui/learn/src/stage/king.ts @@ -1,4 +1,4 @@ -import { LevelPartial, StageNoID } from './list'; +import type { LevelPartial, StageNoID } from './list'; import { arrow, assetUrl, pieceImg, toLevel } from '../util'; const stage: StageNoID = { diff --git a/ui/learn/src/stage/knight.ts b/ui/learn/src/stage/knight.ts index 9379b77594620..24563ed62abb8 100644 --- a/ui/learn/src/stage/knight.ts +++ b/ui/learn/src/stage/knight.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, pieceImg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const stage: StageNoID = { key: 'knight', diff --git a/ui/learn/src/stage/list.ts b/ui/learn/src/stage/list.ts index e4c57bf70831c..90aec2b5cadad 100644 --- a/ui/learn/src/stage/list.ts +++ b/ui/learn/src/stage/list.ts @@ -16,11 +16,11 @@ import enpassant from './enpassant'; import stalemate from './stalemate'; import value from './value'; import check2 from './check2'; -import { AssertData } from '../levelCtrl'; -import { ScenarioLevel } from '../scenario'; -import type { SquareName as Key } from 'chessops'; -import { VNode } from 'snabbdom'; -import { Shape } from '../chessground'; +import type { AssertData } from '../levelCtrl'; +import type { ScenarioLevel } from '../scenario'; +import type { SquareName } from 'chessops'; +import type { VNode } from 'snabbdom'; +import type { Shape } from '../chessground'; export type Level = LevelBase & LevelDefaults; export type LevelPartial = LevelBase & Partial; @@ -49,7 +49,7 @@ export interface LevelBase { export interface LevelDefaults { id: number; - apples: string | Key[]; + apples: string | SquareName[]; color: Color; detectCapture: 'unprotected' | boolean; } diff --git a/ui/learn/src/stage/outOfCheck.ts b/ui/learn/src/stage/outOfCheck.ts index 4974a80b5ada9..c6cfa21564ab4 100644 --- a/ui/learn/src/stage/outOfCheck.ts +++ b/ui/learn/src/stage/outOfCheck.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/guards.svg'; diff --git a/ui/learn/src/stage/pawn.ts b/ui/learn/src/stage/pawn.ts index dfd086a5cd187..8fa8696e9d8d1 100644 --- a/ui/learn/src/stage/pawn.ts +++ b/ui/learn/src/stage/pawn.ts @@ -1,6 +1,6 @@ import { noPieceOn, whitePawnOnAnyOf } from '../assert'; import { arrow, assetUrl, pieceImg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const stage: StageNoID = { key: 'pawn', diff --git a/ui/learn/src/stage/protection.ts b/ui/learn/src/stage/protection.ts index 98e7d5b6c9721..288918b4aaee9 100644 --- a/ui/learn/src/stage/protection.ts +++ b/ui/learn/src/stage/protection.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/bolt-shield.svg'; diff --git a/ui/learn/src/stage/queen.ts b/ui/learn/src/stage/queen.ts index 54325122df889..82f65aa5b9133 100644 --- a/ui/learn/src/stage/queen.ts +++ b/ui/learn/src/stage/queen.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, pieceImg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const stage: StageNoID = { key: 'queen', diff --git a/ui/learn/src/stage/rook.ts b/ui/learn/src/stage/rook.ts index 6e86b8d76b093..47f05a8dce340 100644 --- a/ui/learn/src/stage/rook.ts +++ b/ui/learn/src/stage/rook.ts @@ -1,5 +1,5 @@ import { arrow, assetUrl, pieceImg, toLevel } from '../util'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const stage: StageNoID = { key: 'rook', diff --git a/ui/learn/src/stage/setup.ts b/ui/learn/src/stage/setup.ts index 04dac1b070c09..20d71e433d699 100644 --- a/ui/learn/src/stage/setup.ts +++ b/ui/learn/src/stage/setup.ts @@ -1,6 +1,6 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; import { and, pieceOn } from '../assert'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/rally-the-troops.svg'; diff --git a/ui/learn/src/stage/stalemate.ts b/ui/learn/src/stage/stalemate.ts index 6662f2266c4c9..89c09d696ce78 100644 --- a/ui/learn/src/stage/stalemate.ts +++ b/ui/learn/src/stage/stalemate.ts @@ -1,6 +1,6 @@ import { arrow, assetUrl, circle, roundSvg, toLevel } from '../util'; import { scenarioComplete, scenarioFailed } from '../assert'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/scales.svg'; diff --git a/ui/learn/src/stage/value.ts b/ui/learn/src/stage/value.ts index 67594ec064cf3..758ec2fd69a51 100644 --- a/ui/learn/src/stage/value.ts +++ b/ui/learn/src/stage/value.ts @@ -1,6 +1,6 @@ import { arrow, assetUrl, roundSvg, toLevel } from '../util'; import { scenarioComplete, scenarioFailed } from '../assert'; -import { StageNoID } from './list'; +import type { StageNoID } from './list'; const imgUrl = assetUrl + 'images/learn/sprint.svg'; diff --git a/ui/learn/src/storage.ts b/ui/learn/src/storage.ts index 92113e9efbc16..78313f44b1d29 100644 --- a/ui/learn/src/storage.ts +++ b/ui/learn/src/storage.ts @@ -1,6 +1,6 @@ import * as xhr from 'common/xhr'; import type { LearnProgress } from './learn'; -import { Stage } from './stage/list'; +import type { Stage } from './stage/list'; import { storage } from 'common/storage'; export interface Storage { diff --git a/ui/learn/src/util.ts b/ui/learn/src/util.ts index 0f20e69f712ee..249e93e45f779 100644 --- a/ui/learn/src/util.ts +++ b/ui/learn/src/util.ts @@ -1,8 +1,8 @@ -import type { SquareName as Key } from 'chessops'; -import { Level, LevelPartial } from './stage/list'; +import type { SquareName } from 'chessops'; +import type { Level, LevelPartial } from './stage/list'; import { h } from 'snabbdom'; -import * as cg from 'chessground/types'; -import { DrawShape } from 'chessground/draw'; +import type { DrawShape } from 'chessground/draw'; +import type { BrushColor } from 'chessground/types'; export type WithGround =
(f: (cg: CgApi) => A) => A | false | undefined; @@ -25,21 +25,21 @@ export type PromotionChar = 'n' | 'b' | 'r' | 'q'; export const isRole = (str: PromotionChar | PromotionRole): str is PromotionRole => str.length > 1; -export const arrow = (vector: Uci, brush?: cg.BrushColor): DrawShape => ({ +export const arrow = (vector: Uci, brush?: BrushColor): DrawShape => ({ brush: brush || 'paleGreen', - orig: vector.slice(0, 2) as Key, - dest: vector.slice(2, 4) as Key, + orig: vector.slice(0, 2) as SquareName, + dest: vector.slice(2, 4) as SquareName, }); -export const circle = (key: Key, brush?: cg.BrushColor): DrawShape => ({ +export const circle = (key: SquareName, brush?: BrushColor): DrawShape => ({ brush: brush || 'green', orig: key, }); -export const readKeys = (keys: string | Key[]): Key[] => - typeof keys === 'string' ? (keys.split(' ') as Key[]) : keys; +export const readKeys = (keys: string | SquareName[]): SquareName[] => + typeof keys === 'string' ? (keys.split(' ') as SquareName[]) : keys; -export const pieceImg = (role: cg.Role) => h('div.no-square', h('piece.white.' + role)); +export const pieceImg = (role: Role) => h('div.no-square', h('piece.white.' + role)); export const roundSvg = (url: string) => h('div.round-svg', h('img', { attrs: { src: url } })); @@ -47,6 +47,6 @@ export const withLinebreaks = (text: string) => text.split(/(\n)/g).map(part => (part === '\n' ? h('br') : part)); export const decomposeUci = (uci: string) => - [uci.slice(0, 2), uci.slice(2, 4), uci.slice(4, 5)] as [Key, Key, PromotionChar | '']; + [uci.slice(0, 2), uci.slice(2, 4), uci.slice(4, 5)] as [SquareName, SquareName, PromotionChar | '']; export const oppColor = (color: Color): Color => (color == 'white' ? 'black' : 'white'); diff --git a/ui/learn/src/view.ts b/ui/learn/src/view.ts index 0df82d406f8ea..9f58c3b765e14 100644 --- a/ui/learn/src/view.ts +++ b/ui/learn/src/view.ts @@ -1,11 +1,10 @@ import * as licon from 'common/licon'; -import { h, VNode } from 'snabbdom'; -import { LearnCtrl } from './ctrl'; -import { Stage } from './stage/list'; -import * as stages from './stage/list'; -import { StageProgress } from './learn'; +import { h, type VNode } from 'snabbdom'; +import type { LearnCtrl } from './ctrl'; +import { type Stage, categs } from './stage/list'; +import type { StageProgress } from './learn'; import * as scoring from './score'; -import * as util from './util'; +import { assetUrl } from './util'; import { mapSideView } from './mapSideView'; import { hashHref } from './hashRouting'; import { runView } from './run/runView'; @@ -18,7 +17,7 @@ const mapView = (ctrl: LearnCtrl) => h('div.learn.learn--map', [ h('div.learn__side', mapSideView(ctrl)), h('div.learn__main.learn-stages', [ - ...stages.categs.map(categ => + ...categs.map(categ => h('div.categ', [ h('h2', categ.name), h( @@ -70,7 +69,7 @@ function whatNext(ctrl: LearnCtrl) { const transTitle = title; return h(`a.stage.done.${titleVerbosityClass(transTitle)}`, { attrs: { href: href } }, [ done ? h('span.ribbon-wrapper', h('span.ribbon.done', makeStars(1))) : null, - h('img', { attrs: { src: util.assetUrl + 'images/learn/' + img + '.svg' } }), + h('img', { attrs: { src: assetUrl + 'images/learn/' + img + '.svg' } }), h('div.text', [h('h3', transTitle), h('p.subtitle', subtitle)]), ]); }; diff --git a/ui/lobby/src/ctrl.ts b/ui/lobby/src/ctrl.ts index 37fd7162f5804..39c3f0c93be1b 100644 --- a/ui/lobby/src/ctrl.ts +++ b/ui/lobby/src/ctrl.ts @@ -2,10 +2,10 @@ import { numberFormat } from 'common/number'; import variantConfirm from './variant'; import * as hookRepo from './hookRepo'; import * as seekRepo from './seekRepo'; -import { make as makeStores, Stores } from './store'; +import { make as makeStores, type Stores } from './store'; import * as xhr from './xhr'; import * as poolRangeStorage from './poolRangeStorage'; -import { +import type { LobbyOpts, LobbyData, Tab, diff --git a/ui/lobby/src/filter.ts b/ui/lobby/src/filter.ts index 59fd9e087723a..1c5714984b839 100644 --- a/ui/lobby/src/filter.ts +++ b/ui/lobby/src/filter.ts @@ -1,7 +1,14 @@ -import { Hook } from './interfaces'; -import { FormLines, FormObject, FormStore, toFormLines, toFormObject, makeStore } from './form'; -import LobbyController from './ctrl'; -import { type LichessStorage } from 'common/storage'; +import type { Hook } from './interfaces'; +import { + type FormLines, + type FormObject, + type FormStore, + toFormLines, + toFormObject, + makeStore, +} from './form'; +import type LobbyController from './ctrl'; +import type { LichessStorage } from 'common/storage'; interface FilterData { form: FormLines; diff --git a/ui/lobby/src/form.ts b/ui/lobby/src/form.ts index a313fd0f2f4dd..a4405cb843d33 100644 --- a/ui/lobby/src/form.ts +++ b/ui/lobby/src/form.ts @@ -1,4 +1,4 @@ -import { type LichessStorage } from 'common/storage'; +import type { LichessStorage } from 'common/storage'; export interface FormLines { [key: string]: string; diff --git a/ui/lobby/src/hookRepo.ts b/ui/lobby/src/hookRepo.ts index 58e3182504a16..4c2f517bc7a4f 100644 --- a/ui/lobby/src/hookRepo.ts +++ b/ui/lobby/src/hookRepo.ts @@ -1,5 +1,5 @@ -import LobbyController from './ctrl'; -import { Hook } from './interfaces'; +import type LobbyController from './ctrl'; +import type { Hook } from './interfaces'; function ratingOrder(a: Hook, b: Hook) { return (a.rating || 0) > (b.rating || 0) ? -1 : 1; diff --git a/ui/lobby/src/interfaces.ts b/ui/lobby/src/interfaces.ts index 7ff959e2bfd56..4435750463328 100644 --- a/ui/lobby/src/interfaces.ts +++ b/ui/lobby/src/interfaces.ts @@ -1,5 +1,3 @@ -import { FEN } from 'chessground/types'; - export type Sort = 'rating' | 'time'; export type Mode = 'list' | 'chart'; export type Tab = 'pools' | 'real_time' | 'seeks' | 'now_playing'; diff --git a/ui/lobby/src/lobby.ts b/ui/lobby/src/lobby.ts index 31e78653eb10c..49fad68c12fc5 100644 --- a/ui/lobby/src/lobby.ts +++ b/ui/lobby/src/lobby.ts @@ -1,6 +1,6 @@ import * as xhr from 'common/xhr'; import main from './main'; -import { LobbyOpts } from './interfaces'; +import type { LobbyOpts } from './interfaces'; import StrongSocket from 'common/socket'; import { pubsub } from 'common/pubsub'; diff --git a/ui/lobby/src/main.ts b/ui/lobby/src/main.ts index 74a419e744249..fd53b5b9decdc 100644 --- a/ui/lobby/src/main.ts +++ b/ui/lobby/src/main.ts @@ -1,6 +1,6 @@ import { init, classModule, attributesModule, eventListenersModule } from 'snabbdom'; import { requestIdleCallback } from 'common'; -import { LobbyOpts } from './interfaces'; +import type { LobbyOpts } from './interfaces'; import makeCtrl from './ctrl'; import appView from './view/main'; import tableView from './view/table'; diff --git a/ui/lobby/src/options.ts b/ui/lobby/src/options.ts index ac757ebea91ef..ff4f7c46aed36 100644 --- a/ui/lobby/src/options.ts +++ b/ui/lobby/src/options.ts @@ -1,6 +1,6 @@ import * as licon from 'common/licon'; -import { GameMode, GameType, InputValue, RealValue, TimeMode, Variant } from './interfaces'; +import type { GameMode, GameType, InputValue, RealValue, TimeMode, Variant } from './interfaces'; export const variants: Variant[] = [ { id: 1, icon: licon.Crown, key: 'standard', name: 'Standard' }, diff --git a/ui/lobby/src/poolRangeStorage.ts b/ui/lobby/src/poolRangeStorage.ts index ad912449c73cd..094bdc2ff83df 100644 --- a/ui/lobby/src/poolRangeStorage.ts +++ b/ui/lobby/src/poolRangeStorage.ts @@ -1,4 +1,4 @@ -import { LobbyMe, PoolMember } from './interfaces'; +import type { LobbyMe, PoolMember } from './interfaces'; import { storage } from 'common/storage'; const makeKey = (me: LobbyMe | undefined, poolId: string) => diff --git a/ui/lobby/src/seekRepo.ts b/ui/lobby/src/seekRepo.ts index fdfb6171ff555..566affae131fb 100644 --- a/ui/lobby/src/seekRepo.ts +++ b/ui/lobby/src/seekRepo.ts @@ -1,5 +1,5 @@ -import LobbyController from './ctrl'; -import { Seek } from './interfaces'; +import type LobbyController from './ctrl'; +import type { Seek } from './interfaces'; function order(a: Seek, b: Seek) { return a.rating > b.rating ? -1 : 1; diff --git a/ui/lobby/src/setupCtrl.ts b/ui/lobby/src/setupCtrl.ts index 3540cdd5e1e1f..918b70900e1b2 100644 --- a/ui/lobby/src/setupCtrl.ts +++ b/ui/lobby/src/setupCtrl.ts @@ -1,10 +1,10 @@ -import { Prop, propWithEffect } from 'common'; +import { type Prop, propWithEffect } from 'common'; import { debounce } from 'common/timing'; import * as xhr from 'common/xhr'; -import { storedJsonProp, StoredJsonProp } from 'common/storage'; +import { storedJsonProp } from 'common/storage'; import { clockToSpeed } from 'game'; -import LobbyController from './ctrl'; -import { +import type LobbyController from './ctrl'; +import type { ForceSetupOptions, GameMode, GameType, @@ -34,7 +34,7 @@ const getPerf = (variant: VariantKey, timeMode: TimeMode, time: RealValue, incre export default class SetupController { root: LobbyController; - store: Record, StoredJsonProp>; + store: Record, Prop>; gameType: Exclude | null = null; lastValidFen = ''; fenError = false; diff --git a/ui/lobby/src/socket.ts b/ui/lobby/src/socket.ts index 7cfef44fc6a1e..472d3df821665 100644 --- a/ui/lobby/src/socket.ts +++ b/ui/lobby/src/socket.ts @@ -1,7 +1,7 @@ import * as xhr from './xhr'; import * as hookRepo from './hookRepo'; -import LobbyController from './ctrl'; -import { PoolMember, Hook } from './interfaces'; +import type LobbyController from './ctrl'; +import type { PoolMember, Hook } from './interfaces'; import { idleTimer } from 'common/timing'; interface Handlers { diff --git a/ui/lobby/src/store.ts b/ui/lobby/src/store.ts index 3ed1774497b53..aa8b0f1c4411f 100644 --- a/ui/lobby/src/store.ts +++ b/ui/lobby/src/store.ts @@ -1,4 +1,4 @@ -import { Tab, Mode, Sort } from './interfaces'; +import type { Tab, Mode, Sort } from './interfaces'; import { storage } from 'common/storage'; interface Store { diff --git a/ui/lobby/src/view/correspondence.ts b/ui/lobby/src/view/correspondence.ts index 6c8d70246d81e..b002879dea599 100644 --- a/ui/lobby/src/view/correspondence.ts +++ b/ui/lobby/src/view/correspondence.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; -import { bind, MaybeVNodes } from 'common/snabbdom'; +import { h, type VNode } from 'snabbdom'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; import { tds, perfNames } from './util'; -import LobbyController from '../ctrl'; -import { Seek } from '../interfaces'; +import type LobbyController from '../ctrl'; +import type { Seek } from '../interfaces'; import perfIcons from 'common/perfIcons'; import { confirm } from 'common/dialog'; diff --git a/ui/lobby/src/view/main.ts b/ui/lobby/src/view/main.ts index 6991babedccbe..c2fbe245f81d5 100644 --- a/ui/lobby/src/view/main.ts +++ b/ui/lobby/src/view/main.ts @@ -1,11 +1,11 @@ -import { h, VNodeData } from 'snabbdom'; +import { h, type VNodeData } from 'snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; import renderTabs from './tabs'; import * as renderPools from './pools'; import renderRealTime from './realTime/main'; import renderSeeks from './correspondence'; import renderPlaying from './playing'; -import LobbyController from '../ctrl'; +import type LobbyController from '../ctrl'; export default function (ctrl: LobbyController) { let body, diff --git a/ui/lobby/src/view/playing.ts b/ui/lobby/src/view/playing.ts index c82c7b46fe80b..eaf9919ef076a 100644 --- a/ui/lobby/src/view/playing.ts +++ b/ui/lobby/src/view/playing.ts @@ -1,6 +1,6 @@ import { h } from 'snabbdom'; -import LobbyController from '../ctrl'; -import { NowPlaying } from '../interfaces'; +import type LobbyController from '../ctrl'; +import type { NowPlaying } from '../interfaces'; import { initMiniBoard } from 'common/miniBoard'; import { timeago } from 'common/i18n'; diff --git a/ui/lobby/src/view/pools.ts b/ui/lobby/src/view/pools.ts index f53cdbe0dc70e..5857f96e4f92d 100644 --- a/ui/lobby/src/view/pools.ts +++ b/ui/lobby/src/view/pools.ts @@ -1,6 +1,6 @@ -import { h, Hooks } from 'snabbdom'; +import { h, type Hooks } from 'snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; -import LobbyController from '../ctrl'; +import type LobbyController from '../ctrl'; import { onInsert } from 'common/snabbdom'; const createHandler = (ctrl: LobbyController) => (e: Event) => { diff --git a/ui/lobby/src/view/realTime/chart.ts b/ui/lobby/src/view/realTime/chart.ts index c6dd362f2f95f..f23b328761610 100644 --- a/ui/lobby/src/view/realTime/chart.ts +++ b/ui/lobby/src/view/realTime/chart.ts @@ -1,8 +1,8 @@ -import LobbyController from '../../ctrl'; +import type LobbyController from '../../ctrl'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; -import { h, VNode } from 'snabbdom'; -import { Hook } from '../../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { Hook } from '../../interfaces'; import perfIcons from 'common/perfIcons'; const percents = (v: number) => v + '%'; diff --git a/ui/lobby/src/view/realTime/filter.ts b/ui/lobby/src/view/realTime/filter.ts index 2562fb1680aa9..df6ea2f562ea0 100644 --- a/ui/lobby/src/view/realTime/filter.ts +++ b/ui/lobby/src/view/realTime/filter.ts @@ -2,7 +2,7 @@ import { h } from 'snabbdom'; import * as licon from 'common/licon'; import * as xhr from 'common/xhr'; import { bind } from 'common/snabbdom'; -import LobbyController from '../../ctrl'; +import type LobbyController from '../../ctrl'; function initialize(ctrl: LobbyController, el: HTMLElement) { const f = ctrl.filter.data?.form, diff --git a/ui/lobby/src/view/realTime/list.ts b/ui/lobby/src/view/realTime/list.ts index 644a7f9ca9c3e..b54e251b13b41 100644 --- a/ui/lobby/src/view/realTime/list.ts +++ b/ui/lobby/src/view/realTime/list.ts @@ -1,11 +1,11 @@ import { h } from 'snabbdom'; -import LobbyController from '../../ctrl'; +import type LobbyController from '../../ctrl'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; import { tds, perfNames } from '../util'; import perfIcons from 'common/perfIcons'; import * as hookRepo from '../../hookRepo'; -import { Hook } from '../../interfaces'; +import type { Hook } from '../../interfaces'; function renderHook(ctrl: LobbyController, hook: Hook) { return h( diff --git a/ui/lobby/src/view/realTime/main.ts b/ui/lobby/src/view/realTime/main.ts index cfb6add6950aa..44347ed8457ff 100644 --- a/ui/lobby/src/view/realTime/main.ts +++ b/ui/lobby/src/view/realTime/main.ts @@ -1,7 +1,7 @@ import * as list from './list'; import * as chart from './chart'; import * as filterView from './filter'; -import LobbyController from '../../ctrl'; +import type LobbyController from '../../ctrl'; export default function (ctrl: LobbyController) { let filterBody, body, nbFiltered, modeToggle, res; diff --git a/ui/lobby/src/view/setup/components/colorButtons.ts b/ui/lobby/src/view/setup/components/colorButtons.ts index 607ba6643a9cd..239bf8c985b0d 100644 --- a/ui/lobby/src/view/setup/components/colorButtons.ts +++ b/ui/lobby/src/view/setup/components/colorButtons.ts @@ -1,6 +1,6 @@ import { h } from 'snabbdom'; import { spinnerVdom } from 'common/spinner'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; import { colors, variantsWhereWhiteIsBetter } from '../../../options'; import { option } from './option'; diff --git a/ui/lobby/src/view/setup/components/fenInput.ts b/ui/lobby/src/view/setup/components/fenInput.ts index b65e277b5545f..cbb22bfb1b030 100644 --- a/ui/lobby/src/view/setup/components/fenInput.ts +++ b/ui/lobby/src/view/setup/components/fenInput.ts @@ -1,6 +1,6 @@ import { h } from 'snabbdom'; import * as licon from 'common/licon'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; import { initMiniBoard } from 'common/miniBoard'; export const fenInput = (ctrl: LobbyController) => { diff --git a/ui/lobby/src/view/setup/components/gameModeButtons.ts b/ui/lobby/src/view/setup/components/gameModeButtons.ts index 592c75e502c52..0dae4b9f4d3e8 100644 --- a/ui/lobby/src/view/setup/components/gameModeButtons.ts +++ b/ui/lobby/src/view/setup/components/gameModeButtons.ts @@ -1,7 +1,7 @@ -import { MaybeVNode } from 'common/snabbdom'; +import type { MaybeVNode } from 'common/snabbdom'; import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; -import { GameMode } from '../../../interfaces'; +import type LobbyController from '../../../ctrl'; +import type { GameMode } from '../../../interfaces'; import { gameModes } from '../../../options'; export const gameModeButtons = (ctrl: LobbyController): MaybeVNode => { diff --git a/ui/lobby/src/view/setup/components/levelButtons.ts b/ui/lobby/src/view/setup/components/levelButtons.ts index 95144b7079bb8..2129dddb97749 100644 --- a/ui/lobby/src/view/setup/components/levelButtons.ts +++ b/ui/lobby/src/view/setup/components/levelButtons.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; import { option } from './option'; export const levelButtons = (ctrl: LobbyController) => { diff --git a/ui/lobby/src/view/setup/components/option.ts b/ui/lobby/src/view/setup/components/option.ts index eb85a69df828b..1e25cf17ec115 100644 --- a/ui/lobby/src/view/setup/components/option.ts +++ b/ui/lobby/src/view/setup/components/option.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; export const option = ({ key, name }: { key: string; name: string }, selectedKey: string): VNode => h('option', { attrs: { value: key, selected: key === selectedKey } }, name); diff --git a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts index 215a6d90d2005..69451fac38b37 100644 --- a/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts +++ b/ui/lobby/src/view/setup/components/ratingDifferenceSliders.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; export const ratingDifferenceSliders = (ctrl: LobbyController) => { if (!ctrl.me || site.blindMode || !ctrl.data.ratingMap) return null; diff --git a/ui/lobby/src/view/setup/components/ratingView.ts b/ui/lobby/src/view/setup/components/ratingView.ts index 1c4c454170acf..5f0910ce74bc5 100644 --- a/ui/lobby/src/view/setup/components/ratingView.ts +++ b/ui/lobby/src/view/setup/components/ratingView.ts @@ -1,6 +1,6 @@ -import { MaybeVNode } from 'common/snabbdom'; +import type { MaybeVNode } from 'common/snabbdom'; import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; import { speeds, variants } from '../../../options'; export const ratingView = (ctrl: LobbyController): MaybeVNode => { diff --git a/ui/lobby/src/view/setup/components/timePickerAndSliders.ts b/ui/lobby/src/view/setup/components/timePickerAndSliders.ts index fd7e0213a94ae..490ec365aed9b 100644 --- a/ui/lobby/src/view/setup/components/timePickerAndSliders.ts +++ b/ui/lobby/src/view/setup/components/timePickerAndSliders.ts @@ -1,7 +1,7 @@ -import { Prop } from 'common'; +import type { Prop } from 'common'; import { looseH as h } from 'common/snabbdom'; -import LobbyController from '../../../ctrl'; -import { InputValue, TimeMode } from '../../../interfaces'; +import type LobbyController from '../../../ctrl'; +import type { InputValue, TimeMode } from '../../../interfaces'; import { daysVToDays, incrementVToIncrement, sliderTimes, timeModes } from '../../../options'; import { option } from './option'; diff --git a/ui/lobby/src/view/setup/components/variantPicker.ts b/ui/lobby/src/view/setup/components/variantPicker.ts index a26438eb52d81..b0e91b2550f4b 100644 --- a/ui/lobby/src/view/setup/components/variantPicker.ts +++ b/ui/lobby/src/view/setup/components/variantPicker.ts @@ -1,6 +1,6 @@ import { onInsert } from 'common/snabbdom'; import { h } from 'snabbdom'; -import LobbyController from '../../../ctrl'; +import type LobbyController from '../../../ctrl'; import { variantsBlindMode, variants, variantsForGameType } from '../../../options'; import { option } from './option'; diff --git a/ui/lobby/src/view/setup/modal.ts b/ui/lobby/src/view/setup/modal.ts index 7f040b3d9810e..c40dd937242b7 100644 --- a/ui/lobby/src/view/setup/modal.ts +++ b/ui/lobby/src/view/setup/modal.ts @@ -1,8 +1,8 @@ import { h } from 'snabbdom'; -import { MaybeVNode, MaybeVNodes } from 'common/snabbdom'; +import type { MaybeVNode, MaybeVNodes } from 'common/snabbdom'; import { userLink } from 'common/userLink'; import { snabDialog } from 'common/dialog'; -import LobbyController from '../../ctrl'; +import type LobbyController from '../../ctrl'; import { variantPicker } from './components/variantPicker'; import { timePickerAndSliders } from './components/timePickerAndSliders'; import { gameModeButtons } from './components/gameModeButtons'; diff --git a/ui/lobby/src/view/table.ts b/ui/lobby/src/view/table.ts index 2a7bfacdef7f7..8c463eaf0c11d 100644 --- a/ui/lobby/src/view/table.ts +++ b/ui/lobby/src/view/table.ts @@ -1,7 +1,7 @@ import { h, thunk } from 'snabbdom'; import { bind, onInsert } from 'common/snabbdom'; -import LobbyController from '../ctrl'; -import { GameType } from '../interfaces'; +import type LobbyController from '../ctrl'; +import type { GameType } from '../interfaces'; import renderSetupModal from './setup/modal'; import { numberFormat } from 'common/number'; diff --git a/ui/lobby/src/view/tabs.ts b/ui/lobby/src/view/tabs.ts index 97885153ee0f4..5c531170bcca3 100644 --- a/ui/lobby/src/view/tabs.ts +++ b/ui/lobby/src/view/tabs.ts @@ -1,7 +1,7 @@ import { h } from 'snabbdom'; -import { bind, MaybeVNodes } from 'common/snabbdom'; -import LobbyController from '../ctrl'; -import { Tab } from '../interfaces'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; +import type LobbyController from '../ctrl'; +import type { Tab } from '../interfaces'; function tab(ctrl: LobbyController, key: Tab, active: Tab, content: MaybeVNodes) { return h( diff --git a/ui/lobby/src/view/util.ts b/ui/lobby/src/view/util.ts index 7971709220f01..b9221d06395b6 100644 --- a/ui/lobby/src/view/util.ts +++ b/ui/lobby/src/view/util.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import { MaybeVNodes } from 'common/snabbdom'; +import type { MaybeVNodes } from 'common/snabbdom'; export function tds(bits: MaybeVNodes): MaybeVNodes { return bits.map(bit => h('td', [bit])); diff --git a/ui/lobby/src/xhr.ts b/ui/lobby/src/xhr.ts index 2bf3ac61e935a..aa30261accd8d 100644 --- a/ui/lobby/src/xhr.ts +++ b/ui/lobby/src/xhr.ts @@ -1,15 +1,15 @@ -import * as xhr from 'common/xhr'; +import { json as xhrJson, form } from 'common/xhr'; import debounce from 'debounce-promise'; -import { Pool, Seek } from './interfaces'; +import type { Pool, Seek } from './interfaces'; -export const seeks: () => Promise = debounce(() => xhr.json('/lobby/seeks'), 2000); +export const seeks: () => Promise = debounce(() => xhrJson('/lobby/seeks'), 2000); -export const nowPlaying = () => xhr.json('/account/now-playing').then(o => o.nowPlaying); +export const nowPlaying = () => xhrJson('/account/now-playing').then(o => o.nowPlaying); export const anonPoolSeek = (pool: Pool) => - xhr.json('/setup/hook/' + site.sri, { + xhrJson('/setup/hook/' + site.sri, { method: 'POST', - body: xhr.form({ + body: form({ variant: 1, timeMode: 1, time: pool.lim, diff --git a/ui/mod/src/mod.inquiry.ts b/ui/mod/src/mod.inquiry.ts index 36864d3df559b..108f1b5622ae8 100644 --- a/ui/mod/src/mod.inquiry.ts +++ b/ui/mod/src/mod.inquiry.ts @@ -1,4 +1,4 @@ -import * as xhr from 'common/xhr'; +import { formToXhr } from 'common/xhr'; import { expandMentions } from 'common/richText'; import { storage } from 'common/storage'; @@ -26,8 +26,7 @@ site.load.then(() => { $(this) .parents('form') .each((_, form: HTMLFormElement) => - xhr - .formToXhr(form, this) + formToXhr(form, this) .then(html => $notes.replaceWith(html)) .then(noteStore.remove) .then(() => loadNotes()) diff --git a/ui/mod/src/mod.search.ts b/ui/mod/src/mod.search.ts index 626401e57ee3c..e15e217393a09 100644 --- a/ui/mod/src/mod.search.ts +++ b/ui/mod/src/mod.search.ts @@ -1,4 +1,4 @@ -import * as xhr from 'common/xhr'; +import { text as xhrText } from 'common/xhr'; import extendTablesortNumber from 'common/tablesortNumber'; import tablesort from 'tablesort'; import { checkBoxAll, expandCheckboxZone, selector, shiftClickCheckboxRange } from './checkBoxes'; @@ -9,7 +9,7 @@ site.load.then(() => { .find('.mark-alt') .on('click', async function (this: HTMLAnchorElement) { if (await confirm('Close alt account?')) { - xhr.text(this.getAttribute('href')!, { method: 'post' }); + xhrText(this.getAttribute('href')!, { method: 'post' }); $(this).remove(); } }); @@ -34,7 +34,7 @@ site.load.then(() => { ); if (usernames.length > 0 && (await confirm(`Close ${usernames.length} alt accounts?`))) { console.log(usernames); - await xhr.text('/mod/alt-many', { method: 'post', body: usernames.join(' ') }); + await xhrText('/mod/alt-many', { method: 'post', body: usernames.join(' ') }); location.reload(); } } diff --git a/ui/mod/src/mod.teamAdmin.ts b/ui/mod/src/mod.teamAdmin.ts index faeff268ba17d..758ff46df466a 100644 --- a/ui/mod/src/mod.teamAdmin.ts +++ b/ui/mod/src/mod.teamAdmin.ts @@ -1,6 +1,6 @@ import Tagify from '@yaireo/tagify'; import debounce from 'debounce-promise'; -import * as xhr from 'common/xhr'; +import { json as xhrJson, url as xhrUrl } from 'common/xhr'; import { userComplete } from 'common/userComplete'; site.load.then(() => { @@ -55,7 +55,7 @@ function initTagify(input: HTMLInputElement, maxTags: number) { }, }); const doFetch: (term: string) => Promise = debounce( - (term: string) => xhr.json(xhr.url('/api/player/autocomplete', { term, names: 1, team })), + (term: string) => xhrJson(xhrUrl('/api/player/autocomplete', { term, names: 1, team })), 300, ); tagify.on('input', e => { diff --git a/ui/mod/src/mod.user.ts b/ui/mod/src/mod.user.ts index 1d4020076f8bd..7fcd549c194cf 100644 --- a/ui/mod/src/mod.user.ts +++ b/ui/mod/src/mod.user.ts @@ -1,4 +1,4 @@ -import * as xhr from 'common/xhr'; +import { formToXhr, text as xhrText } from 'common/xhr'; import { debounce } from 'common/timing'; import * as licon from 'common/licon'; import extendTablesortNumber from 'common/tablesortNumber'; @@ -97,7 +97,7 @@ site.load.then(() => { confirmButton(el); $(el).on('submit', () => { $(el).addClass('ready').find('input').prop('disabled', true); - xhr.formToXhr(el).then(html => { + formToXhr(el).then(html => { $zone.find('.mz-section--actions').replaceWith(html); userMod($inZone); }); @@ -113,7 +113,7 @@ site.load.then(() => { makeReady('form.pm-preset select', (el: HTMLSelectElement) => $(el).on('change', () => { const form = $(el).parent('form')[0] as HTMLFormElement; - xhr.text(form.getAttribute('action') + encodeURIComponent(el.value), { method: 'post' }); + xhrText(form.getAttribute('action') + encodeURIComponent(el.value), { method: 'post' }); $(form).html('Sent!'); }), ); @@ -138,7 +138,7 @@ site.load.then(() => { .map((_, input) => $(input).parents('tr').find('td:first-child').data('sort')), ); if (usernames.length > 0 && (await confirm(`Close ${usernames.length} alt accounts?`))) { - await xhr.text('/mod/alt-many', { method: 'post', body: usernames.join(' ') }); + await xhrText('/mod/alt-many', { method: 'post', body: usernames.join(' ') }); reloadZone(); } } @@ -156,7 +156,7 @@ site.load.then(() => { $(el) .find('.button') .on('click', function (this: HTMLAnchorElement) { - xhr.text($(this).attr('href')!, { method: 'post' }); + xhrText($(this).attr('href')!, { method: 'post' }); $(this).parent().parent().toggleClass('blocked'); return false; }); diff --git a/ui/msg/src/ctrl.ts b/ui/msg/src/ctrl.ts index 5e7d8540bda2a..5b6f18721f547 100644 --- a/ui/msg/src/ctrl.ts +++ b/ui/msg/src/ctrl.ts @@ -1,4 +1,4 @@ -import { +import type { MsgData, Contact, Convo, diff --git a/ui/msg/src/msg.ts b/ui/msg/src/msg.ts index 0e9fad3d772fc..3c63386992f44 100644 --- a/ui/msg/src/msg.ts +++ b/ui/msg/src/msg.ts @@ -2,7 +2,7 @@ import view from './view/main'; import { init, classModule, attributesModule } from 'snabbdom'; -import { MsgOpts } from './interfaces'; +import type { MsgOpts } from './interfaces'; import { upgradeData } from './network'; import MsgCtrl from './ctrl'; diff --git a/ui/msg/src/network.ts b/ui/msg/src/network.ts index 5aaa20549552d..c387ae8f410f4 100644 --- a/ui/msg/src/network.ts +++ b/ui/msg/src/network.ts @@ -1,5 +1,5 @@ -import MsgCtrl from './ctrl'; -import { MsgData, Contact, User, Msg, Convo, SearchResult } from './interfaces'; +import type MsgCtrl from './ctrl'; +import type { MsgData, Contact, User, Msg, Convo, SearchResult } from './interfaces'; import { json, form } from 'common/xhr'; import { pubsub } from 'common/pubsub'; diff --git a/ui/msg/src/view/actions.ts b/ui/msg/src/view/actions.ts index afe6107a8d3b9..1590021e1ee6e 100644 --- a/ui/msg/src/view/actions.ts +++ b/ui/msg/src/view/actions.ts @@ -1,9 +1,9 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind } from 'common/snabbdom'; import { confirm } from 'common/dialog'; import { Convo } from '../interfaces'; -import MsgCtrl from '../ctrl'; +import type MsgCtrl from '../ctrl'; export default function renderActions(ctrl: MsgCtrl, convo: Convo): VNode[] { if (convo.user.id == 'lichess') return []; diff --git a/ui/msg/src/view/contact.ts b/ui/msg/src/view/contact.ts index c3227efb31c48..bb7dc6ae0e178 100644 --- a/ui/msg/src/view/contact.ts +++ b/ui/msg/src/view/contact.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; -import { Contact, LastMsg, User } from '../interfaces'; -import MsgCtrl from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import type { Contact, LastMsg, User } from '../interfaces'; +import type MsgCtrl from '../ctrl'; import * as licon from 'common/licon'; import { hookMobileMousedown } from 'common/device'; import { fullName, userLine } from 'common/userLink'; diff --git a/ui/msg/src/view/convo.ts b/ui/msg/src/view/convo.ts index 10eef553665ff..c3c6cfdea10e7 100644 --- a/ui/msg/src/view/convo.ts +++ b/ui/msg/src/view/convo.ts @@ -1,9 +1,9 @@ -import MsgCtrl from '../ctrl'; +import type MsgCtrl from '../ctrl'; import renderActions from './actions'; import renderInteract from './interact'; import renderMsgs from './msgs'; -import { Convo } from '../interfaces'; -import { h, VNode } from 'snabbdom'; +import type { Convo } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { hookMobileMousedown } from 'common/device'; import { userLink } from 'common/userLink'; diff --git a/ui/msg/src/view/interact.ts b/ui/msg/src/view/interact.ts index 9104277f5c67e..0dc14da54f20f 100644 --- a/ui/msg/src/view/interact.ts +++ b/ui/msg/src/view/interact.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bindSubmit } from 'common/snabbdom'; -import { User } from '../interfaces'; -import MsgCtrl from '../ctrl'; +import type { User } from '../interfaces'; +import type MsgCtrl from '../ctrl'; import { throttle } from 'common/timing'; import { alert } from 'common/dialog'; diff --git a/ui/msg/src/view/main.ts b/ui/msg/src/view/main.ts index 588c6d0af49c1..2fa777dc1e826 100644 --- a/ui/msg/src/view/main.ts +++ b/ui/msg/src/view/main.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { spinnerVdom as spinner } from 'common/spinner'; -import MsgCtrl from '../ctrl'; +import type MsgCtrl from '../ctrl'; import renderConvo from './convo'; import renderContact from './contact'; import * as search from './search'; diff --git a/ui/msg/src/view/msgs.ts b/ui/msg/src/view/msgs.ts index e15c6f3eaa276..7b9ff4a6da169 100644 --- a/ui/msg/src/view/msgs.ts +++ b/ui/msg/src/view/msgs.ts @@ -1,11 +1,11 @@ -import { h, VNode } from 'snabbdom'; -import * as xhr from 'common/xhr'; +import { h, type VNode } from 'snabbdom'; +import { json as xhrJson, form as xhrForm } from 'common/xhr'; import { bind } from 'common/snabbdom'; -import { Convo, Msg, Daily } from '../interfaces'; -import * as enhance from './enhance'; +import type { Convo, Msg, Daily } from '../interfaces'; +import { enhance, isMoreThanText, expandLpvs } from './enhance'; import { makeLinkPopups } from 'common/linkPopup'; import { scroller } from './scroller'; -import MsgCtrl from '../ctrl'; +import type MsgCtrl from '../ctrl'; import { alert, confirm } from 'common/dialog'; export default function renderMsgs(ctrl: MsgCtrl, convo: Convo): VNode { @@ -95,12 +95,12 @@ const sameDay = (d: Date, e: Date) => d.getDate() == e.getDate() && d.getMonth() == e.getMonth() && d.getFullYear() == e.getFullYear(); const renderText = (msg: Msg) => - enhance.isMoreThanText(msg.text) + isMoreThanText(msg.text) ? h('t', { hook: { create(_, vnode: VNode) { const el = vnode.elm as HTMLElement; - el.innerHTML = enhance.enhance(msg.text); + el.innerHTML = enhance(msg.text); el.querySelectorAll('img').forEach(c => c.addEventListener('load', scroller.auto, { once: true }), ); @@ -116,17 +116,15 @@ const renderText = (msg: Msg) => const setupMsgs = (insert: boolean) => (vnode: VNode) => { const el = vnode.elm as HTMLElement; if (insert) scroller.init(el); - enhance.expandLpvs(el); + expandLpvs(el); makeLinkPopups(el, 'their a[href^="http"]'); scroller.toMarker() || scroller.auto(); }; const teamUnsub = async (form: HTMLFormElement) => { if (await confirm('Unsubscribe?')) - xhr - .json(form.action, { - method: 'post', - body: xhr.form({ subscribe: false }), - }) - .then(() => alert('Done!')); + xhrJson(form.action, { + method: 'post', + body: xhrForm({ subscribe: false }), + }).then(() => alert('Done!')); }; diff --git a/ui/msg/src/view/search.ts b/ui/msg/src/view/search.ts index 78698d41e028d..177abe4798dbb 100644 --- a/ui/msg/src/view/search.ts +++ b/ui/msg/src/view/search.ts @@ -1,7 +1,7 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { throttle } from 'common/timing'; -import MsgCtrl from '../ctrl'; -import { SearchResult, User } from '../interfaces'; +import type MsgCtrl from '../ctrl'; +import type { SearchResult, User } from '../interfaces'; import renderContacts, { userIcon } from './contact'; import { fullName } from 'common/userLink'; import { hookMobileMousedown } from 'common/device'; diff --git a/ui/notify/src/ctrl.ts b/ui/notify/src/ctrl.ts index 14c0c125c12b1..33f7a53e396da 100644 --- a/ui/notify/src/ctrl.ts +++ b/ui/notify/src/ctrl.ts @@ -1,6 +1,6 @@ -import { Ctrl, NotifyOpts, NotifyData, Redraw } from './interfaces'; +import type { Ctrl, NotifyOpts, NotifyData, Redraw } from './interfaces'; -import * as xhr from 'common/xhr'; +import { json as xhrJson, url as xhrUrl, text as xhrText } from 'common/xhr'; import { storage } from 'common/storage'; export default function makeCtrl(opts: NotifyOpts, redraw: Redraw): Ctrl { @@ -36,7 +36,7 @@ export default function makeCtrl(opts: NotifyOpts, redraw: Redraw): Ctrl { } const loadPage = (page: number) => - xhr.json(xhr.url('/notify', { page: page || 1 })).then( + xhrJson(xhrUrl('/notify', { page: page || 1 })).then( d => update(d), _ => site.announce({ msg: 'Failed to load notifications' }), ); @@ -92,7 +92,7 @@ export default function makeCtrl(opts: NotifyOpts, redraw: Redraw): Ctrl { }; function clear() { - xhr.text('/notify/clear', { method: 'post' }).then( + xhrText('/notify/clear', { method: 'post' }).then( _ => update(emptyNotifyData), _ => site.announce({ msg: 'Failed to clear notifications' }), ); diff --git a/ui/notify/src/interfaces.ts b/ui/notify/src/interfaces.ts index 780fdaa562b9d..67d010848959e 100644 --- a/ui/notify/src/interfaces.ts +++ b/ui/notify/src/interfaces.ts @@ -1,4 +1,4 @@ -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; export interface NotifyOpts { el: Element; diff --git a/ui/notify/src/notify.ts b/ui/notify/src/notify.ts index 57e9a811192c2..b26bc86f1ce84 100644 --- a/ui/notify/src/notify.ts +++ b/ui/notify/src/notify.ts @@ -1,7 +1,7 @@ import { init, classModule, attributesModule } from 'snabbdom'; import makeCtrl from './ctrl'; import view from './view'; -import { NotifyOpts, NotifyData, BumpUnread } from './interfaces'; +import type { NotifyOpts, NotifyData, BumpUnread } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/notify/src/renderers.ts b/ui/notify/src/renderers.ts index 9068359e79f30..e05121bc179a1 100644 --- a/ui/notify/src/renderers.ts +++ b/ui/notify/src/renderers.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { Notification, Renderer, Renderers } from './interfaces'; +import type { Notification, Renderer, Renderers } from './interfaces'; import { timeago } from 'common/i18n'; export default function makeRenderers(): Renderers { diff --git a/ui/notify/src/view.ts b/ui/notify/src/view.ts index e12cf7807b11c..dbcf335ab3dd2 100644 --- a/ui/notify/src/view.ts +++ b/ui/notify/src/view.ts @@ -1,5 +1,5 @@ -import { Ctrl, NotifyData, type Notification } from './interfaces'; -import { h, VNode } from 'snabbdom'; +import type { Ctrl, NotifyData, Notification } from './interfaces'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import makeRenderers from './renderers'; diff --git a/ui/nvui/package.json b/ui/nvui/package.json index 7381ec240b9c8..82e7ce98a42c2 100644 --- a/ui/nvui/package.json +++ b/ui/nvui/package.json @@ -24,7 +24,6 @@ "license": "AGPL-3.0-or-later", "dependencies": { "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*" } } diff --git a/ui/nvui/src/chess.ts b/ui/nvui/src/chess.ts index ff166cd242f54..240140d0b5fa3 100644 --- a/ui/nvui/src/chess.ts +++ b/ui/nvui/src/chess.ts @@ -1,14 +1,13 @@ -import { h, VNode, VNodeChildren } from 'snabbdom'; -import { Dests, Pieces, Rank, File, files } from 'chessground/types'; +import { h, type VNode, type VNodeChildren } from 'snabbdom'; +import { type Pieces, files } from 'chessground/types'; import { invRanks, allKeys } from 'chessground/util'; -import { Api } from 'chessground/api'; -import { Setting, makeSetting } from './setting'; +import { type Setting, makeSetting } from './setting'; import { parseFen } from 'chessops/fen'; import { chessgroundDests } from 'chessops/compat'; -import { SquareName, RULES, Rules } from 'chessops/types'; +import { type SquareName, RULES, type Rules } from 'chessops/types'; import { setupPosition } from 'chessops/variant'; import { parseUci } from 'chessops/util'; -import { SanToUci, sanWriter } from 'chess'; +import { type SanToUci, sanWriter } from 'chess'; import { storage } from 'common/storage'; export type Style = 'uci' | 'san' | 'literate' | 'nato' | 'anna'; @@ -321,7 +320,7 @@ export function renderBoard( positionStyle: PositionStyle, boardStyle: BoardStyle, ): VNode { - const doRankHeader = (rank: Rank): VNode => { + const doRankHeader = (rank: Ranks): VNode => { return h('th', { attrs: { scope: 'row' } }, rank); }; const doFileHeaders = (): VNode => { @@ -329,7 +328,7 @@ export function renderBoard( if (pov === 'black') ths.reverse(); return h('tr', [h('td'), ...ths, h('td')]); }; - const renderPositionStyle = (rank: Rank, file: File, orig: string) => { + const renderPositionStyle = (rank: Ranks, file: Files, orig: string) => { switch (positionStyle) { case 'before': return file.toUpperCase() + rank + ' ' + orig; @@ -340,8 +339,8 @@ export function renderBoard( } }; const doPieceButton = ( - rank: Rank, - file: File, + rank: Ranks, + file: Files, letter: string, color: Color | 'none', text: string, @@ -354,7 +353,7 @@ export function renderBoard( text, ); }; - const doPiece = (rank: Rank, file: File): VNode => { + const doPiece = (rank: Ranks, file: Files): VNode => { const key = (file + rank) as Key; const piece = pieces.get(key); const pieceWrapper = boardStyle === 'table' ? 'td' : 'span'; @@ -370,7 +369,7 @@ export function renderBoard( return h(pieceWrapper, doPieceButton(rank, file, letter, 'none', text)); } }; - const doRank = (pov: Color, rank: Rank): VNode => { + const doRank = (pov: Color, rank: Ranks): VNode => { const rankElements = []; if (boardStyle === 'table') rankElements.push(doRankHeader(rank)); rankElements.push(...files.map(file => doPiece(rank, file))); @@ -682,7 +681,7 @@ function sanToUci(san: string, legalSans: SanToUci): Uci | undefined { return; } -export function inputToLegalUci(input: string, fen: string, chessground: Api): string | undefined { +export function inputToLegalUci(input: string, fen: string, chessground: CgApi): string | undefined { const legalUcis = destsToUcis(chessground.state.movable.dests!), legalSans = sanWriter(fen, legalUcis); let uci = sanToUci(input, legalSans) || input, diff --git a/ui/nvui/src/command.ts b/ui/nvui/src/command.ts index 332ffb5549ece..dc0e6b564afb5 100644 --- a/ui/nvui/src/command.ts +++ b/ui/nvui/src/command.ts @@ -1,5 +1,5 @@ -import { renderPieceKeys, renderPiecesOn, Style } from './chess'; -import { Pieces } from 'chessground/types'; +import { renderPieceKeys, renderPiecesOn, type Style } from './chess'; +import type { Pieces } from 'chessground/types'; export const commands = { piece: { diff --git a/ui/nvui/src/notify.ts b/ui/nvui/src/notify.ts index bafab2e44ac0f..cd844b0853850 100644 --- a/ui/nvui/src/notify.ts +++ b/ui/nvui/src/notify.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { requestIdleCallback } from 'common'; type Notification = { diff --git a/ui/nvui/src/setting.ts b/ui/nvui/src/setting.ts index c8b7b108e58e9..b4159224cceba 100644 --- a/ui/nvui/src/setting.ts +++ b/ui/nvui/src/setting.ts @@ -1,5 +1,5 @@ -import { h, VNode } from 'snabbdom'; -import { type LichessStorage } from 'common/storage'; +import { h, type VNode } from 'snabbdom'; +import type { LichessStorage } from 'common/storage'; export interface Setting { choices: Choices; diff --git a/ui/nvui/tests/command.test.ts b/ui/nvui/tests/command.test.ts index 7b6ca6c4a9996..1d6fb2cba654f 100644 --- a/ui/nvui/tests/command.test.ts +++ b/ui/nvui/tests/command.test.ts @@ -1,6 +1,6 @@ import { expect, test } from 'vitest'; import { commands } from '../src/command'; -import { Pieces } from 'chessground/types'; +import type { Pieces } from 'chessground/types'; const pieces: Pieces = new Map(); pieces.set('a1', { color: 'white', role: 'king' }); diff --git a/ui/opening/src/chart.ts b/ui/opening/src/chart.ts index 691b14c576c77..77b3beb3b0510 100644 --- a/ui/opening/src/chart.ts +++ b/ui/opening/src/chart.ts @@ -1,7 +1,7 @@ import * as chart from 'chart.js'; import 'chartjs-adapter-dayjs-4'; import dayjs from 'dayjs'; -import { OpeningPage } from './interfaces'; +import type { OpeningPage } from './interfaces'; chart.Chart.register( chart.LineController, diff --git a/ui/opening/src/opening.ts b/ui/opening/src/opening.ts index ad6096ab6c48b..a9e360ff347f3 100644 --- a/ui/opening/src/opening.ts +++ b/ui/opening/src/opening.ts @@ -1,12 +1,11 @@ import Lpv from 'lichess-pgn-viewer'; import { initMiniBoards } from 'common/miniBoard'; import { requestIdleCallback } from 'common'; -import { OpeningPage } from './interfaces'; +import type { OpeningPage } from './interfaces'; import { renderHistoryChart } from './chart'; import { init as searchEngine } from './search'; import panels from './panels'; import renderPlaceholderWiki from './wiki'; -import { Config } from 'chessground/config'; export function initModule(data?: OpeningPage): void { data ? page(data) : searchEngine(); @@ -41,7 +40,7 @@ function page(data: OpeningPage) { }); } -const cgConfig: Config = { +const cgConfig: CgConfig = { coordinates: false, }; diff --git a/ui/opening/src/search.ts b/ui/opening/src/search.ts index c6c65123cc0eb..e316b74936664 100644 --- a/ui/opening/src/search.ts +++ b/ui/opening/src/search.ts @@ -1,4 +1,4 @@ -import * as xhr from 'common/xhr'; +import { text as xhrText, url as xhrUrl } from 'common/xhr'; import debounce from 'debounce-promise'; import { initMiniBoards } from 'common/miniBoard'; @@ -6,7 +6,7 @@ export function init(): void { const debounced = debounce((str: string) => { const q = str.trim(); if (q) - xhr.text(xhr.url('/opening', { q })).then((html: string) => { + xhrText(xhrUrl('/opening', { q })).then((html: string) => { selectResults().replaceWith(html).removeClass('none'); initMiniBoards(); }); diff --git a/ui/opening/src/wiki.ts b/ui/opening/src/wiki.ts index 6690b1e0808db..23e0c42c33fb6 100644 --- a/ui/opening/src/wiki.ts +++ b/ui/opening/src/wiki.ts @@ -1,4 +1,4 @@ -import { OpeningPage } from './interfaces'; +import type { OpeningPage } from './interfaces'; export default function wikiTheory(data: OpeningPage): void { $('.opening__wiki__markup__placeholder').each(function (this: HTMLDivElement) { diff --git a/ui/puz/package.json b/ui/puz/package.json index 71d9a50188398..93523dc979baf 100644 --- a/ui/puz/package.json +++ b/ui/puz/package.json @@ -17,7 +17,6 @@ "author": "Thibault Duplessis", "license": "AGPL-3.0-or-later", "dependencies": { - "chessops": "^0.14.2", "common": "workspace:*" } } diff --git a/ui/puz/src/clock.ts b/ui/puz/src/clock.ts index afed57c99da71..ab1089ff733b8 100644 --- a/ui/puz/src/clock.ts +++ b/ui/puz/src/clock.ts @@ -1,4 +1,4 @@ -import { Config } from './interfaces'; +import type { Config } from './interfaces'; import { getNow } from './util'; export class Clock { diff --git a/ui/puz/src/combo.ts b/ui/puz/src/combo.ts index dff706c33a8fc..a29c7c60ed955 100644 --- a/ui/puz/src/combo.ts +++ b/ui/puz/src/combo.ts @@ -1,4 +1,4 @@ -import { Config, TimeMod } from './interfaces'; +import type { Config, TimeMod } from './interfaces'; import { getNow } from './util'; export class Combo { diff --git a/ui/puz/src/current.ts b/ui/puz/src/current.ts index 50053a69848ca..c09efa3591726 100644 --- a/ui/puz/src/current.ts +++ b/ui/puz/src/current.ts @@ -1,6 +1,6 @@ import { Chess, opposite, parseUci, san } from 'chessops'; import { parseFen } from 'chessops/fen'; -import { Puzzle } from './interfaces'; +import type { Puzzle } from './interfaces'; import { getNow } from './util'; export default class CurrentPuzzle { diff --git a/ui/puz/src/filters.ts b/ui/puz/src/filters.ts index cc8a6d05c0d1c..4670a9ba6279e 100644 --- a/ui/puz/src/filters.ts +++ b/ui/puz/src/filters.ts @@ -1,5 +1,4 @@ -import { Redraw } from 'chessground/types'; -import { toggle, Toggle } from 'common'; +import { toggle, type Toggle } from 'common'; export class PuzFilters { fail: Toggle; diff --git a/ui/puz/src/interfaces.ts b/ui/puz/src/interfaces.ts index 5bc94174e6f21..85bdaf5992f8c 100644 --- a/ui/puz/src/interfaces.ts +++ b/ui/puz/src/interfaces.ts @@ -1,8 +1,8 @@ import type { Clock } from './clock'; import type { Combo } from './combo'; import type CurrentPuzzle from './current'; -import { PuzFilters } from './filters'; -import * as Prefs from 'common/prefs'; +import type { PuzFilters } from './filters'; +import type { Coords } from 'common/prefs'; export interface PuzCtrl { run: Run; @@ -11,7 +11,7 @@ export interface PuzCtrl { } export interface PuzPrefs { - coords: Prefs.Coords; + coords: Coords; is3d: boolean; destination: boolean; rookCastle: boolean; diff --git a/ui/puz/src/run.ts b/ui/puz/src/run.ts index 72fd7efa2cd08..56d44e6f18f16 100644 --- a/ui/puz/src/run.ts +++ b/ui/puz/src/run.ts @@ -1,5 +1,4 @@ -import { Run } from './interfaces'; -import { Config as CgConfig } from 'chessground/config'; +import type { Run } from './interfaces'; import { opposite, uciToMove } from 'chessground/util'; import { makeFen } from 'chessops/fen'; import { chessgroundDests } from 'chessops/compat'; diff --git a/ui/puz/src/util.ts b/ui/puz/src/util.ts index 9129ba36bacdd..f0bd38af3413d 100644 --- a/ui/puz/src/util.ts +++ b/ui/puz/src/util.ts @@ -1,4 +1,4 @@ -import { Puzzle } from './interfaces'; +import type { Puzzle } from './interfaces'; import { opposite } from 'chessops'; import { parseFen } from 'chessops/fen'; diff --git a/ui/puz/src/view/chessground.ts b/ui/puz/src/view/chessground.ts index 33c47b4c69844..0a5589ca0c110 100644 --- a/ui/puz/src/view/chessground.ts +++ b/ui/puz/src/view/chessground.ts @@ -1,7 +1,6 @@ import resizeHandle from 'common/resize'; -import { Config as CgConfig } from 'chessground/config'; -import { PuzPrefs, UserMove } from '../interfaces'; -import * as Prefs from 'common/prefs'; +import type { PuzPrefs, UserMove } from '../interfaces'; +import { ShowResizeHandle, Coords } from 'common/prefs'; import { storage } from 'common/storage'; export function makeConfig(opts: CgConfig, pref: PuzPrefs, userMove: UserMove): CgConfig { @@ -11,8 +10,8 @@ export function makeConfig(opts: CgConfig, pref: PuzPrefs, userMove: UserMove): turnColor: opts.turnColor, check: opts.check, lastMove: opts.lastMove, - coordinates: pref.coords !== Prefs.Coords.Hidden, - coordinatesOnSquares: pref.coords === Prefs.Coords.All, + coordinates: pref.coords !== Coords.Hidden, + coordinatesOnSquares: pref.coords === Coords.All, addPieceZIndex: pref.is3d, addDimensionsCssVarsTo: document.body, movable: { @@ -32,7 +31,7 @@ export function makeConfig(opts: CgConfig, pref: PuzPrefs, userMove: UserMove): events: { move: userMove, insert(elements) { - resizeHandle(elements, Prefs.ShowResizeHandle.OnlyAtStart, 0, p => p == 0); + resizeHandle(elements, ShowResizeHandle.OnlyAtStart, 0, p => p == 0); }, }, premovable: { diff --git a/ui/puz/src/view/clock.ts b/ui/puz/src/view/clock.ts index 0650afcdc741d..b5da2e1d63080 100644 --- a/ui/puz/src/view/clock.ts +++ b/ui/puz/src/view/clock.ts @@ -1,7 +1,7 @@ import { defined } from 'common'; import { getNow } from '../util'; -import { h, VNode } from 'snabbdom'; -import { Run, TimeMod } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { Run, TimeMod } from '../interfaces'; type OnFlag = () => void; diff --git a/ui/puz/src/view/history.ts b/ui/puz/src/view/history.ts index ba5f14455a896..0d40d681f8493 100644 --- a/ui/puz/src/view/history.ts +++ b/ui/puz/src/view/history.ts @@ -1,11 +1,11 @@ import { initMiniBoardWith } from 'common/miniBoard'; -import { PuzCtrl } from '../interfaces'; +import type { PuzCtrl } from '../interfaces'; import { Chess } from 'chessops/chess'; -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { parseFen, makeFen } from 'chessops/fen'; import { parseUci } from 'chessops/util'; import { onInsert } from 'common/snabbdom'; -import { Toggle } from 'common'; +import type { Toggle } from 'common'; const slowPuzzleIds = (ctrl: PuzCtrl): Set | undefined => { if (!ctrl.filters.slow() || !ctrl.run.history.length) return undefined; diff --git a/ui/puz/src/view/util.ts b/ui/puz/src/view/util.ts index 9057aebd229bf..e9f17dbcce22e 100644 --- a/ui/puz/src/view/util.ts +++ b/ui/puz/src/view/util.ts @@ -1,5 +1,5 @@ -import { h, VNode } from 'snabbdom'; -import { Config, Run } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { Config, Run } from '../interfaces'; import { getNow } from '../util'; export const playModifiers = ( diff --git a/ui/puzzle/package.json b/ui/puzzle/package.json index dafc84fc1bddc..75ae2afaab9ab 100644 --- a/ui/puzzle/package.json +++ b/ui/puzzle/package.json @@ -16,7 +16,6 @@ "ceval": "workspace:*", "chart.js": "4.4.6", "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*", "keyboardMove": "workspace:*", "nvui": "workspace:*", diff --git a/ui/puzzle/src/autoShape.ts b/ui/puzzle/src/autoShape.ts index 3411b0177ebc4..28f209fc732bd 100644 --- a/ui/puzzle/src/autoShape.ts +++ b/ui/puzzle/src/autoShape.ts @@ -1,8 +1,8 @@ -import { winningChances, CevalCtrl } from 'ceval'; +import { winningChances, type CevalCtrl } from 'ceval'; import { annotationShapes } from 'chess/glyphs'; -import { DrawModifiers, DrawShape } from 'chessground/draw'; +import type { DrawModifiers, DrawShape } from 'chessground/draw'; import { opposite, parseUci, makeSquare } from 'chessops/util'; -import { NormalMove, Square } from 'chessops/types'; +import type { NormalMove, Square } from 'chessops/types'; interface Opts { node: Tree.Node; diff --git a/ui/puzzle/src/control.ts b/ui/puzzle/src/control.ts index 36578220460f2..f8d8ec6973b93 100644 --- a/ui/puzzle/src/control.ts +++ b/ui/puzzle/src/control.ts @@ -1,5 +1,5 @@ import { path as treePath } from 'tree'; -import PuzzleCtrl from './ctrl'; +import type PuzzleCtrl from './ctrl'; export function canGoForward(ctrl: PuzzleCtrl): boolean { return ctrl.node.children.length > 0; diff --git a/ui/puzzle/src/ctrl.ts b/ui/puzzle/src/ctrl.ts index 544242b1ceb37..b7c669bd32de1 100755 --- a/ui/puzzle/src/ctrl.ts +++ b/ui/puzzle/src/ctrl.ts @@ -6,7 +6,7 @@ import moveTest from './moveTest'; import PuzzleSession from './session'; import PuzzleStreak from './streak'; import { throttle } from 'common/timing'; -import { +import type { PuzzleOpts, PuzzleData, MoveTest, @@ -16,29 +16,26 @@ import { PuzzleRound, RoundThemes, } from './interfaces'; -import { Api as CgApi } from 'chessground/api'; -import { build as treeBuild, ops as treeOps, path as treePath, TreeWrapper } from 'tree'; +import { build as treeBuild, ops as treeOps, path as treePath, type TreeWrapper } from 'tree'; import { Chess, normalizeMove } from 'chessops/chess'; import { chessgroundDests, scalachessCharPair } from 'chessops/compat'; -import { Config as CgConfig } from 'chessground/config'; import { CevalCtrl } from 'ceval'; -import { makeVoiceMove, VoiceMove } from 'voice'; -import { ctrl as makeKeyboardMove, KeyboardMove, KeyboardMoveRootCtrl } from 'keyboardMove'; -import { Deferred, defer } from 'common/defer'; -import { defined, prop, Prop, propWithEffect, Toggle, toggle, requestIdleCallback } from 'common'; +import { makeVoiceMove, type VoiceMove } from 'voice'; +import { ctrl as makeKeyboardMove, type KeyboardMove, type KeyboardMoveRootCtrl } from 'keyboardMove'; +import { type Deferred, defer } from 'common/defer'; +import { defined, prop, type Prop, propWithEffect, type Toggle, toggle, requestIdleCallback } from 'common'; import { makeSanAndPlay } from 'chessops/san'; import { parseFen, makeFen } from 'chessops/fen'; import { parseSquare, parseUci, makeSquare, makeUci, opposite } from 'chessops/util'; import { pgnToTree, mergeSolution, nextCorrectMove } from './moveTree'; import { PromotionCtrl } from 'chess/promotion'; -import { Role, Move, Outcome } from 'chessops/types'; -import { StoredProp, storedBooleanProp, storedBooleanPropWithEffect, storage } from 'common/storage'; +import type { Role, Move, Outcome } from 'chessops/types'; +import { type StoredProp, storedBooleanProp, storedBooleanPropWithEffect, storage } from 'common/storage'; import { fromNodeList } from 'tree/dist/path'; import Report from './report'; import { last } from 'tree/dist/ops'; import { uciToMove } from 'chessground/util'; -import { Redraw } from 'common/snabbdom'; -import { ParentCtrl } from 'ceval/src/types'; +import type { ParentCtrl } from 'ceval/src/types'; import { pubsub } from 'common/pubsub'; import { alert } from 'common/dialog'; diff --git a/ui/puzzle/src/interfaces.ts b/ui/puzzle/src/interfaces.ts index d2a9e8d51ed36..2c008cc84480c 100644 --- a/ui/puzzle/src/interfaces.ts +++ b/ui/puzzle/src/interfaces.ts @@ -1,10 +1,9 @@ -import { Move } from 'chessops/types'; -import { VNode } from 'snabbdom'; -import * as Prefs from 'common/prefs'; +import type { Move } from 'chessops/types'; +import type { VNode } from 'snabbdom'; +import type { Coords } from 'common/prefs'; import perfIcons from 'common/perfIcons'; -import PuzzleCtrl from './ctrl'; -import { FEN } from 'chessground/types'; -import { ExternalEngineInfo } from 'ceval'; +import type PuzzleCtrl from './ctrl'; +import type { ExternalEngineInfo } from 'ceval'; export type PuzzleId = string; export type ThemeKey = keyof I18n['puzzleTheme']; @@ -40,7 +39,7 @@ export interface PuzzleOpts { } export interface PuzzlePrefs { - coords: Prefs.Coords; + coords: Coords; is3d: boolean; destination: boolean; rookCastle: boolean; diff --git a/ui/puzzle/src/keyboard.ts b/ui/puzzle/src/keyboard.ts index 10e4288f17019..78538e662b01d 100644 --- a/ui/puzzle/src/keyboard.ts +++ b/ui/puzzle/src/keyboard.ts @@ -1,5 +1,5 @@ import * as control from './control'; -import PuzzleCtrl from './ctrl'; +import type PuzzleCtrl from './ctrl'; import { snabDialog } from 'common/dialog'; import { pubsub } from 'common/pubsub'; diff --git a/ui/puzzle/src/moveTest.ts b/ui/puzzle/src/moveTest.ts index 282a509832b7d..0a8cf85f19a17 100644 --- a/ui/puzzle/src/moveTest.ts +++ b/ui/puzzle/src/moveTest.ts @@ -1,10 +1,15 @@ -import { altCastles } from 'chess'; import { parseUci } from 'chessops/util'; import { path as pathOps } from 'tree'; -import { MoveTest } from './interfaces'; -import PuzzleCtrl from './ctrl'; +import type { MoveTest } from './interfaces'; +import type PuzzleCtrl from './ctrl'; type MoveTestReturn = undefined | 'fail' | 'win' | MoveTest; +const altCastles = { + e1a1: 'e1c1', + e1h1: 'e1g1', + e8a8: 'e8c8', + e8h8: 'e8g8', +}; type AltCastle = keyof typeof altCastles; diff --git a/ui/puzzle/src/moveTree.ts b/ui/puzzle/src/moveTree.ts index ef428b86dfa0a..2ac44224e0a70 100644 --- a/ui/puzzle/src/moveTree.ts +++ b/ui/puzzle/src/moveTree.ts @@ -3,10 +3,9 @@ import { INITIAL_FEN, makeFen, parseFen } from 'chessops/fen'; import { makeSan, parseSan } from 'chessops/san'; import { makeSquare, makeUci, parseUci } from 'chessops/util'; import { scalachessCharPair } from 'chessops/compat'; -import { TreeWrapper } from 'tree'; -import { path as pathOps } from 'tree'; -import { isNormal, Move, NormalMove } from 'chessops/types'; -import PuzzleCtrl from './ctrl'; +import { type TreeWrapper, path as pathOps } from 'tree'; +import { isNormal, type Move, type NormalMove } from 'chessops/types'; +import type PuzzleCtrl from './ctrl'; export function pgnToTree(pgn: San[]): Tree.Node { const pos = Chess.default(); diff --git a/ui/puzzle/src/plugins/puzzle.nvui.ts b/ui/puzzle/src/plugins/puzzle.nvui.ts index c994f4ec0ff26..0afcb870e991e 100644 --- a/ui/puzzle/src/plugins/puzzle.nvui.ts +++ b/ui/puzzle/src/plugins/puzzle.nvui.ts @@ -1,4 +1,4 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { puzzleBox, renderDifficultyForm, userBox } from '../view/side'; import theme from '../view/theme'; import { @@ -26,11 +26,10 @@ import { makeConfig } from '../view/chessground'; import { renderSetting } from 'nvui/setting'; import { Notify } from 'nvui/notify'; import { commands } from 'nvui/command'; -import * as control from '../control'; +import { next as controlNext } from '../control'; import { bind, onInsert } from 'common/snabbdom'; -import { Api } from 'chessground/api'; import { throttle } from 'common/timing'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleCtrl from '../ctrl'; import { Chessground as makeChessground } from 'chessground'; const throttled = (sound: string) => throttle(100, () => site.sound.play(sound)); @@ -246,7 +245,7 @@ function onSubmit( notify: (txt: string) => void, style: () => Style, $input: Cash, - ground: Api, + ground: CgApi, ): () => false { return () => { let input = castlingFlavours(($input.val() as string).trim()); @@ -309,7 +308,7 @@ function viewOrAdvanceSolution(ctrl: PuzzleCtrl, notify: (txt: string) => void): next = nextNode(node), nextNext = nextNode(next); if (isInSolution(next) || (isInSolution(node) && isInSolution(nextNext))) { - control.next(ctrl); + controlNext(ctrl); ctrl.redraw(); } else if (isInSolution(node)) { notify('Puzzle complete!'); diff --git a/ui/puzzle/src/puzzle.ts b/ui/puzzle/src/puzzle.ts index cf14ad4b63d36..5f24e5f159d77 100644 --- a/ui/puzzle/src/puzzle.ts +++ b/ui/puzzle/src/puzzle.ts @@ -2,7 +2,7 @@ import { attributesModule, classModule, init } from 'snabbdom'; import PuzzleCtrl from './ctrl'; import menuHover from 'common/menuHover'; import view from './view/main'; -import { PuzzleOpts, NvuiPlugin } from './interfaces'; +import type { PuzzleOpts, NvuiPlugin } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/puzzle/src/report.ts b/ui/puzzle/src/report.ts index 8b8552d3d5328..0ec160a6e77ff 100644 --- a/ui/puzzle/src/report.ts +++ b/ui/puzzle/src/report.ts @@ -1,9 +1,9 @@ -import * as xhr from './xhr'; -import PuzzleCtrl from './ctrl'; -import { PuzzleId, ThemeKey } from './interfaces'; +import { report as xhrReport } from './xhr'; +import type PuzzleCtrl from './ctrl'; +import type { PuzzleId, ThemeKey } from './interfaces'; import { winningChances } from 'ceval'; import * as licon from 'common/licon'; -import { StoredProp, storedIntProp } from 'common/storage'; +import { type StoredProp, storedIntProp } from 'common/storage'; import { domDialog } from 'common/dialog'; export default class Report { @@ -95,7 +95,7 @@ export default class Report { dlg.close(); }); $('.apply', dlg.view).on('click', () => { - xhr.report(puzzleId, reason); + xhrReport(puzzleId, reason); dlg.close(); }); dlg.showModal(); diff --git a/ui/puzzle/src/session.ts b/ui/puzzle/src/session.ts index 350910b1cf811..fc5bf8691d7a9 100644 --- a/ui/puzzle/src/session.ts +++ b/ui/puzzle/src/session.ts @@ -1,6 +1,6 @@ import { prop } from 'common'; import { storedJsonProp } from 'common/storage'; -import { ThemeKey } from './interfaces'; +import type { ThemeKey } from './interfaces'; interface SessionRound { id: string; diff --git a/ui/puzzle/src/streak.ts b/ui/puzzle/src/streak.ts index b730bcb4bb8b7..0e3c88cb1a0cb 100644 --- a/ui/puzzle/src/streak.ts +++ b/ui/puzzle/src/streak.ts @@ -1,5 +1,6 @@ -import { StoredJsonProp, storedJsonProp } from 'common/storage'; -import { PuzzleData, Puzzle, PuzzleId, PuzzleGame } from './interfaces'; +import type { Prop } from 'common'; +import { storedJsonProp } from 'common/storage'; +import type { PuzzleData, Puzzle, PuzzleId, PuzzleGame } from './interfaces'; interface Current { puzzle: Puzzle; @@ -16,7 +17,7 @@ interface StreakData { export default class PuzzleStreak { data: StreakData; fail = false; - store: StoredJsonProp; + store: Prop; constructor(data: PuzzleData) { this.store = storedJsonProp(`puzzle.streak.${data.user?.id || 'anon'}`, () => null); diff --git a/ui/puzzle/src/view/after.ts b/ui/puzzle/src/view/after.ts index ebbadaba5594e..13dfc81ae6f4c 100644 --- a/ui/puzzle/src/view/after.ts +++ b/ui/puzzle/src/view/after.ts @@ -1,8 +1,7 @@ import * as licon from 'common/licon'; -import { MaybeVNodes, bind, dataIcon, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; +import { type VNode, type MaybeVNodes, bind, dataIcon, looseH as h } from 'common/snabbdom'; import * as router from 'common/router'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleCtrl from '../ctrl'; const renderVote = (ctrl: PuzzleCtrl): VNode => h( diff --git a/ui/puzzle/src/view/boardMenu.ts b/ui/puzzle/src/view/boardMenu.ts index ebdb06992856b..62f51332d54f5 100644 --- a/ui/puzzle/src/view/boardMenu.ts +++ b/ui/puzzle/src/view/boardMenu.ts @@ -2,7 +2,7 @@ import { h } from 'snabbdom'; import { toggle } from 'common'; import { menu as menuDropdown } from 'board/menu'; import { boolPrefXhrToggle } from 'common/controls'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleCtrl from '../ctrl'; export default function (ctrl: PuzzleCtrl) { return menuDropdown(ctrl.redraw, ctrl.menu, menu => [ diff --git a/ui/puzzle/src/view/chessground.ts b/ui/puzzle/src/view/chessground.ts index c9587200c286d..6a38c180d885b 100644 --- a/ui/puzzle/src/view/chessground.ts +++ b/ui/puzzle/src/view/chessground.ts @@ -1,8 +1,7 @@ import resizeHandle from 'common/resize'; -import { Config as CgConfig } from 'chessground/config'; -import { h, VNode } from 'snabbdom'; -import * as Prefs from 'common/prefs'; -import PuzzleCtrl from '../ctrl'; +import { h, type VNode } from 'snabbdom'; +import { Coords, ShowResizeHandle } from 'common/prefs'; +import type PuzzleCtrl from '../ctrl'; import { storage } from 'common/storage'; import { Chessground as makeChessground } from 'chessground'; @@ -23,8 +22,8 @@ export function makeConfig(ctrl: PuzzleCtrl): CgConfig { turnColor: opts.turnColor, check: opts.check, lastMove: opts.lastMove, - coordinates: ctrl.pref.coords !== Prefs.Coords.Hidden, - coordinatesOnSquares: ctrl.pref.coords === Prefs.Coords.All, + coordinates: ctrl.pref.coords !== Coords.Hidden, + coordinatesOnSquares: ctrl.pref.coords === Coords.All, addPieceZIndex: ctrl.pref.is3d, addDimensionsCssVarsTo: document.body, movable: { @@ -44,7 +43,7 @@ export function makeConfig(ctrl: PuzzleCtrl): CgConfig { events: { move: ctrl.userMove, insert(elements) { - resizeHandle(elements, Prefs.ShowResizeHandle.Always, ctrl.node.ply); + resizeHandle(elements, ShowResizeHandle.Always, ctrl.node.ply); }, }, premovable: { diff --git a/ui/puzzle/src/view/feedback.ts b/ui/puzzle/src/view/feedback.ts index e5c242e6f219f..4af90e3e20a5c 100644 --- a/ui/puzzle/src/view/feedback.ts +++ b/ui/puzzle/src/view/feedback.ts @@ -1,7 +1,7 @@ -import { bind, MaybeVNode } from 'common/snabbdom'; -import { h, VNode } from 'snabbdom'; +import { bind, type MaybeVNode } from 'common/snabbdom'; +import { h, type VNode } from 'snabbdom'; import afterView from './after'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleCtrl from '../ctrl'; const viewSolution = (ctrl: PuzzleCtrl): VNode => ctrl.streak @@ -17,7 +17,7 @@ const viewSolution = (ctrl: PuzzleCtrl): VNode => ? h( 'a.button' + (ctrl.showHint() ? '' : '.button-empty'), { hook: bind('click', ctrl.toggleHint) }, - 'Hint', + i18n.site.getAHint, ) : undefined, h('a.button.button-empty', { hook: bind('click', ctrl.viewSolution) }, i18n.site.viewTheSolution), diff --git a/ui/puzzle/src/view/main.ts b/ui/puzzle/src/view/main.ts index fa70aea05f9fe..30209ae81bc20 100644 --- a/ui/puzzle/src/view/main.ts +++ b/ui/puzzle/src/view/main.ts @@ -1,12 +1,12 @@ import * as control from '../control'; -import * as keyboard from '../keyboard'; -import * as side from './side'; +import { view as keyboardView } from '../keyboard'; +import { replay, puzzleBox, userBox, streakBox, config } from './side'; import theme from './theme'; import chessground from './chessground'; import feedbackView from './feedback'; import * as licon from 'common/licon'; import { stepwiseScroll } from 'common/controls'; -import { VNode, h } from 'snabbdom'; +import { type VNode, h } from 'snabbdom'; import { onInsert, bindNonPassive, looseH as lh } from 'common/snabbdom'; import { bindMobileMousedown } from 'common/device'; import { render as treeView } from './tree'; @@ -15,8 +15,8 @@ import { renderVoiceBar } from 'voice'; import { render as renderKeyboardMove } from 'keyboardMove'; import { toggleButton as boardMenuToggleButton } from 'board/menu'; import boardMenu from './boardMenu'; -import * as Prefs from 'common/prefs'; -import PuzzleCtrl from '../ctrl'; +import { Coords } from 'common/prefs'; +import type PuzzleCtrl from '../ctrl'; import { dispatchChessgroundResize } from 'common/resize'; import { storage } from 'common/storage'; @@ -78,7 +78,7 @@ export default function (ctrl: PuzzleCtrl): VNode { hook: { postpatch(old, vnode) { if (old.data!.gaugeOn !== gaugeOn) { - if (ctrl.pref.coords === Prefs.Coords.Outside) { + if (ctrl.pref.coords === Coords.Outside) { $('body').toggleClass('coords-in', gaugeOn).toggleClass('coords-out', !gaugeOn); } dispatchChessgroundResize(); @@ -89,10 +89,10 @@ export default function (ctrl: PuzzleCtrl): VNode { }, [ lh('aside.puzzle__side', [ - side.replay(ctrl), - side.puzzleBox(ctrl), - ctrl.streak ? side.streakBox(ctrl) : side.userBox(ctrl), - side.config(ctrl), + replay(ctrl), + puzzleBox(ctrl), + ctrl.streak ? streakBox(ctrl) : userBox(ctrl), + config(ctrl), theme(ctrl), ]), lh( @@ -136,7 +136,7 @@ export default function (ctrl: PuzzleCtrl): VNode { controls(ctrl), ctrl.keyboardMove && renderKeyboardMove(ctrl.keyboardMove), session(ctrl), - ctrl.keyboardHelp() && keyboard.view(ctrl), + ctrl.keyboardHelp() && keyboardView(ctrl), ], ); } diff --git a/ui/puzzle/src/view/side.ts b/ui/puzzle/src/view/side.ts index 2a5c23a930827..7b3d141ced170 100644 --- a/ui/puzzle/src/view/side.ts +++ b/ui/puzzle/src/view/side.ts @@ -1,13 +1,12 @@ -import { Puzzle, PuzzleGame, PuzzleDifficulty } from '../interfaces'; +import type { Puzzle, PuzzleGame, PuzzleDifficulty } from '../interfaces'; import * as licon from 'common/licon'; -import { dataIcon, onInsert, MaybeVNode, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; +import { type VNode, dataIcon, onInsert, type MaybeVNode, looseH as h } from 'common/snabbdom'; import { numberFormat } from 'common/number'; import perfIcons from 'common/perfIcons'; -import * as router from 'common/router'; +import { withLang } from 'common/router'; import { userLink } from 'common/userLink'; -import PuzzleStreak from '../streak'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleStreak from '../streak'; +import type PuzzleCtrl from '../ctrl'; export function puzzleBox(ctrl: PuzzleCtrl): VNode { const data = ctrl.data; @@ -37,7 +36,7 @@ const puzzleInfos = (ctrl: PuzzleCtrl, puzzle: Puzzle): VNode => 'a', { attrs: { - href: router.withLang(`/training/${puzzle.id}`), + href: withLang(`/training/${puzzle.id}`), ...(ctrl.streak ? { target: '_blank', rel: 'noopener' } : {}), }, }, @@ -101,7 +100,7 @@ export const userBox = (ctrl: PuzzleCtrl): VNode => { if (!data.user) return h('div.puzzle__side__user', [ h('p', i18n.puzzle.toGetPersonalizedPuzzles), - h('a.button', { attrs: { href: router.withLang('/signup') } }, i18n.site.signUp), + h('a.button', { attrs: { href: withLang('/signup') } }, i18n.site.signUp), ]); const diff = ctrl.round?.ratingDiff, ratedId = `puzzle-toggle-rated_hint-${ctrl.hintHasBeenShown()}`; diff --git a/ui/puzzle/src/view/theme.ts b/ui/puzzle/src/view/theme.ts index a073d1eb18790..2cfba49024886 100644 --- a/ui/puzzle/src/view/theme.ts +++ b/ui/puzzle/src/view/theme.ts @@ -1,10 +1,9 @@ import * as licon from 'common/licon'; -import * as router from 'common/router'; -import { MaybeVNode, bind, dataIcon, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; -import { ThemeKey, RoundThemes } from '../interfaces'; +import { withLang } from 'common/router'; +import { type VNode, type MaybeVNode, bind, dataIcon, looseH as h } from 'common/snabbdom'; +import type { ThemeKey, RoundThemes } from '../interfaces'; import { renderColorForm } from './side'; -import PuzzleCtrl from '../ctrl'; +import type PuzzleCtrl from '../ctrl'; const studyUrl = 'https://lichess.org/study/viiWlKjv'; @@ -14,7 +13,7 @@ export default function theme(ctrl: PuzzleCtrl): MaybeVNode { const showEditor = ctrl.mode == 'view' && !ctrl.autoNexting(); if (data.replay) return showEditor ? h('div.puzzle__side__theme', editor(ctrl)) : null; const puzzleMenu = (v: VNode): VNode => - h('a', { attrs: { href: router.withLang(`/training/${angle.opening ? 'openings' : 'themes'}`) } }, v); + h('a', { attrs: { href: withLang(`/training/${angle.opening ? 'openings' : 'themes'}`) } }, v); return ctrl.streak ? null : ctrl.isDaily diff --git a/ui/puzzle/src/view/tree.ts b/ui/puzzle/src/view/tree.ts index ee1c2d1b1fdb9..7b0cb023fa1b3 100644 --- a/ui/puzzle/src/view/tree.ts +++ b/ui/puzzle/src/view/tree.ts @@ -1,10 +1,10 @@ -import { VNode, Classes } from 'snabbdom'; +import type { VNode, Classes } from 'snabbdom'; import { defined } from 'common'; import { throttle } from 'common/timing'; import { renderEval as normalizeEval } from 'ceval'; import { path as treePath } from 'tree'; -import { MaybeVNode, LooseVNodes, looseH as h } from 'common/snabbdom'; -import PuzzleCtrl from '../ctrl'; +import { type MaybeVNode, type LooseVNodes, looseH as h } from 'common/snabbdom'; +import type PuzzleCtrl from '../ctrl'; interface Ctx { ctrl: PuzzleCtrl; diff --git a/ui/puzzle/src/xhr.ts b/ui/puzzle/src/xhr.ts index 6d51c05144ba2..b7d87858845b7 100644 --- a/ui/puzzle/src/xhr.ts +++ b/ui/puzzle/src/xhr.ts @@ -1,5 +1,5 @@ -import * as xhr from 'common/xhr'; -import PuzzleStreak from './streak'; +import { json as xhrJson, form as xhrForm, text as xhrText } from 'common/xhr'; +import type PuzzleStreak from './streak'; import { throttlePromiseDelay } from 'common/timing'; import { defined } from 'common'; import { PuzzleReplay, PuzzleResult, ThemeKey } from './interfaces'; @@ -14,9 +14,9 @@ export const complete = ( streak?: PuzzleStreak, color?: Color, ): Promise => - xhr.json(`/training/complete/${theme}/${puzzleId}`, { + xhrJson(`/training/complete/${theme}/${puzzleId}`, { method: 'POST', - body: xhr.form({ + body: xhrForm({ win, ...(replay ? { replayDays: replay.days } : {}), ...(streak ? { streakId: streak.nextId(), streakScore: streak.data.index } : {}), @@ -26,28 +26,28 @@ export const complete = ( }); export const vote = (puzzleId: string, vote: boolean): Promise => - xhr.json(`/training/${puzzleId}/vote`, { + xhrJson(`/training/${puzzleId}/vote`, { method: 'POST', - body: xhr.form({ vote }), + body: xhrForm({ vote }), }); export const voteTheme = (puzzleId: string, theme: ThemeKey, vote: boolean | undefined): Promise => - xhr.json(`/training/${puzzleId}/vote/${theme}`, { + xhrJson(`/training/${puzzleId}/vote/${theme}`, { method: 'POST', - body: defined(vote) ? xhr.form({ vote }) : undefined, + body: defined(vote) ? xhrForm({ vote }) : undefined, }); export const report = (puzzleId: string, reason: string): Promise => - xhr.json(`/training/${puzzleId}/report`, { + xhrJson(`/training/${puzzleId}/report`, { method: 'POST', - body: xhr.form({ reason: reason }), + body: xhrForm({ reason: reason }), }); export const setZen = throttlePromiseDelay( () => 1000, zen => - xhr.text('/pref/zen', { + xhrText('/pref/zen', { method: 'post', - body: xhr.form({ zen: zen ? 1 : 0 }), + body: xhrForm({ zen: zen ? 1 : 0 }), }), ); diff --git a/ui/racer/package.json b/ui/racer/package.json index 6d2fbac48ca24..64fb086527c5d 100644 --- a/ui/racer/package.json +++ b/ui/racer/package.json @@ -13,7 +13,6 @@ "license": "AGPL-3.0-or-later", "dependencies": { "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*", "puz": "workspace:*" }, diff --git a/ui/racer/src/boost.ts b/ui/racer/src/boost.ts index 61aba2ca54cc5..065272ebf946c 100644 --- a/ui/racer/src/boost.ts +++ b/ui/racer/src/boost.ts @@ -1,5 +1,5 @@ import { getNow } from 'puz/util'; -import { PlayerWithScore } from './interfaces'; +import type { PlayerWithScore } from './interfaces'; type Timestamp = number; diff --git a/ui/racer/src/config.ts b/ui/racer/src/config.ts index fce2bcc2d3be1..1955c12431358 100644 --- a/ui/racer/src/config.ts +++ b/ui/racer/src/config.ts @@ -1,4 +1,4 @@ -import { RacerConfig } from './interfaces'; +import type { RacerConfig } from './interfaces'; const config: RacerConfig = { clock: { diff --git a/ui/racer/src/countdown.ts b/ui/racer/src/countdown.ts index cd57ce8a5f93b..1fb62d4605c13 100644 --- a/ui/racer/src/countdown.ts +++ b/ui/racer/src/countdown.ts @@ -1,4 +1,4 @@ -import { Clock } from 'puz/clock'; +import type { Clock } from 'puz/clock'; export class Countdown { played = new Set(); diff --git a/ui/racer/src/ctrl.ts b/ui/racer/src/ctrl.ts index cff3f5f9830dc..638ee646b7041 100644 --- a/ui/racer/src/ctrl.ts +++ b/ui/racer/src/ctrl.ts @@ -1,8 +1,7 @@ import config from './config'; import CurrentPuzzle from 'puz/current'; import { throttle, throttlePromiseDelay } from 'common/timing'; -import * as xhr from 'common/xhr'; -import { Api as CgApi } from 'chessground/api'; +import { text as xhrText, form as xhrForm } from 'common/xhr'; import { Boost } from './boost'; import { Clock } from 'puz/clock'; import { Combo } from 'puz/combo'; @@ -10,10 +9,10 @@ import { Countdown } from './countdown'; import { getNow, puzzlePov, sound } from 'puz/util'; import { makeCgOpts } from 'puz/run'; import { parseUci } from 'chessops/util'; -import { PuzCtrl, Run } from 'puz/interfaces'; +import type { PuzCtrl, Run } from 'puz/interfaces'; import { PuzFilters } from 'puz/filters'; import { defined, prop } from 'common'; -import { +import type { RacerOpts, RacerData, RacerVm, @@ -23,7 +22,6 @@ import { RaceStatus, WithGround, } from './interfaces'; -import { Role } from 'chessground/types'; import { storedBooleanProp } from 'common/storage'; import { PromotionCtrl } from 'chess/promotion'; import StrongSocket from 'common/socket'; @@ -264,9 +262,9 @@ export default class RacerCtrl implements PuzCtrl { private setZen = throttlePromiseDelay( () => 1000, zen => - xhr.text('/pref/zen', { + xhrText('/pref/zen', { method: 'post', - body: xhr.form({ zen: zen ? 1 : 0 }), + body: xhrForm({ zen: zen ? 1 : 0 }), }), ); diff --git a/ui/racer/src/interfaces.ts b/ui/racer/src/interfaces.ts index c38971785e187..ea85f57491da6 100644 --- a/ui/racer/src/interfaces.ts +++ b/ui/racer/src/interfaces.ts @@ -1,5 +1,4 @@ -import { Config, PuzPrefs, Puzzle } from 'puz/interfaces'; -import { Api as CgApi } from 'chessground/api'; +import type { Config, PuzPrefs, Puzzle } from 'puz/interfaces'; export type RaceStatus = 'pre' | 'racing' | 'post'; diff --git a/ui/racer/src/racer.ts b/ui/racer/src/racer.ts index 05b0f2f42dab7..70efd00732bb3 100644 --- a/ui/racer/src/racer.ts +++ b/ui/racer/src/racer.ts @@ -1,7 +1,7 @@ -import { attributesModule, classModule, init, VNode } from 'snabbdom'; +import { attributesModule, classModule, init, type VNode } from 'snabbdom'; import menuHover from 'common/menuHover'; import RacerCtrl from './ctrl'; -import { RacerOpts } from './interfaces'; +import type { RacerOpts } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/racer/src/view/board.ts b/ui/racer/src/view/board.ts index 656fdb9b303a6..e54cae106291e 100644 --- a/ui/racer/src/view/board.ts +++ b/ui/racer/src/view/board.ts @@ -1,7 +1,7 @@ -import RacerCtrl from '../ctrl'; +import type RacerCtrl from '../ctrl'; import { makeCgOpts } from 'puz/run'; import { makeConfig as makeCgConfig } from 'puz/view/chessground'; -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { INITIAL_BOARD_FEN } from 'chessops/fen'; import { Chessground as makeChessground } from 'chessground'; import { pubsub } from 'common/pubsub'; diff --git a/ui/racer/src/view/main.ts b/ui/racer/src/view/main.ts index 3747dd27e383f..071722746a5ad 100644 --- a/ui/racer/src/view/main.ts +++ b/ui/racer/src/view/main.ts @@ -1,11 +1,10 @@ import config from '../config'; -import RacerCtrl from '../ctrl'; +import type RacerCtrl from '../ctrl'; import renderClock from 'puz/view/clock'; import renderHistory from 'puz/view/history'; import * as licon from 'common/licon'; import { copyMeInput } from 'common/copyMe'; -import { MaybeVNodes, bind, looseH as h } from 'common/snabbdom'; -import { VNode } from 'snabbdom'; +import { type VNode, type MaybeVNodes, bind, looseH as h } from 'common/snabbdom'; import { playModifiers, renderCombo } from 'puz/view/util'; import { renderRace } from './race'; import { renderBoard } from './board'; diff --git a/ui/racer/src/view/race.ts b/ui/racer/src/view/race.ts index 5257a7bb059e4..849f9c23f175b 100644 --- a/ui/racer/src/view/race.ts +++ b/ui/racer/src/view/race.ts @@ -1,7 +1,7 @@ -import RacerCtrl from '../ctrl'; -import { h, VNodes } from 'snabbdom'; -import { PlayerWithScore } from '../interfaces'; -import { Boost } from '../boost'; +import type RacerCtrl from '../ctrl'; +import { h, type VNodes } from 'snabbdom'; +import type { PlayerWithScore } from '../interfaces'; +import type { Boost } from '../boost'; import { userLink } from 'common/userLink'; // to [0,1] diff --git a/ui/round/src/atomic.ts b/ui/round/src/atomic.ts index d9eb94e56c183..ade88c7196c86 100644 --- a/ui/round/src/atomic.ts +++ b/ui/round/src/atomic.ts @@ -1,11 +1,11 @@ -import * as util from 'chessground/util'; -import * as cg from 'chessground/types'; -import RoundController from './ctrl'; +import { key2pos, pos2key } from 'chessground/util'; +import type { PiecesDiff } from 'chessground/types'; +import type RoundController from './ctrl'; -export function capture(ctrl: RoundController, key: cg.Key): void { - const exploding: cg.Key[] = [], - diff: cg.PiecesDiff = new Map(), - orig = util.key2pos(key), +export function capture(ctrl: RoundController, key: Key): void { + const exploding: Key[] = [], + diff: PiecesDiff = new Map(), + orig = key2pos(key), minX = Math.max(0, orig[0] - 1), maxX = Math.min(7, orig[0] + 1), minY = Math.max(0, orig[1] - 1), @@ -13,7 +13,7 @@ export function capture(ctrl: RoundController, key: cg.Key): void { for (let x = minX; x <= maxX; x++) { for (let y = minY; y <= maxY; y++) { - const k = util.pos2key([x, y]); + const k = pos2key([x, y]); exploding.push(k); const p = ctrl.chessground.state.pieces.get(k); const explodes = p && (k === key || p.role !== 'pawn'); diff --git a/ui/round/src/cevalSub.ts b/ui/round/src/cevalSub.ts index c91240b3ced4c..4682aaa65ef5f 100644 --- a/ui/round/src/cevalSub.ts +++ b/ui/round/src/cevalSub.ts @@ -1,8 +1,7 @@ import { lastStep } from './util'; -import RoundController from './ctrl'; -import { ApiMove, RoundData } from './interfaces'; -import * as xhr from 'common/xhr'; -import { FEN } from 'chessground/types'; +import type RoundController from './ctrl'; +import type { ApiMove, RoundData } from './interfaces'; +import { text as xhrText } from 'common/xhr'; import { storage } from 'common/storage'; let found = false; @@ -30,7 +29,7 @@ export function subscribe(ctrl: RoundController): void { e.value && truncateFen(step.fen) === truncateFen(e.value) ) { - xhr.text(`/jslog/${d.game.id}${d.player.id}?n=ceval`, { method: 'post' }); + xhrText(`/jslog/${d.game.id}${d.player.id}?n=ceval`, { method: 'post' }); found = true; } }); diff --git a/ui/round/src/clock/clockCtrl.ts b/ui/round/src/clock/clockCtrl.ts index 9ebb9d012f3b8..f2817487505bb 100644 --- a/ui/round/src/clock/clockCtrl.ts +++ b/ui/round/src/clock/clockCtrl.ts @@ -1,7 +1,7 @@ import { updateElements } from './clockView'; -import { RoundData } from '../interfaces'; +import type { RoundData } from '../interfaces'; import { playedTurns, playable } from 'game'; -import * as Prefs from 'common/prefs'; +import { ShowClockTenths } from 'common/prefs'; import { reducedMotion } from 'common/device'; interface ClockOpts { @@ -17,7 +17,7 @@ export interface ClockData { white: Seconds; black: Seconds; emerg: Seconds; - showTenths: Prefs.ShowClockTenths; + showTenths: ShowClockTenths; showBar: boolean; moretime: number; } @@ -79,9 +79,9 @@ export class ClockController { ) { const cdata = d.clock!; - if (cdata.showTenths === Prefs.ShowClockTenths.Never) this.showTenths = () => false; + if (cdata.showTenths === ShowClockTenths.Never) this.showTenths = () => false; else { - const cutoff = cdata.showTenths === Prefs.ShowClockTenths.Below10Secs ? 10000 : 3600000; + const cutoff = cdata.showTenths === ShowClockTenths.Below10Secs ? 10000 : 3600000; this.showTenths = time => time < cutoff; } diff --git a/ui/round/src/clock/clockView.ts b/ui/round/src/clock/clockView.ts index 34c0014f7c1ab..f2532e71da680 100644 --- a/ui/round/src/clock/clockView.ts +++ b/ui/round/src/clock/clockView.ts @@ -1,14 +1,14 @@ import * as licon from 'common/licon'; -import * as button from '../view/button'; -import * as game from 'game'; -import RoundController from '../ctrl'; -import { bind, justIcon } from '../util'; -import { ClockElements, ClockController } from './clockCtrl'; -import { Hooks } from 'snabbdom'; -import { looseH as h, VNode } from 'common/snabbdom'; -import { Position } from '../interfaces'; +import { moretime } from '../view/button'; +import { playable, berserkableBy, bothPlayersHavePlayed, type Player } from 'game'; +import type RoundController from '../ctrl'; +import { justIcon } from '../util'; +import type { ClockElements, ClockController } from './clockCtrl'; +import type { Hooks } from 'snabbdom'; +import { looseH as h, type VNode, bind } from 'common/snabbdom'; +import type { Position } from '../interfaces'; -export function renderClock(ctrl: RoundController, player: game.Player, position: Position): VNode { +export function renderClock(ctrl: RoundController, player: Player, position: Position): VNode { const clock = ctrl.clock!, millis = clock.millisOf(player.color), isPlayer = ctrl.data.player.color === player.color, @@ -33,10 +33,10 @@ export function renderClock(ctrl: RoundController, player: game.Player, position clock.opts.nvui ? [h('div.time', { attrs: { role: 'timer' }, hook: timeHook })] : [ - clock.showBar && game.bothPlayersHavePlayed(ctrl.data) ? showBar(ctrl, player.color) : undefined, + clock.showBar && bothPlayersHavePlayed(ctrl.data) ? showBar(ctrl, player.color) : undefined, h('div.time', { class: { hour: millis > 3600 * 1000 }, hook: timeHook }), renderBerserk(ctrl, player.color, position), - isPlayer ? goBerserk(ctrl) : button.moretime(ctrl), + isPlayer ? goBerserk(ctrl) : moretime(ctrl), clockSide(ctrl, player.color, position), ], ); @@ -122,13 +122,13 @@ export function updateElements(clock: ClockController, els: ClockElements, milli } const showBerserk = (ctrl: RoundController, color: Color): boolean => - !!ctrl.goneBerserk[color] && ctrl.data.game.turns <= 1 && game.playable(ctrl.data); + !!ctrl.goneBerserk[color] && ctrl.data.game.turns <= 1 && playable(ctrl.data); const renderBerserk = (ctrl: RoundController, color: Color, position: Position) => showBerserk(ctrl, color) ? h('div.berserked.' + position, justIcon(licon.Berserk)) : null; const goBerserk = (ctrl: RoundController) => { - if (!game.berserkableBy(ctrl.data)) return; + if (!berserkableBy(ctrl.data)) return; if (ctrl.goneBerserk[ctrl.data.player.color]) return; return h('button.fbt.go-berserk', { attrs: { title: 'GO BERSERK! Half the time, no increment, bonus point', 'data-icon': licon.Berserk }, diff --git a/ui/round/src/corresClock/corresClockCtrl.ts b/ui/round/src/corresClock/corresClockCtrl.ts index 2731fe124eb2b..de4691451429e 100644 --- a/ui/round/src/corresClock/corresClockCtrl.ts +++ b/ui/round/src/corresClock/corresClockCtrl.ts @@ -1,4 +1,4 @@ -import RoundController from '../ctrl'; +import type RoundController from '../ctrl'; export interface CorresClockData { daysPerTurn: number; diff --git a/ui/round/src/corresClock/corresClockView.ts b/ui/round/src/corresClock/corresClockView.ts index 8c393921361ea..8d610e17d4f9f 100644 --- a/ui/round/src/corresClock/corresClockView.ts +++ b/ui/round/src/corresClock/corresClockView.ts @@ -1,6 +1,6 @@ -import { looseH as h, VNode } from 'common/snabbdom'; -import { Position } from '../interfaces'; -import { CorresClockController } from './corresClockCtrl'; +import { looseH as h, type VNode } from 'common/snabbdom'; +import type { Position } from '../interfaces'; +import type { CorresClockController } from './corresClockCtrl'; import { moretime } from '../view/button'; const prefixInteger = (num: number, length: number): string => diff --git a/ui/round/src/crazy/crazyCtrl.ts b/ui/round/src/crazy/crazyCtrl.ts index 27a91b5fec9a5..94ff172b68614 100644 --- a/ui/round/src/crazy/crazyCtrl.ts +++ b/ui/round/src/crazy/crazyCtrl.ts @@ -1,20 +1,20 @@ import { isPlayerTurn } from 'game/game'; import { dragNewPiece } from 'chessground/drag'; import { setDropMode, cancelDropMode } from 'chessground/drop'; -import RoundController from '../ctrl'; -import * as cg from 'chessground/types'; -import { RoundData } from '../interfaces'; +import type RoundController from '../ctrl'; +import type { MouchEvent } from 'chessground/types'; +import type { RoundData } from '../interfaces'; import { storage } from 'common/storage'; import { pubsub } from 'common/pubsub'; -export const pieceRoles: cg.Role[] = ['pawn', 'knight', 'bishop', 'rook', 'queen']; +export const pieceRoles: Role[] = ['pawn', 'knight', 'bishop', 'rook', 'queen']; -export function drag(ctrl: RoundController, e: cg.MouchEvent): void { +export function drag(ctrl: RoundController, e: MouchEvent): void { if (e.button !== undefined && e.button !== 0) return; // only touch or left click if (ctrl.replaying() || !ctrl.isPlaying()) return; const el = e.target as HTMLElement, - role = el.getAttribute('data-role') as cg.Role, - color = el.getAttribute('data-color') as cg.Color, + role = el.getAttribute('data-role') as Role, + color = el.getAttribute('data-color') as Color, number = el.getAttribute('data-nb'); if (!role || !color || number === '0') return; e.stopPropagation(); @@ -26,7 +26,7 @@ let dropWithKey = false; let dropWithDrag = false; let mouseIconsLoaded = false; -export function valid(data: RoundData, role: cg.Role, key: cg.Key): boolean { +export function valid(data: RoundData, role: Role, key: Key): boolean { if (crazyKeys.length === 0) dropWithDrag = true; else { dropWithKey = true; diff --git a/ui/round/src/crazy/crazyView.ts b/ui/round/src/crazy/crazyView.ts index 50c6a106ea433..240056cb6bbb8 100644 --- a/ui/round/src/crazy/crazyView.ts +++ b/ui/round/src/crazy/crazyView.ts @@ -1,8 +1,8 @@ -import * as cg from 'chessground/types'; -import { onInsert, LooseVNode } from 'common/snabbdom'; +import type { MouchEvent } from 'chessground/types'; +import { onInsert, type LooseVNode } from 'common/snabbdom'; import { h } from 'snabbdom'; -import RoundController from '../ctrl'; -import { Position } from '../interfaces'; +import type RoundController from '../ctrl'; +import type { Position } from '../interfaces'; import { plyStep } from '../util'; import { crazyKeys, drag, pieceRoles } from './crazyCtrl'; @@ -25,7 +25,7 @@ export default function pocket(ctrl: RoundController, color: Color, position: Po class: { usable }, hook: onInsert(el => eventNames.forEach(name => - el.addEventListener(name, (e: cg.MouchEvent) => { + el.addEventListener(name, (e: MouchEvent) => { if (position === (ctrl.flip ? 'top' : 'bottom') && crazyKeys.length == 0) drag(ctrl, e); }), ), diff --git a/ui/round/src/ctrl.ts b/ui/round/src/ctrl.ts index 0c1d401a5e704..c5ba2327661ac 100644 --- a/ui/round/src/ctrl.ts +++ b/ui/round/src/ctrl.ts @@ -3,15 +3,15 @@ import * as ab from 'ab'; import * as game from 'game'; import { game as gameRoute } from 'game/router'; -import * as status from 'game/status'; -import * as ground from './ground'; +import { playing } from 'game/status'; +import { boardOrientation, reload as groundReload } from './ground'; import * as licon from 'common/licon'; import notify from 'common/notification'; -import { make as makeSocket, RoundSocket } from './socket'; +import { make as makeSocket, type RoundSocket } from './socket'; import * as title from './title'; import * as blur from './blur'; import viewStatus from 'game/view/status'; -import * as cg from 'chessground/types'; +import type { MoveMetadata as CgMoveMetadata } from 'chessground/types'; import { ClockController } from './clock/clockCtrl'; import { CorresClockController } from './corresClock/corresClockCtrl'; import MoveOn from './moveOn'; @@ -20,18 +20,18 @@ import * as atomic from './atomic'; import * as util from './util'; import * as xhr from './xhr'; import { valid as crazyValid, init as crazyInit, onEnd as crazyEndHook } from './crazy/crazyCtrl'; -import { MoveRootCtrl } from 'chess/moveRootCtrl'; -import { ctrl as makeKeyboardMove, KeyboardMove } from 'keyboardMove'; -import { makeVoiceMove, VoiceMove } from 'voice'; -import * as renderUser from './view/user'; +import type { MoveRootCtrl } from 'chess/moveRootCtrl'; +import { ctrl as makeKeyboardMove, type KeyboardMove } from 'keyboardMove'; +import { makeVoiceMove, type VoiceMove } from 'voice'; +import { userTxt } from './view/user'; import * as cevalSub from './cevalSub'; -import * as keyboard from './keyboard'; +import { init as keyboardInit } from './keyboard'; import { PromotionCtrl, promote } from 'chess/promotion'; import * as wakeLock from 'common/wakeLock'; import { opposite, uciToMove } from 'chessground/util'; -import * as Prefs from 'common/prefs'; +import { Replay } from 'common/prefs'; import { endGameView } from './view/main'; -import { +import type { Step, CrazyPocket, RoundOpts, @@ -46,8 +46,7 @@ import { NvuiPlugin, RoundTour, } from './interfaces'; -import { defined, Toggle, toggle, requestIdleCallback } from 'common'; -import { Redraw } from 'common/snabbdom'; +import { defined, type Toggle, toggle, requestIdleCallback } from 'common'; import { storage, once, type LichessBooleanStorage } from 'common/storage'; import { pubsub } from 'common/pubsub'; @@ -77,18 +76,17 @@ export default class RoundController implements MoveRootCtrl { loadingTimeout: number; redirecting = false; transientMove?: TransientMove; - moveToSubmit?: SocketMove; - dropToSubmit?: SocketDrop; + toSubmit?: SocketMove | SocketDrop; goneBerserk: GoneBerserk = {}; resignConfirm?: Timeout = undefined; drawConfirm?: Timeout = undefined; preventDrawOffer?: Timeout = undefined; // will be replaced by view layer autoScroll: () => void = () => {}; - justDropped?: cg.Role; - justCaptured?: cg.Piece; + justDropped?: Role; + justCaptured?: Piece; shouldSendMoveTime = false; - preDrop?: cg.Role; + preDrop?: Role; sign: string = Math.random().toString(36); keyboardHelp: boolean = location.hash === '#keyboard'; blindfoldStorage: LichessBooleanStorage; @@ -159,18 +157,18 @@ export default class RoundController implements MoveRootCtrl { setTimeout(this.showExpiration, 250); }; - private onUserMove = (orig: cg.Key, dest: cg.Key, meta: cg.MoveMetadata) => { + private onUserMove = (orig: Key, dest: Key, meta: CgMoveMetadata) => { if (!this.keyboardMove?.usedSan) ab.move(this, meta, pubsub.emit); if (!this.startPromotion(orig, dest, meta)) this.sendMove(orig, dest, undefined, meta); }; - private onUserNewPiece = (role: cg.Role, key: cg.Key, meta: cg.MoveMetadata) => { + private onUserNewPiece = (role: Role, key: Key, meta: CgMoveMetadata) => { if (!this.replaying() && crazyValid(this.data, role, key)) { this.sendNewPiece(role, key, !!meta.predrop); } else this.jump(this.ply); }; - private onMove = (orig: cg.Key, dest: cg.Key, captured?: cg.Piece) => { + private onMove = (orig: Key, dest: Key, captured?: Piece) => { if (captured || this.enpassant(orig, dest)) { if (this.data.game.variant.key === 'atomic') { site.sound.play('explosion'); @@ -179,7 +177,7 @@ export default class RoundController implements MoveRootCtrl { } else site.sound.move({ name: 'move', filter: 'game' }); }; - private startPromotion = (orig: cg.Key, dest: cg.Key, meta: cg.MoveMetadata) => + private startPromotion = (orig: Key, dest: Key, meta: CgMoveMetadata) => this.promotion.start( orig, dest, @@ -191,26 +189,25 @@ export default class RoundController implements MoveRootCtrl { this.keyboardMove?.justSelected(), ); - private onPremove = (orig: cg.Key, dest: cg.Key, meta: cg.MoveMetadata) => - this.startPromotion(orig, dest, meta); + private onPremove = (orig: Key, dest: Key, meta: CgMoveMetadata) => this.startPromotion(orig, dest, meta); private onCancelPremove = () => this.promotion.cancelPrePromotion(); - private onNewPiece = (piece: cg.Piece, key: cg.Key): void => { + private onNewPiece = (piece: Piece, key: Key): void => { if (piece.role === 'pawn' && (key[1] === '1' || key[1] === '8')) return; site.sound.move(); }; - private onPredrop = (role: cg.Role | undefined, _?: Key) => { + private onPredrop = (role: Role | undefined, _?: Key) => { this.preDrop = role; this.redraw(); }; private isSimulHost = () => this.data.simul && this.data.simul.hostId === this.opts.userId; - private enpassant = (orig: cg.Key, dest: cg.Key): boolean => { + private enpassant = (orig: Key, dest: Key): boolean => { if (orig[0] === dest[0] || this.chessground.state.pieces.get(dest)?.role !== 'pawn') return false; - const pos = (dest[0] + orig[1]) as cg.Key; + const pos = (dest[0] + orig[1]) as Key; this.chessground.setPieces(new Map([[pos, undefined]])); return true; }; @@ -230,7 +227,7 @@ export default class RoundController implements MoveRootCtrl { replaying = (): boolean => this.ply !== this.lastPly() && !this.opts.local; userJump = (ply: Ply): void => { - this.cancelMove(); + this.toSubmit = undefined; this.chessground.selectSquare(null); if (ply != this.ply && this.jump(ply)) site.sound.saySan(this.stepAt(this.ply).san, true); else this.redraw(); @@ -259,6 +256,7 @@ export default class RoundController implements MoveRootCtrl { color: this.isPlaying() ? this.data.player.color : undefined, dests: util.parsePossibleMoves(this.data.possibleMoves), }; + this.chessground.cancelPremove(); this.chessground.set(config); if (s.san && isForwardStep) site.sound.move(s); this.autoScroll(); @@ -272,13 +270,13 @@ export default class RoundController implements MoveRootCtrl { replayEnabledByPref = (): boolean => { const d = this.data; return ( - d.pref.replay === Prefs.Replay.Always || - (d.pref.replay === Prefs.Replay.OnlySlowGames && + d.pref.replay === Replay.Always || + (d.pref.replay === Replay.OnlySlowGames && (d.game.speed === 'classical' || d.game.speed === 'correspondence')) ); }; - isLate = (): boolean => this.replaying() && status.playing(this.data); + isLate = (): boolean => this.replaying() && playing(this.data); playerAt = (position: Position): game.Player => this.flip != (position === 'top') ? this.data.opponent : this.data.player; @@ -286,7 +284,7 @@ export default class RoundController implements MoveRootCtrl { flipNow = (): void => { this.flip = !this.nvui && !this.flip; this.chessground.set({ - orientation: ground.boardOrientation(this.data, this.flip), + orientation: boardOrientation(this.data, this.flip), }); pubsub.emit('flip', this.flip); this.redraw(); @@ -320,7 +318,7 @@ export default class RoundController implements MoveRootCtrl { this.redraw(); }; - pluginMove = (orig: cg.Key, dest: cg.Key, role?: cg.Role): void => { + pluginMove = (orig: Key, dest: Key, role?: Role): void => { if (!role) { this.chessground.move(orig, dest); this.chessground.state.movable.dests = undefined; @@ -336,7 +334,7 @@ export default class RoundController implements MoveRootCtrl { this.keyboardMove?.update({ fen, canMove: this.canMove() }); }; - sendMove = (orig: cg.Key, dest: cg.Key, prom: cg.Role | undefined, meta: cg.MoveMetadata): void => { + sendMove = (orig: Key, dest: Key, prom: Role | undefined, meta: CgMoveMetadata): void => { const move: SocketMove = { u: orig + dest, }; @@ -344,7 +342,7 @@ export default class RoundController implements MoveRootCtrl { if (blur.get()) move.b = 1; this.resign(false); if (this.data.pref.submitMove && this.confirmMoveEnabled() && !meta.premove) { - this.moveToSubmit = move; + this.toSubmit = move; this.redraw(); } else { this.actualSendMove('move', move, { @@ -354,12 +352,12 @@ export default class RoundController implements MoveRootCtrl { } }; - sendNewPiece = (role: cg.Role, key: cg.Key, isPredrop: boolean): void => { + sendNewPiece = (role: Role, key: Key, isPredrop: boolean): void => { const drop: SocketDrop = { role, pos: key }; if (blur.get()) drop.b = 1; this.resign(false); if (this.data.pref.submitMove && this.confirmMoveEnabled() && !isPredrop) { - this.dropToSubmit = drop; + this.toSubmit = drop; this.redraw(); } else { this.actualSendMove('drop', drop, { @@ -372,7 +370,7 @@ export default class RoundController implements MoveRootCtrl { showYourMoveNotification = (): void => { if (this.opts.local) return; const d = this.data; - const opponent = $('body').hasClass('zen') ? 'Your opponent' : renderUser.userTxt(d.opponent); + const opponent = $('body').hasClass('zen') ? 'Your opponent' : userTxt(d.opponent); const joined = `${opponent}\njoined the game.`; if (game.isPlayerTurn(d)) notify(() => { @@ -414,7 +412,7 @@ export default class RoundController implements MoveRootCtrl { role: o.role, color: playedColor, }, - o.uci.slice(2, 4) as cg.Key, + o.uci.slice(2, 4) as Key, ); else { // This block needs to be idempotent, even for castling moves in @@ -497,7 +495,7 @@ export default class RoundController implements MoveRootCtrl { return true; // prevents default socket pubsub }; - crazyValid = (role: cg.Role, key: cg.Key): boolean => crazyValid(this.data, role, key); + crazyValid = (role: Role, key: Key): boolean => crazyValid(this.data, role, key); getCrazyhousePockets = (): [CrazyPocket, CrazyPocket] | undefined => this.data.crazyhouse?.pockets; @@ -522,7 +520,7 @@ export default class RoundController implements MoveRootCtrl { this.updateClockCtrl(); if (this.clock) this.clock.setClock(d, d.clock!.white, d.clock!.black); if (this.corresClock) this.corresClock.update(d.correspondence!.white, d.correspondence!.black); - if (!this.replaying() && !this.opts.local) ground.reload(this); + if (!this.replaying() && !this.opts.local) groundReload(this); this.setTitle(); this.moveOn.next(); this.setQuietMode(); @@ -629,7 +627,7 @@ export default class RoundController implements MoveRootCtrl { }; question = (): QuestionOpts | false => { - if (this.moveToSubmit || this.dropToSubmit) { + if (this.toSubmit) { setTimeout(() => this.voiceMove?.listenForResponse('submitMove', this.submitMove)); return { prompt: i18n.site.confirmMove, @@ -729,23 +727,16 @@ export default class RoundController implements MoveRootCtrl { }; submitMove = (v: boolean): void => { - const toSubmit = this.moveToSubmit || this.dropToSubmit; - if (v && toSubmit) { - if (this.moveToSubmit) this.actualSendMove('move', this.moveToSubmit); - else this.actualSendMove('drop', this.dropToSubmit); + if (!this.toSubmit) return; + + const submit = this.toSubmit; + this.toSubmit = undefined; + this.setLoading(true, 300); + + if (v) { + this.actualSendMove('u' in submit ? 'move' : 'drop', submit); site.sound.play('confirmation'); } else this.jump(this.ply); - this.cancelMove(); - //cancel premove when you cancel move - if (!v && toSubmit) { - this.chessground.cancelPremove(); - } - if (toSubmit) this.setLoading(true, 300); - }; - - cancelMove = (): void => { - this.moveToSubmit = undefined; - this.dropToSubmit = undefined; }; private onChange = () => { @@ -892,7 +883,7 @@ export default class RoundController implements MoveRootCtrl { cevalSub.subscribe(this); } - if (!this.nvui) keyboard.init(this); + if (!this.nvui) keyboardInit(this); if (this.isPlaying() && d.steps.length === 1) { this.blindfold(this.blindfoldStorage.get()); } diff --git a/ui/round/src/ground.ts b/ui/round/src/ground.ts index c0a453d5eecaa..1248cf63dcd1c 100644 --- a/ui/round/src/ground.ts +++ b/ui/round/src/ground.ts @@ -1,16 +1,16 @@ import * as util from './util'; +import { onInsert } from 'common/snabbdom'; import resizeHandle from 'common/resize'; -import RoundController from './ctrl'; -import { Config } from 'chessground/config'; -import { h, VNode } from 'snabbdom'; +import type RoundController from './ctrl'; +import { h, type VNode } from 'snabbdom'; import { plyStep } from './util'; -import { RoundData } from './interfaces'; +import type { RoundData } from './interfaces'; import { uciToMove } from 'chessground/util'; -import * as Prefs from 'common/prefs'; +import { ShowResizeHandle, Coords, MoveEvent } from 'common/prefs'; import { storage } from 'common/storage'; import { Chessground as makeChessground } from 'chessground'; -export function makeConfig(ctrl: RoundController): Config { +export function makeConfig(ctrl: RoundController): CgConfig { const data = ctrl.data, hooks = ctrl.makeCgHooks(), step = plyStep(data, ctrl.ply), @@ -21,8 +21,8 @@ export function makeConfig(ctrl: RoundController): Config { turnColor: step.ply % 2 === 0 ? 'white' : 'black', lastMove: uciToMove(step.uci), check: !!step.check, - coordinates: data.pref.coords !== Prefs.Coords.Hidden, - coordinatesOnSquares: data.pref.coords === Prefs.Coords.All, + coordinates: data.pref.coords !== Coords.Hidden, + coordinatesOnSquares: data.pref.coords === Coords.All, addPieceZIndex: ctrl.data.pref.is3d, addDimensionsCssVarsTo: document.body, highlight: { @@ -38,7 +38,7 @@ export function makeConfig(ctrl: RoundController): Config { const showUntil = firstPly + 2 + +isSecond; resizeHandle( elements, - playing ? ctrl.data.pref.resizeHandle : Prefs.ShowResizeHandle.Always, + playing ? ctrl.data.pref.resizeHandle : ShowResizeHandle.Always, ctrl.ply, p => p <= showUntil, ); @@ -78,11 +78,11 @@ export function makeConfig(ctrl: RoundController): Config { }, }, draggable: { - enabled: data.pref.moveEvent !== Prefs.MoveEvent.Click, + enabled: data.pref.moveEvent !== MoveEvent.Click, showGhost: data.pref.highlight, }, selectable: { - enabled: data.pref.moveEvent !== Prefs.MoveEvent.Drag, + enabled: data.pref.moveEvent !== MoveEvent.Drag, }, drawable: { enabled: true, @@ -105,5 +105,5 @@ export const boardOrientation = (data: RoundData, flip: boolean): Color => export const render = (ctrl: RoundController): VNode => h('div.cg-wrap', { - hook: util.onInsert(el => ctrl.setChessground(makeChessground(el, makeConfig(ctrl)))), + hook: onInsert(el => ctrl.setChessground(makeChessground(el, makeConfig(ctrl)))), }); diff --git a/ui/round/src/interfaces.ts b/ui/round/src/interfaces.ts index 2e7aaf162933b..7ca4876fef623 100644 --- a/ui/round/src/interfaces.ts +++ b/ui/round/src/interfaces.ts @@ -4,7 +4,6 @@ import type { ClockData } from './clock/clockCtrl'; import type { CorresClockData } from './corresClock/corresClockCtrl'; import type RoundController from './ctrl'; import type { ChatCtrl, ChatPlugin } from 'chat'; -import * as cg from 'chessground/types'; import * as Prefs from 'common/prefs'; import type { EnhanceOpts } from 'common/richText'; import type { RoundSocket } from './socket'; @@ -38,8 +37,8 @@ export interface SocketMove { b?: 1; } export interface SocketDrop { - role: cg.Role; - pos: cg.Key; + role: Role; + pos: Key; b?: 1; } @@ -48,7 +47,6 @@ export type EncodedDests = | { [key: string]: string; }; -export type Dests = cg.Dests; export interface RoundData extends GameData { clock?: ClockData; @@ -116,7 +114,7 @@ export interface ChatOpts { export interface Step { ply: Ply; - fen: cg.FEN; + fen: FEN; san: San; uci: Uci; check?: boolean; @@ -142,15 +140,15 @@ export interface ApiMove { wDraw?: boolean; bDraw?: boolean; crazyhouse?: CrazyData; - role?: cg.Role; + role?: Role; drops?: string; promotion?: { - key: cg.Key; - pieceClass: cg.Role; + key: Key; + pieceClass: Role; }; castle?: { - king: [cg.Key, cg.Key]; - rook: [cg.Key, cg.Key]; + king: [Key, Key]; + rook: [Key, Key]; color: Color; }; isMove?: true; @@ -200,8 +198,8 @@ export interface Pref { export interface MoveMetadata { premove?: boolean; - justDropped?: cg.Role; - justCaptured?: cg.Piece; + justDropped?: Role; + justCaptured?: Piece; } export type Position = 'top' | 'bottom'; diff --git a/ui/round/src/keyboard.ts b/ui/round/src/keyboard.ts index 33da22a6154a3..7ff532e8971cf 100644 --- a/ui/round/src/keyboard.ts +++ b/ui/round/src/keyboard.ts @@ -1,5 +1,5 @@ -import RoundController from './ctrl'; -import { VNode } from 'snabbdom'; +import type RoundController from './ctrl'; +import type { VNode } from 'snabbdom'; import { snabDialog } from 'common/dialog'; import { pubsub } from 'common/pubsub'; diff --git a/ui/round/src/moveOn.ts b/ui/round/src/moveOn.ts index c527695531525..8591581e3e9c3 100644 --- a/ui/round/src/moveOn.ts +++ b/ui/round/src/moveOn.ts @@ -1,6 +1,6 @@ -import * as game from 'game'; -import * as xhr from './xhr'; -import RoundController from './ctrl'; +import { isSwitchable, isPlayerTurn } from 'game'; +import { whatsNext } from './xhr'; +import type RoundController from './ctrl'; import { storage } from 'common/storage'; export default class MoveOn { @@ -25,13 +25,13 @@ export default class MoveOn { next = (force?: boolean): void => { const d = this.ctrl.data; - if (d.player.spectator || !game.isSwitchable(d) || game.isPlayerTurn(d) || !this.get()) return; + if (d.player.spectator || !isSwitchable(d) || isPlayerTurn(d) || !this.get()) return; if (force) this.redirect('/round-next/' + d.game.id); else if (d.simul) { if (d.simul.hostId === this.ctrl.opts.userId && d.simul.nbPlaying > 1) this.redirect('/round-next/' + d.game.id); } else - xhr.whatsNext(this.ctrl).then(data => { + whatsNext(this.ctrl).then(data => { if (data.next) this.redirect('/' + data.next); }); }; diff --git a/ui/round/src/plugins/round.nvui.ts b/ui/round/src/plugins/round.nvui.ts index 3ccf7186448c3..0dd2b09ee7d03 100644 --- a/ui/round/src/plugins/round.nvui.ts +++ b/ui/round/src/plugins/round.nvui.ts @@ -1,15 +1,15 @@ -import { VNode } from 'snabbdom'; -import { looseH as h } from 'common/snabbdom'; -import RoundController from '../ctrl'; +import { type VNode, looseH as h, onInsert } from 'common/snabbdom'; +import type RoundController from '../ctrl'; import { renderClock } from '../clock/clockView'; import { renderTableWatch, renderTablePlay, renderTableEnd } from '../view/table'; import { makeConfig as makeCgConfig } from '../ground'; import renderCorresClock from '../corresClock/corresClockView'; import { renderResult } from '../view/replay'; -import { onInsert, plyStep } from '../util'; -import { Step, Position, NvuiPlugin } from '../interfaces'; -import * as game from 'game'; +import { plyStep } from '../util'; +import type { Step, Position, NvuiPlugin } from '../interfaces'; +import { type Player, playable } from 'game'; import { + type Style, renderSan, renderPieces, renderBoard, @@ -27,7 +27,6 @@ import { pieceJumpingHandler, castlingFlavours, supportedVariant, - Style, inputToLegalUci, } from 'nvui/chess'; import { renderSetting } from 'nvui/setting'; @@ -143,7 +142,7 @@ export function initModule(): NvuiPlugin { h('h2', 'Actions'), ...(ctrl.data.player.spectator ? renderTableWatch(ctrl) - : game.playable(ctrl.data) + : playable(ctrl.data) ? renderTablePlay(ctrl) : renderTableEnd(ctrl)), h('h2', 'Board'), @@ -363,7 +362,7 @@ function renderMoves(steps: Step[], style: Style) { return res; } -function playerHtml(ctrl: RoundController, player: game.Player) { +function playerHtml(ctrl: RoundController, player: Player) { if (player.ai) return i18n.site.aiNameLevelAiLevel('Stockfish', player.ai); const d = ctrl.data, user = player.user, @@ -384,7 +383,7 @@ function playerHtml(ctrl: RoundController, player: game.Player) { : 'Anonymous'; } -function playerText(ctrl: RoundController, player: game.Player) { +function playerText(ctrl: RoundController, player: Player) { if (player.ai) return i18n.site.aiNameLevelAiLevel('Stockfish', player.ai); const d = ctrl.data, user = player.user, diff --git a/ui/round/src/plugins/round.tour.ts b/ui/round/src/plugins/round.tour.ts index 8a50ac6ebf3a0..d505fa4c8e2c2 100644 --- a/ui/round/src/plugins/round.tour.ts +++ b/ui/round/src/plugins/round.tour.ts @@ -1,4 +1,4 @@ -import { RoundTour } from '../interfaces'; +import type { RoundTour } from '../interfaces'; import Shepherd from 'shepherd.js'; export function initModule(): RoundTour { diff --git a/ui/round/src/round.ts b/ui/round/src/round.ts index 38ce504588698..7d9a3c96747ea 100644 --- a/ui/round/src/round.ts +++ b/ui/round/src/round.ts @@ -1,12 +1,12 @@ -import { RoundData, RoundOpts, NvuiPlugin } from './interfaces'; +import type { RoundData, RoundOpts, NvuiPlugin } from './interfaces'; import { attributesModule, classModule, init } from 'snabbdom'; import menuHover from 'common/menuHover'; import RoundController from './ctrl'; import { main as view } from './view/main'; -import * as xhr from 'common/xhr'; -import MoveOn from './moveOn'; -import { TourPlayer } from 'game'; -import { tourStandingCtrl, TourStandingCtrl } from './tourStanding'; +import { text as xhrText } from 'common/xhr'; +import type MoveOn from './moveOn'; +import type { TourPlayer } from 'game'; +import { tourStandingCtrl, type TourStandingCtrl } from './tourStanding'; import StrongSocket from 'common/socket'; import { storage } from 'common/storage'; import { setClockWidget } from 'common/clock'; @@ -70,7 +70,7 @@ async function boot( ); }, endData() { - xhr.text(`${data.tv ? '/tv' : ''}/${data.game.id}/${data.player.color}/sides`).then(html => { + xhrText(`${data.tv ? '/tv' : ''}/${data.game.id}/${data.player.color}/sides`).then(html => { const $html = $(html), $meta = $html.find('.game__meta'); $meta.length && $('.game__meta').replaceWith($meta); diff --git a/ui/round/src/socket.ts b/ui/round/src/socket.ts index 517dec6feacb9..ffc351736fda8 100644 --- a/ui/round/src/socket.ts +++ b/ui/round/src/socket.ts @@ -1,7 +1,7 @@ -import * as game from 'game'; +import { type Simul, setOnGame, isPlayerTurn } from 'game'; import { throttle } from 'common/timing'; -import * as xhr from './xhr'; -import RoundController from './ctrl'; +import { reload as xhrReload } from './xhr'; +import type RoundController from './ctrl'; import { defined } from 'common'; import { domDialog } from 'common/dialog'; import { pubsub } from 'common/pubsub'; @@ -55,7 +55,7 @@ export function make(send: SocketSend, ctrl: RoundController): RoundSocket { ctrl.setLoading(false); handlers[o.t]!(o.d); } else - xhr.reload(ctrl).then(data => { + xhrReload(ctrl).then(data => { const version = site.socket.getVersion(); if (version !== false && version > data.player.version) { // race condition! try to reload again @@ -93,7 +93,7 @@ export function make(send: SocketSend, ctrl: RoundController): RoundSocket { }, crowd(o: { white: boolean; black: boolean }) { (['white', 'black'] as const).forEach(c => { - if (defined(o[c])) game.setOnGame(ctrl.data, c, o[c]); + if (defined(o[c])) setOnGame(ctrl.data, c, o[c]); }); ctrl.redraw(); }, @@ -139,14 +139,14 @@ export function make(send: SocketSend, ctrl: RoundController): RoundSocket { ctrl.opts.userId == ctrl.data.simul.hostId && gameId !== ctrl.data.game.id && ctrl.moveOn.get() && - !game.isPlayerTurn(ctrl.data) + !isPlayerTurn(ctrl.data) ) { ctrl.setRedirecting(); site.sound.play('move'); location.href = '/' + gameId; } }, - simulEnd(simul: game.Simul) { + simulEnd(simul: Simul) { domDialog({ htmlText: '

Simul complete!



' + diff --git a/ui/round/src/title.ts b/ui/round/src/title.ts index 74c34aa5a7c01..fbc6a8a4c1e35 100644 --- a/ui/round/src/title.ts +++ b/ui/round/src/title.ts @@ -1,4 +1,4 @@ -import RoundController from './ctrl'; +import type RoundController from './ctrl'; import { aborted, finished } from 'game/status'; import { isPlayerTurn } from 'game'; diff --git a/ui/round/src/tourStanding.ts b/ui/round/src/tourStanding.ts index 18ada4b4f570b..079d5e33f703e 100644 --- a/ui/round/src/tourStanding.ts +++ b/ui/round/src/tourStanding.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { onInsert } from './util'; -import { ChatPlugin } from 'chat'; -import { Team, TourPlayer } from 'game'; +import { onInsert } from 'common/snabbdom'; +import type { ChatPlugin } from 'chat'; +import type { Team, TourPlayer } from 'game'; export interface TourStandingCtrl extends ChatPlugin { set(players: TourPlayer[]): void; diff --git a/ui/round/src/transientMove.ts b/ui/round/src/transientMove.ts index 80bbecea572b9..297fdb102e159 100644 --- a/ui/round/src/transientMove.ts +++ b/ui/round/src/transientMove.ts @@ -1,5 +1,5 @@ -import { RoundSocket } from './socket'; -import * as xhr from 'common/xhr'; +import type { RoundSocket } from './socket'; +import { text as xhrText } from 'common/xhr'; /* Tracks moves that were played on the board, * sent to the server, possibly acked, @@ -24,7 +24,7 @@ export default class TransientMove { }; expire = (): void => { - xhr.text('/statlog?e=roundTransientExpire', { method: 'post' }); + xhrText('/statlog?e=roundTransientExpire', { method: 'post' }); this.socket.reload(); }; } diff --git a/ui/round/src/util.ts b/ui/round/src/util.ts index cc9c797dbf07f..dac9d218dbf1d 100644 --- a/ui/round/src/util.ts +++ b/ui/round/src/util.ts @@ -1,8 +1,5 @@ -import * as cg from 'chessground/types'; -import { VNodeData } from 'snabbdom'; -import { Dests, EncodedDests, RoundData, Step } from './interfaces'; - -export { bind, onInsert } from 'common/snabbdom'; +import type { VNodeData } from 'snabbdom'; +import type { EncodedDests, RoundData, Step } from './interfaces'; export const justIcon = (icon: string): VNodeData => ({ attrs: { 'data-icon': icon }, @@ -13,9 +10,9 @@ export function parsePossibleMoves(dests?: EncodedDests): Dests { if (!dests) return dec; if (typeof dests == 'string') for (const ds of dests.split(' ')) { - dec.set(ds.slice(0, 2), ds.slice(2).match(/.{2}/g) as cg.Key[]); + dec.set(ds.slice(0, 2), ds.slice(2).match(/.{2}/g) as Key[]); } - else for (const k in dests) dec.set(k, dests[k].match(/.{2}/g) as cg.Key[]); + else for (const k in dests) dec.set(k, dests[k].match(/.{2}/g) as Key[]); return dec; } diff --git a/ui/round/src/view/boardMenu.ts b/ui/round/src/view/boardMenu.ts index 33a76f8b37239..29a82bdb5373a 100644 --- a/ui/round/src/view/boardMenu.ts +++ b/ui/round/src/view/boardMenu.ts @@ -1,6 +1,6 @@ import { h } from 'snabbdom'; -import { LooseVNode } from 'common/snabbdom'; -import RoundController from '../ctrl'; +import type { LooseVNode } from 'common/snabbdom'; +import type RoundController from '../ctrl'; import { menu as menuDropdown } from 'board/menu'; import { toggle } from 'common'; import { boolPrefXhrToggle } from 'common/controls'; diff --git a/ui/round/src/view/button.ts b/ui/round/src/view/button.ts index c6ce16d638bdd..bec280eb2e3be 100644 --- a/ui/round/src/view/button.ts +++ b/ui/round/src/view/button.ts @@ -1,14 +1,14 @@ -import { VNode, Hooks } from 'snabbdom'; +import type { VNode, Hooks } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; -import * as util from '../util'; -import * as game from 'game'; -import * as status from 'game/status'; +import { justIcon } from '../util'; +import { replayable, rematchable, moretimeable, type PlayerUser } from 'game'; +import { finished, aborted } from 'game/status'; import { game as gameRoute } from 'game/router'; -import { RoundData } from '../interfaces'; -import { ClockData } from '../clock/clockCtrl'; -import RoundController from '../ctrl'; -import { LooseVNodes, LooseVNode, looseH as h } from 'common/snabbdom'; +import type { RoundData } from '../interfaces'; +import type { ClockData } from '../clock/clockCtrl'; +import type RoundController from '../ctrl'; +import { type LooseVNodes, type LooseVNode, looseH as h, bind, onInsert } from 'common/snabbdom'; import { pubsub } from 'common/pubsub'; export interface ButtonState { @@ -20,7 +20,7 @@ function analysisBoardOrientation(data: RoundData) { return data.game.variant.key === 'racingKings' ? 'white' : data.player.color; } -function poolUrl(clock: ClockData, blocking?: game.PlayerUser) { +function poolUrl(clock: ClockData, blocking?: PlayerUser) { return '/#pool/' + clock.initial / 60 + '+' + clock.increment + (blocking ? '/' + blocking.id : ''); } @@ -28,12 +28,12 @@ function analysisButton(ctrl: RoundController): VNode | false { const d = ctrl.data, url = gameRoute(d, analysisBoardOrientation(d)) + '#' + ctrl.ply; return ( - game.replayable(d) && + replayable(d) && h( 'a.fbt', { attrs: { href: url }, - hook: util.bind('click', _ => { + hook: bind('click', _ => { // force page load in case the URL is the same if (location.pathname === url.split('#')[0]) location.reload(); }), @@ -48,14 +48,14 @@ function rematchButtons(ctrl: RoundController): LooseVNodes { me = !!d.player.offeringRematch, disabled = !me && !d.opponent.onGame && (!!d.clock || !d.player.user || !d.opponent.user), them = !!d.opponent.offeringRematch && !disabled; - if (!game.rematchable(d)) return []; + if (!rematchable(d)) return []; return [ them && h( 'button.rematch-decline', { attrs: { 'data-icon': licon.X, title: i18n.site.decline }, - hook: util.bind('click', () => ctrl.socket.send('rematch-no')), + hook: bind('click', () => ctrl.socket.send('rematch-no')), }, ctrl.nvui ? i18n.site.decline : '', ), @@ -70,7 +70,7 @@ function rematchButtons(ctrl: RoundController): LooseVNodes { ? i18n.site.rematchOfferSent : '', }, - hook: util.bind( + hook: bind( 'click', () => { const d = ctrl.data; @@ -107,11 +107,11 @@ export function standard( 'button.fbt.' + socketMsg, { attrs: { disabled: !enabled(), title: hintFn() }, - hook: util.bind('click', () => { + hook: bind('click', () => { if (enabled()) onclick ? onclick() : ctrl.socket.sendLoading(socketMsg); }), }, - [h('span', ctrl.nvui ? [hintFn()] : util.justIcon(icon))], + [h('span', ctrl.nvui ? [hintFn()] : justIcon(icon))], ); } @@ -123,12 +123,12 @@ export function opponentGone(ctrl: RoundController): LooseVNode { h('p', { hook: onSuggestionHook }, i18n.site.opponentLeftChoices), h( 'button.button', - { hook: util.bind('click', () => ctrl.socket.sendLoading('resign-force')) }, + { hook: bind('click', () => ctrl.socket.sendLoading('resign-force')) }, i18n.site.forceResignation, ), h( 'button.button', - { hook: util.bind('click', () => ctrl.socket.sendLoading('draw-force')) }, + { hook: bind('click', () => ctrl.socket.sendLoading('draw-force')) }, i18n.site.forceDraw, ), ]) @@ -139,14 +139,14 @@ export function opponentGone(ctrl: RoundController): LooseVNode { const fbtCancel = (f: (v: boolean) => void) => h('button.fbt.no', { attrs: { title: i18n.site.cancel, 'data-icon': licon.X }, - hook: util.bind('click', () => f(false)), + hook: bind('click', () => f(false)), }); export const resignConfirm = (ctrl: RoundController): VNode => h('div.act-confirm', [ h('button.fbt.yes', { attrs: { title: i18n.site.resign, 'data-icon': licon.FlagOutline }, - hook: util.bind('click', () => ctrl.resign(true)), + hook: bind('click', () => ctrl.resign(true)), }), fbtCancel(ctrl.resign), ]); @@ -155,7 +155,7 @@ export const drawConfirm = (ctrl: RoundController): VNode => h('div.act-confirm', [ h('button.fbt.yes.draw-yes', { attrs: { title: i18n.site.offerDraw, 'data-icon': licon.OneHalf }, - hook: util.bind('click', () => ctrl.offerDraw(true)), + hook: bind('click', () => ctrl.offerDraw(true)), }), fbtCancel(ctrl.offerDraw), ]); @@ -164,7 +164,7 @@ export const claimThreefold = (ctrl: RoundController, condition: (d: RoundData) h( 'button.button.draw-yes', { - hook: util.bind('click', () => + hook: bind('click', () => condition(ctrl.data).enabled ? ctrl.socket.sendLoading('draw-claim') : undefined, ), attrs: { @@ -192,12 +192,12 @@ export function backToTournament(ctrl: RoundController): LooseVNode { 'a.text.fbt.strong.glowing', { attrs: { 'data-icon': licon.PlayTriangle, href: '/tournament/' + d.tournament.id }, - hook: util.bind('click', ctrl.setRedirecting), + hook: bind('click', ctrl.setRedirecting), }, i18n.site.backToTournament, ), h('form', { attrs: { method: 'post', action: '/tournament/' + d.tournament.id + '/withdraw' } }, [ - h('button.text.fbt.weak', util.justIcon(licon.Pause), i18n.site.pause), + h('button.text.fbt.weak', justIcon(licon.Pause), i18n.site.pause), ]), analysisButton(ctrl), ]) @@ -213,7 +213,7 @@ export function backToSwiss(ctrl: RoundController): LooseVNode { 'a.text.fbt.strong.glowing', { attrs: { 'data-icon': licon.PlayTriangle, href: '/swiss/' + d.swiss.id }, - hook: util.bind('click', ctrl.setRedirecting), + hook: bind('click', ctrl.setRedirecting), }, i18n.site.backToTournament, ), @@ -224,7 +224,7 @@ export function backToSwiss(ctrl: RoundController): LooseVNode { export function moretime(ctrl: RoundController): LooseVNode { return ( - game.moretimeable(ctrl.data) && + moretimeable(ctrl.data) && h('a.moretime', { attrs: { title: ctrl.data.clock @@ -232,7 +232,7 @@ export function moretime(ctrl: RoundController): LooseVNode { : i18n.preferences.giveMoreTime, 'data-icon': licon.PlusButton, }, - hook: util.bind('click', ctrl.socket.moreTime), + hook: bind('click', ctrl.socket.moreTime), }) ); } @@ -241,13 +241,12 @@ export function followUp(ctrl: RoundController): VNode { const d = ctrl.data, rematchable = !d.game.rematch && - (status.finished(d) || - (status.aborted(d) && (!d.game.rated || !['lobby', 'pool'].includes(d.game.source)))) && + (finished(d) || (aborted(d) && (!d.game.rated || !['lobby', 'pool'].includes(d.game.source)))) && !d.tournament && !d.simul && !d.swiss && !d.game.boosted, - newable = (status.finished(d) || status.aborted(d)) && ['lobby', 'pool', 'local'].includes(d.game.source), + newable = (finished(d) || aborted(d)) && ['lobby', 'pool', 'local'].includes(d.game.source), rematchZone = rematchable || d.game.rematch ? rematchButtons(ctrl) : []; return h('div.follow-up', [ ...rematchZone, @@ -282,4 +281,4 @@ export function watcherFollowUp(ctrl: RoundController): LooseVNode { return content.find(x => !!x) && h('div.follow-up', content); } -const onSuggestionHook: Hooks = util.onInsert(el => pubsub.emit('round.suggestion', el.textContent)); +const onSuggestionHook: Hooks = onInsert(el => pubsub.emit('round.suggestion', el.textContent)); diff --git a/ui/round/src/view/expiration.ts b/ui/round/src/view/expiration.ts index 1c79a3acbd223..60145c5c4e5f5 100644 --- a/ui/round/src/view/expiration.ts +++ b/ui/round/src/view/expiration.ts @@ -1,7 +1,7 @@ import { h } from 'snabbdom'; -import RoundController from '../ctrl'; +import type RoundController from '../ctrl'; import { isPlayerTurn, playable } from 'game'; -import { MaybeVNode } from 'common/snabbdom'; +import type { MaybeVNode } from 'common/snabbdom'; let rang = false; diff --git a/ui/round/src/view/main.ts b/ui/round/src/view/main.ts index 01d21cdddce84..eb5f7480a2fde 100644 --- a/ui/round/src/view/main.ts +++ b/ui/round/src/view/main.ts @@ -1,10 +1,8 @@ -import * as keyboard from '../keyboard'; -import * as util from '../util'; +import { next, prev, view } from '../keyboard'; import crazyView from '../crazy/crazyView'; -import RoundController from '../ctrl'; +import type RoundController from '../ctrl'; import { stepwiseScroll } from 'common/controls'; -import { VNode } from 'snabbdom'; -import { looseH as h } from 'common/snabbdom'; +import { type VNode, looseH as h, bind } from 'common/snabbdom'; import { render as renderKeyboardMove } from 'keyboardMove'; import { render as renderGround } from '../ground'; import { renderTable } from './table'; @@ -35,13 +33,13 @@ export function main(ctrl: RoundController): VNode { hook: 'ontouchstart' in window || !storage.boolean('scrollMoves').getOrDefault(true) ? undefined - : util.bind( + : bind( 'wheel', stepwiseScroll((e: WheelEvent, scroll: boolean) => { if (!ctrl.isPlaying()) { e.preventDefault(); - if (e.deltaY > 0 && scroll) keyboard.next(ctrl); - else if (e.deltaY < 0 && scroll) keyboard.prev(ctrl); + if (e.deltaY > 0 && scroll) next(ctrl); + else if (e.deltaY < 0 && scroll) prev(ctrl); ctrl.redraw(); } }), @@ -52,7 +50,7 @@ export function main(ctrl: RoundController): VNode { [renderGround(ctrl), ctrl.promotion.view(ctrl.data.game.variant.key === 'antichess')], ), ctrl.voiceMove && renderVoiceBar(ctrl.voiceMove.ctrl, ctrl.redraw), - ctrl.keyboardHelp && keyboard.view(ctrl), + ctrl.keyboardHelp && view(ctrl), crazyView(ctrl, topColor, 'top') || materialDiffs[0], ...renderTable(ctrl), crazyView(ctrl, bottomColor, 'bottom') || materialDiffs[1], diff --git a/ui/round/src/view/replay.ts b/ui/round/src/view/replay.ts index ae27cd415bbb8..9863b34cc5559 100644 --- a/ui/round/src/view/replay.ts +++ b/ui/round/src/view/replay.ts @@ -1,16 +1,15 @@ import * as licon from 'common/licon'; -import * as game from 'game'; -import * as status from 'game/status'; +import { userAnalysable, playable } from 'game'; +import { finished, aborted } from 'game/status'; import * as util from '../util'; import { isCol1 } from 'common/device'; -import RoundController from '../ctrl'; +import type RoundController from '../ctrl'; import { throttle } from 'common/timing'; import viewStatus from 'game/view/status'; import { game as gameRoute } from 'game/router'; -import { VNode } from 'snabbdom'; -import { Step } from '../interfaces'; +import type { Step } from '../interfaces'; import { toggleButton as boardMenuToggleButton } from 'board/menu'; -import { LooseVNodes, LooseVNode, looseH as h } from 'common/snabbdom'; +import { type VNode, type LooseVNodes, type LooseVNode, looseH as h, bind, onInsert } from 'common/snabbdom'; import boardMenu from './boardMenu'; const scrollMax = 99999, @@ -53,7 +52,7 @@ const renderMove = (step: Step, curPly: number, orEmpty: boolean, drawOffers: Se export function renderResult(ctrl: RoundController): VNode | undefined { let result: string | undefined; - if (status.finished(ctrl.data)) + if (finished(ctrl.data)) switch (ctrl.data.game.winner) { case 'white': result = '1-0'; @@ -64,13 +63,13 @@ export function renderResult(ctrl: RoundController): VNode | undefined { default: result = '½-½'; } - if (result || status.aborted(ctrl.data)) { + if (result || aborted(ctrl.data)) { return h('div.result-wrap', [ h('p.result', result || ''), h( 'p.status', { - hook: util.onInsert(() => { + hook: onInsert(() => { if (ctrl.autoScroll) ctrl.autoScroll(); else setTimeout(() => ctrl.autoScroll(), 200); }), @@ -114,7 +113,7 @@ function renderMoves(ctrl: RoundController): LooseVNodes { export function analysisButton(ctrl: RoundController): LooseVNode { const forecastCount = ctrl.data.forecastCount; return ( - game.userAnalysable(ctrl.data) && + userAnalysable(ctrl.data) && h( 'a.fbt.analysis', { @@ -138,7 +137,7 @@ function renderButtons(ctrl: RoundController) { return h( 'div.buttons', { - hook: util.bind( + hook: bind( 'mousedown', e => { const target = e.target as HTMLElement; @@ -171,7 +170,7 @@ function initMessage(ctrl: RoundController) { const d = ctrl.data; return ( (ctrl.replayEnabledByPref() || !isCol1()) && - game.playable(d) && + playable(d) && d.game.turns === 0 && !d.player.spectator && h('div.message', util.justIcon(licon.InfoCircle), [ @@ -186,7 +185,7 @@ function initMessage(ctrl: RoundController) { const col1Button = (ctrl: RoundController, dir: number, icon: string, disabled: boolean) => h('button.fbt', { attrs: { disabled: disabled, 'data-icon': icon, 'data-ply': ctrl.ply + dir }, - hook: util.bind('mousedown', e => { + hook: bind('mousedown', e => { e.preventDefault(); ctrl.userJump(ctrl.ply + dir); ctrl.redraw(); @@ -200,7 +199,7 @@ export function render(ctrl: RoundController): LooseVNode { h( movesTag, { - hook: util.onInsert(el => { + hook: onInsert(el => { el.addEventListener('mousedown', e => { let node = e.target as HTMLElement, offset = -2; diff --git a/ui/round/src/view/table.ts b/ui/round/src/view/table.ts index 3a6f90d6e8832..255958ac112be 100644 --- a/ui/round/src/view/table.ts +++ b/ui/round/src/view/table.ts @@ -1,16 +1,15 @@ import * as licon from 'common/licon'; -import { Position } from '../interfaces'; -import { bind } from '../util'; -import * as game from 'game'; -import * as status from 'game/status'; +import type { Position } from '../interfaces'; +import { abortable, playable, drawableSwiss, resignable, takebackable } from 'game'; +import { aborted, finished } from 'game/status'; import { renderClock } from '../clock/clockView'; import renderCorresClock from '../corresClock/corresClockView'; -import * as replay from './replay'; +import { render as renderReplay, analysisButton } from './replay'; import renderExpiration from './expiration'; -import * as renderUser from './user'; +import { userHtml } from './user'; import * as button from './button'; -import RoundController from '../ctrl'; -import { LooseVNodes, looseH as h } from 'common/snabbdom'; +import type RoundController from '../ctrl'; +import { type LooseVNodes, looseH as h, bind } from 'common/snabbdom'; import { toggleButton as boardMenuToggleButton } from 'board/menu'; function renderPlayer(ctrl: RoundController, position: Position) { @@ -22,7 +21,7 @@ function renderPlayer(ctrl: RoundController, position: Position) { h('i.line'), h('name', i18n.site.aiNameLevelAiLevel('Stockfish', player.ai)), ]) - : (ctrl.opts.local?.userVNode(player, position) ?? renderUser.userHtml(ctrl, player, position)); + : (ctrl.opts.local?.userVNode(player, position) ?? userHtml(ctrl, player, position)); } const isLoading = (ctrl: RoundController): boolean => ctrl.loading || ctrl.redirecting; @@ -30,7 +29,7 @@ const isLoading = (ctrl: RoundController): boolean => ctrl.loading || ctrl.redir const loader = () => h('i.ddloader'); const renderTableWith = (ctrl: RoundController, buttons: LooseVNodes) => [ - replay.render(ctrl), + renderReplay(ctrl), buttons.find(x => !!x) && h('div.rcontrols', buttons), ]; @@ -43,7 +42,7 @@ export const renderTableEnd = (ctrl: RoundController): LooseVNodes => export const renderTableWatch = (ctrl: RoundController): LooseVNodes => renderTableWith(ctrl, [ - isLoading(ctrl) ? loader() : game.playable(ctrl.data) ? undefined : button.watcherFollowUp(ctrl), + isLoading(ctrl) ? loader() : playable(ctrl.data) ? undefined : button.watcherFollowUp(ctrl), ]); const prompt = (ctrl: RoundController) => { @@ -73,11 +72,11 @@ export const renderTablePlay = (ctrl: RoundController): LooseVNodes => { loading || isQuestion ? [] : [ - game.abortable(d) + abortable(d) ? button.standard(ctrl, undefined, licon.X, i18n.site.abortGame, 'abort') : button.standard( ctrl, - d => ({ enabled: game.takebackable(d) }), + d => ({ enabled: takebackable(d) }), licon.Back, i18n.site.proposeATakeback, 'takeback-yes', @@ -87,7 +86,7 @@ export const renderTablePlay = (ctrl: RoundController): LooseVNodes => { ? button.drawConfirm(ctrl) : ctrl.data.game.threefold ? button.claimThreefold(ctrl, d => { - const threefoldable = game.drawableSwiss(d); + const threefoldable = drawableSwiss(d); return { enabled: threefoldable, overrideHint: threefoldable ? undefined : i18n.site.noDrawBeforeSwissLimit, @@ -97,7 +96,7 @@ export const renderTablePlay = (ctrl: RoundController): LooseVNodes => { ctrl, d => ({ enabled: ctrl.canOfferDraw(), - overrideHint: game.drawableSwiss(d) ? undefined : i18n.site.noDrawBeforeSwissLimit, + overrideHint: drawableSwiss(d) ? undefined : i18n.site.noDrawBeforeSwissLimit, }), licon.OneHalf, i18n.site.offerDraw, @@ -108,20 +107,20 @@ export const renderTablePlay = (ctrl: RoundController): LooseVNodes => { ? button.resignConfirm(ctrl) : button.standard( ctrl, - d => ({ enabled: game.resignable(d) }), + d => ({ enabled: resignable(d) }), licon.FlagOutline, i18n.site.resign, 'resign', () => ctrl.resign(true), ), - replay.analysisButton(ctrl), + analysisButton(ctrl), boardMenuToggleButton(ctrl.menu, i18n.site.menu), ], buttons = loading ? [loader()] : [promptVNode, button.opponentGone(ctrl), button.threefoldSuggestion(ctrl)]; return [ - replay.render(ctrl), + renderReplay(ctrl), h('div.rcontrols', [ h('div.ricons', { class: { 'yes-no-confirm': !!(ctrl.drawConfirm || ctrl.resignConfirm) } }, icons), ...buttons, @@ -131,7 +130,7 @@ export const renderTablePlay = (ctrl: RoundController): LooseVNodes => { function whosTurn(ctrl: RoundController, color: Color, position: Position) { const d = ctrl.data; - if (status.finished(d) || status.aborted(d)) return; + if (finished(d) || aborted(d)) return; return h( 'div.rclock.rclock-turn.rclock-' + position, d.game.player === color && @@ -158,7 +157,7 @@ export const renderTable = (ctrl: RoundController): LooseVNodes => [ renderPlayer(ctrl, 'top'), ...(ctrl.data.player.spectator ? renderTableWatch(ctrl) - : game.playable(ctrl.data) + : playable(ctrl.data) ? renderTablePlay(ctrl) : renderTableEnd(ctrl)), renderPlayer(ctrl, 'bottom'), diff --git a/ui/round/src/view/user.ts b/ui/round/src/view/user.ts index a390f86ef95e9..561670e1b1ea0 100644 --- a/ui/round/src/view/user.ts +++ b/ui/round/src/view/user.ts @@ -1,8 +1,8 @@ -import { looseH as h, VNode } from 'common/snabbdom'; +import { looseH as h, type VNode } from 'common/snabbdom'; import * as licon from 'common/licon'; -import { Player } from 'game'; -import { Position } from '../interfaces'; -import RoundController from '../ctrl'; +import type { Player } from 'game'; +import type { Position } from '../interfaces'; +import type RoundController from '../ctrl'; import { ratingDiff, userLink } from 'common/userLink'; export function userHtml(ctrl: RoundController, player: Player, position: Position): VNode { diff --git a/ui/round/src/xhr.ts b/ui/round/src/xhr.ts index 9b32e70cee706..7a647da4749ac 100644 --- a/ui/round/src/xhr.ts +++ b/ui/round/src/xhr.ts @@ -1,31 +1,31 @@ -import RoundController from './ctrl'; +import type RoundController from './ctrl'; import { throttlePromiseDelay } from 'common/timing'; -import * as xhr from 'common/xhr'; -import { RoundData } from './interfaces'; +import { text, json, form } from 'common/xhr'; +import type { RoundData } from './interfaces'; export const reload = (ctrl: RoundController): Promise => { const url = ctrl.data.player.spectator ? `/${ctrl.data.game.id}/${ctrl.data.player.color}` : `/${ctrl.data.game.id}${ctrl.data.player.id}`; - return xhr.json(url); + return json(url); }; export const setPreference = (key: string, value: string): Promise => - xhr.text(`/pref/${key}`, { method: 'post', body: xhr.form({ [key]: value }) }); + text(`/pref/${key}`, { method: 'post', body: form({ [key]: value }) }); export const whatsNext = (ctrl: RoundController): Promise<{ next?: string }> => - xhr.json(`/whats-next/${ctrl.data.game.id}${ctrl.data.player.id}`); + json(`/whats-next/${ctrl.data.game.id}${ctrl.data.player.id}`); export const challengeRematch = (gameId: string): Promise => - xhr.json('/challenge/rematch-of/' + gameId, { + json('/challenge/rematch-of/' + gameId, { method: 'post', }); export const setZen: (zen: boolean) => Promise = throttlePromiseDelay( () => 1000, zen => - xhr.text('/pref/zen', { + text('/pref/zen', { method: 'post', - body: xhr.form({ zen: zen ? 1 : 0 }), + body: form({ zen: zen ? 1 : 0 }), }), ); diff --git a/ui/simul/src/ctrl.ts b/ui/simul/src/ctrl.ts index 9365f0200bf3b..83624db541ce8 100644 --- a/ui/simul/src/ctrl.ts +++ b/ui/simul/src/ctrl.ts @@ -1,6 +1,6 @@ -import { makeSocket, SimulSocket } from './socket'; +import { makeSocket, type SimulSocket } from './socket'; import xhr from './xhr'; -import { SimulData, SimulOpts } from './interfaces'; +import type { SimulData, SimulOpts } from './interfaces'; import { storage } from 'common/storage'; import { idleTimer } from 'common/timing'; diff --git a/ui/simul/src/simul.ts b/ui/simul/src/simul.ts index 38e5ef007de49..2381a7cb4d705 100644 --- a/ui/simul/src/simul.ts +++ b/ui/simul/src/simul.ts @@ -1,5 +1,5 @@ import { init, VNode, classModule, attributesModule } from 'snabbdom'; -import { SimulOpts } from './interfaces'; +import type { SimulOpts } from './interfaces'; import SimulCtrl from './ctrl'; import StrongSocket from 'common/socket'; diff --git a/ui/simul/src/socket.ts b/ui/simul/src/socket.ts index 9b8f2f96e298e..3f1dae26f1df0 100644 --- a/ui/simul/src/socket.ts +++ b/ui/simul/src/socket.ts @@ -1,5 +1,5 @@ -import SimulCtrl from './ctrl'; -import { SimulData } from './interfaces'; +import type SimulCtrl from './ctrl'; +import type { SimulData } from './interfaces'; export interface SimulSocket { send: SocketSend; diff --git a/ui/simul/src/view/created.ts b/ui/simul/src/view/created.ts index 02098e22abbd9..075553fa72156 100644 --- a/ui/simul/src/view/created.ts +++ b/ui/simul/src/view/created.ts @@ -1,9 +1,9 @@ -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { confirm, domDialog } from 'common/dialog'; import { bind, looseH as h } from 'common/snabbdom'; -import SimulCtrl from '../ctrl'; -import { Applicant } from '../interfaces'; +import type SimulCtrl from '../ctrl'; +import type { Applicant } from '../interfaces'; import xhr from '../xhr'; import * as util from './util'; diff --git a/ui/simul/src/view/main.ts b/ui/simul/src/view/main.ts index b3fd01a1ad512..9d3e38806a345 100644 --- a/ui/simul/src/view/main.ts +++ b/ui/simul/src/view/main.ts @@ -1,6 +1,6 @@ import { onInsert, looseH as h } from 'common/snabbdom'; -import SimulCtrl from '../ctrl'; -import * as util from './util'; +import type SimulCtrl from '../ctrl'; +import { title } from './util'; import created from './created'; import { richHTML } from 'common/richText'; import results from './results'; @@ -31,14 +31,14 @@ const showText = (ctrl: SimulCtrl) => ctrl.data.text.length > 0 && h('div.simul-text', [h('p', { hook: richHTML(ctrl.data.text) })]); const started = (ctrl: SimulCtrl) => [ - h('div.box__top', util.title(ctrl)), + h('div.box__top', title(ctrl)), showText(ctrl), results(ctrl), pairings(ctrl), ]; const finished = (ctrl: SimulCtrl) => [ - h('div.box__top', [util.title(ctrl), h('div.box__top__actions', h('div.finished', i18n.site.finished))]), + h('div.box__top', [title(ctrl), h('div.box__top__actions', h('div.finished', i18n.site.finished))]), showText(ctrl), results(ctrl), pairings(ctrl), diff --git a/ui/simul/src/view/pairings.ts b/ui/simul/src/view/pairings.ts index cc71d8b0a4268..825dcfc96fa4a 100644 --- a/ui/simul/src/view/pairings.ts +++ b/ui/simul/src/view/pairings.ts @@ -1,8 +1,8 @@ import { h } from 'snabbdom'; import { onInsert } from 'common/snabbdom'; import { renderClock } from 'common/miniBoard'; -import SimulCtrl from '../ctrl'; -import { Pairing } from '../interfaces'; +import type SimulCtrl from '../ctrl'; +import type { Pairing } from '../interfaces'; import { opposite } from 'chessground/util'; import { userFlair } from 'common/userLink'; diff --git a/ui/simul/src/view/results.ts b/ui/simul/src/view/results.ts index 41ff707335d1e..5a72f57f102fc 100644 --- a/ui/simul/src/view/results.ts +++ b/ui/simul/src/view/results.ts @@ -1,8 +1,8 @@ import { h } from 'snabbdom'; import * as status from 'game/status'; -import { Pairing } from '../interfaces'; +import type { Pairing } from '../interfaces'; import { opposite } from 'chessground/util'; -import SimulCtrl from '../ctrl'; +import type SimulCtrl from '../ctrl'; export default function (ctrl: SimulCtrl) { return h('div.results', [ diff --git a/ui/simul/src/view/util.ts b/ui/simul/src/view/util.ts index f26f453662957..64cde83da10a4 100644 --- a/ui/simul/src/view/util.ts +++ b/ui/simul/src/view/util.ts @@ -1,7 +1,7 @@ import { h } from 'snabbdom'; -import { Player } from '../interfaces'; -import SimulCtrl from '../ctrl'; +import type { Player } from '../interfaces'; +import type SimulCtrl from '../ctrl'; import { fullName, userLine, userRating } from 'common/userLink'; export function player(p: Player, ctrl: SimulCtrl) { diff --git a/ui/site/src/api.ts b/ui/site/src/api.ts index 39328fe20e3e1..4039e43c0ad79 100644 --- a/ui/site/src/api.ts +++ b/ui/site/src/api.ts @@ -1,4 +1,4 @@ -import { Pubsub, PubsubCallback, PubsubEvent } from 'common/pubsub'; +import type { Pubsub, PubsubCallback, PubsubEvent } from 'common/pubsub'; // #TODO document these somewhere const publicEvents = ['ply', 'analysis.change', 'chat.resize', 'analysis.closeAll']; diff --git a/ui/site/src/asset.ts b/ui/site/src/asset.ts index d6c2f88858573..2df8be8802cea 100644 --- a/ui/site/src/asset.ts +++ b/ui/site/src/asset.ts @@ -1,4 +1,4 @@ -import * as xhr from 'common/xhr'; +import { script as xhrScript } from 'common/xhr'; import { memoize } from 'common'; export const baseUrl = memoize(() => document.body.getAttribute('data-asset-url') || ''); @@ -53,7 +53,7 @@ export const jsModule = (name: string, prefix: string = 'compiled/') => { const scriptCache = new Map>(); export const loadIife = (u: string, opts: AssetUrlOpts = {}): Promise => { - if (!scriptCache.has(u)) scriptCache.set(u, xhr.script(url(u, opts))); + if (!scriptCache.has(u)) scriptCache.set(u, xhrScript(url(u, opts))); return scriptCache.get(u)!; }; diff --git a/ui/site/src/boot.ts b/ui/site/src/boot.ts index 7d66cf2deae1a..bc48663b074ed 100644 --- a/ui/site/src/boot.ts +++ b/ui/site/src/boot.ts @@ -1,7 +1,7 @@ import * as licon from 'common/licon'; import { initMiniBoards, initMiniGames, updateMiniGame, finishMiniGame } from 'common/miniBoard'; import { prefersLight } from 'common/theme'; -import * as xhr from 'common/xhr'; +import { text as xhrText } from 'common/xhr'; import announce from './announce'; import OnlineFriends from './friends'; import powertip from './powertip'; @@ -97,7 +97,7 @@ export function boot() { .attr('href', url + '/withdraw') .text(i18n.site.pause) .on('click', function (this: HTMLAnchorElement) { - xhr.text(this.href, { method: 'post' }); + xhrText(this.href, { method: 'post' }); $('#announce').remove(); return false; }), diff --git a/ui/site/src/domHandlers.ts b/ui/site/src/domHandlers.ts index 2f22cb1e2cb39..93d11b8ae45fa 100644 --- a/ui/site/src/domHandlers.ts +++ b/ui/site/src/domHandlers.ts @@ -1,5 +1,5 @@ import * as licon from 'common/licon'; -import * as xhr from 'common/xhr'; +import { text as xhrText } from 'common/xhr'; import topBar from './topBar'; import { userComplete } from 'common/userComplete'; import { confirm } from 'common/dialog'; @@ -24,7 +24,7 @@ export function attachDomHandlers() { $('body').on('click', '.relation-button', function (this: HTMLAnchorElement) { const $a = $(this).addClass('processing').css('opacity', 0.3); - xhr.text(this.href, { method: 'post' }).then(html => { + xhrText(this.href, { method: 'post' }).then(html => { if ($a.hasClass('aclose')) $a.hide(); else if (html.includes('relation-actions')) $a.parent().replaceWith(html); else $a.replaceWith(html); @@ -58,7 +58,7 @@ export function attachDomHandlers() { $('#main-wrap').on('click', 'a.bookmark', function (this: HTMLAnchorElement) { const t = $(this).toggleClass('bookmarked'); - xhr.text(this.href, { method: 'post' }); + xhrText(this.href, { method: 'post' }); const count = (parseInt(t.text(), 10) || 0) + (t.hasClass('bookmarked') ? 1 : -1); t.find('span').html('' + (count > 0 ? count : '')); return false; diff --git a/ui/site/src/powertip.ts b/ui/site/src/powertip.ts index 074d75c4b6005..a5762f5dd475d 100644 --- a/ui/site/src/powertip.ts +++ b/ui/site/src/powertip.ts @@ -1,5 +1,5 @@ import * as licon from 'common/licon'; -import * as xhr from 'common/xhr'; +import { text as xhrText } from 'common/xhr'; import { requestIdleCallback, $as } from 'common'; import { spinnerHtml } from 'common/spinner'; @@ -10,7 +10,7 @@ const inCrosstable = (el: HTMLElement) => document.querySelector('.crosstable')? const onPowertipPreRender = (id: string, preload?: (url: string) => void) => (el: HTMLAnchorElement) => { const url = (el.dataset.href || el.href).replace(/\?.+$/, ''); if (preload) preload(url); - xhr.text(url + '/mini').then(html => { + xhrText(url + '/mini').then(html => { const el = document.getElementById(id) as HTMLElement; el.innerHTML = html; window.lichess.initializeDom(el); diff --git a/ui/site/src/site.lpvEmbed.ts b/ui/site/src/site.lpvEmbed.ts index 67cbe09b29267..6ff2b0a74fd55 100644 --- a/ui/site/src/site.lpvEmbed.ts +++ b/ui/site/src/site.lpvEmbed.ts @@ -1,5 +1,5 @@ import Lpv from 'lichess-pgn-viewer'; -import { Opts } from 'lichess-pgn-viewer/interfaces'; +import type { Opts } from 'lichess-pgn-viewer/interfaces'; interface OptsWithI18n extends Opts { i18n: any; diff --git a/ui/site/src/sound.ts b/ui/site/src/sound.ts index ebdbbbe240e1b..a3136b45ca13c 100644 --- a/ui/site/src/sound.ts +++ b/ui/site/src/sound.ts @@ -1,8 +1,7 @@ import { storage } from 'common/storage'; import { isIOS } from 'common/device'; import { throttle } from 'common/timing'; -import { defined } from 'common'; -import { charRole } from 'chess'; +import { defined, charToRole } from 'common'; type Name = string; type Path = string; @@ -192,7 +191,7 @@ export default new (class implements SoundI { const code = c.charCodeAt(0); if (code > 48 && code < 58) return c; // 1-8 if (code > 96 && code < 105) return c.toUpperCase(); - return charRole(c) || c; + return charToRole(c) || c; }) .join(' ') .replace(/^A /, 'A, ') // "A takes" & "A 3" are mispronounced diff --git a/ui/storm/package.json b/ui/storm/package.json index 033c218889ff2..6537fc9772b8a 100644 --- a/ui/storm/package.json +++ b/ui/storm/package.json @@ -13,7 +13,6 @@ "license": "AGPL-3.0-or-later", "dependencies": { "chess": "workspace:*", - "chessops": "^0.14.2", "common": "workspace:*", "puz": "workspace:*" }, diff --git a/ui/storm/src/config.ts b/ui/storm/src/config.ts index 3543a9c189cba..6bd731be198b8 100644 --- a/ui/storm/src/config.ts +++ b/ui/storm/src/config.ts @@ -1,4 +1,4 @@ -import { StormConfig } from './interfaces'; +import type { StormConfig } from './interfaces'; const config: StormConfig = { // all times in seconds diff --git a/ui/storm/src/ctrl.ts b/ui/storm/src/ctrl.ts index 73559c50b0d40..5fea78b673b84 100644 --- a/ui/storm/src/ctrl.ts +++ b/ui/storm/src/ctrl.ts @@ -10,10 +10,9 @@ import { makeCgOpts } from 'puz/run'; import { parseUci } from 'chessops/util'; import { PromotionCtrl } from 'chess/promotion'; import { prop, type Prop } from 'common'; -import { PuzCtrl, Run } from 'puz/interfaces'; +import type { PuzCtrl, Run } from 'puz/interfaces'; import { PuzFilters } from 'puz/filters'; -import { Role } from 'chessground/types'; -import { StormOpts, StormVm, StormRecap, StormPrefs, StormData } from './interfaces'; +import type { StormOpts, StormVm, StormRecap, StormPrefs, StormData } from './interfaces'; import { storage } from 'common/storage'; import { pubsub } from 'common/pubsub'; diff --git a/ui/storm/src/interfaces.ts b/ui/storm/src/interfaces.ts index e9992a277ab16..660833d2cafa5 100644 --- a/ui/storm/src/interfaces.ts +++ b/ui/storm/src/interfaces.ts @@ -1,5 +1,5 @@ -import { Prop } from 'common'; -import { Config, PuzPrefs, Puzzle } from 'puz/interfaces'; +import type { Prop } from 'common'; +import type { Config, PuzPrefs, Puzzle } from 'puz/interfaces'; export interface StormOpts { puzzles: Puzzle[]; diff --git a/ui/storm/src/storm.ts b/ui/storm/src/storm.ts index 4b240c8e71a3c..cc037ca87c458 100644 --- a/ui/storm/src/storm.ts +++ b/ui/storm/src/storm.ts @@ -1,7 +1,7 @@ import { attributesModule, classModule, init, VNode } from 'snabbdom'; import menuHover from 'common/menuHover'; import StormCtrl from './ctrl'; -import { StormOpts } from './interfaces'; +import type { StormOpts } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/storm/src/view/end.ts b/ui/storm/src/view/end.ts index 99a2cd57023d2..b8a97253fe7a0 100644 --- a/ui/storm/src/view/end.ts +++ b/ui/storm/src/view/end.ts @@ -1,8 +1,8 @@ -import StormCtrl from '../ctrl'; +import type StormCtrl from '../ctrl'; import { getNow } from 'puz/util'; import renderHistory from 'puz/view/history'; import { numberSpread } from 'common/number'; -import { onInsert, LooseVNodes, looseH as h } from 'common/snabbdom'; +import { onInsert, type LooseVNodes, looseH as h } from 'common/snabbdom'; const renderEnd = (ctrl: StormCtrl): LooseVNodes => [...renderSummary(ctrl), renderHistory(ctrl)]; diff --git a/ui/storm/src/view/main.ts b/ui/storm/src/view/main.ts index e927d25e3eaff..a1a0d8da46500 100644 --- a/ui/storm/src/view/main.ts +++ b/ui/storm/src/view/main.ts @@ -1,8 +1,8 @@ import config from '../config'; import renderClock from 'puz/view/clock'; import renderEnd from './end'; -import StormCtrl from '../ctrl'; -import { VNode } from 'snabbdom'; +import type StormCtrl from '../ctrl'; +import type { VNode } from 'snabbdom'; import { makeCgOpts, povMessage } from 'puz/run'; import { makeConfig as makeCgConfig } from 'puz/view/chessground'; import { getNow } from 'puz/util'; diff --git a/ui/storm/src/xhr.ts b/ui/storm/src/xhr.ts index df16de47f1b4a..bde573eef3153 100644 --- a/ui/storm/src/xhr.ts +++ b/ui/storm/src/xhr.ts @@ -1,11 +1,11 @@ -import * as xhr from 'common/xhr'; +import { text as xhrText, json as xhrJson, form as xhrForm } from 'common/xhr'; import { throttlePromiseDelay } from 'common/timing'; -import { RunResponse, StormRecap } from './interfaces'; +import type { RunResponse, StormRecap } from './interfaces'; export function record(run: StormRecap): Promise { - return xhr.json('/storm', { + return xhrJson('/storm', { method: 'POST', - body: xhr.form({ + body: xhrForm({ ...run, time: Math.round(run.time), notAnExploit: @@ -17,8 +17,8 @@ export function record(run: StormRecap): Promise { export const setZen: (zen: any) => Promise = throttlePromiseDelay( () => 1000, zen => - xhr.text('/pref/zen', { + xhrText('/pref/zen', { method: 'post', - body: xhr.form({ zen: zen ? 1 : 0 }), + body: xhrForm({ zen: zen ? 1 : 0 }), }), ); diff --git a/ui/swiss/src/ctrl.ts b/ui/swiss/src/ctrl.ts index 805c749ccf680..274fb2f47367a 100644 --- a/ui/swiss/src/ctrl.ts +++ b/ui/swiss/src/ctrl.ts @@ -1,8 +1,8 @@ -import { makeSocket, SwissSocket } from './socket'; +import { makeSocket, type SwissSocket } from './socket'; import xhr from './xhr'; import { throttlePromiseDelay } from 'common/timing'; import { maxPerPage, myPage, players } from './pagination'; -import { SwissData, SwissOpts, Pages, Standing, Player } from './interfaces'; +import type { SwissData, SwissOpts, Pages, Standing, Player } from './interfaces'; import { storage } from 'common/storage'; export default class SwissCtrl { diff --git a/ui/swiss/src/pagination.ts b/ui/swiss/src/pagination.ts index e7218a6555e56..cf72d9f2d2266 100644 --- a/ui/swiss/src/pagination.ts +++ b/ui/swiss/src/pagination.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, MaybeVNodes } from 'common/snabbdom'; -import SwissCtrl from './ctrl'; -import { Pager } from './interfaces'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; +import type SwissCtrl from './ctrl'; +import type { Pager } from './interfaces'; import * as search from './search'; export const maxPerPage = 10; diff --git a/ui/swiss/src/search.ts b/ui/swiss/src/search.ts index f98013a2e6a28..2396da680e72f 100644 --- a/ui/swiss/src/search.ts +++ b/ui/swiss/src/search.ts @@ -1,7 +1,7 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind, onInsert } from 'common/snabbdom'; -import TournamentController from './ctrl'; +import type TournamentController from './ctrl'; import { userComplete } from 'common/userComplete'; export function button(ctrl: TournamentController): VNode { diff --git a/ui/swiss/src/socket.ts b/ui/swiss/src/socket.ts index 9f072c48f8914..e75c4ef25e30d 100644 --- a/ui/swiss/src/socket.ts +++ b/ui/swiss/src/socket.ts @@ -1,4 +1,4 @@ -import SwissCtrl from './ctrl'; +import type SwissCtrl from './ctrl'; export interface SwissSocket { send: SocketSend; diff --git a/ui/swiss/src/swiss.ts b/ui/swiss/src/swiss.ts index 9abc235096448..75fb7459f2e3f 100644 --- a/ui/swiss/src/swiss.ts +++ b/ui/swiss/src/swiss.ts @@ -1,5 +1,5 @@ import { init, VNode, classModule, attributesModule } from 'snabbdom'; -import { SwissOpts } from './interfaces'; +import type { SwissOpts } from './interfaces'; import SwissCtrl from './ctrl'; import StrongSocket from 'common/socket'; diff --git a/ui/swiss/src/util.ts b/ui/swiss/src/util.ts index 0ab5b3bc7224e..3a3161ebc35d8 100644 --- a/ui/swiss/src/util.ts +++ b/ui/swiss/src/util.ts @@ -1,3 +1,3 @@ -import { Outcome, PairingExt } from './interfaces'; +import type { Outcome, PairingExt } from './interfaces'; export const isOutcome = (s: PairingExt | string): s is Outcome => s == 'absent' || s == 'late' || s == 'bye'; diff --git a/ui/swiss/src/view/boards.ts b/ui/swiss/src/view/boards.ts index 33c9fd9570961..ee6bcf00ab17b 100644 --- a/ui/swiss/src/view/boards.ts +++ b/ui/swiss/src/view/boards.ts @@ -1,6 +1,6 @@ -import { Board, SwissOpts } from '../interfaces'; +import type { Board, SwissOpts } from '../interfaces'; import { renderClock } from 'common/miniBoard'; -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { opposite } from 'chessground/util'; import { player as renderPlayer } from './util'; diff --git a/ui/swiss/src/view/header.ts b/ui/swiss/src/view/header.ts index 451c4a9913815..e884106f22a38 100644 --- a/ui/swiss/src/view/header.ts +++ b/ui/swiss/src/view/header.ts @@ -1,7 +1,7 @@ -import { h, Hooks, VNode } from 'snabbdom'; +import { h, type Hooks, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { dataIcon } from 'common/snabbdom'; -import SwissCtrl from '../ctrl'; +import type SwissCtrl from '../ctrl'; import { setClockWidget } from 'common/clock'; const startClock = (time: number): Hooks => ({ diff --git a/ui/swiss/src/view/main.ts b/ui/swiss/src/view/main.ts index 96a63cd2fb5d9..0aff2ebf05f47 100644 --- a/ui/swiss/src/view/main.ts +++ b/ui/swiss/src/view/main.ts @@ -1,11 +1,10 @@ -import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; -import { dataIcon, bind, onInsert, LooseVNodes, looseH as h } from 'common/snabbdom'; +import { type VNode, dataIcon, bind, onInsert, type LooseVNodes, looseH as h } from 'common/snabbdom'; import { numberRow } from './util'; -import SwissCtrl from '../ctrl'; -import * as pagination from '../pagination'; -import { SwissData, Pager } from '../interfaces'; +import type SwissCtrl from '../ctrl'; +import { players, renderPager } from '../pagination'; +import type { SwissData, Pager } from '../interfaces'; import header from './header'; import standing from './standing'; import * as boards from './boards'; @@ -40,7 +39,7 @@ export default function (ctrl: SwissCtrl) { } function created(ctrl: SwissCtrl): LooseVNodes { - const pag = pagination.players(ctrl); + const pag = players(ctrl); return [ header(ctrl), nextRound(ctrl), @@ -63,7 +62,7 @@ const notice = (ctrl: SwissCtrl) => { }; function started(ctrl: SwissCtrl): LooseVNodes { - const pag = pagination.players(ctrl); + const pag = players(ctrl); return [ header(ctrl), joinTheGame(ctrl) || notice(ctrl), @@ -74,7 +73,7 @@ function started(ctrl: SwissCtrl): LooseVNodes { } function finished(ctrl: SwissCtrl): LooseVNodes { - const pag = pagination.players(ctrl); + const pag = players(ctrl); return [ h('div.podium-wrap', [confetti(ctrl.data), header(ctrl), podium(ctrl)]), controls(ctrl, pag), @@ -83,7 +82,7 @@ function finished(ctrl: SwissCtrl): LooseVNodes { } function controls(ctrl: SwissCtrl, pag: Pager): VNode { - return h('div.swiss__controls', [h('div.pager', pagination.renderPager(ctrl, pag)), joinButton(ctrl)]); + return h('div.swiss__controls', [h('div.pager', renderPager(ctrl, pag)), joinButton(ctrl)]); } function nextRound(ctrl: SwissCtrl): VNode | undefined { diff --git a/ui/swiss/src/view/playerInfo.ts b/ui/swiss/src/view/playerInfo.ts index ef5c90c857bc9..83989a295c045 100644 --- a/ui/swiss/src/view/playerInfo.ts +++ b/ui/swiss/src/view/playerInfo.ts @@ -1,11 +1,11 @@ -import { VNode } from 'snabbdom'; +import type { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import { bind, dataIcon, looseH as h } from 'common/snabbdom'; import { player as renderPlayer, numberRow } from './util'; -import { Pairing } from '../interfaces'; +import type { Pairing } from '../interfaces'; import { isOutcome } from '../util'; -import SwissCtrl from '../ctrl'; +import type SwissCtrl from '../ctrl'; import { fullName } from 'common/userLink'; export default function (ctrl: SwissCtrl): VNode | undefined { diff --git a/ui/swiss/src/view/podium.ts b/ui/swiss/src/view/podium.ts index bb17cb8bfd717..e0f1f2f9b7a0c 100644 --- a/ui/swiss/src/view/podium.ts +++ b/ui/swiss/src/view/podium.ts @@ -1,6 +1,6 @@ -import { h, VNode } from 'snabbdom'; -import SwissCtrl from '../ctrl'; -import { PodiumPlayer } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type SwissCtrl from '../ctrl'; +import type { PodiumPlayer } from '../interfaces'; import { userLink } from 'common/userLink'; const podiumStats = (p: PodiumPlayer, ctrl: SwissCtrl): VNode => diff --git a/ui/swiss/src/view/standing.ts b/ui/swiss/src/view/standing.ts index 45c151a98cb7a..e77b0f48fec85 100644 --- a/ui/swiss/src/view/standing.ts +++ b/ui/swiss/src/view/standing.ts @@ -1,9 +1,9 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, MaybeVNodes, onInsert } from 'common/snabbdom'; -import SwissCtrl from '../ctrl'; +import { bind, type MaybeVNodes, onInsert } from 'common/snabbdom'; +import type SwissCtrl from '../ctrl'; import { player as renderPlayer } from './util'; -import { Player, Pager } from '../interfaces'; +import type { Player, Pager } from '../interfaces'; function playerTr(ctrl: SwissCtrl, player: Player) { const userId = player.user.id; diff --git a/ui/swiss/src/view/util.ts b/ui/swiss/src/view/util.ts index 466bd80fb1366..5f64218301a2d 100644 --- a/ui/swiss/src/view/util.ts +++ b/ui/swiss/src/view/util.ts @@ -1,5 +1,5 @@ import { h } from 'snabbdom'; -import { BasePlayer } from '../interfaces'; +import type { BasePlayer } from '../interfaces'; import { numberFormat } from 'common/number'; import { fullName, userRating } from 'common/userLink'; diff --git a/ui/swiss/src/xhr.ts b/ui/swiss/src/xhr.ts index e94980ca99d12..912655a7bbfb7 100644 --- a/ui/swiss/src/xhr.ts +++ b/ui/swiss/src/xhr.ts @@ -1,8 +1,8 @@ import { throttlePromiseDelay } from 'common/timing'; import { json, form } from 'common/xhr'; -import SwissCtrl from './ctrl'; +import type SwissCtrl from './ctrl'; import { isOutcome } from './util'; -import { Sheet } from './interfaces'; +import type { Sheet } from './interfaces'; // when the tournament no longer exists const onFail = () => site.reload(); diff --git a/ui/tournament/src/ctrl.ts b/ui/tournament/src/ctrl.ts index 6c06046f00285..3f61ee5355105 100644 --- a/ui/tournament/src/ctrl.ts +++ b/ui/tournament/src/ctrl.ts @@ -1,8 +1,16 @@ -import { TournamentSocket, makeSocket } from './socket'; +import { type TournamentSocket, makeSocket } from './socket'; import * as xhr from './xhr'; import { maxPerPage, myPage, players } from './pagination'; import * as sound from './sound'; -import { TournamentData, TournamentOpts, Pages, PlayerInfo, TeamInfo, Standing, Player } from './interfaces'; +import type { + TournamentData, + TournamentOpts, + Pages, + PlayerInfo, + TeamInfo, + Standing, + Player, +} from './interfaces'; import { storage } from 'common/storage'; import { pubsub } from 'common/pubsub'; import { alerts, prompt } from 'common/dialog'; diff --git a/ui/tournament/src/interfaces.ts b/ui/tournament/src/interfaces.ts index 00af5bd37bf9b..e23d22457ea7d 100644 --- a/ui/tournament/src/interfaces.ts +++ b/ui/tournament/src/interfaces.ts @@ -1,5 +1,3 @@ -import { FEN } from 'chessground/types'; - export interface StandingPlayer extends SimplePlayer { id: string; withdraw?: boolean; diff --git a/ui/tournament/src/pagination.ts b/ui/tournament/src/pagination.ts index eb23a8d2d7061..77954642fa50c 100644 --- a/ui/tournament/src/pagination.ts +++ b/ui/tournament/src/pagination.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, MaybeVNodes } from 'common/snabbdom'; -import TournamentController from './ctrl'; -import { Pagination } from './interfaces'; +import { bind, type MaybeVNodes } from 'common/snabbdom'; +import type TournamentController from './ctrl'; +import type { Pagination } from './interfaces'; import * as search from './search'; export const maxPerPage = 10; diff --git a/ui/tournament/src/search.ts b/ui/tournament/src/search.ts index d88c8a91b96f5..3fb4af469f638 100644 --- a/ui/tournament/src/search.ts +++ b/ui/tournament/src/search.ts @@ -1,7 +1,7 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { bind, onInsert } from 'common/snabbdom'; -import TournamentController from './ctrl'; +import type TournamentController from './ctrl'; import { userComplete } from 'common/userComplete'; export function button(ctrl: TournamentController): VNode { diff --git a/ui/tournament/src/socket.ts b/ui/tournament/src/socket.ts index e9474866f04eb..d22e376cc6e0c 100644 --- a/ui/tournament/src/socket.ts +++ b/ui/tournament/src/socket.ts @@ -1,4 +1,4 @@ -import TournamentController from './ctrl'; +import type TournamentController from './ctrl'; export interface TournamentSocket { send: SocketSend; diff --git a/ui/tournament/src/sound.ts b/ui/tournament/src/sound.ts index 8dfee5ed8cd72..80c5353069f0d 100644 --- a/ui/tournament/src/sound.ts +++ b/ui/tournament/src/sound.ts @@ -1,5 +1,5 @@ import notify from 'common/notification'; -import { TournamentData } from './interfaces'; +import type { TournamentData } from './interfaces'; import { once } from 'common/storage'; let countDownTimeout: number | undefined; diff --git a/ui/tournament/src/tournament.calendar.ts b/ui/tournament/src/tournament.calendar.ts index 06a7b5a6bc7f0..c3b62419dbd95 100644 --- a/ui/tournament/src/tournament.calendar.ts +++ b/ui/tournament/src/tournament.calendar.ts @@ -1,7 +1,7 @@ import view from './view/calendarView'; import { init, VNode, classModule, attributesModule } from 'snabbdom'; -import { Tournament } from './interfaces'; +import type { Tournament } from './interfaces'; const patch = init([classModule, attributesModule]); diff --git a/ui/tournament/src/tournament.schedule.ts b/ui/tournament/src/tournament.schedule.ts index 828003285f1cb..7d7498251ec4d 100644 --- a/ui/tournament/src/tournament.schedule.ts +++ b/ui/tournament/src/tournament.schedule.ts @@ -1,7 +1,7 @@ import view from './view/scheduleView'; -import { init, VNode, classModule, attributesModule } from 'snabbdom'; -import { Tournament } from './interfaces'; +import { init, type VNode, classModule, attributesModule } from 'snabbdom'; +import type { Tournament } from './interfaces'; import StrongSocket from 'common/socket'; import { pubsub } from 'common/pubsub'; diff --git a/ui/tournament/src/tournament.ts b/ui/tournament/src/tournament.ts index 7297f3da2f95b..6476f02b4cec6 100644 --- a/ui/tournament/src/tournament.ts +++ b/ui/tournament/src/tournament.ts @@ -1,5 +1,5 @@ import { init, classModule, attributesModule } from 'snabbdom'; -import { TournamentOpts } from './interfaces'; +import type { TournamentOpts } from './interfaces'; import StrongSocket from 'common/socket'; const patch = init([classModule, attributesModule]); diff --git a/ui/tournament/src/view/arena.ts b/ui/tournament/src/view/arena.ts index 26a7ec725f21c..10315ac41f86b 100644 --- a/ui/tournament/src/view/arena.ts +++ b/ui/tournament/src/view/arena.ts @@ -1,12 +1,12 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import { bind, dataIcon, MaybeVNodes } from 'common/snabbdom'; -import TournamentController from '../ctrl'; +import { bind, dataIcon, type MaybeVNodes } from 'common/snabbdom'; +import type TournamentController from '../ctrl'; import { player as renderPlayer, ratio2percent } from './util'; import { teamName } from './battle'; -import { Pagination, PodiumPlayer, StandingPlayer } from '../interfaces'; -import * as button from './button'; -import * as pagination from '../pagination'; +import type { Pagination, PodiumPlayer, StandingPlayer } from '../interfaces'; +import { joinWithdraw } from './button'; +import { renderPager } from '../pagination'; import { userLink } from 'common/userLink'; const renderScoreString = (scoreString: string, streakable: boolean) => { @@ -103,10 +103,7 @@ export function podium(ctrl: TournamentController) { } export function controls(ctrl: TournamentController, pag: Pagination): VNode { - return h('div.tour__controls', [ - h('div.pager', pagination.renderPager(ctrl, pag)), - button.joinWithdraw(ctrl), - ]); + return h('div.tour__controls', [h('div.pager', renderPager(ctrl, pag)), joinWithdraw(ctrl)]); } export function standing(ctrl: TournamentController, pag: Pagination, klass?: string): VNode { diff --git a/ui/tournament/src/view/battle.ts b/ui/tournament/src/view/battle.ts index 04e12dd304d86..49516c0371d68 100644 --- a/ui/tournament/src/view/battle.ts +++ b/ui/tournament/src/view/battle.ts @@ -1,9 +1,9 @@ -import TournamentController from '../ctrl'; -import { bind, MaybeVNode } from 'common/snabbdom'; +import type TournamentController from '../ctrl'; +import { bind, type MaybeVNode } from 'common/snabbdom'; import { fullName, userFlair } from 'common/userLink'; import { snabDialog } from 'common/dialog'; -import { h, VNode } from 'snabbdom'; -import { TeamBattle, RankedTeam, LightTeam } from '../interfaces'; +import { h, type VNode } from 'snabbdom'; +import type { TeamBattle, RankedTeam, LightTeam } from '../interfaces'; export function joinWithTeamSelector(ctrl: TournamentController) { const tb = ctrl.data.teamBattle!; diff --git a/ui/tournament/src/view/button.ts b/ui/tournament/src/view/button.ts index 12209e6a08b1c..573af40d72f22 100644 --- a/ui/tournament/src/view/button.ts +++ b/ui/tournament/src/view/button.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import { bind, dataIcon } from 'common/snabbdom'; -import TournamentController from '../ctrl'; +import type TournamentController from '../ctrl'; function orJoinSpinner(ctrl: TournamentController, f: () => VNode): VNode { return ctrl.joinSpinner ? spinner() : f(); diff --git a/ui/tournament/src/view/calendarView.ts b/ui/tournament/src/view/calendarView.ts index 4bd6536329bcb..c6dbf078eb2de 100644 --- a/ui/tournament/src/view/calendarView.ts +++ b/ui/tournament/src/view/calendarView.ts @@ -1,12 +1,12 @@ -import { Classes, h, VNode } from 'snabbdom'; +import { type Classes, h, type VNode } from 'snabbdom'; import eachDayOfInterval from 'date-fns/eachDayOfInterval'; import addDays from 'date-fns/addDays'; import getHours from 'date-fns/getHours'; import getMinutes from 'date-fns/getMinutes'; import areIntervalsOverlapping from 'date-fns/areIntervalsOverlapping'; import format from 'date-fns/format'; -import { Tournament } from '../interfaces'; -import { Ctrl, Lanes } from '../tournament.calendar'; +import type { Tournament } from '../interfaces'; +import type { Ctrl, Lanes } from '../tournament.calendar'; import * as licon from 'common/licon'; import perfIcons from 'common/perfIcons'; diff --git a/ui/tournament/src/view/created.ts b/ui/tournament/src/view/created.ts index 2200b57ed1d98..e52d9be677c03 100644 --- a/ui/tournament/src/view/created.ts +++ b/ui/tournament/src/view/created.ts @@ -1,7 +1,7 @@ -import { h, VNode } from 'snabbdom'; -import { MaybeVNodes, onInsert } from 'common/snabbdom'; -import TournamentController from '../ctrl'; -import * as pagination from '../pagination'; +import { h, type VNode } from 'snabbdom'; +import { type MaybeVNodes, onInsert } from 'common/snabbdom'; +import type TournamentController from '../ctrl'; +import { players } from '../pagination'; import { controls, standing } from './arena'; import { teamStanding } from './battle'; import teamInfo from './teamInfo'; @@ -10,7 +10,7 @@ import header from './header'; export const name = 'created'; export function main(ctrl: TournamentController): MaybeVNodes { - const pag = pagination.players(ctrl); + const pag = players(ctrl); return [ header(ctrl), teamStanding(ctrl, 'created'), diff --git a/ui/tournament/src/view/finished.ts b/ui/tournament/src/view/finished.ts index 9128f548aff72..2f76e1fc4da30 100644 --- a/ui/tournament/src/view/finished.ts +++ b/ui/tournament/src/view/finished.ts @@ -1,15 +1,15 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; -import TournamentController from '../ctrl'; -import { TournamentData } from '../interfaces'; -import * as pagination from '../pagination'; +import type TournamentController from '../ctrl'; +import type { TournamentData } from '../interfaces'; +import { players } from '../pagination'; import { controls, standing, podium } from './arena'; import { teamStanding } from './battle'; import header from './header'; import playerInfo from './playerInfo'; import teamInfo from './teamInfo'; import { numberRow } from './util'; -import { MaybeVNodes } from 'common/snabbdom'; +import { type MaybeVNodes } from 'common/snabbdom'; import { once } from 'common/storage'; function confetti(data: TournamentData): VNode | undefined { @@ -98,7 +98,7 @@ function stats(ctrl: TournamentController): VNode | undefined { export const name = 'finished'; export function main(ctrl: TournamentController): MaybeVNodes { - const pag = pagination.players(ctrl); + const pag = players(ctrl); const teamS = teamStanding(ctrl, 'finished'); return [ ...(teamS diff --git a/ui/tournament/src/view/header.ts b/ui/tournament/src/view/header.ts index 301369efc4dee..873323210e47b 100644 --- a/ui/tournament/src/view/header.ts +++ b/ui/tournament/src/view/header.ts @@ -1,9 +1,9 @@ -import { h, Hooks, VNode } from 'snabbdom'; +import { h, type Hooks, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { dataIcon } from 'common/snabbdom'; -import TournamentController from '../ctrl'; +import type TournamentController from '../ctrl'; import perfIcons from 'common/perfIcons'; -import { TournamentData } from '../interfaces'; +import type { TournamentData } from '../interfaces'; import { setClockWidget } from 'common/clock'; const startClock = (time: number): Hooks => ({ diff --git a/ui/tournament/src/view/main.ts b/ui/tournament/src/view/main.ts index a9f283173754c..3e5627da19c0f 100644 --- a/ui/tournament/src/view/main.ts +++ b/ui/tournament/src/view/main.ts @@ -1,10 +1,10 @@ -import { h, VNode } from 'snabbdom'; -import { onInsert, MaybeVNodes } from 'common/snabbdom'; +import { h, type VNode } from 'snabbdom'; +import { onInsert, type MaybeVNodes } from 'common/snabbdom'; import * as created from './created'; import * as started from './started'; import * as finished from './finished'; import { joinWithTeamSelector } from './battle'; -import TournamentController from '../ctrl'; +import type TournamentController from '../ctrl'; import { watchers } from 'common/watchers'; import { makeChat } from 'chat'; diff --git a/ui/tournament/src/view/playerInfo.ts b/ui/tournament/src/view/playerInfo.ts index ec87c0a6c9b0d..b5d00fd4e41de 100644 --- a/ui/tournament/src/view/playerInfo.ts +++ b/ui/tournament/src/view/playerInfo.ts @@ -1,13 +1,12 @@ -import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; -import { bind, dataIcon, looseH as h } from 'common/snabbdom'; +import { type VNode, bind, dataIcon, looseH as h } from 'common/snabbdom'; import { numberRow, player as renderPlayer } from './util'; import { fullName } from 'common/userLink'; import { teamName } from './battle'; -import * as status from 'game/status'; -import TournamentController from '../ctrl'; -import { Player } from '../interfaces'; +import { ids } from 'game/status'; +import type TournamentController from '../ctrl'; +import type { Player } from '../interfaces'; function result(win: boolean, stat: number): string { switch (win) { @@ -16,7 +15,7 @@ function result(win: boolean, stat: number): string { case false: return '0'; default: - return stat >= status.ids.mate ? '½' : '*'; + return stat >= ids.mate ? '½' : '*'; } } diff --git a/ui/tournament/src/view/scheduleView.ts b/ui/tournament/src/view/scheduleView.ts index 2671478b5bbd5..cea686dd2b39d 100644 --- a/ui/tournament/src/view/scheduleView.ts +++ b/ui/tournament/src/view/scheduleView.ts @@ -1,8 +1,8 @@ -import { Classes, h, VNode } from 'snabbdom'; +import { type Classes, h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import perfIcons from 'common/perfIcons'; -import { Tournament, Clock } from '../interfaces'; -import { Ctrl, Lane } from '../tournament.schedule'; +import type { Tournament, Clock } from '../interfaces'; +import type { Ctrl, Lane } from '../tournament.schedule'; import dragscroll from 'dragscroll'; const scale = 8; diff --git a/ui/tournament/src/view/started.ts b/ui/tournament/src/view/started.ts index ded49e0215218..c4c33d423942b 100644 --- a/ui/tournament/src/view/started.ts +++ b/ui/tournament/src/view/started.ts @@ -1,12 +1,12 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import { controls, standing } from './arena'; import { teamStanding } from './battle'; import header from './header'; import tourTable from './table'; import playerInfo from './playerInfo'; import teamInfo from './teamInfo'; -import * as pagination from '../pagination'; -import TournamentController from '../ctrl'; +import { players } from '../pagination'; +import type TournamentController from '../ctrl'; import { MaybeVNodes } from 'common/snabbdom'; function joinTheGame(gameId: string) { @@ -27,7 +27,7 @@ export const name = 'started'; export function main(ctrl: TournamentController): MaybeVNodes { const gameId = ctrl.myGameId(), - pag = pagination.players(ctrl); + pag = players(ctrl); return [ header(ctrl), gameId ? joinTheGame(gameId) : ctrl.isIn() ? notice(ctrl) : null, diff --git a/ui/tournament/src/view/table.ts b/ui/tournament/src/view/table.ts index 855cb57f6ee23..e547f787ba17f 100644 --- a/ui/tournament/src/view/table.ts +++ b/ui/tournament/src/view/table.ts @@ -1,11 +1,10 @@ -import { VNode } from 'snabbdom'; import { opposite } from 'chessground/util'; import * as licon from 'common/licon'; -import { bind, onInsert, looseH as h } from 'common/snabbdom'; +import { type VNode, bind, onInsert, looseH as h } from 'common/snabbdom'; import { player as renderPlayer } from './util'; -import { Duel, DuelPlayer, FeaturedGame, TournamentOpts } from '../interfaces'; +import type { Duel, DuelPlayer, FeaturedGame, TournamentOpts } from '../interfaces'; import { teamName } from './battle'; -import TournamentController from '../ctrl'; +import type TournamentController from '../ctrl'; import { initMiniGames } from 'common/miniBoard'; function featuredPlayer(game: FeaturedGame, color: Color, opts: TournamentOpts) { diff --git a/ui/tournament/src/view/teamInfo.ts b/ui/tournament/src/view/teamInfo.ts index 6b9d8c3d1b292..41874927a9160 100644 --- a/ui/tournament/src/view/teamInfo.ts +++ b/ui/tournament/src/view/teamInfo.ts @@ -1,8 +1,8 @@ -import { h, VNode } from 'snabbdom'; +import { h, type VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { spinnerVdom as spinner } from 'common/spinner'; import { bind, dataIcon } from 'common/snabbdom'; -import TournamentController from '../ctrl'; +import type TournamentController from '../ctrl'; import { numberRow, player as renderPlayer } from './util'; import { teamName } from './battle'; diff --git a/ui/tournament/src/view/util.ts b/ui/tournament/src/view/util.ts index 5251344cfe63e..1e25fa7e13e62 100644 --- a/ui/tournament/src/view/util.ts +++ b/ui/tournament/src/view/util.ts @@ -1,9 +1,9 @@ -import { h, VNode, VNodeChildren } from 'snabbdom'; +import { h, type VNode, type VNodeChildren } from 'snabbdom'; import * as licon from 'common/licon'; import { numberFormat } from 'common/number'; import { dataIcon } from 'common/snabbdom'; import { fullName, userRating } from 'common/userLink'; -import { SimplePlayer } from '../interfaces'; +import type { SimplePlayer } from '../interfaces'; export const ratio2percent = (r: number) => Math.round(100 * r) + '%'; diff --git a/ui/tournament/src/xhr.ts b/ui/tournament/src/xhr.ts index 90d3b198ee2c7..ab6f348c3644f 100644 --- a/ui/tournament/src/xhr.ts +++ b/ui/tournament/src/xhr.ts @@ -1,6 +1,6 @@ import { finallyDelay, throttlePromiseDelay } from 'common/timing'; import * as xhr from 'common/xhr'; -import TournamentController from './ctrl'; +import type TournamentController from './ctrl'; import { alert } from 'common/dialog'; // when the tournament no longer exists diff --git a/ui/voice/src/interfaces.ts b/ui/voice/src/interfaces.ts index 893e17e9dbbb8..2fd33213e6d18 100644 --- a/ui/voice/src/interfaces.ts +++ b/ui/voice/src/interfaces.ts @@ -1,5 +1,5 @@ -import { Toggle } from 'common'; -import { VNode } from 'snabbdom'; +import type { Toggle } from 'common'; +import type { VNode } from 'snabbdom'; export type MsgType = 'full' | 'partial' | 'status' | 'error' | 'stop' | 'start'; export type ListenMode = 'full' | 'partial'; diff --git a/ui/voice/src/mic.ts b/ui/voice/src/mic.ts index f097a487ad558..ac5d9c4b8d10c 100644 --- a/ui/voice/src/mic.ts +++ b/ui/voice/src/mic.ts @@ -1,5 +1,5 @@ import { objectStorage } from 'common/objectStorage'; -import { Switch, Selectable } from './switch'; +import { Switch, type Selectable } from './switch'; import { storedStringProp } from 'common/storage'; import type { VoskModule, Listener, Microphone, MsgType } from './interfaces'; diff --git a/ui/voice/src/move/arrows.ts b/ui/voice/src/move/arrows.ts index 89f8e2aa029ab..c7a4ee1978201 100644 --- a/ui/voice/src/move/arrows.ts +++ b/ui/voice/src/move/arrows.ts @@ -1,5 +1,4 @@ -import { DrawBrush, DrawShape } from 'chessground/draw'; -import { to, from } from 'chess'; +import type { DrawBrush, DrawShape } from 'chessground/draw'; export const brushes: Map = new Map([ ['green', { key: 'vgn', color: '#15781B', opacity: 0.8, lineWidth: 12 }], @@ -20,8 +19,8 @@ export function numberedArrows(choices: [string, Uci][], timer: number | undefin const preferred = choices[0][0] === 'yes' ? choices.shift()?.[1] : undefined; choices.forEach(([, uci], i) => { shapes.push({ - orig: from(uci), - dest: to(uci), + orig: uci.slice(0, 2) as Key, + dest: uci.slice(2, 4) as Key, brush: `v-grey`, modifiers: { hilite: uci === preferred }, label: choices.length > 1 ? { text: `${i + 1}` } : undefined, @@ -41,8 +40,8 @@ export function coloredArrows(choices: [string, Uci][], timer: number | undefine const preferred = choices[0][0] === 'yes' ? choices.shift()?.[1] : undefined; choices.forEach(([c, uci]) => { shapes.push({ - orig: from(uci), - dest: to(uci), + orig: uci.slice(0, 2) as Key, + dest: uci.slice(2, 4) as Key, brush: `v-${c}`, modifiers: { hilite: uci === preferred }, }); diff --git a/ui/voice/src/move/interfaces.ts b/ui/voice/src/move/interfaces.ts index 92baac9ff9d74..99a456b3a258c 100644 --- a/ui/voice/src/move/interfaces.ts +++ b/ui/voice/src/move/interfaces.ts @@ -1,11 +1,10 @@ -import { PromotionCtrl } from 'chess/promotion'; -import { MoveUpdate } from 'chess/moveRootCtrl'; -import { VoiceModule } from '../interfaces'; -import * as cg from 'chessground/types'; +import type { PromotionCtrl } from 'chess/promotion'; +import type { MoveUpdate } from 'chess/moveRootCtrl'; +import type { VoiceModule } from '../interfaces'; export interface VoiceMove extends VoiceModule { update: (up: MoveUpdate) => void; - promotionHook: () => (ctrl: PromotionCtrl, roles: cg.Role[] | false) => void; + promotionHook: () => (ctrl: PromotionCtrl, roles: Role[] | false) => void; listenForResponse: (request: string, action: (v: boolean) => void) => void; question: () => QuestionOpts | false; } diff --git a/ui/voice/src/move/view.ts b/ui/voice/src/move/view.ts index 18e9ca8eb842f..a0311c69308f9 100644 --- a/ui/voice/src/move/view.ts +++ b/ui/voice/src/move/view.ts @@ -1,5 +1,5 @@ -import { h, VNode } from 'snabbdom'; -import { Prop } from 'common'; +import { h, type VNode } from 'snabbdom'; +import type { Prop } from 'common'; import { bind } from 'common/snabbdom'; import { rangeConfig } from 'common/controls'; diff --git a/ui/voice/src/move/voice.move.ts b/ui/voice/src/move/voice.move.ts index 66740e5c4e48b..a6b3fe321be60 100644 --- a/ui/voice/src/move/voice.move.ts +++ b/ui/voice/src/move/voice.move.ts @@ -1,14 +1,14 @@ -import * as xhr from 'common/xhr'; -import * as prop from 'common/storage'; +import { jsonSimple } from 'common/xhr'; +import { storedIntProp, storedBooleanPropWithEffect, storedIntPropWithEffect } from 'common/storage'; import * as licon from 'common/licon'; -import * as cs from 'chess'; -import { from as src, to as dest } from 'chess'; -import { PromotionCtrl, promote } from 'chess/promotion'; -import { MoveRootCtrl, MoveUpdate } from 'chess/moveRootCtrl'; -import { VoiceMove, VoiceCtrl, Entry, Match } from '../voice'; +import { sanOf, readFen, destsToUcis, square, type Board } from 'chess'; +import { charToRole } from 'common'; +import { type PromotionCtrl, promote } from 'chess/promotion'; +import type { MoveRootCtrl, MoveUpdate } from 'chess/moveRootCtrl'; +import type { VoiceMove, VoiceCtrl, Entry, Match } from '../voice'; import { coloredArrows, numberedArrows, brushes } from './arrows'; import { settingNodes } from './view'; -import { MsgType } from '../interfaces'; +import type { MsgType } from '../interfaces'; import { type Transform, type SparseMap, @@ -20,6 +20,9 @@ import { movesTo, findTransforms, as, + src, + dest, + promo, } from '../util'; export function initModule({ @@ -35,7 +38,7 @@ export function initModule({ let cg: CgApi; let entries: Entry[] = []; let partials: Record = { commands: [], colors: [], numbers: [] }; - let board: cs.Board; + let board: Board; let ucis: Uci[]; // every legal move in uci const byVal: SparseMap = new Map(); // map values to lexicon entries const byTok: Map = new Map(); // map token chars to lexicon entries @@ -49,9 +52,9 @@ export function initModule({ let command: Confirm | undefined; // confirm player commands (before sending request) let choices: Map | undefined; // map choice arrows (yes, blue, red, 1, 2, etc) to moves let choiceTimeout: number | undefined; // timeout for ambiguity choices - const clarityPref = prop.storedIntProp('voice.clarity', 0); - const colorsPref = prop.storedBooleanPropWithEffect('voice.useColors', true, () => initTimerRec()); - const timerPref = prop.storedIntPropWithEffect('voice.timer', 3, () => initTimerRec()); + const clarityPref = storedIntProp('voice.clarity', 0); + const colorsPref = storedBooleanPropWithEffect('voice.useColors', true, () => initTimerRec()); + const timerPref = storedIntPropWithEffect('voice.timer', 3, () => initTimerRec()); const listenHandlers = [handleConfirm, handleCommand, handleAmbiguity, handleMove]; @@ -88,7 +91,7 @@ export function initModule({ }; async function initGrammar(): Promise { - const g = await xhr.jsonSimple(site.asset.url(`compiled/grammar/move-${voice.lang()}.json`)); + const g = await jsonSimple(site.asset.url(`compiled/grammar/move-${voice.lang()}.json`)); byWord.clear(); byTok.clear(); byVal.clear(); @@ -130,7 +133,6 @@ export function initModule({ if (results.includes('ok')) { if (results.includes('clear')) clearConfirm(); - root.redraw(); return; } } @@ -327,9 +329,9 @@ export function initModule({ let arrows = true; if (root.blindfold?.()) { if (preferred) { - site.sound.saySan(cs.sanOf(board, options[0][0])); - arrows = !site.sound.say('confirm?'); - } + site.sound.saySan(sanOf(board, options[0][0]), false, true); + arrows = !site.sound.say('confirm?', false, true); + } else site.sound.say('try again', false, true); } if (arrows) { const arrowTime = choiceTimeout ? timer() : undefined; @@ -346,9 +348,9 @@ export function initModule({ cg = up.cg; for (const [color, brush] of brushes) cg.state.drawable.brushes[`v-${color}`] = brush; } - board = cs.readFen(up.fen); + board = readFen(up.fen); cg.setShapes([]); - ucis = up.canMove && cg.state.movable.dests ? cs.destsToUcis(cg.state.movable.dests) : []; + ucis = up.canMove && cg.state.movable.dests ? destsToUcis(cg.state.movable.dests) : []; buildMoves(); buildSquares(); } @@ -363,7 +365,7 @@ export function initModule({ cg.redrawAll(); return true; } - const role = cs.promo(uci); + const role = promo(uci); cg.cancelMove(); if (role) promote(cg, dest(uci), role); root.pluginMove(src(uci), dest(uci), role); @@ -371,13 +373,13 @@ export function initModule({ } function promotionHook() { - return (ctrl: PromotionCtrl, roles: cs.Role[] | false) => + return (ctrl: PromotionCtrl, roles: Role[] | false) => roles ? voice.mic.addListener( (text: string) => { const val = matchOneTags(text, ['role'], ['no']); voice.mic.stopPropagation(); - if (val && roles.includes(cs.charRole(val))) ctrl.finish(cs.charRole(val)); + if (val && roles.includes(charToRole(val))) ctrl.finish(charToRole(val)); else if (val === 'no') ctrl.cancel(); }, { listenerId: 'promotion' }, @@ -398,8 +400,8 @@ export function initModule({ for (const uci of ucis) { const usrc = src(uci), udest = dest(uci), - nsrc = cs.square(usrc), - ndest = cs.square(udest), + nsrc = square(usrc), + ndest = square(udest), dp = board.pieces[ndest], srole = board.pieces[nsrc].toUpperCase(); @@ -467,16 +469,14 @@ export function initModule({ if (sel && !uci.startsWith(sel)) continue; const usrc = src(uci), udest = dest(uci), - nsrc = cs.square(usrc), - ndest = cs.square(udest), + nsrc = square(usrc), + ndest = square(udest), dp = board.pieces[ndest], srole = board.pieces[nsrc].toUpperCase() as 'P' | 'N' | 'B' | 'R' | 'Q' | 'K'; pushMap(squares, `${usrc[0]},${usrc[1]}`, usrc); pushMap(squares, `${udest[0]},${udest[1]}`, uci); - //if (srole !== 'P') { pushMap(squares, srole, uci); pushMap(squares, srole, usrc); - //} if (dp && !isOurs(dp)) pushMap(squares, dp.toUpperCase(), uci); } // deconflict role partials for move & select diff --git a/ui/voice/src/util.ts b/ui/voice/src/util.ts index 9bc680212cb45..3a13463ba86f0 100644 --- a/ui/voice/src/util.ts +++ b/ui/voice/src/util.ts @@ -1,4 +1,5 @@ -import * as cs from 'chess'; +import { squareDist, type Board } from 'chess'; +import { charToRole } from 'common'; // findTransforms & validOps also found in .build/src/makeGrammar.ts @@ -49,19 +50,19 @@ function validOps(h: string, x: string, pos: number) { // optimizations for xval mappings when most keys only map to 1 value. On V8 using // voice move data, this is 50% faster while using half the memory of Map -export function movesTo(s: number, role: string, board: cs.Board): number[] { +export function movesTo(s: number, role: string, board: Board): number[] { const deltas = (d: number[], s = 0) => d.flatMap(x => [s - x, s + x]); - if (role === 'K') return deltas([1, 7, 8, 9], s).filter(o => o >= 0 && o < 64 && cs.squareDist(s, o) === 1); + if (role === 'K') return deltas([1, 7, 8, 9], s).filter(o => o >= 0 && o < 64 && squareDist(s, o) === 1); else if (role === 'N') - return deltas([6, 10, 15, 17], s).filter(o => o >= 0 && o < 64 && cs.squareDist(s, o) <= 2); + return deltas([6, 10, 15, 17], s).filter(o => o >= 0 && o < 64 && squareDist(s, o) <= 2); const dests: number[] = []; for (const delta of deltas( role === 'Q' ? [1, 7, 8, 9] : role === 'R' ? [1, 8] : role === 'B' ? [7, 9] : [], )) { for ( let square = s + delta; - square >= 0 && square < 64 && cs.squareDist(square, square - delta) === 1; + square >= 0 && square < 64 && squareDist(square, square - delta) === 1; square += delta ) { dests.push(square); @@ -113,3 +114,15 @@ export function pushMap(m: SparseMap, key: string, val: T): void { else if (v !== val) m.set(key, new Set([v as T, val])); } } + +export function src(uci: Uci) { + return uci.slice(0, 2) as Key; +} + +export function dest(uci: Uci) { + return uci.slice(2, 4) as Key; +} + +export function promo(uci: Uci): Role { + return charToRole(uci.slice(4, 5)); +} diff --git a/ui/voice/src/view.ts b/ui/voice/src/view.ts index e8073a20232f4..056119daca4d6 100644 --- a/ui/voice/src/view.ts +++ b/ui/voice/src/view.ts @@ -1,9 +1,9 @@ import * as licon from 'common/licon'; -import { onInsert, bind, looseH as h, VNode } from 'common/snabbdom'; -import * as xhr from 'common/xhr'; -import { snabDialog, Dialog } from 'common/dialog'; +import { onInsert, bind, looseH as h, type VNode } from 'common/snabbdom'; +import { jsonSimple } from 'common/xhr'; +import { snabDialog, type Dialog } from 'common/dialog'; import { onClickAway, $as } from 'common'; -import { Entry, VoiceCtrl, MsgType } from './interfaces'; +import type { Entry, VoiceCtrl, MsgType } from './interfaces'; import { supportedLangs } from './voice'; export function renderVoiceBar(ctrl: VoiceCtrl, redraw: () => void, cls?: string): VNode { @@ -166,7 +166,7 @@ function renderHelpModal(ctrl: VoiceCtrl) { const grammar = ctrl.moduleId === 'coords' ? [] - : await xhr.jsonSimple(site.asset.url(`compiled/grammar/${ctrl.moduleId}-${ctrl.lang()}.json`)); + : await jsonSimple(site.asset.url(`compiled/grammar/${ctrl.moduleId}-${ctrl.lang()}.json`)); const valToWord = (val: string, phonetic: boolean) => grammar.entries.find( diff --git a/ui/voice/src/voice.ts b/ui/voice/src/voice.ts index 85787814a47e6..f887860c83863 100644 --- a/ui/voice/src/voice.ts +++ b/ui/voice/src/voice.ts @@ -1,10 +1,15 @@ import { propWithEffect, toggle as commonToggle } from 'common'; -import * as prop from 'common/storage'; import { MoveRootCtrl, MoveUpdate } from 'chess/moveRootCtrl'; import type { VoiceCtrl, VoiceModule } from './interfaces'; import type { VoiceMove } from './move/interfaces'; import { Mic } from './mic'; import { flash } from './view'; +import { + once, + storedBooleanProp, + storedStringPropWithEffect, + storedBooleanPropWithEffect, +} from 'common/storage'; export * from './interfaces'; export * from './move/interfaces'; @@ -30,16 +35,16 @@ export function makeVoice(opts: { }): VoiceCtrl { let keyupTimeout: number; const mic = new Mic(); - const enabled = prop.storedBooleanProp('voice.on', false); + const enabled = storedBooleanProp('voice.on', false); const showHelp = propWithEffect(false, opts.redraw); - const pushTalk = prop.storedBooleanPropWithEffect('voice.pushTalk', false, val => { + const pushTalk = storedBooleanPropWithEffect('voice.pushTalk', false, val => { mic.stop(); enabled(val); if (enabled()) mic.start(!val); }); - const lang = prop.storedStringPropWithEffect('voice.lang', 'en', code => { + const lang = storedStringPropWithEffect('voice.lang', 'en', code => { if (code === mic.lang) return; mic.setLang(code); opts @@ -84,7 +89,7 @@ export function makeVoice(opts: { enabled(false); pushTalk(false); } else enabled(!enabled()) ? mic.start() : mic.stop(); - if (opts.tpe === 'move' && prop.once('voice.rtfm')) showHelp(true); + if (opts.tpe === 'move' && once('voice.rtfm')) showHelp(true); } function micId(deviceId?: string) {