From 50b874bfb346af67dfcd4a150d6067854a216056 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Mon, 29 Apr 2019 22:26:07 +0700 Subject: [PATCH] extract speech plugin, enable speech in analysis --- package.json | 1 + ui/@types/lichess/index.d.ts | 24 +++++++------- ui/analyse/src/ctrl.ts | 4 +++ ui/analyse/src/speech.ts | 18 ++++++++++ ui/round/gulpfile.js | 5 --- ui/round/src/ctrl.ts | 3 +- ui/round/src/speech.ts | 29 +++++++++++----- ui/speech/gulpfile.js | 3 ++ ui/speech/package.json | 33 +++++++++++++++++++ .../plugins/speech.ts => speech/src/main.ts} | 0 ui/speech/tsconfig.json | 15 +++++++++ 11 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 ui/analyse/src/speech.ts create mode 100644 ui/speech/gulpfile.js create mode 100644 ui/speech/package.json rename ui/{round/src/plugins/speech.ts => speech/src/main.ts} (100%) create mode 100644 ui/speech/tsconfig.json diff --git a/package.json b/package.json index 5e0a0d89bb..07cf854f66 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "ui/editor", "ui/game", "ui/nvui", + "ui/speech", "ui/insight", "ui/learn", "ui/lobby", diff --git a/ui/@types/lichess/index.d.ts b/ui/@types/lichess/index.d.ts index 18e558d189..c30cc33ef8 100644 --- a/ui/@types/lichess/index.d.ts +++ b/ui/@types/lichess/index.d.ts @@ -13,10 +13,10 @@ interface Lichess { compiledScript(path: string): string keyboardMove: any slider(): any - raf(f: () => void): void - requestIdleCallback(f: () => void): void - loadCss(path: string): void - loadCssPath(path: string): void + raf(f: () => void): void; + requestIdleCallback(f: () => void): void; + loadCss(path: string): void; + loadCssPath(path: string): void; loadedCss: { [key: string]: boolean; } @@ -54,16 +54,18 @@ interface Lichess { render(ctrl: any): any; } playMusic(): any; - Speech?: { - say(t: string, cut: boolean): void; - step(s: { san?: San }, cut: boolean): void; - }; + LichessSpeech?: LichessSpeech; spinnerHtml: string; movetimeChart: any; hasTouchEvents: boolean; mousedownEvent: 'mousedown' | 'touchstart'; } +interface LichessSpeech { + say(t: string, cut: boolean): void; + step(s: { san?: San }, cut: boolean): void; +} + interface Cookie { name: string; value: string; @@ -88,9 +90,9 @@ interface Trans { type PubsubCallback = (...data: any[]) => void; interface Pubsub { - on(msg: string, f: PubsubCallback): void - off(msg: string, f: PubsubCallback): void - emit(msg: string): (...args: any[]) => void + on(msg: string, f: PubsubCallback): void; + off(msg: string, f: PubsubCallback): void; + emit(msg: string): (...args: any[]) => void; } interface LichessStorageHelper { diff --git a/ui/analyse/src/ctrl.ts b/ui/analyse/src/ctrl.ts index dcdf362d3a..057e1b7179 100644 --- a/ui/analyse/src/ctrl.ts +++ b/ui/analyse/src/ctrl.ts @@ -29,6 +29,7 @@ import { make as makePractice, PracticeCtrl } from './practice/practiceCtrl'; import { make as makeEvalCache, EvalCache } from './evalCache'; import { compute as computeAutoShapes } from './autoShape'; import { nextGlyphSymbol } from './nodeFinder'; +import * as speech from './speech'; import { AnalyseOpts, AnalyseData, ServerEvalData, Key, CgDests, JustCaptured, NvuiPlugin, Redraw } from './interfaces'; import GamebookPlayCtrl from './study/gamebook/gamebookPlayCtrl'; import { ctrl as treeViewCtrl, TreeView } from './treeView/treeView'; @@ -168,6 +169,8 @@ export default class AnalyseCtrl { this.jumpToIndex(index); this.redraw() }); + + speech.setup(); } initialize(data: AnalyseData, merge: boolean): void { @@ -339,6 +342,7 @@ export default class AnalyseCtrl { this.threatMode(false); this.ceval.stop(); this.startCeval(); + speech.node(this.node); } this.justPlayed = this.justDropped = this.justCaptured = undefined; this.explorer.setNode(); diff --git a/ui/analyse/src/speech.ts b/ui/analyse/src/speech.ts new file mode 100644 index 0000000000..9c1ec99e65 --- /dev/null +++ b/ui/analyse/src/speech.ts @@ -0,0 +1,18 @@ +export function setup() { + window.lichess.pubsub.on('speech.enabled', onSpeechChange); + onSpeechChange(window.lichess.sound.speech()); +} + +function onSpeechChange(enabled: boolean) { + if (!window.LichessSpeech && enabled) + window.lichess.loadScript(window.lichess.compiledScript('speech')); + else if (window.LichessSpeech && !enabled) window.LichessSpeech = undefined; +} + +export function node(n: Tree.Node) { + withSpeech(s => s.step(n, true)); +} + +export function withSpeech(f: (speech: LichessSpeech) => void) { + if (window.LichessSpeech) f(window.LichessSpeech); +} diff --git a/ui/round/gulpfile.js b/ui/round/gulpfile.js index eaa7fae93f..a3fb07e45b 100644 --- a/ui/round/gulpfile.js +++ b/ui/round/gulpfile.js @@ -10,11 +10,6 @@ lilaGulpPlugins([ entries: ['src/plugins/keyboardMove.ts'], target: 'lichess.round.keyboardMove.min.js' }, - { - standalone: 'Speech', - entries: ['src/plugins/speech.ts'], - target: 'lichess.round.speech.min.js' - }, { standalone: 'NVUI', entries: ['src/plugins/nvui.ts'], diff --git a/ui/round/src/ctrl.ts b/ui/round/src/ctrl.ts index 95470e82c7..10456338d0 100644 --- a/ui/round/src/ctrl.ts +++ b/ui/round/src/ctrl.ts @@ -710,8 +710,7 @@ export default class RoundController { if (!this.nvui) keyboard.init(this); - li.pubsub.on('speech.enabled', speech.onSpeechChange(this)); - speech.onSpeechChange(this)(li.sound.speech()); + speech.setup(this); this.onChange(); }); diff --git a/ui/round/src/speech.ts b/ui/round/src/speech.ts index 18ca378457..9e70a5c5fa 100644 --- a/ui/round/src/speech.ts +++ b/ui/round/src/speech.ts @@ -2,29 +2,40 @@ import RoundController from './ctrl'; import { Step } from './interfaces'; import viewStatus from 'game/view/status'; -export function onSpeechChange(ctrl: RoundController) { +export function setup(ctrl: RoundController) { + window.lichess.pubsub.on('speech.enabled', onSpeechChange(ctrl)); + onSpeechChange(ctrl)(window.lichess.sound.speech()); +} + +function onSpeechChange(ctrl: RoundController) { return function(enabled: boolean) { - if (!window.Speech && enabled) - window.lichess.loadScript('compiled/lichess.round.speech.min.js').then(() => status(ctrl)); - else if (window.Speech && !enabled) window.Speech = undefined; + if (!window.LichessSpeech && enabled) + window.lichess.loadScript( + window.lichess.compiledScript('speech') + ).then(() => status(ctrl)); + else if (window.LichessSpeech && !enabled) window.LichessSpeech = undefined; }; } export function status(ctrl: RoundController) { const s = viewStatus(ctrl); - if (s == 'playingRightNow') window.Speech!.step(ctrl.stepAt(ctrl.ply), false); + if (s == 'playingRightNow') window.LichessSpeech!.step(ctrl.stepAt(ctrl.ply), false); else { - window.Speech!.say(s); + withSpeech(speech => speech.say(s, false)); const w = ctrl.data.game.winner; - if (w) window.Speech!.say(ctrl.trans.noarg(w + 'IsVictorious'), false) + if (w) withSpeech(speech => speech.say(ctrl.trans.noarg(w + 'IsVictorious'), false)); } } export function userJump(ctrl: RoundController, ply: Ply) { - if (window.Speech) window.Speech.step(ctrl.stepAt(ply), true); + withSpeech(s => s.step(ctrl.stepAt(ply), true)); } export function step(step: Step) { - if (window.Speech) window.Speech.step(step, false); + withSpeech(s => s.step(step, false)); +} + +export function withSpeech(f: (speech: LichessSpeech) => void) { + if (window.LichessSpeech) f(window.LichessSpeech); } diff --git a/ui/speech/gulpfile.js b/ui/speech/gulpfile.js new file mode 100644 index 0000000000..a3ba9277a6 --- /dev/null +++ b/ui/speech/gulpfile.js @@ -0,0 +1,3 @@ +const lilaGulp = require('../gulp/tsProject.js'); + +lilaGulp('LichessSpeech', 'lichess.speech', __dirname); diff --git a/ui/speech/package.json b/ui/speech/package.json new file mode 100644 index 0000000000..37ec11c338 --- /dev/null +++ b/ui/speech/package.json @@ -0,0 +1,33 @@ +{ + "name": "speech", + "version": "1.0.0", + "description": "lichess.org speech synthesis", + "main": "dist/main.js", + "types": "dist/main", + "repository": { + "type": "git", + "url": "https://github.com/ornicar/lila" + }, + "keywords": [ + "chess", + "lichess", + "non-visual", + "speech synthesis", + "accessibility" + ], + "author": "Thibault Duplessis", + "license": "AGPL-3.0", + "bugs": { + "url": "https://github.com/ornicar/lila/issues" + }, + "homepage": "https://github.com/ornicar/lila", + "scripts": { + "compile": "tsc" + }, + "devDependencies": { + "@types/lichess": "1.0.0", + "typescript": "^3" + }, + "dependencies": { + } +} diff --git a/ui/round/src/plugins/speech.ts b/ui/speech/src/main.ts similarity index 100% rename from ui/round/src/plugins/speech.ts rename to ui/speech/src/main.ts diff --git a/ui/speech/tsconfig.json b/ui/speech/tsconfig.json new file mode 100644 index 0000000000..25a6fcf64c --- /dev/null +++ b/ui/speech/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "noImplicitAny": true, + "strictNullChecks": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noEmitOnError": false, + "alwaysStrict": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "moduleResolution": "node", + "target": "ES5", + "lib": ["DOM", "ES5", "es2015.core", "es2015.Promise"] + } +}