@internetarchive/bookreader 5.0.0-35 → 5.0.0-36

Sign up to get free protection for your applications and to get access to all the features.
@@ -258,7 +258,7 @@ export class WebTTSSound {
258
258
  }
259
259
  }
260
260
 
261
- resume() {
261
+ async resume() {
262
262
  if (!this.started) {
263
263
  this.play();
264
264
  return;
@@ -278,16 +278,15 @@ export class WebTTSSound {
278
278
  speechSynthesis.resume();
279
279
 
280
280
  if (resumeMightNotFire) {
281
- Promise.race([resumePromise, sleep(100).then(() => 'timeout')])
282
- .then(result => {
283
- if (result != 'timeout') return;
281
+ const result = await Promise.race([resumePromise, sleep(100).then(() => 'timeout')]);
284
282
 
285
- this.utterance.dispatchEvent(new CustomEvent('resume', {}));
286
- if (resumeMightNotWork) {
287
- const reloadPromise = this.reload();
288
- reloadPromise.then(() => this.play());
289
- }
290
- });
283
+ if (result != 'timeout') return;
284
+
285
+ this.utterance.dispatchEvent(new CustomEvent('resume', {}));
286
+ if (resumeMightNotWork) {
287
+ await this.reload();
288
+ this.play();
289
+ }
291
290
  }
292
291
  }
293
292
 
@@ -308,45 +307,41 @@ export class WebTTSSound {
308
307
  * We avoid this (as described here: https://bugs.chromium.org/p/chromium/issues/detail?id=679437#c15 )
309
308
  * by pausing after 14 seconds and ~instantly resuming.
310
309
  */
311
- _chromePausingBugFix() {
310
+ async _chromePausingBugFix() {
312
311
  const timeoutPromise = sleep(14000).then(() => 'timeout');
313
312
  const pausePromise = promisifyEvent(this.utterance, 'pause').then(() => 'paused');
314
313
  const endPromise = promisifyEvent(this.utterance, 'end').then(() => 'ended');
315
- return Promise.race([timeoutPromise, pausePromise, endPromise])
316
- .then(result => {
317
- if (location.toString().indexOf('_debugReadAloud=true') != -1) {
318
- console.log(`CHROME-PAUSE-HACK: ${result}`);
319
- }
320
- switch (result) {
321
- case 'ended':
322
- // audio was stopped/finished; nothing to do
323
- break;
324
- case 'paused':
325
- // audio was paused; wait for resume
326
- // Chrome won't let you resume the audio if 14s have passed 🤷‍
327
- // We could do the same as before (but resume+pause instead of pause+resume),
328
- // but that means we'd _constantly_ be running in the background. So in that
329
- // case, let's just restart the chunk
330
- Promise.race([
331
- promisifyEvent(this.utterance, 'resume'),
332
- sleep(14000).then(() => 'timeout'),
333
- ])
334
- .then(result => {
335
- result == 'timeout' ? this.reload() : this._chromePausingBugFix();
336
- });
337
- break;
338
- case 'timeout':
339
- // We hit Chrome's secret cut off time. Pause/resume
340
- // to be able to keep TTS-ing
341
- speechSynthesis.pause();
342
- sleep(25)
343
- .then(() => {
344
- speechSynthesis.resume();
345
- this._chromePausingBugFix();
346
- });
347
- break;
348
- }
349
- });
314
+ const result = await Promise.race([timeoutPromise, pausePromise, endPromise]);
315
+ if (location.toString().indexOf('_debugReadAloud=true') != -1) {
316
+ console.log(`CHROME-PAUSE-HACK: ${result}`);
317
+ }
318
+ switch (result) {
319
+ case 'ended':
320
+ // audio was stopped/finished; nothing to do
321
+ break;
322
+ case 'paused':
323
+ // audio was paused; wait for resume
324
+ // Chrome won't let you resume the audio if 14s have passed 🤷‍
325
+ // We could do the same as before (but resume+pause instead of pause+resume),
326
+ // but that means we'd _constantly_ be running in the background. So in that
327
+ // case, let's just restart the chunk
328
+ Promise.race([
329
+ promisifyEvent(this.utterance, 'resume'),
330
+ sleep(14000).then(() => 'timeout'),
331
+ ])
332
+ .then(result => {
333
+ result == 'timeout' ? this.reload() : this._chromePausingBugFix();
334
+ });
335
+ break;
336
+ case 'timeout':
337
+ // We hit Chrome's secret cut off time. Pause/resume
338
+ // to be able to keep TTS-ing
339
+ speechSynthesis.pause();
340
+ await sleep(25);
341
+ speechSynthesis.resume();
342
+ this._chromePausingBugFix();
343
+ break;
344
+ }
350
345
  }
351
346
  }
352
347
 
@@ -261,9 +261,7 @@ BookReader.prototype.ttsStop = function () {
261
261
  BookReader.prototype.ttsBeforeChunkPlay = async function(chunk) {
262
262
  await this.ttsMaybeFlipToIndex(chunk.leafIndex);
263
263
  this.ttsHighlightChunk(chunk);
264
- // This appears not to work; ttsMaybeFlipToIndex causes a scroll to the top of
265
- // the active page :/ Disabling cause the extra scroll just adds an odd jitter.
266
- // this.ttsScrollToChunk(chunk);
264
+ this.ttsScrollToChunk(chunk);
267
265
  };
268
266
 
269
267
  /**
@@ -292,10 +290,7 @@ BookReader.prototype.ttsMaybeFlipToIndex = function (leafIndex) {
292
290
  resolve();
293
291
  } else {
294
292
  this.animationFinishedCallback = resolve;
295
- const mustGoNext = leafIndex > Math.max(this.twoPage.currentIndexR, this.twoPage.currentIndexL);
296
- if (mustGoNext) this.next();
297
- else this.prev();
298
- promise.then(this.ttsMaybeFlipToIndex.bind(this, leafIndex));
293
+ this.jumpToIndex(leafIndex);
299
294
  }
300
295
  }
301
296
 
@@ -329,9 +324,20 @@ BookReader.prototype.ttsHighlightChunk = function(chunk) {
329
324
  * @param {PageChunk} chunk
330
325
  */
331
326
  BookReader.prototype.ttsScrollToChunk = function(chunk) {
332
- if (this.constMode1up != this.mode) return;
333
-
334
- $(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`)[0]?.scrollIntoView();
327
+ // It behaves weird if used in thumb mode
328
+ if (this.constModeThumb == this.mode) return;
329
+
330
+ $(`.pagediv${chunk.leafIndex} .ttsHiliteLayer rect`).last()?.[0]?.scrollIntoView({
331
+ // Only vertically center the highlight if we're in 1up or in full screen. In
332
+ // 2up, if we're not fullscreen, the whole body gets scrolled around to try to
333
+ // center the highlight 🙄 See:
334
+ // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move/11041376
335
+ // Note: nearest doesn't quite work great, because the ReadAloud toolbar is now
336
+ // full-width, and covers up the last line of the highlight.
337
+ block: this.constMode1up == this.mode || this.isFullscreenActive ? 'center' : 'nearest',
338
+ inline: 'center',
339
+ behavior: 'smooth',
340
+ });
335
341
  };
336
342
 
337
343
  // ttsRemoveHilites()
@@ -1,6 +1,6 @@
1
1
  import { runBaseTests } from './helpers/base';
2
2
  import BookReader from './models/BookReader';
3
- import { runDesktopSearchTests } from './helpers/desktopSearch';
3
+ // import { runDesktopSearchTests } from './helpers/desktopSearch';
4
4
  // import { runMobileSearchTests } from './helpers/mobileSearch';
5
5
  import params from './helpers/params';
6
6
 
@@ -21,10 +21,13 @@ ocaids.forEach(ocaid => {
21
21
  fixture `Base Tests for: ${ocaid}`.page `${url}`;
22
22
  runBaseTests(new BookReader());
23
23
 
24
- fixture `Desktop Search Tests for: ${ocaid}`
25
- .page `${url}`;
26
- runDesktopSearchTests(new BookReader());
27
24
 
25
+ // Todo: Re-enable when testing side panel
26
+ // fixture `Desktop Search Tests for: ${ocaid}`
27
+ // .page `${url}`;
28
+ // runDesktopSearchTests(new BookReader());
29
+
30
+ // Todo: deprecated, will remove once mmenu is removed.
28
31
  // fixture `Mobile Search Tests for: ${ocaid}`
29
32
  // .page `${url}`
30
33
  // runMobileSearchTests(new BookReader());
@@ -1,7 +1,7 @@
1
1
  // @ts-check
2
2
  class TestParams {
3
3
  baseUrl = process.env.BASE_URL?.replace(/\/+$/, '') ?? 'http://127.0.0.1:8000'
4
- ocaids = process.env.OCAIDS?.split(',') ?? [];
4
+ ocaids = process.env.OCAIDS?.split(',') ?? null;
5
5
  /** Whether the url we're testing is a prod (or near prod) IA url, or a demos url */
6
6
  isIA = new URL(this.baseUrl).hostname.endsWith('archive.org');
7
7
 
@@ -1,36 +1,36 @@
1
- // import { Selector } from 'testcafe';
2
- // import BookReader from './models/BookReader';
3
- // import params from './helpers/params';
1
+ import { Selector } from 'testcafe';
2
+ import BookReader from './models/BookReader';
3
+ import params from './helpers/params';
4
4
 
5
- // fixture `Viewmode carousel`.page `${params.baseUrl}/BookReaderDemo/viewmode-cycle.html`;
5
+ fixture `Viewmode carousel`.page `${params.baseUrl}/BookReaderDemo/demo-internetarchive.html?ocaid=goody`;
6
6
 
7
- // test('Clicking `view mode` cycles through view modes', async t => {
8
- // const { nav } = (new BookReader());
7
+ test('Clicking `view mode` cycles through view modes', async t => {
8
+ const { nav } = (new BookReader());
9
9
 
10
- // // viewmode button only appear on mobile devices
11
- // await t.resizeWindow(400, 800);
12
- // // Flip forward one
13
- // await t.pressKey('right');
10
+ // viewmode button only appear on mobile devices
11
+ await t.resizeWindow(400, 800);
12
+ // Flip forward one
13
+ await t.pressKey('right');
14
14
 
15
- // // 2up to thumb
16
- // await t.click(nav.desktop.viewmode);
17
- // const thumbnailContainer = Selector('.BRmodeThumb');
18
- // await t.expect(thumbnailContainer.visible).ok();
19
- // const thumbImages = thumbnailContainer.find('.BRpageview img');
20
- // await t.expect(thumbImages.count).gt(0);
15
+ // 2up to thumb
16
+ await t.click(nav.desktop.viewmode);
17
+ const thumbnailContainer = Selector('.BRmodeThumb');
18
+ await t.expect(thumbnailContainer.visible).ok();
19
+ const thumbImages = thumbnailContainer.find('.BRpageview img');
20
+ await t.expect(thumbImages.count).gt(0);
21
21
 
22
- // // thumb to 1up
23
- // await t.click(nav.desktop.viewmode);
24
- // const onePageViewContainer = Selector('br-mode-1up');
25
- // await t.expect(onePageViewContainer.visible).ok();
26
- // const onePageImages = onePageViewContainer.find('.BRmode1up .BRpagecontainer');
27
- // // we usually pre-fetch the page in question & 1 before/after it
28
- // await t.expect(onePageImages.count).gte(3);
22
+ // thumb to 1up
23
+ await t.click(nav.desktop.viewmode);
24
+ const onePageViewContainer = Selector('br-mode-1up');
25
+ await t.expect(onePageViewContainer.visible).ok();
26
+ const onePageImages = onePageViewContainer.find('.BRmode1up .BRpagecontainer');
27
+ // we usually pre-fetch the page in question & 1 before/after it
28
+ await t.expect(onePageImages.count).gte(3);
29
29
 
30
- // // 1up to 2up
31
- // await t.click(nav.desktop.viewmode);
32
- // const twoPageContainer = Selector('.BRtwopageview');
33
- // await t.expect(twoPageContainer.visible).ok();
34
- // const twoPageImages = twoPageContainer.find('img.BRpageimage');
35
- // await t.expect(twoPageImages.count).gte(2);
36
- // });
30
+ // 1up to 2up
31
+ await t.click(nav.desktop.viewmode);
32
+ const twoPageContainer = Selector('.BRtwopageview');
33
+ await t.expect(twoPageContainer.visible).ok();
34
+ const twoPageImages = twoPageContainer.find('img.BRpageimage');
35
+ await t.expect(twoPageImages.count).gte(2);
36
+ });