@internetarchive/bookreader 5.0.0-35 → 5.0.0-36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  /**