@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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 5.0.0-36
2
+ Fix: Readaloud scrolls along with dext @cdrini
3
+ Dev: ES6 var to let/const updates @sancodes
4
+ Dev: ES6 async/await updates @sancodes
5
+ Dev: Re-enable testcafe tests in GH action @iisa
6
+ Fix: Search results bar clears and closes properly @iisa
7
+
1
8
  # 5.0.0-35
2
9
  Fix: global syle leak specify colorbox styles @iisa
3
10
  Fix: br menu reinits with shared ro load @iisa
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@internetarchive/bookreader",
3
- "version": "5.0.0-35",
3
+ "version": "5.0.0-36",
4
4
  "description": "The Internet Archive BookReader.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -185,13 +185,19 @@ export class BookNavigator extends LitElement {
185
185
  /* refresh br instance reference */
186
186
  this.bookreader = brInstance;
187
187
  }
188
+
189
+ this.updateMenuContents();
190
+
191
+ if (searchUpdates.openMenu === false) {
192
+ return;
193
+ }
194
+
188
195
  if (this.isWideEnoughToOpenMenu && !searchUpdates?.searchCanceled) {
189
196
  /* open side search menu */
190
197
  setTimeout(() => {
191
198
  this.updateSideMenu('search', 'open');
192
199
  }, 0);
193
200
  }
194
- this.updateMenuContents();
195
201
  },
196
202
  });
197
203
  }
@@ -229,36 +229,35 @@ class IABookmarks extends LitElement {
229
229
  return bookmark;
230
230
  }
231
231
 
232
- fetchBookmarks() {
233
- return this.api.getAll().then(res => res.text()).then((res) => {
234
- let response;
235
- try {
236
- response = JSON.parse(res);
237
- } catch (e) {
238
- response = { error: e.message };
239
- }
240
- return response;
241
- }).then((response) => {
242
- const {
243
- success,
244
- error = 'Something happened while fetching bookmarks.',
245
- value: bkmrks = [],
246
- } = response;
247
- if (!success) {
248
- console?.warn('Error fetching bookmarks', error);
249
- }
232
+ async fetchBookmarks() {
233
+ const resText = await this.api.getAll().then(r=> r.text());
234
+ let parsedResponse;
235
+ try {
236
+ parsedResponse = JSON.parse(resText);
237
+ } catch (e) {
238
+ parsedResponse = {error : e.message};
239
+ }
250
240
 
251
- const bookmarks = {};
252
- Object.keys(bkmrks).forEach((leafNum) => {
253
- const bookmark = bkmrks[leafNum];
254
- const formattedLeafNum = parseInt(leafNum, 10);
255
- const formattedBookmark = this.formatBookmark({ ...bookmark, leafNum: formattedLeafNum });
256
- bookmarks[leafNum] = formattedBookmark;
257
- });
241
+ const {
242
+ success,
243
+ error = 'Something happened while fetching bookmarks.',
244
+ value: bkmrks = [],
245
+ } = parsedResponse;
258
246
 
259
- this.bookmarks = bookmarks;
260
- return bookmarks;
247
+ if (!success) {
248
+ console?.warn('Error fetching bookmarks', error);
249
+ }
250
+
251
+ const bookmarks = {};
252
+ Object.keys(bkmrks).forEach((leafNum) => {
253
+ const bookmark = bkmrks[leafNum];
254
+ const formattedLeafNum = parseInt(leafNum, 10);
255
+ const formattedBookmark = this.formatBookmark({ ...bookmark, leafNum: formattedLeafNum });
256
+ bookmarks[leafNum] = formattedBookmark;
261
257
  });
258
+
259
+ this.bookmarks = bookmarks;
260
+ return bookmarks;
262
261
  }
263
262
 
264
263
  emitBookmarksChanged() {
@@ -144,8 +144,8 @@ export default class SearchProvider {
144
144
  queryInProgress: false,
145
145
  errorMessage: '',
146
146
  };
147
- this.updateMenu();
148
- this.bookreader?.searchView?.clearSearchFieldAndResults();
147
+ this.updateMenu({ openMenu: false });
148
+ this.bookreader?.searchView?.clearSearchFieldAndResults(false);
149
149
  }
150
150
 
151
151
  /**
package/src/BookReader.js CHANGED
@@ -333,9 +333,9 @@ BookReader.util = utils;
333
333
  * @private
334
334
  */
335
335
  BookReader.prototype.extendParams = function(params, newParams) {
336
- var modifiedNewParams = $.extend({}, newParams);
336
+ const modifiedNewParams = $.extend({}, newParams);
337
337
  if ('undefined' != typeof(modifiedNewParams.page)) {
338
- var pageIndex = this._models.book.parsePageString(modifiedNewParams.page);
338
+ const pageIndex = this._models.book.parsePageString(modifiedNewParams.page);
339
339
  if (!isNaN(pageIndex))
340
340
  modifiedNewParams.index = pageIndex;
341
341
  delete modifiedNewParams.page;
@@ -349,7 +349,7 @@ BookReader.prototype.extendParams = function(params, newParams) {
349
349
  * @return {object} the parsed params
350
350
  */
351
351
  BookReader.prototype.initParams = function() {
352
- var params = {};
352
+ const params = {};
353
353
  // Flag initializing for updateFromParams()
354
354
  params.init = true;
355
355
 
@@ -398,7 +398,7 @@ BookReader.prototype.initParams = function() {
398
398
  // Check for URL plugin
399
399
  if (this.options.enableUrlPlugin) {
400
400
  // Params explicitly set in URL take precedence over all other methods
401
- var urlParams = this.paramsFromFragment(this.urlReadFragment());
401
+ let urlParams = this.paramsFromFragment(this.urlReadFragment());
402
402
 
403
403
  // Get params if hash fragment available with 'history' urlMode
404
404
  const hasHashURL = !Object.keys(urlParams).length && this.urlReadHashFragment();
@@ -481,8 +481,8 @@ BookReader.prototype.readQueryString = function() {
481
481
  */
482
482
  BookReader.prototype.getInitialMode = function(params) {
483
483
  // Use params or browser width to set view mode
484
- var windowWidth = $(window).width();
485
- var nextMode;
484
+ const windowWidth = $(window).width();
485
+ let nextMode;
486
486
  if ('undefined' != typeof(params.mode)) {
487
487
  nextMode = params.mode;
488
488
  } else if (this.ui == 'full'
@@ -509,7 +509,7 @@ BookReader.prototype.init = function() {
509
509
  this.init.initComplete = false;
510
510
  this.pageScale = this.reduce; // preserve current reduce
511
511
 
512
- var params = this.initParams();
512
+ const params = this.initParams();
513
513
 
514
514
  this.firstIndex = params.index ? params.index : 0;
515
515
 
@@ -653,8 +653,8 @@ BookReader.prototype.resize = function() {
653
653
  } else {
654
654
  // used when zoomed in
655
655
  // Re-center if the scrollbars have disappeared
656
- var center = this.twoPageGetViewCenter();
657
- var doRecenter = false;
656
+ const center = this.twoPageGetViewCenter();
657
+ let doRecenter = false;
658
658
  if (this.twoPage.totalWidth < this.refs.$brContainer.prop('clientWidth')) {
659
659
  center.percentageX = 0.5;
660
660
  doRecenter = true;
@@ -816,8 +816,8 @@ BookReader.prototype.bindGestures = function(jElement) {
816
816
  // when you move the book with one finger and then add another
817
817
  // finger to pinch. Gestures are aware of scroll state.
818
818
 
819
- var self = this;
820
- var numTouches = 1;
819
+ const self = this;
820
+ let numTouches = 1;
821
821
 
822
822
  jElement.unbind('touchmove').bind('touchmove', function(e) {
823
823
  if (e.originalEvent.cancelable) numTouches = e.originalEvent.touches.length;
@@ -901,8 +901,8 @@ BookReader.prototype.resizeBRcontainer = function(animate) {
901
901
  };
902
902
 
903
903
  BookReader.prototype.centerPageView = function() {
904
- var scrollWidth = this.refs.$brContainer.prop('scrollWidth');
905
- var clientWidth = this.refs.$brContainer.prop('clientWidth');
904
+ const scrollWidth = this.refs.$brContainer.prop('scrollWidth');
905
+ const clientWidth = this.refs.$brContainer.prop('clientWidth');
906
906
  if (scrollWidth > clientWidth) {
907
907
  this.refs.$brContainer.prop('scrollLeft', (scrollWidth - clientWidth) / 2);
908
908
  }
@@ -990,7 +990,7 @@ BookReader.prototype._reduceSort = (a, b) => a.reduce - b.reduce;
990
990
  * @return {boolean} Returns true if page could be found, false otherwise.
991
991
  */
992
992
  BookReader.prototype.jumpToPage = function(pageNum) {
993
- var pageIndex = this._models.book.parsePageString(pageNum);
993
+ const pageIndex = this._models.book.parsePageString(pageNum);
994
994
 
995
995
  if ('undefined' != typeof(pageIndex)) {
996
996
  this.jumpToIndex(pageIndex);
@@ -1119,14 +1119,14 @@ BookReader.prototype.switchMode = function(
1119
1119
  if (!(this.suppressFragmentChange || suppressFragmentChange)) {
1120
1120
  this.trigger(BookReader.eventNames.fragmentChange);
1121
1121
  }
1122
- var eventName = mode + 'PageViewSelected';
1122
+ const eventName = mode + 'PageViewSelected';
1123
1123
  this.trigger(BookReader.eventNames[eventName]);
1124
1124
 
1125
1125
  this.textSelectionPlugin?.stopPageFlip(this.refs.$brContainer);
1126
1126
  };
1127
1127
 
1128
1128
  BookReader.prototype.updateBrClasses = function() {
1129
- var modeToClass = {};
1129
+ const modeToClass = {};
1130
1130
  modeToClass[this.constMode1up] = 'BRmode1up';
1131
1131
  modeToClass[this.constMode2up] = 'BRmode2Up';
1132
1132
  modeToClass[this.constModeThumb] = 'BRmodeThumb';
@@ -1222,7 +1222,7 @@ BookReader.prototype.exitFullScreen = async function () {
1222
1222
 
1223
1223
  $(document).off('keyup', this._fullscreenCloseHandler);
1224
1224
 
1225
- var windowWidth = $(window).width();
1225
+ const windowWidth = $(window).width();
1226
1226
 
1227
1227
  const canShow2up = this.options.controls.twoPage.visible;
1228
1228
  if (canShow2up && (windowWidth <= this.onePageMinBreakpoint)) {
@@ -1706,7 +1706,7 @@ BookReader.prototype.bindNavigationHandlers = function() {
1706
1706
  },
1707
1707
  full: () => {
1708
1708
  if (this.ui == 'embed') {
1709
- var url = this.$('.BRembedreturn a').attr('href');
1709
+ const url = this.$('.BRembedreturn a').attr('href');
1710
1710
  window.open(url);
1711
1711
  } else {
1712
1712
  this.toggleFullscreen();
@@ -1725,12 +1725,12 @@ BookReader.prototype.bindNavigationHandlers = function() {
1725
1725
  });
1726
1726
  }
1727
1727
 
1728
- var $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
1729
- var $brNavCntlTopEl = this.$('.BRnavCntlTop');
1728
+ const $brNavCntlBtmEl = this.$('.BRnavCntlBtm');
1729
+ const $brNavCntlTopEl = this.$('.BRnavCntlTop');
1730
1730
 
1731
1731
  this.$('.BRnavCntl').click(
1732
1732
  function() {
1733
- var promises = [];
1733
+ const promises = [];
1734
1734
  // TODO don't use magic constants
1735
1735
  // TODO move this to a function
1736
1736
  if ($brNavCntlBtmEl.hasClass('BRdn')) {
@@ -1827,7 +1827,7 @@ BookReader.prototype.navigationMousemoveHandler = function(event) {
1827
1827
  if (event.data['br'].uiAutoHide) {
1828
1828
  // 77px is an approximate height of the Internet Archive Top Nav
1829
1829
  // 75 & 76 (pixels) provide used in this context is checked against the IA top nav height
1830
- var navkey = $(document).height() - 75;
1830
+ const navkey = $(document).height() - 75;
1831
1831
  if ((event.pageY < 76) || (event.pageY > navkey)) {
1832
1832
  // inside or near navigation elements
1833
1833
  event.data['br'].hideNavigation();
@@ -1858,7 +1858,7 @@ BookReader.prototype.initSwipeData = function(clientX, clientY) {
1858
1858
  };
1859
1859
 
1860
1860
  BookReader.prototype.swipeMousedownHandler = function(event) {
1861
- var self = event.data['br'];
1861
+ const self = event.data['br'];
1862
1862
 
1863
1863
  // We should be the last bubble point for the page images
1864
1864
  // Disable image drag and select, but keep right-click
@@ -1888,8 +1888,8 @@ BookReader.prototype.swipeMousedownHandler = function(event) {
1888
1888
  };
1889
1889
 
1890
1890
  BookReader.prototype.swipeMousemoveHandler = function(event) {
1891
- var self = event.data['br'];
1892
- var _swipe = self._swipe;
1891
+ const self = event.data['br'];
1892
+ const _swipe = self._swipe;
1893
1893
  if (! _swipe.mightBeSwiping) {
1894
1894
  return;
1895
1895
  }
@@ -1899,12 +1899,12 @@ BookReader.prototype.swipeMousemoveHandler = function(event) {
1899
1899
  _swipe.deltaY = event.clientY - _swipe.startY;
1900
1900
  _swipe.deltaT = (new Date).getTime() - _swipe.startTime;
1901
1901
 
1902
- var absX = Math.abs(_swipe.deltaX);
1903
- var absY = Math.abs(_swipe.deltaY);
1902
+ const absX = Math.abs(_swipe.deltaX);
1903
+ const absY = Math.abs(_swipe.deltaY);
1904
1904
 
1905
1905
  // Minimum distance in the amount of tim to trigger the swipe
1906
- var minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
1907
- var maxSwipeTime = 400;
1906
+ const minSwipeLength = Math.min(self.refs.$br.width() / 5, 80);
1907
+ const maxSwipeTime = 400;
1908
1908
 
1909
1909
  // Check for horizontal swipe
1910
1910
  if (absX > absY && (absX > minSwipeLength) && _swipe.deltaT < maxSwipeTime) {
@@ -1938,7 +1938,7 @@ BookReader.prototype.swipeMousemoveHandler = function(event) {
1938
1938
  };
1939
1939
 
1940
1940
  BookReader.prototype.swipeMouseupHandler = function(event) {
1941
- var _swipe = event.data['br']._swipe;
1941
+ const _swipe = event.data['br']._swipe;
1942
1942
  _swipe.mightBeSwiping = false;
1943
1943
  _swipe.mightBeDragging = false;
1944
1944
 
@@ -1955,7 +1955,7 @@ BookReader.prototype.swipeMouseupHandler = function(event) {
1955
1955
  };
1956
1956
 
1957
1957
  BookReader.prototype.bindMozTouchHandlers = function() {
1958
- var self = this;
1958
+ const self = this;
1959
1959
 
1960
1960
  // Currently only want touch handlers in 2up
1961
1961
  this.refs.$br
@@ -1982,8 +1982,8 @@ BookReader.prototype.bindMozTouchHandlers = function() {
1982
1982
  */
1983
1983
  BookReader.prototype.navigationIsVisible = function() {
1984
1984
  // $$$ doesn't account for transitioning states, nav must be fully visible to return true
1985
- var toolpos = this.refs.$BRtoolbar.position();
1986
- var tooltop = toolpos.top;
1985
+ const toolpos = this.refs.$BRtoolbar.position();
1986
+ const tooltop = toolpos.top;
1987
1987
  return tooltop == 0;
1988
1988
  };
1989
1989
 
@@ -1992,19 +1992,19 @@ BookReader.prototype.navigationIsVisible = function() {
1992
1992
  * Defaults to SHOW the navigation chrome
1993
1993
  */
1994
1994
  BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
1995
- var animationLength = this.constNavAnimationDuration;
1996
- var animationType = 'linear';
1997
- var resizePageContainer = function resizePageContainer () {
1995
+ const animationLength = this.constNavAnimationDuration;
1996
+ const animationType = 'linear';
1997
+ const resizePageContainer = function resizePageContainer () {
1998
1998
  /* main page container fills whole container */
1999
1999
  if (this.constMode2up !== this.mode) {
2000
- var animate = true;
2000
+ const animate = true;
2001
2001
  this.resizeBRcontainer(animate);
2002
2002
  }
2003
2003
  this.trigger(BookReader.eventNames.navToggled);
2004
2004
  }.bind(this);
2005
2005
 
2006
- var toolbarHeight = 0;
2007
- var navbarHeight = 0;
2006
+ let toolbarHeight = 0;
2007
+ let navbarHeight = 0;
2008
2008
  if (hide) {
2009
2009
  toolbarHeight = this.getToolBarHeight() * -1;
2010
2010
  navbarHeight = this.getFooterHeight() * -1;
@@ -2035,7 +2035,7 @@ BookReader.prototype.setNavigationView = function brSetNavigationView(hide) {
2035
2035
  BookReader.prototype.hideNavigation = function() {
2036
2036
  // Check if navigation is showing
2037
2037
  if (this.navigationIsVisible()) {
2038
- var hide = true;
2038
+ const hide = true;
2039
2039
  this.setNavigationView(hide);
2040
2040
  }
2041
2041
  };
@@ -2086,7 +2086,7 @@ BookReader.prototype.firstDisplayableIndex = function() {
2086
2086
  */
2087
2087
  BookReader.prototype.lastDisplayableIndex = function() {
2088
2088
 
2089
- var lastIndex = this._models.book.getNumLeafs() - 1;
2089
+ const lastIndex = this._models.book.getNumLeafs() - 1;
2090
2090
 
2091
2091
  if (this.mode != this.constMode2up) {
2092
2092
  return lastIndex;
@@ -2325,7 +2325,7 @@ BookReader.prototype.initUIStrings = function() {
2325
2325
  // the toolbar and nav bar easier
2326
2326
 
2327
2327
  // Setup tooltips -- later we could load these from a file for i18n
2328
- var titles = {
2328
+ const titles = {
2329
2329
  '.logo': 'Go to Archive.org', // $$$ update after getting OL record
2330
2330
  '.zoom_in': 'Zoom in',
2331
2331
  '.zoom_out': 'Zoom out',
@@ -2357,7 +2357,7 @@ BookReader.prototype.initUIStrings = function() {
2357
2357
  titles['.book_rightmost'] = 'First page';
2358
2358
  }
2359
2359
 
2360
- for (var icon in titles) {
2360
+ for (const icon in titles) {
2361
2361
  this.$(icon).prop('title', titles[icon]);
2362
2362
  }
2363
2363
  };
@@ -2368,7 +2368,7 @@ BookReader.prototype.initUIStrings = function() {
2368
2368
  BookReader.prototype.reloadImages = function() {
2369
2369
  this.refs.$brContainer.find('img').each(function(index, elem) {
2370
2370
  if (!elem.complete || elem.naturalHeight === 0) {
2371
- var src = elem.src;
2371
+ const src = elem.src;
2372
2372
  elem.src = '';
2373
2373
  setTimeout(function() {
2374
2374
  elem.src = src;
@@ -2382,10 +2382,10 @@ BookReader.prototype.reloadImages = function() {
2382
2382
  * @return {number}
2383
2383
  */
2384
2384
  BookReader.prototype.getFooterHeight = function() {
2385
- var $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
2385
+ const $heightEl = this.mode == this.constMode2up ? this.refs.$BRfooter : this.refs.$BRnav;
2386
2386
  if ($heightEl && this.refs.$BRfooter) {
2387
- var outerHeight = $heightEl.outerHeight();
2388
- var bottom = parseInt(this.refs.$BRfooter.css('bottom'));
2387
+ const outerHeight = $heightEl.outerHeight();
2388
+ const bottom = parseInt(this.refs.$BRfooter.css('bottom'));
2389
2389
  if (!isNaN(outerHeight) && !isNaN(bottom)) {
2390
2390
  return outerHeight + bottom;
2391
2391
  }
@@ -2401,11 +2401,11 @@ BookReader.prototype.getFooterHeight = function() {
2401
2401
  * @return {Object}
2402
2402
  */
2403
2403
  BookReader.prototype.paramsFromCurrent = function() {
2404
- var params = {};
2404
+ const params = {};
2405
2405
 
2406
2406
  // Path params
2407
- var index = this.currentIndex();
2408
- var pageNum = this._models.book.getPageNum(index);
2407
+ const index = this.currentIndex();
2408
+ const pageNum = this._models.book.getPageNum(index);
2409
2409
  if ((pageNum === 0) || pageNum) {
2410
2410
  params.page = pageNum;
2411
2411
  }
@@ -2444,7 +2444,7 @@ BookReader.prototype.paramsFromCurrent = function() {
2444
2444
  * @return {Object}
2445
2445
  */
2446
2446
  BookReader.prototype.paramsFromFragment = function(fragment) {
2447
- var params = {};
2447
+ const params = {};
2448
2448
 
2449
2449
  // For backwards compatibility we allow an initial # character
2450
2450
  // (as from window.location.hash) but don't require it
@@ -2453,7 +2453,7 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2453
2453
  }
2454
2454
 
2455
2455
  // Simple #nn syntax
2456
- var oldStyleLeafNum = parseInt( /^\d+$/.exec(fragment) );
2456
+ const oldStyleLeafNum = parseInt( /^\d+$/.exec(fragment) );
2457
2457
  if ( !isNaN(oldStyleLeafNum) ) {
2458
2458
  params.index = oldStyleLeafNum;
2459
2459
 
@@ -2462,9 +2462,9 @@ BookReader.prototype.paramsFromFragment = function(fragment) {
2462
2462
  }
2463
2463
 
2464
2464
  // Split into key-value pairs
2465
- var urlArray = fragment.split('/');
2466
- var urlHash = {};
2467
- for (var i = 0; i < urlArray.length; i += 2) {
2465
+ const urlArray = fragment.split('/');
2466
+ const urlHash = {};
2467
+ for (let i = 0; i < urlArray.length; i += 2) {
2468
2468
  urlHash[urlArray[i]] = urlArray[i + 1];
2469
2469
  }
2470
2470
 
@@ -40,6 +40,7 @@ export class IaBookReader extends LitElement {
40
40
  this.loaded = false;
41
41
  this.menuShortcuts = [];
42
42
  this.menuContents = [];
43
+ this.openMenuName = '';
43
44
  }
44
45
 
45
46
  updated() {
@@ -98,10 +99,11 @@ export class IaBookReader extends LitElement {
98
99
  return;
99
100
  }
100
101
 
102
+ this.openMenuName = menuId;
103
+
101
104
  if (action === 'open') {
102
105
  this.itemNav?.openShortcut(menuId);
103
106
  } else if (action === 'toggle') {
104
- this.itemNav?.openMenu(menuId);
105
107
  this.itemNav?.toggleMenu();
106
108
  }
107
109
  }
@@ -119,6 +121,7 @@ export class IaBookReader extends LitElement {
119
121
  ?signedIn=${this.signedIn}
120
122
  .menuShortcuts=${this.menuShortcuts}
121
123
  .menuContents=${this.menuContents}
124
+ .openMenu=${this.openMenuName}
122
125
  >
123
126
  <div slot="header">
124
127
  <slot name="header"></slot>
@@ -125,13 +125,13 @@ export default class AbstractTTSEngine {
125
125
  }
126
126
 
127
127
  /** @public */
128
- jumpBackward() {
129
- Promise.all([
128
+ async jumpBackward() {
129
+ await Promise.all([
130
130
  this.activeSound.stop(),
131
131
  this._chunkIterator.decrement()
132
132
  .then(() => this._chunkIterator.decrement())
133
- ])
134
- .then(() => this.step());
133
+ ]);
134
+ this.step();
135
135
  }
136
136
 
137
137
  /** @param {number} newRate */
@@ -147,36 +147,33 @@ export default class AbstractTTSEngine {
147
147
  }
148
148
 
149
149
  /** @private */
150
- step() {
151
- this._chunkIterator.next()
152
- .then(chunk => {
153
- if (chunk == PageChunkIterator.AT_END) {
154
- this.stop();
155
- this.opts.onDone();
156
- return;
157
- }
158
-
159
- this.opts.onLoadingStart();
160
- const sound = this.createSound(chunk);
161
- sound.chunk = chunk;
162
- sound.rate = this.playbackRate;
163
- sound.voice = this.voice;
164
- sound.load(() => this.opts.onLoadingComplete());
165
-
166
- this.opts.onLoadingComplete();
167
- return this.opts.beforeChunkPlay(chunk).then(() => sound);
168
- })
169
- .then(sound => {
170
- if (!this.playing) return;
171
-
172
- const playPromise = this.playSound(sound)
173
- .then(() => this.opts.afterChunkPlay(sound.chunk));
174
- if (this.paused) this.pause();
175
- return playPromise;
176
- })
177
- .then(() => {
178
- if (this.playing) return this.step();
179
- });
150
+ async step() {
151
+ const chunk = await this._chunkIterator.next();
152
+ if (chunk == PageChunkIterator.AT_END) {
153
+ this.stop();
154
+ this.opts.onDone();
155
+ return;
156
+ }
157
+ this.opts.onLoadingStart();
158
+ const sound = this.createSound(chunk);
159
+ sound.chunk = chunk;
160
+ sound.rate = this.playbackRate;
161
+ sound.voice = this.voice;
162
+ sound.load(() => this.opts.onLoadingComplete());
163
+
164
+ this.opts.onLoadingComplete();
165
+
166
+ await this.opts.beforeChunkPlay(chunk);
167
+
168
+ if (!this.playing) return;
169
+
170
+ const playPromise = await this.playSound(sound)
171
+ .then(()=> this.opts.afterChunkPlay(sound.chunk));
172
+
173
+ if (this.paused) this.pause();
174
+ await playPromise;
175
+
176
+ if (this.playing) return this.step();
180
177
  }
181
178
 
182
179
  /**
@@ -53,22 +53,18 @@ export default class PageChunkIterator {
53
53
  * in the correct order.
54
54
  * @return {PromiseLike<"__PageChunkIterator.AT_END__" | PageChunk>}
55
55
  */
56
- _nextUncontrolled() {
56
+ async _nextUncontrolled() {
57
57
  if (this._cursor.page == this.pageCount) {
58
58
  return Promise.resolve(PageChunkIterator.AT_END);
59
59
  }
60
-
61
60
  this._recenterBuffer(this._cursor.page);
62
-
63
- return this._fetchPageChunks(this._cursor.page)
64
- .then(chunks => {
65
- if (this._cursor.chunk == chunks.length) {
66
- this._cursor.page++;
67
- this._cursor.chunk = 0;
68
- return this._nextUncontrolled();
69
- }
70
- return chunks[this._cursor.chunk++];
71
- });
61
+ const chunks = await this._fetchPageChunks(this._cursor.page);
62
+ if (this._cursor.chunk == chunks.length) {
63
+ this._cursor.page++;
64
+ this._cursor.chunk = 0;
65
+ return this._nextUncontrolled();
66
+ }
67
+ return chunks[this._cursor.chunk++];
72
68
  }
73
69
 
74
70
  /**