Skip to content

Commit 1cb20a6

Browse files
committed
fix error in console
1 parent cb2b131 commit 1cb20a6

File tree

4 files changed

+116
-18
lines changed

4 files changed

+116
-18
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ jobs:
4949
cache: npm
5050
cache-dependency-path: tests/package-lock.json
5151

52+
- name: Install app dependencies
53+
run: npm ci
54+
5255
- name: Install dependencies
5356
working-directory: tests
5457
run: npm ci

browser/dasher/controlpanel.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,20 @@ export default class ControlPanel {
545545
// presumably because the browser has by then rendered
546546
// everything.
547547
setTimeout(() => {
548+
const parentNode = panelNode.parentNode;
549+
if (
550+
!(panelNode instanceof Element) ||
551+
!(parentNode instanceof Element)
552+
) {
553+
return;
554+
}
555+
548556
const panelX = panelNode.getBoundingClientRect().x;
549557
const parentX = (
550-
panelNode.parentNode.getBoundingClientRect().x);
551-
panelNode.parentNode.scrollTo({
558+
parentNode.getBoundingClientRect().x);
559+
parentNode.scrollTo({
552560
left: (
553-
panelNode.parentNode.scrollLeft +
561+
parentNode.scrollLeft +
554562
(panelX - parentX)
555563
),
556564
behavior: 'smooth',

browser/dasher/predictor_ppm_new.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ let learningEnabled = false;
3636
let learnedText = '';
3737
let createPredictorFunction = null;
3838
let predictorModuleLoadAttempted = false;
39+
const gutenbergStartMarker = /\*\*\*\s*START OF THIS PROJECT GUTENBERG EBOOK[\s\S]*?\*\*\*/i;
40+
const gutenbergEndMarker = /\*\*\*\s*END OF THIS PROJECT GUTENBERG EBOOK[\s\S]*?\*\*\*/i;
3941

4042
// Simple training text for fast initial startup
4143
const quickTrainingText = 'The quick brown fox jumps over the lazy dog. ' +
@@ -44,6 +46,29 @@ const quickTrainingText = 'The quick brown fox jumps over the lazy dog. ' +
4446
'A B C D E F G H I J K L M N O P Q R S T U V W X Y Z. ' +
4547
'the and for are but not you all any can had has him his how man new now old see two way who boy did its let put say she too use dad mom car dog eat fun get go good hi hot job key law lay lie low mad off out own pay red run set sit top try win yes ';
4648

49+
function sanitiseTrainingText(text) {
50+
const source = typeof text === 'string' ? text : '';
51+
const startMatch = source.match(gutenbergStartMarker);
52+
53+
let body = source;
54+
if (startMatch !== null) {
55+
body = body.slice(startMatch.index + startMatch[0].length);
56+
}
57+
const endMatch = body.match(gutenbergEndMarker);
58+
if (endMatch !== null) {
59+
body = body.slice(0, endMatch.index);
60+
}
61+
62+
return body
63+
.replace(/\r\n/g, '\n')
64+
.replace(/[ \t]+/g, ' ')
65+
.replace(/\n{3,}/g, '\n\n')
66+
.trim();
67+
}
68+
69+
const aliceTrainingText = sanitiseTrainingText(bufferAlice);
70+
const sherlockTrainingText = sanitiseTrainingText(bufferSherlockHolmes);
71+
4772
/**
4873
* Initialize the predictor with training data.
4974
* Uses fast initialization with minimal training, then trains on full corpus in background.
@@ -83,14 +108,14 @@ async function initialize() {
83108
predictor.train(quickTrainingText);
84109

85110
isInitialized = true;
86-
console.log('@willwade/ppmpredictor ready (background training in progress...');
111+
console.log('@willwade/ppmpredictor ready (background training in progress)...');
87112

88113
// Train on full corpus in background without blocking UI
89114
setTimeout(() => {
90115
console.log('Background training on Alice in Wonderland...');
91-
predictor.train(bufferAlice);
116+
predictor.train(aliceTrainingText);
92117
console.log('Background training on Sherlock Holmes...');
93-
predictor.train(bufferSherlockHolmes);
118+
predictor.train(sherlockTrainingText);
94119
console.log('Background training complete.');
95120
}, 100);
96121

@@ -186,8 +211,8 @@ export function ppmNewReset(palette, otherText) {
186211

187212
// Train on full corpus in background
188213
setTimeout(() => {
189-
predictor.train(bufferAlice);
190-
predictor.train(bufferSherlockHolmes);
214+
predictor.train(aliceTrainingText);
215+
predictor.train(sherlockTrainingText);
191216
// Train on additional text if provided
192217
if (otherText && otherText.length > 0) {
193218
predictor.train(otherText);
@@ -224,6 +249,11 @@ export function ppmNewGetPredictor() {
224249
return predictor;
225250
}
226251

252+
export async function ppmNewGetPredictorAsync() {
253+
await initialize();
254+
return predictor;
255+
}
256+
227257
/**
228258
* Update the predictor configuration.
229259
*

browser/dasher/userinterface.js

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import predictor_basic from './predictor.js';
2323
import predictor_test from './predictor_test.js';
2424
import {ppmModelPredict} from './predictor_ppm.js';
2525
import predictor_ppm_new, {
26-
ppmNewGetPredictor,
26+
ppmNewGetPredictorAsync,
2727
ppmNewAddCorpus,
2828
ppmNewSetLearningEnabled,
2929
ppmNewGetLearningEnabled,
@@ -41,6 +41,7 @@ import * as LanguageManager from './languageManager.js';
4141

4242
const messageLabelText = '';
4343
const speechAnnouncement = 'Speech is now active.';
44+
const legacyRenderIntervalMillis = 400;
4445

4546
const defaultPredictorList = [{
4647
'label': 'PPM (Enhanced)', 'item': predictor_ppm_new,
@@ -58,6 +59,9 @@ export default class UserInterface {
5859
constructor(parent) {
5960
this._parent = parent;
6061
this._intervalRender = undefined;
62+
this._renderLoopKind = null;
63+
this._lastRenderTimestamp = null;
64+
this._renderAccumulator = 0;
6165

6266
this._keyboardMode = parent.classList.contains('keyboard');
6367

@@ -941,6 +945,10 @@ export default class UserInterface {
941945
return this._currentSpeed.toFixed(1);
942946
}
943947

948+
_normalise_speed(speed) {
949+
return speed * (this._transitionMillis / legacyRenderIntervalMillis);
950+
}
951+
944952
_longest_common_prefix(a, b) {
945953
const max = Math.min(a.length, b.length);
946954
let i = 0;
@@ -1196,7 +1204,7 @@ export default class UserInterface {
11961204
_select_behaviour(index) {
11971205
this._limits.targetRight = (index === 0);
11981206
this._currentSpeed = (index === 0 ? 0.1 : 0.2);
1199-
this._pointer.multiplierLeftRight = this._currentSpeed;
1207+
this._pointer.multiplierLeftRight = this._normalise_speed(this._currentSpeed);
12001208
// if (this._speedLeftRightInput !== undefined) {
12011209
const speedLeftRightInput = this._panels.speed.horizontal.node;
12021210
if (speedLeftRightInput !== undefined) {
@@ -1212,7 +1220,7 @@ export default class UserInterface {
12121220
// Update predictor with language-specific corpus
12131221
// Only works with PPM (Enhanced) predictor
12141222
try {
1215-
const predictor = ppmNewGetPredictor();
1223+
const predictor = await ppmNewGetPredictorAsync();
12161224
if (predictor) {
12171225
// Get lexicon for the language
12181226
const lexicon = await LanguageManager.getLexicon(language.code, 5000);
@@ -1514,20 +1522,26 @@ export default class UserInterface {
15141522
if (this._keyboardMode) {
15151523
// Can't show settings in input controls in keyboard mode. The input
15161524
// would itself require a keyboard. Set some slower default values.
1517-
this._pointer.multiplierLeftRight = 0.2;
1518-
this._pointer.multiplierUpDown = 0.2;
1525+
this._pointer.multiplierLeftRight = this._normalise_speed(0.2);
1526+
this._pointer.multiplierUpDown = this._normalise_speed(0.2);
15191527
this._select_behaviour(1);
15201528
return;
15211529
}
15221530

15231531
this._panels.speed.horizontal.listener = (value) => {
15241532
this._currentSpeed = value;
1525-
this._pointer.multiplierLeftRight = value;
1533+
this._pointer.multiplierLeftRight = this._normalise_speed(value);
15261534
this._sync_quick_controls();
15271535
};
15281536
this._select_behaviour(0);
1537+
const initialVerticalSpeed = Number.parseFloat(
1538+
this._panels.speed.vertical.node.value,
1539+
);
1540+
if (!Number.isNaN(initialVerticalSpeed)) {
1541+
this._pointer.multiplierUpDown = this._normalise_speed(initialVerticalSpeed);
1542+
}
15291543
this._panels.speed.vertical.listener = (value) => {
1530-
this._pointer.multiplierUpDown = value;
1544+
this._pointer.multiplierUpDown = this._normalise_speed(value);
15311545
};
15321546
}
15331547

@@ -1635,8 +1649,44 @@ export default class UserInterface {
16351649

16361650
if (render_one() && continuous) {
16371651
this._stopGoTextNode.nodeValue = 'Started';
1638-
this._intervalRender = setInterval(
1639-
render_one, this._transitionMillis);
1652+
if (typeof window.requestAnimationFrame === 'function') {
1653+
this._renderLoopKind = 'raf';
1654+
this._lastRenderTimestamp = null;
1655+
this._renderAccumulator = 0;
1656+
1657+
const tick = (timestamp) => {
1658+
if (this._intervalRender === null) {
1659+
return;
1660+
}
1661+
1662+
if (this._lastRenderTimestamp === null) {
1663+
this._lastRenderTimestamp = timestamp;
1664+
}
1665+
const elapsed = timestamp - this._lastRenderTimestamp;
1666+
this._lastRenderTimestamp = timestamp;
1667+
1668+
this._renderAccumulator = Math.min(
1669+
this._renderAccumulator + elapsed,
1670+
this._transitionMillis * 4,
1671+
);
1672+
1673+
while (this._renderAccumulator >= this._transitionMillis) {
1674+
this._renderAccumulator -= this._transitionMillis;
1675+
if (!render_one()) {
1676+
this._stop_render();
1677+
return;
1678+
}
1679+
}
1680+
1681+
this._intervalRender = window.requestAnimationFrame(tick);
1682+
};
1683+
1684+
this._intervalRender = window.requestAnimationFrame(tick);
1685+
} else {
1686+
this._renderLoopKind = 'interval';
1687+
this._intervalRender = setInterval(
1688+
render_one, this._transitionMillis);
1689+
}
16401690
} else {
16411691
this._stop_render();
16421692
}
@@ -1649,8 +1699,15 @@ export default class UserInterface {
16491699
}
16501700

16511701
if (this._intervalRender !== null) {
1652-
clearInterval(this._intervalRender);
1702+
if (this._renderLoopKind === 'raf') {
1703+
window.cancelAnimationFrame(this._intervalRender);
1704+
} else {
1705+
clearInterval(this._intervalRender);
1706+
}
16531707
this._intervalRender = null;
1708+
this._renderLoopKind = null;
1709+
this._lastRenderTimestamp = null;
1710+
this._renderAccumulator = 0;
16541711
this._stopGoTextNode.nodeValue = 'Stopped';
16551712
if (this._quickControls.playButton !== undefined) {
16561713
this._quickControls.playButton.textContent = 'Play';

0 commit comments

Comments
 (0)