@internetarchive/bookreader 5.0.0-9 → 5.0.0-91
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/.eslintrc.js +21 -19
- package/.github/workflows/node.js.yml +76 -11
- package/.github/workflows/npm-publish.yml +6 -20
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +404 -1125
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +20 -20
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1782 -0
- package/BookReader/ia-bookreader-bundle.js.LICENSE.txt +7 -0
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/1up.svg +1 -1
- package/BookReader/icons/2up.svg +1 -1
- package/BookReader/icons/advance.svg +1 -1
- package/BookReader/icons/chevron-right.svg +1 -1
- package/BookReader/icons/close-circle-dark.svg +1 -1
- package/BookReader/icons/close-circle.svg +1 -1
- package/BookReader/icons/fullscreen.svg +1 -1
- package/BookReader/icons/fullscreen_exit.svg +1 -1
- package/BookReader/icons/hamburger.svg +1 -1
- package/BookReader/icons/left-arrow.svg +1 -1
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/magnify.svg +1 -1
- package/BookReader/icons/pause.svg +1 -1
- package/BookReader/icons/play.svg +1 -1
- package/BookReader/icons/playback-speed.svg +1 -1
- package/BookReader/icons/read-aloud.svg +1 -1
- package/BookReader/icons/review.svg +1 -1
- package/BookReader/icons/thumbnails.svg +1 -1
- package/BookReader/icons/voice.svg +1 -0
- package/BookReader/icons/volume-full.svg +1 -1
- package/BookReader/images/BRicons.svg +3 -3
- package/BookReader/images/books_graphic.svg +1 -1
- package/BookReader/images/icon_book.svg +1 -1
- package/BookReader/images/icon_bookmark.svg +1 -1
- package/BookReader/images/icon_gear.svg +1 -1
- package/BookReader/images/icon_hamburger.svg +1 -1
- package/BookReader/images/icon_home.svg +1 -1
- package/BookReader/images/icon_info.svg +1 -1
- package/BookReader/images/icon_one_page.svg +1 -1
- package/BookReader/images/icon_pause.svg +1 -1
- package/BookReader/images/icon_play.svg +1 -1
- package/BookReader/images/icon_playback-rate.svg +1 -1
- package/BookReader/images/icon_search_button.svg +1 -1
- package/BookReader/images/icon_share.svg +1 -1
- package/BookReader/images/icon_skip-ahead.svg +1 -1
- package/BookReader/images/icon_skip-back.svg +1 -1
- package/BookReader/images/icon_speaker.svg +1 -1
- package/BookReader/images/icon_speaker_open.svg +1 -1
- package/BookReader/images/icon_thumbnails.svg +1 -1
- package/BookReader/images/icon_toc.svg +1 -1
- package/BookReader/images/icon_two_pages.svg +1 -1
- package/BookReader/images/marker_chap-off.svg +1 -1
- package/BookReader/images/marker_chap-on.svg +1 -1
- package/BookReader/images/marker_srch-on.svg +1 -1
- package/BookReader/images/unviewable_page.png +0 -0
- package/BookReader/jquery-3.js +2 -0
- package/BookReader/jquery-3.js.LICENSE.txt +24 -0
- package/BookReader/plugins/plugin.archive_analytics.js +1 -1
- package/BookReader/plugins/plugin.archive_analytics.js.map +1 -1
- package/BookReader/plugins/plugin.autoplay.js +1 -1
- package/BookReader/plugins/plugin.autoplay.js.map +1 -1
- package/BookReader/plugins/plugin.chapters.js +25 -1
- package/BookReader/plugins/plugin.chapters.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.chapters.js.map +1 -1
- package/BookReader/plugins/plugin.iframe.js +1 -1
- package/BookReader/plugins/plugin.iframe.js.map +1 -1
- package/BookReader/plugins/plugin.iiif.js +2 -0
- package/BookReader/plugins/plugin.iiif.js.map +1 -0
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +2 -1
- package/BookReader/plugins/plugin.search.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +2 -1
- package/BookReader/plugins/plugin.text_selection.js.LICENSE.txt +1 -0
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- package/BookReader/plugins/plugin.tts.js.LICENSE.txt +2 -0
- package/BookReader/plugins/plugin.tts.js.map +1 -1
- package/BookReader/plugins/plugin.url.js +1 -1
- package/BookReader/plugins/plugin.url.js.map +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js +1 -1
- package/BookReader/plugins/plugin.vendor-fullscreen.js.map +1 -1
- package/BookReader/webcomponents-bundle.js +3 -0
- package/BookReader/webcomponents-bundle.js.LICENSE.txt +9 -0
- package/BookReader/webcomponents-bundle.js.map +1 -0
- package/BookReaderDemo/BookReaderDemo.css +18 -19
- package/BookReaderDemo/BookReaderJSAdvanced.js +0 -3
- package/BookReaderDemo/BookReaderJSSimple.js +1 -0
- package/BookReaderDemo/IADemoBr.js +144 -0
- package/BookReaderDemo/demo-advanced.html +2 -2
- package/BookReaderDemo/demo-embed-iframe-src.html +2 -1
- package/BookReaderDemo/demo-fullscreen-mobile.html +3 -5
- package/BookReaderDemo/demo-fullscreen.html +2 -4
- package/BookReaderDemo/demo-iiif.html +99 -12
- package/BookReaderDemo/demo-internetarchive.html +214 -18
- package/BookReaderDemo/demo-multiple.html +2 -1
- package/BookReaderDemo/demo-preview-pages.html +526 -525
- package/BookReaderDemo/demo-simple.html +2 -1
- package/BookReaderDemo/demo-vendor-fullscreen.html +2 -4
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +2 -2
- package/BookReaderDemo/immersion-mode.html +2 -4
- package/BookReaderDemo/toggle_controls.html +3 -2
- package/BookReaderDemo/view_mode.html +2 -1
- package/BookReaderDemo/viewmode-cycle.html +2 -3
- package/CHANGELOG.md +600 -33
- package/README.md +14 -1
- package/babel.config.js +20 -0
- package/codecov.yml +6 -0
- package/index.html +5 -2
- package/jsconfig.json +19 -0
- package/netlify.toml +9 -0
- package/package.json +70 -62
- package/renovate.json +52 -0
- package/scripts/preversion.js +0 -1
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +5 -2
- package/src/BookNavigator/assets/ia-logo.js +17 -0
- package/src/BookNavigator/assets/icon_checkmark.js +1 -1
- package/src/BookNavigator/assets/icon_close.js +1 -1
- package/src/BookNavigator/book-navigator.js +590 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +3 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +2 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +4 -9
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +27 -17
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +116 -67
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +36 -21
- package/src/BookNavigator/downloads/downloads.js +29 -25
- package/src/BookNavigator/search/search-provider.js +50 -28
- package/src/BookNavigator/search/search-results.js +24 -10
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/viewable-files.js +95 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +13 -12
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +7 -7
- package/src/BookReader/BookModel.js +79 -43
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/ImageCache.js +48 -15
- package/src/BookReader/Mode1Up.js +56 -351
- package/src/BookReader/Mode1UpLit.js +388 -0
- package/src/BookReader/Mode2Up.js +73 -1318
- package/src/BookReader/Mode2UpLit.js +777 -0
- package/src/BookReader/ModeCoordinateSpace.js +29 -0
- package/src/BookReader/ModeSmoothZoom.js +312 -0
- package/src/BookReader/ModeThumb.js +19 -13
- package/src/BookReader/Navbar/Navbar.js +70 -54
- package/src/BookReader/PageContainer.js +116 -22
- package/src/BookReader/ReduceSet.js +3 -3
- package/src/BookReader/Toolbar/Toolbar.js +14 -41
- package/src/BookReader/events.js +2 -3
- package/src/BookReader/options.js +75 -15
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils/SelectionObserver.js +45 -0
- package/src/BookReader/utils/classes.js +1 -1
- package/src/BookReader/utils.js +128 -13
- package/src/BookReader.js +559 -1083
- package/src/BookReaderPlugin.js +44 -0
- package/src/assets/icons/magnify-minus.svg +3 -7
- package/src/assets/icons/magnify-plus.svg +3 -7
- package/src/assets/icons/voice.svg +1 -0
- package/src/assets/images/unviewable_page.png +0 -0
- package/src/css/BookReader.scss +1 -5
- package/src/css/_BRBookmarks.scss +1 -1
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRicon.scss +8 -2
- package/src/css/_BRmain.scss +16 -3
- package/src/css/_BRnav.scss +12 -42
- package/src/css/_BRpages.scss +170 -42
- package/src/css/_BRsearch.scss +68 -25
- package/src/css/_BRtoolbar.scss +5 -5
- package/src/css/_TextSelection.scss +87 -27
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +24 -7
- package/src/css/_icons.scss +1 -1
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.archive_analytics.js +84 -78
- package/src/plugins/plugin.autoplay.js +99 -104
- package/src/plugins/plugin.chapters.js +310 -201
- package/src/plugins/plugin.iframe.js +1 -1
- package/src/plugins/plugin.iiif.js +141 -0
- package/src/plugins/plugin.resume.js +53 -50
- package/src/plugins/plugin.text_selection.js +519 -175
- package/src/plugins/plugin.vendor-fullscreen.js +7 -7
- package/src/plugins/search/plugin.search.js +151 -127
- package/src/plugins/search/utils.js +43 -0
- package/src/plugins/search/view.js +37 -59
- package/src/plugins/tts/AbstractTTSEngine.js +75 -45
- package/src/plugins/tts/FestivalTTSEngine.js +21 -31
- package/src/plugins/tts/PageChunk.js +16 -23
- package/src/plugins/tts/PageChunkIterator.js +11 -17
- package/src/plugins/tts/WebTTSEngine.js +126 -84
- package/src/plugins/tts/plugin.tts.js +308 -350
- package/src/plugins/tts/utils.js +29 -26
- package/src/plugins/url/UrlPlugin.js +191 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +47 -18
- package/src/util/browserSniffing.js +33 -1
- package/src/util/docCookies.js +21 -2
- package/src/util/strings.js +1 -0
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +9 -6
- package/tests/e2e/base.test.js +8 -16
- package/tests/e2e/helpers/base.js +55 -50
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/mockSearch.js +19 -22
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/helpers/rightToLeft.js +8 -14
- package/tests/e2e/helpers/search.js +73 -0
- package/tests/e2e/models/Navigation.js +20 -37
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +40 -33
- package/tests/jest/BookNavigator/book-navigator.test.js +661 -0
- package/tests/jest/BookNavigator/bookmarks/bookmark-button.test.js +43 -0
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmark-edit.test.js +25 -26
- package/tests/{karma → jest}/BookNavigator/bookmarks/bookmarks-list.test.js +41 -42
- package/tests/jest/BookNavigator/bookmarks/ia-bookmarks.test.js +45 -0
- package/tests/jest/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/jest/BookNavigator/downloads/downloads.test.js +53 -0
- package/tests/jest/BookNavigator/search/search-provider.test.js +167 -0
- package/tests/{karma → jest}/BookNavigator/search/search-results.test.js +109 -60
- package/tests/jest/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/jest/BookNavigator/viewable-files/viewable-files-provider.test.js +80 -0
- package/tests/jest/BookNavigator/visual-adjustments.test.js +200 -0
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +74 -14
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +263 -0
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +73 -0
- package/tests/jest/BookReader/Mode2Up.test.js +98 -0
- package/tests/jest/BookReader/Mode2UpLit.test.js +190 -0
- package/tests/jest/BookReader/ModeCoordinateSpace.test.js +16 -0
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +218 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +42 -29
- package/tests/jest/BookReader/PageContainer.test.js +238 -0
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +3 -3
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/jest/BookReader/utils/SelectionObserver.test.js +57 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +250 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +10 -2
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +43 -53
- package/tests/jest/plugins/plugin.archive_analytics.test.js +20 -0
- package/tests/jest/plugins/plugin.autoplay.test.js +35 -0
- package/tests/jest/plugins/plugin.chapters.test.js +193 -0
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +4 -4
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +22 -35
- package/tests/jest/plugins/plugin.text_selection.test.js +316 -0
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +19 -47
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +42 -9
- package/tests/jest/plugins/search/utils.js +25 -0
- package/tests/jest/plugins/search/utils.test.js +29 -0
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +30 -10
- package/tests/{plugins → jest/plugins}/tts/FestivalTTSEngine.test.js +4 -4
- package/tests/{plugins → jest/plugins}/tts/PageChunk.test.js +1 -1
- package/tests/{plugins → jest/plugins}/tts/PageChunkIterator.test.js +3 -3
- package/tests/{plugins → jest/plugins}/tts/WebTTSEngine.test.js +65 -13
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +1 -60
- package/tests/jest/plugins/url/UrlPlugin.test.js +198 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +57 -18
- package/tests/jest/setup.js +3 -0
- package/tests/{util → jest/util}/browserSniffing.test.js +10 -4
- package/tests/jest/util/docCookies.test.js +24 -0
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/jest/utils.js +83 -0
- package/webpack.config.js +16 -10
- package/.babelrc +0 -12
- package/.dependabot/config.yml +0 -6
- package/.testcaferc.json +0 -5
- package/BookReader/bookreader-component-bundle.js +0 -1450
- package/BookReader/bookreader-component-bundle.js.LICENSE.txt +0 -38
- package/BookReader/bookreader-component-bundle.js.map +0 -1
- package/BookReader/jquery-1.10.1.js +0 -2
- package/BookReader/jquery-1.10.1.js.LICENSE.txt +0 -24
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReader/plugins/plugin.mobile_nav.js +0 -2
- package/BookReader/plugins/plugin.mobile_nav.js.map +0 -1
- package/BookReaderDemo/BookReaderJSAutoplay.js +0 -56
- package/BookReaderDemo/IIIFBookReader.js +0 -207
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-autoplay.html +0 -38
- package/BookReaderDemo/demo-iiif.js +0 -26
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/karma.conf.js +0 -23
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -446
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookNavigator/search/a-search-result.js +0 -55
- package/src/BookReader/DebugConsole.js +0 -54
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -376
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/css/_MobileNav.scss +0 -194
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/src/plugins/plugin.mobile_nav.js +0 -287
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/DebugConsole.test.js +0 -25
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/Mode2Up.test.js +0 -247
- package/tests/BookReader/PageContainer.test.js +0 -115
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/e2e/helpers/desktopSearch.js +0 -72
- package/tests/e2e/helpers/mobileSearch.js +0 -85
- package/tests/e2e/ia-production/ia-prod-base.js +0 -17
- package/tests/karma/BookNavigator/book-navigator.test.js +0 -132
- package/tests/karma/BookNavigator/search/search-provider.test.js +0 -23
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -201
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
- package/tests/plugins/plugin.archive_analytics.test.js +0 -23
- package/tests/plugins/plugin.autoplay.test.js +0 -52
- package/tests/plugins/plugin.chapters.test.js +0 -130
- package/tests/plugins/plugin.mobile_nav.test.js +0 -66
- package/tests/plugins/plugin.text_selection.test.js +0 -203
- package/tests/util/docCookies.test.js +0 -15
- package/tests/utils.js +0 -42
@@ -1,6 +1,7 @@
|
|
1
1
|
/* global br */
|
2
2
|
import { isChrome, isFirefox } from '../../util/browserSniffing.js';
|
3
|
-
import {
|
3
|
+
import { isAndroid, DEBUG_READ_ALOUD } from './utils.js';
|
4
|
+
import { promisifyEvent, sleep } from '../../BookReader/utils.js';
|
4
5
|
import AbstractTTSEngine from './AbstractTTSEngine.js';
|
5
6
|
/** @typedef {import("./AbstractTTSEngine.js").PageChunk} PageChunk */
|
6
7
|
/** @typedef {import("./AbstractTTSEngine.js").AbstractTTSSound} AbstractTTSSound */
|
@@ -12,7 +13,7 @@ import AbstractTTSEngine from './AbstractTTSEngine.js';
|
|
12
13
|
**/
|
13
14
|
export default class WebTTSEngine extends AbstractTTSEngine {
|
14
15
|
static isSupported() {
|
15
|
-
return typeof(window.speechSynthesis) !== 'undefined'
|
16
|
+
return typeof(window.speechSynthesis) !== 'undefined';
|
16
17
|
}
|
17
18
|
|
18
19
|
/** @param {TTSEngineOptions} options */
|
@@ -44,7 +45,11 @@ export default class WebTTSEngine extends AbstractTTSEngine {
|
|
44
45
|
// album: 'The Ultimate Collection (Remastered)',
|
45
46
|
artwork: [
|
46
47
|
{ src: br.options.thumbnail, type: 'image/jpg' },
|
47
|
-
]
|
48
|
+
],
|
49
|
+
});
|
50
|
+
|
51
|
+
navigator.mediaSession.setPositionState({
|
52
|
+
duration: Infinity,
|
48
53
|
});
|
49
54
|
|
50
55
|
navigator.mediaSession.setActionHandler('play', () => {
|
@@ -70,7 +75,22 @@ export default class WebTTSEngine extends AbstractTTSEngine {
|
|
70
75
|
}
|
71
76
|
|
72
77
|
/** @override */
|
73
|
-
getVoices() {
|
78
|
+
getVoices() {
|
79
|
+
const voices = speechSynthesis.getVoices();
|
80
|
+
if (voices.filter(v => v.default).length != 1) {
|
81
|
+
// iOS bug where the default system voice is sometimes
|
82
|
+
// missing from the list
|
83
|
+
voices.unshift({
|
84
|
+
voiceURI: 'bookreader.SystemDefault',
|
85
|
+
name: 'System Default',
|
86
|
+
// Not necessarily true, but very likely
|
87
|
+
lang: navigator.language,
|
88
|
+
default: true,
|
89
|
+
localService: true,
|
90
|
+
});
|
91
|
+
}
|
92
|
+
return voices;
|
93
|
+
}
|
74
94
|
|
75
95
|
/** @override */
|
76
96
|
createSound(chunk) {
|
@@ -121,18 +141,22 @@ export class WebTTSSound {
|
|
121
141
|
this.started = false;
|
122
142
|
|
123
143
|
this.utterance = new SpeechSynthesisUtterance(this.text.slice(this._charIndex));
|
124
|
-
|
144
|
+
// iOS bug where the default system voice is sometimes
|
145
|
+
// missing from the list
|
146
|
+
if (this.voice?.voiceURI !== 'bookreader.SystemDefault') {
|
147
|
+
this.utterance.voice = this.voice;
|
148
|
+
}
|
125
149
|
// Need to also set lang (for some reason); won't set voice on Chrome@Android otherwise
|
126
150
|
if (this.voice) this.utterance.lang = this.voice.lang;
|
127
151
|
this.utterance.rate = this.rate;
|
128
152
|
|
129
153
|
// Useful for debugging things
|
130
|
-
if (
|
154
|
+
if (DEBUG_READ_ALOUD) {
|
131
155
|
this.utterance.addEventListener('pause', () => console.log('pause'));
|
132
156
|
this.utterance.addEventListener('resume', () => console.log('resume'));
|
133
157
|
this.utterance.addEventListener('start', () => console.log('start'));
|
134
158
|
this.utterance.addEventListener('end', () => console.log('end'));
|
135
|
-
this.utterance.addEventListener('error',
|
159
|
+
this.utterance.addEventListener('error', ev => console.log('error', ev));
|
136
160
|
this.utterance.addEventListener('boundary', () => console.log('boundary'));
|
137
161
|
this.utterance.addEventListener('mark', () => console.log('mark'));
|
138
162
|
this.utterance.addEventListener('finish', () => console.log('finish'));
|
@@ -167,7 +191,7 @@ export class WebTTSSound {
|
|
167
191
|
* left off.
|
168
192
|
* @return {Promise<void>}
|
169
193
|
*/
|
170
|
-
reload() {
|
194
|
+
async reload() {
|
171
195
|
// We'll restore the pause state, so copy it here
|
172
196
|
const wasPaused = this.paused;
|
173
197
|
// Use recent event to determine where we'll restart from
|
@@ -179,14 +203,12 @@ export class WebTTSSound {
|
|
179
203
|
}
|
180
204
|
|
181
205
|
// We can't modify the utterance object, so we have to make a new one
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
if (!wasPaused) this.play();
|
189
|
-
});
|
206
|
+
await this.stop();
|
207
|
+
this.load();
|
208
|
+
// Instead of playing and immediately pausing, we don't start playing. Note
|
209
|
+
// this is a requirement because pause doesn't work consistently across
|
210
|
+
// browsers.
|
211
|
+
if (!wasPaused) this.play();
|
190
212
|
}
|
191
213
|
|
192
214
|
play() {
|
@@ -222,15 +244,16 @@ export class WebTTSSound {
|
|
222
244
|
return endPromise;
|
223
245
|
}
|
224
246
|
|
225
|
-
finish() {
|
226
|
-
this.stop()
|
247
|
+
async finish() {
|
248
|
+
await this.stop();
|
249
|
+
this.utterance.dispatchEvent(new Event('finish'));
|
227
250
|
}
|
228
251
|
|
229
252
|
/**
|
230
253
|
* @override
|
231
254
|
* Will fire a pause event unless already paused
|
232
255
|
**/
|
233
|
-
pause() {
|
256
|
+
async pause() {
|
234
257
|
if (this.paused) return;
|
235
258
|
|
236
259
|
const pausePromise = promisifyEvent(this.utterance, 'pause');
|
@@ -241,25 +264,25 @@ export class WebTTSSound {
|
|
241
264
|
// 2. Pause doesn't work and doesn't fire
|
242
265
|
// 3. Pause works but doesn't fire
|
243
266
|
const pauseMightNotWork = (isFirefox() && isAndroid());
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
this.utterance.dispatchEvent(new CustomEvent('pause', this._lastEvents.start));
|
255
|
-
// if pause might not work, then we'll stop entirely and restart later
|
256
|
-
if (pauseMightNotWork) this.stop();
|
257
|
-
});
|
267
|
+
|
268
|
+
// Pause sometimes works, but doesn't fire the event, so wait to see if it fires
|
269
|
+
const winner = await Promise.race([pausePromise, sleep(100).then(() => 'timeout')]);
|
270
|
+
|
271
|
+
// We got our pause event; nothing to do!
|
272
|
+
if (winner != 'timeout') return;
|
273
|
+
|
274
|
+
if (DEBUG_READ_ALOUD) {
|
275
|
+
console.log('TTS: Firing pause event manually');
|
258
276
|
}
|
277
|
+
|
278
|
+
this.utterance.dispatchEvent(new CustomEvent('pause', this._lastEvents.start));
|
279
|
+
|
280
|
+
// if pause might not work, then we'll stop entirely and restart later
|
281
|
+
if (pauseMightNotWork) this.stop();
|
259
282
|
}
|
260
283
|
|
261
|
-
resume() {
|
262
|
-
if (!this.started) {
|
284
|
+
async resume() {
|
285
|
+
if (!this.started || this.stopped) {
|
263
286
|
this.play();
|
264
287
|
return;
|
265
288
|
}
|
@@ -271,23 +294,24 @@ export class WebTTSSound {
|
|
271
294
|
// 2. Resume works + doesn't fire (Chrome Desktop)
|
272
295
|
// 3. Resume doesn't work + doesn't fire (Chrome/FF Android)
|
273
296
|
const resumeMightNotWork = (isChrome() && isAndroid()) || (isFirefox() && isAndroid());
|
274
|
-
const resumeMightNotFire = isChrome() || resumeMightNotWork;
|
275
297
|
|
276
298
|
// Try resume
|
277
299
|
const resumePromise = promisifyEvent(this.utterance, 'resume');
|
278
300
|
speechSynthesis.resume();
|
279
301
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
if (result != 'timeout') return;
|
302
|
+
const winner = await Promise.race([resumePromise, sleep(100).then(() => 'timeout')]);
|
303
|
+
// We got resume! All is good
|
304
|
+
if (winner != 'timeout') return;
|
284
305
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
306
|
+
if (DEBUG_READ_ALOUD) {
|
307
|
+
console.log('TTS: Firing resume event manually');
|
308
|
+
}
|
309
|
+
|
310
|
+
// Fake it
|
311
|
+
this.utterance.dispatchEvent(new CustomEvent('resume', {}));
|
312
|
+
if (resumeMightNotWork) {
|
313
|
+
await this.reload();
|
314
|
+
this.play();
|
291
315
|
}
|
292
316
|
}
|
293
317
|
|
@@ -296,6 +320,11 @@ export class WebTTSSound {
|
|
296
320
|
this.reload();
|
297
321
|
}
|
298
322
|
|
323
|
+
/** @param {SpeechSynthesisVoice} voice */
|
324
|
+
setVoice(voice) {
|
325
|
+
this.voice = voice;
|
326
|
+
this.reload();
|
327
|
+
}
|
299
328
|
/**
|
300
329
|
* @private
|
301
330
|
* Chrome has a bug where it only plays 15 seconds of TTS and then
|
@@ -303,45 +332,58 @@ export class WebTTSSound {
|
|
303
332
|
* We avoid this (as described here: https://bugs.chromium.org/p/chromium/issues/detail?id=679437#c15 )
|
304
333
|
* by pausing after 14 seconds and ~instantly resuming.
|
305
334
|
*/
|
306
|
-
_chromePausingBugFix() {
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
this._chromePausingBugFix();
|
341
|
-
});
|
342
|
-
break;
|
335
|
+
async _chromePausingBugFix() {
|
336
|
+
if (DEBUG_READ_ALOUD) {
|
337
|
+
console.log('CHROME-PAUSE-HACK: starting');
|
338
|
+
}
|
339
|
+
|
340
|
+
const result = await Promise.race([
|
341
|
+
sleep(14000).then(() => 'timeout'),
|
342
|
+
promisifyEvent(this.utterance, 'pause').then(() => 'pause'),
|
343
|
+
promisifyEvent(this.utterance, 'end').then(() => 'end'),
|
344
|
+
// Some browsers (Edge) trigger error when the utterance is interrupted/stopped
|
345
|
+
promisifyEvent(this.utterance, 'error').then(() => 'error'),
|
346
|
+
]);
|
347
|
+
|
348
|
+
if (DEBUG_READ_ALOUD) {
|
349
|
+
console.log(`CHROME-PAUSE-HACK: ${result}`);
|
350
|
+
}
|
351
|
+
if (result == 'end' || result == 'error') {
|
352
|
+
// audio was stopped/finished; nothing to do
|
353
|
+
if (DEBUG_READ_ALOUD) {
|
354
|
+
console.log('CHROME-PAUSE-HACK: stopped (end/error)');
|
355
|
+
}
|
356
|
+
} else if (result == 'pause') {
|
357
|
+
// audio was paused; wait for resume
|
358
|
+
// Chrome won't let you resume the audio if 14s have passed 🤷
|
359
|
+
// We could do the same as before (but resume+pause instead of pause+resume),
|
360
|
+
// but that means we'd _constantly_ be running in the background. So in that
|
361
|
+
// case, let's just restart the chunk
|
362
|
+
const result2 = await Promise.race([
|
363
|
+
promisifyEvent(this.utterance, 'resume').then(() => 'resume'),
|
364
|
+
sleep(14000).then(() => 'timeout'),
|
365
|
+
]);
|
366
|
+
if (result2 == 'timeout') {
|
367
|
+
if (DEBUG_READ_ALOUD) {
|
368
|
+
console.log('CHROME-PAUSE-HACK: stopped (timed out while paused)');
|
343
369
|
}
|
344
|
-
|
370
|
+
// We hit Chrome's secret cut off time while paused, and
|
371
|
+
// won't be able to resume normally, so trigger a stop.
|
372
|
+
this.stop();
|
373
|
+
} else {
|
374
|
+
// The user resumed before the cut off! Continue as normal
|
375
|
+
this._chromePausingBugFix();
|
376
|
+
}
|
377
|
+
} else if (result == 'timeout') {
|
378
|
+
// We hit Chrome's secret cut off time while playing.
|
379
|
+
// To be able to keep TTS-ing, quickly pause/resume.
|
380
|
+
speechSynthesis.pause();
|
381
|
+
await sleep(25);
|
382
|
+
speechSynthesis.resume();
|
383
|
+
|
384
|
+
// Listen for more
|
385
|
+
this._chromePausingBugFix();
|
386
|
+
}
|
345
387
|
}
|
346
388
|
}
|
347
389
|
|