@internetarchive/bookreader 5.0.0-4 → 5.0.0-40-a1
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 +17 -15
- package/.github/workflows/node.js.yml +75 -4
- package/.github/workflows/npm-publish.yml +2 -16
- package/.testcaferc.js +10 -0
- package/BookReader/BookReader.css +83 -323
- package/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.LICENSE.txt +24 -0
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +1623 -0
- package/BookReader/{bookreader-component-bundle.js.LICENSE.txt → ia-bookreader-bundle.js.LICENSE.txt} +14 -10
- package/BookReader/ia-bookreader-bundle.js.map +1 -0
- package/BookReader/icons/close-circle-dark.svg +1 -0
- package/BookReader/icons/magnify-minus.svg +1 -1
- package/BookReader/icons/magnify-plus.svg +1 -1
- package/BookReader/icons/voice.svg +1 -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 +1 -1
- 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.mobile_nav.js +1 -1
- package/BookReader/plugins/plugin.mobile_nav.js.map +1 -1
- package/BookReader/plugins/plugin.resume.js +1 -1
- package/BookReader/plugins/plugin.resume.js.map +1 -1
- package/BookReader/plugins/plugin.search.js +1 -1
- package/BookReader/plugins/plugin.search.js.map +1 -1
- package/BookReader/plugins/plugin.text_selection.js +1 -1
- package/BookReader/plugins/plugin.text_selection.js.map +1 -1
- package/BookReader/plugins/plugin.tts.js +1 -1
- 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 +14 -1
- package/BookReaderDemo/IADemoBr.js +120 -0
- package/BookReaderDemo/demo-advanced.html +1 -1
- package/BookReaderDemo/demo-autoplay.html +1 -0
- package/BookReaderDemo/demo-embed-iframe-src.html +1 -0
- package/BookReaderDemo/demo-fullscreen-mobile.html +1 -0
- package/BookReaderDemo/demo-fullscreen.html +1 -0
- package/BookReaderDemo/demo-iiif.html +1 -0
- package/BookReaderDemo/demo-internetarchive.html +74 -17
- package/BookReaderDemo/demo-multiple.html +1 -0
- package/BookReaderDemo/demo-preview-pages.html +1 -0
- package/BookReaderDemo/demo-simple.html +1 -0
- package/BookReaderDemo/demo-vendor-fullscreen.html +1 -0
- package/BookReaderDemo/ia-multiple-volumes-manifest.js +170 -0
- package/BookReaderDemo/immersion-1up.html +1 -0
- package/BookReaderDemo/immersion-mode.html +1 -0
- package/BookReaderDemo/toggle_controls.html +1 -0
- package/BookReaderDemo/view_mode.html +1 -0
- package/BookReaderDemo/viewmode-cycle.html +1 -2
- package/CHANGELOG.md +166 -0
- package/README.md +14 -1
- package/babel.config.js +18 -0
- package/codecov.yml +6 -0
- package/index.html +3 -0
- package/jsconfig.json +19 -0
- package/package.json +62 -47
- package/renovate.json +43 -0
- package/src/BookNavigator/assets/bookmark-colors.js +1 -1
- package/src/BookNavigator/assets/button-base.js +9 -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/assets/icon_sort_asc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_desc.js +5 -0
- package/src/BookNavigator/assets/icon_sort_neutral.js +5 -0
- package/src/BookNavigator/assets/icon_volumes.js +11 -0
- package/src/BookNavigator/book-navigator.js +556 -0
- package/src/BookNavigator/bookmarks/bookmark-button.js +3 -2
- package/src/BookNavigator/bookmarks/bookmark-edit.js +4 -4
- package/src/BookNavigator/bookmarks/bookmarks-list.js +3 -3
- package/src/BookNavigator/bookmarks/bookmarks-loginCTA.js +3 -8
- package/src/BookNavigator/bookmarks/bookmarks-provider.js +23 -12
- package/src/BookNavigator/bookmarks/ia-bookmarks.js +98 -62
- package/src/BookNavigator/delete-modal-actions.js +1 -1
- package/src/BookNavigator/downloads/downloads-provider.js +23 -17
- package/src/BookNavigator/downloads/downloads.js +17 -25
- package/src/BookNavigator/search/a-search-result.js +3 -3
- package/src/BookNavigator/search/search-provider.js +57 -24
- package/src/BookNavigator/search/search-results.js +8 -20
- package/src/BookNavigator/sharing.js +27 -0
- package/src/BookNavigator/visual-adjustments/visual-adjustments-provider.js +11 -13
- package/src/BookNavigator/visual-adjustments/visual-adjustments.js +4 -3
- package/src/BookNavigator/volumes/volumes-provider.js +114 -0
- package/src/BookNavigator/volumes/volumes.js +188 -0
- package/src/BookReader/DebugConsole.js +3 -3
- package/src/BookReader/DragScrollable.js +233 -0
- package/src/BookReader/Mode1Up.js +51 -351
- package/src/BookReader/Mode1UpLit.js +441 -0
- package/src/BookReader/Mode2Up.js +104 -71
- package/src/BookReader/ModeSmoothZoom.js +179 -0
- package/src/BookReader/ModeThumb.js +16 -8
- package/src/BookReader/Navbar/Navbar.js +2 -31
- package/src/BookReader/PageContainer.js +57 -6
- package/src/BookReader/ReduceSet.js +1 -1
- package/src/BookReader/Toolbar/Toolbar.js +7 -7
- package/src/BookReader/options.js +10 -0
- package/src/BookReader/utils/HTMLDimensionsCacher.js +44 -0
- package/src/BookReader/utils/ScrollClassAdder.js +31 -0
- package/src/BookReader/utils.js +68 -13
- package/src/BookReader.js +375 -289
- package/src/assets/icons/close-circle-dark.svg +1 -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/css/BookReader.scss +0 -12
- package/src/css/_BRComponent.scss +1 -1
- package/src/css/_BRmain.scss +19 -24
- package/src/css/_BRnav.scss +4 -26
- package/src/css/_BRpages.scss +35 -0
- package/src/css/_BRsearch.scss +11 -215
- package/src/css/_TextSelection.scss +14 -17
- package/src/css/_colorbox.scss +2 -2
- package/src/css/_controls.scss +16 -3
- package/src/css/_icons.scss +6 -0
- package/src/ia-bookreader/ia-bookreader.js +224 -0
- package/src/plugins/plugin.chapters.js +26 -33
- package/src/plugins/plugin.mobile_nav.js +11 -10
- package/src/plugins/plugin.resume.js +3 -3
- package/src/plugins/plugin.text_selection.js +26 -39
- package/src/plugins/plugin.vendor-fullscreen.js +4 -4
- package/src/plugins/search/plugin.search.js +106 -107
- package/src/plugins/search/view.js +50 -163
- package/src/plugins/tts/AbstractTTSEngine.js +46 -37
- package/src/plugins/tts/FestivalTTSEngine.js +12 -13
- package/src/plugins/tts/PageChunk.js +15 -21
- package/src/plugins/tts/PageChunkIterator.js +8 -12
- package/src/plugins/tts/WebTTSEngine.js +64 -68
- package/src/plugins/tts/plugin.tts.js +79 -108
- package/src/plugins/url/UrlPlugin.js +184 -0
- package/src/plugins/{plugin.url.js → url/plugin.url.js} +28 -6
- package/tests/e2e/README.md +37 -0
- package/tests/e2e/autoplay.test.js +2 -2
- package/tests/e2e/base.test.js +7 -7
- package/tests/e2e/helpers/base.js +8 -3
- package/tests/e2e/helpers/debug.js +1 -1
- package/tests/e2e/helpers/desktopSearch.js +14 -13
- package/tests/e2e/helpers/mobileSearch.js +3 -3
- package/tests/e2e/helpers/params.js +17 -0
- package/tests/e2e/models/Navigation.js +12 -3
- package/tests/e2e/rightToLeft.test.js +4 -5
- package/tests/e2e/viewmode.test.js +38 -33
- package/tests/{BookReader → jest/BookReader}/BookModel.test.js +3 -3
- package/tests/jest/BookReader/BookReaderPublicFunctions.test.js +176 -0
- package/tests/{BookReader → jest/BookReader}/DebugConsole.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/ImageCache.test.js +4 -4
- package/tests/jest/BookReader/Mode1UpLit.test.js +88 -0
- package/tests/{BookReader → jest/BookReader}/Mode2Up.test.js +5 -7
- package/tests/jest/BookReader/ModeSmoothZoom.test.js +149 -0
- package/tests/jest/BookReader/ModeThumb.test.js +71 -0
- package/tests/{BookReader → jest/BookReader}/Navbar/Navbar.test.js +7 -7
- package/tests/{BookReader → jest/BookReader}/PageContainer.test.js +79 -6
- package/tests/{BookReader → jest/BookReader}/ReduceSet.test.js +1 -1
- package/tests/{BookReader → jest/BookReader}/Toolbar/Toolbar.test.js +2 -2
- package/tests/jest/BookReader/utils/HTMLDimensionsCacher.test.js +59 -0
- package/tests/jest/BookReader/utils/ScrollClassAdder.test.js +49 -0
- package/tests/{BookReader → jest/BookReader}/utils/classes.test.js +1 -1
- package/tests/jest/BookReader/utils.test.js +136 -0
- package/tests/jest/BookReader.keyboard.test.js +190 -0
- package/tests/{BookReader.options.test.js → jest/BookReader.options.test.js} +9 -1
- package/tests/{BookReader.test.js → jest/BookReader.test.js} +20 -4
- package/tests/{plugins → jest/plugins}/plugin.archive_analytics.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.autoplay.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.chapters.test.js +8 -8
- package/tests/{plugins → jest/plugins}/plugin.iframe.test.js +2 -2
- package/tests/{plugins → jest/plugins}/plugin.mobile_nav.test.js +5 -5
- package/tests/{plugins → jest/plugins}/plugin.resume.test.js +3 -3
- package/tests/{plugins → jest/plugins}/plugin.text_selection.test.js +39 -47
- package/tests/{plugins → jest/plugins}/plugin.vendor-fullscreen.test.js +2 -2
- package/tests/{plugins → jest/plugins}/search/plugin.search.test.js +24 -25
- package/tests/{plugins → jest/plugins}/search/plugin.search.view.test.js +6 -6
- package/tests/{plugins → jest/plugins}/tts/AbstractTTSEngine.test.js +6 -6
- 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 +1 -1
- package/tests/{plugins → jest/plugins}/tts/utils.test.js +3 -3
- package/tests/jest/plugins/url/UrlPlugin.test.js +190 -0
- package/tests/{plugins → jest/plugins/url}/plugin.url.test.js +33 -14
- package/tests/{util → jest/util}/browserSniffing.test.js +1 -1
- package/tests/{util → jest/util}/docCookies.test.js +1 -1
- package/tests/{util → jest/util}/strings.test.js +1 -1
- package/tests/{utils.js → jest/utils.js} +38 -0
- package/tests/karma/BookNavigator/book-navigator.test.js +501 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-button.test.js +44 -0
- package/tests/karma/BookNavigator/bookmarks/bookmark-edit.test.js +1 -3
- package/tests/karma/BookNavigator/bookmarks/bookmarks-list.test.js +3 -4
- package/tests/karma/BookNavigator/bookmarks/ia-bookmarks.test.js +57 -0
- package/tests/karma/BookNavigator/downloads/downloads-provider.test.js +67 -0
- package/tests/karma/BookNavigator/downloads/downloads.test.js +54 -0
- package/tests/karma/BookNavigator/search/search-provider.test.js +123 -0
- package/tests/karma/BookNavigator/{search-results.test.js → search/search-results.test.js} +1 -4
- package/tests/karma/BookNavigator/sharing/sharing-provider.test.js +49 -0
- package/tests/karma/BookNavigator/visual-adjustments.test.js +0 -2
- package/tests/karma/BookNavigator/volumes/volumes-provider.test.js +184 -0
- package/tests/karma/BookNavigator/volumes/volumes.test.js +98 -0
- package/webpack.config.js +10 -4
- 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.map +0 -1
- package/BookReader/plugins/plugin.menu_toggle.js +0 -2
- package/BookReader/plugins/plugin.menu_toggle.js.map +0 -1
- package/BookReaderDemo/bookreader-template-bundle.js +0 -7178
- package/BookReaderDemo/demo-plugin-menu-toggle.html +0 -34
- package/src/BookNavigator/BookModel.js +0 -14
- package/src/BookNavigator/BookNavigator.js +0 -435
- package/src/BookNavigator/assets/book-loader.js +0 -27
- package/src/BookNavigator/br-fullscreen-mgr.js +0 -83
- package/src/BookReaderComponent/BookReaderComponent.js +0 -112
- package/src/ItemNavigator/ItemNavigator.js +0 -372
- package/src/ItemNavigator/providers/sharing.js +0 -29
- package/src/dragscrollable-br.js +0 -261
- package/src/plugins/menu_toggle/plugin.menu_toggle.js +0 -324
- package/tests/BookReader/BookReaderPublicFunctions.test.js +0 -171
- package/tests/BookReader/Mode1Up.test.js +0 -164
- package/tests/BookReader/utils.test.js +0 -109
- package/tests/plugins/menu_toggle/plugin.menu_toggle.test.js +0 -68
@@ -1,5 +1,6 @@
|
|
1
|
-
import {
|
2
|
-
|
1
|
+
import { LitElement, html, css, render } from 'lit';
|
2
|
+
// eslint-disable-next-line no-unused-vars
|
3
|
+
import { ModalConfig, ModalManager } from '@internetarchive/modal-manager';
|
3
4
|
import buttonStyles from '../assets/button-base.js';
|
4
5
|
import './bookmarks-loginCTA.js';
|
5
6
|
|
@@ -57,9 +58,11 @@ class IABookmarks extends LitElement {
|
|
57
58
|
activeBookmarkID: { type: String },
|
58
59
|
bookmarks: { type: Array },
|
59
60
|
bookreader: { type: Object },
|
60
|
-
options: { type: Object },
|
61
61
|
displayMode: { type: String },
|
62
62
|
editedBookmark: { type: Object },
|
63
|
+
deleteModalConfig: { type: Object},
|
64
|
+
modal: { attribute: false },
|
65
|
+
loginOptions: { type: Object, attribute: false }
|
63
66
|
};
|
64
67
|
}
|
65
68
|
|
@@ -92,7 +95,12 @@ class IABookmarks extends LitElement {
|
|
92
95
|
this.bookmarks = [];
|
93
96
|
this.bookreader = {};
|
94
97
|
this.editedBookmark = {};
|
95
|
-
|
98
|
+
/** @type {ModalManager} */
|
99
|
+
this.modal = undefined;
|
100
|
+
this.loginOptions = {
|
101
|
+
loginClicked: () => {},
|
102
|
+
loginUrl: '',
|
103
|
+
};
|
96
104
|
/**
|
97
105
|
* Toggles display to either bookmarks or login cta
|
98
106
|
* @param {('bookmarks'|'login')} displayMode
|
@@ -113,21 +121,45 @@ class IABookmarks extends LitElement {
|
|
113
121
|
// eslint-disable-next-line
|
114
122
|
this.defaultColor = this.bookmarkColors[0];
|
115
123
|
this.api = api;
|
124
|
+
this.deleteModalConfig = new ModalConfig({
|
125
|
+
title: 'Delete Bookmark',
|
126
|
+
headline: 'This bookmark contains a note. Deleting it will permanently delete the note. Are you sure?',
|
127
|
+
headerColor: '#194880',
|
128
|
+
});
|
116
129
|
}
|
117
130
|
|
118
|
-
updated() {
|
131
|
+
updated(changed) {
|
132
|
+
if (changed.has('displayMode')) {
|
133
|
+
this.updateDisplay();
|
134
|
+
}
|
135
|
+
|
119
136
|
this.emitBookmarksChanged();
|
120
137
|
}
|
121
138
|
|
122
139
|
setup() {
|
123
140
|
this.api.identifier = this.bookreader.bookId;
|
124
|
-
this.
|
125
|
-
|
126
|
-
|
141
|
+
if (this.displayMode === 'login') {
|
142
|
+
return;
|
143
|
+
}
|
144
|
+
this.fetchUserBookmarks();
|
145
|
+
this.setBREventListeners();
|
127
146
|
}
|
128
147
|
|
129
|
-
|
130
|
-
this.displayMode
|
148
|
+
updateDisplay() {
|
149
|
+
if (this.displayMode === 'bookmarks') {
|
150
|
+
this.fetchUserBookmarks();
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
async fetchUserBookmarks() {
|
155
|
+
if (!this.api.identifier) {
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
await this.fetchBookmarks();
|
159
|
+
this.initializeBookmarks();
|
160
|
+
}
|
161
|
+
|
162
|
+
setBREventListeners() {
|
131
163
|
['3PageViewSelected'].forEach((event) => {
|
132
164
|
window.addEventListener(`BookReader:${event}`, (e) => {
|
133
165
|
setTimeout(() => {
|
@@ -147,12 +179,12 @@ class IABookmarks extends LitElement {
|
|
147
179
|
});
|
148
180
|
['zoomOut', 'zoomIn', 'resize'].forEach((event) => {
|
149
181
|
window.addEventListener(`BookReader:${event}`, () => {
|
150
|
-
|
151
|
-
this.renderBookmarkButtons();
|
152
|
-
}
|
182
|
+
this.renderBookmarkButtons();
|
153
183
|
});
|
154
184
|
});
|
185
|
+
}
|
155
186
|
|
187
|
+
initializeBookmarks() {
|
156
188
|
this.renderBookmarkButtons();
|
157
189
|
this.markActiveBookmark(true);
|
158
190
|
this.emitBookmarksChanged();
|
@@ -194,27 +226,35 @@ class IABookmarks extends LitElement {
|
|
194
226
|
return bookmark;
|
195
227
|
}
|
196
228
|
|
197
|
-
fetchBookmarks() {
|
198
|
-
|
229
|
+
async fetchBookmarks() {
|
230
|
+
const resText = await this.api.getAll().then(r=> r.text());
|
231
|
+
let parsedResponse;
|
232
|
+
try {
|
233
|
+
parsedResponse = JSON.parse(resText);
|
234
|
+
} catch (e) {
|
235
|
+
parsedResponse = {error : e.message};
|
236
|
+
}
|
237
|
+
|
238
|
+
const {
|
199
239
|
success,
|
200
240
|
error = 'Something happened while fetching bookmarks.',
|
201
241
|
value: bkmrks = [],
|
202
|
-
}
|
203
|
-
if (!success) {
|
204
|
-
throw new Error(`Failed to load bookmarks: ${error}`);
|
205
|
-
}
|
242
|
+
} = parsedResponse;
|
206
243
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
const formattedLeafNum = parseInt(leafNum, 10);
|
211
|
-
const formattedBookmark = this.formatBookmark({ ...bookmark, leafNum: formattedLeafNum });
|
212
|
-
bookmarks[leafNum] = formattedBookmark;
|
213
|
-
});
|
244
|
+
if (!success) {
|
245
|
+
console?.warn('Error fetching bookmarks', error);
|
246
|
+
}
|
214
247
|
|
215
|
-
|
216
|
-
|
248
|
+
const bookmarks = {};
|
249
|
+
Object.keys(bkmrks).forEach((leafNum) => {
|
250
|
+
const bookmark = bkmrks[leafNum];
|
251
|
+
const formattedLeafNum = parseInt(leafNum, 10);
|
252
|
+
const formattedBookmark = this.formatBookmark({ ...bookmark, leafNum: formattedLeafNum });
|
253
|
+
bookmarks[leafNum] = formattedBookmark;
|
217
254
|
});
|
255
|
+
|
256
|
+
this.bookmarks = bookmarks;
|
257
|
+
return bookmarks;
|
218
258
|
}
|
219
259
|
|
220
260
|
emitBookmarksChanged() {
|
@@ -250,7 +290,9 @@ class IABookmarks extends LitElement {
|
|
250
290
|
|
251
291
|
pages.forEach((pageEl) => {
|
252
292
|
const existingButton = pageEl.querySelector('.bookmark-button');
|
253
|
-
if (existingButton) {
|
293
|
+
if (existingButton) {
|
294
|
+
existingButton.remove();
|
295
|
+
}
|
254
296
|
const pageID = +pageEl.classList.value.match(/pagediv\d+/)[0].replace(/\D/g, '');
|
255
297
|
const pageBookmark = this.getBookmark(pageID);
|
256
298
|
const bookmarkState = pageBookmark ? 'filled' : 'hollow';
|
@@ -390,33 +432,26 @@ class IABookmarks extends LitElement {
|
|
390
432
|
confirmDeletion(pageID) {
|
391
433
|
const existingBookmark = this.getBookmark(pageID);
|
392
434
|
if (existingBookmark.note) {
|
393
|
-
this.
|
435
|
+
this.displayDeletionModal(pageID);
|
394
436
|
return;
|
395
437
|
}
|
396
438
|
this.deleteBookmark({ detail: { id: `${pageID}` } });
|
397
439
|
}
|
398
440
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
.cancelAction=${() => this.emitCloseModal()}
|
408
|
-
.pageID=${pageID}
|
409
|
-
></delete-modal-actions>
|
410
|
-
`,
|
411
|
-
},
|
412
|
-
}));
|
413
|
-
}
|
441
|
+
displayDeletionModal(pageID) {
|
442
|
+
const customModalContent = html`
|
443
|
+
<delete-modal-actions
|
444
|
+
.deleteAction=${() => this.deleteBookmark({ detail: { id: `${pageID}` } })}
|
445
|
+
.cancelAction=${() => this.modal.closeModal()}
|
446
|
+
.pageID=${pageID}
|
447
|
+
></delete-modal-actions>
|
448
|
+
`;
|
414
449
|
|
415
|
-
|
416
|
-
this.
|
417
|
-
|
418
|
-
|
419
|
-
})
|
450
|
+
|
451
|
+
this.modal.showModal({
|
452
|
+
config: this.deleteModalConfig,
|
453
|
+
customModalContent,
|
454
|
+
});
|
420
455
|
}
|
421
456
|
|
422
457
|
deleteBookmark({ detail }) {
|
@@ -427,18 +462,10 @@ class IABookmarks extends LitElement {
|
|
427
462
|
|
428
463
|
this.api.delete(detail.id);
|
429
464
|
this.editedBookmark = {};
|
430
|
-
this.
|
465
|
+
this.modal.closeModal();
|
431
466
|
this.renderBookmarkButtons();
|
432
467
|
}
|
433
468
|
|
434
|
-
/**
|
435
|
-
* call `loginClicked` callback
|
436
|
-
*/
|
437
|
-
loginClick() {
|
438
|
-
const { loginClicked = () => {} } = this.options;
|
439
|
-
loginClicked();
|
440
|
-
}
|
441
|
-
|
442
469
|
/**
|
443
470
|
* Tells us if we should allow user to add bookmark via menu panel
|
444
471
|
* returns { Boolean }
|
@@ -460,6 +487,7 @@ class IABookmarks extends LitElement {
|
|
460
487
|
return html`
|
461
488
|
<button
|
462
489
|
class="ia-button primary"
|
490
|
+
tabindex="-1"
|
463
491
|
?disabled=${this.shouldEnableAddBookmarkButton}
|
464
492
|
@click=${this.addBookmark}>
|
465
493
|
Add bookmark
|
@@ -483,15 +511,23 @@ class IABookmarks extends LitElement {
|
|
483
511
|
`;
|
484
512
|
}
|
485
513
|
|
514
|
+
get bookmarkHelperMessage() {
|
515
|
+
return html`<p>Please use 1up or 2up view modes to add bookmark.</p>`;
|
516
|
+
}
|
517
|
+
|
486
518
|
render() {
|
487
|
-
const { loginUrl } = this.options;
|
488
519
|
const bookmarks = html`
|
489
520
|
${this.bookmarksList}
|
490
|
-
${this.allowAddingBookmark ? this.addBookmarkButton :
|
521
|
+
${this.allowAddingBookmark ? this.addBookmarkButton : this.bookmarkHelperMessage}
|
491
522
|
`;
|
492
523
|
return html`
|
493
524
|
<section class="bookmarks">
|
494
|
-
|
525
|
+
${ this.displayMode === 'login'
|
526
|
+
? html`<bookmarks-login
|
527
|
+
@click=${() => this.loginOptions.loginClicked()}
|
528
|
+
.url=${this.loginOptions.loginUrl}></bookmarks-login>`
|
529
|
+
: bookmarks
|
530
|
+
}
|
495
531
|
</section>
|
496
532
|
`;
|
497
533
|
}
|
@@ -1,10 +1,7 @@
|
|
1
|
-
import { html } from 'lit
|
1
|
+
import { html } from 'lit';
|
2
|
+
import '@internetarchive/icon-dl/icon-dl';
|
3
|
+
import './downloads';
|
2
4
|
|
3
|
-
/* register subpanel */
|
4
|
-
import { IABookDownloads } from './downloads';
|
5
|
-
customElements.define('ia-book-downloads', IABookDownloads);
|
6
|
-
|
7
|
-
let downloads = [];
|
8
5
|
const menuBase = {
|
9
6
|
pdf: {
|
10
7
|
type: 'Encrypted Adobe PDF',
|
@@ -18,25 +15,33 @@ const menuBase = {
|
|
18
15
|
}
|
19
16
|
};
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
const publicMenuBase = {
|
19
|
+
pdf: "PDF",
|
20
|
+
epub: "ePub"
|
21
|
+
};
|
22
|
+
|
23
|
+
export default class DownloadsProvider {
|
24
|
+
|
25
|
+
constructor({ bookreader }) {
|
26
|
+
this.icon = html`<ia-icon-dl style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-dl>`;
|
24
27
|
this.label = 'Downloadable files';
|
25
28
|
this.menuDetails = '';
|
29
|
+
this.downloads = [];
|
26
30
|
this.id = 'downloads';
|
27
31
|
this.component = '';
|
32
|
+
this.isBookProtected = bookreader?.options?.isProtected || false;
|
28
33
|
|
29
34
|
this.computeAvailableTypes = this.computeAvailableTypes.bind(this);
|
30
35
|
this.update = this.update.bind(this);
|
31
36
|
}
|
32
37
|
|
33
|
-
|
34
38
|
update(downloadTypes) {
|
35
39
|
this.computeAvailableTypes(downloadTypes);
|
36
40
|
this.component = this.menu;
|
41
|
+
this.component.isBookProtected = this.isBookProtected;
|
37
42
|
|
38
|
-
const ending = downloads.length === 1 ? '' : 's';
|
39
|
-
this.menuDetails = `(${downloads.length} format${ending})`;
|
43
|
+
const ending = this.downloads.length === 1 ? '' : 's';
|
44
|
+
this.menuDetails = `(${this.downloads.length} format${ending})`;
|
40
45
|
}
|
41
46
|
|
42
47
|
/**
|
@@ -45,22 +50,23 @@ export default class {
|
|
45
50
|
* @param availableTypes
|
46
51
|
*/
|
47
52
|
computeAvailableTypes(availableTypes = []) {
|
48
|
-
const menuData = availableTypes.reduce((found, incoming = []
|
53
|
+
const menuData = availableTypes.reduce((found, incoming = []) => {
|
49
54
|
const [ type = '', link = '' ] = incoming;
|
50
55
|
const formattedType = type.toLowerCase();
|
51
56
|
const downloadOption = menuBase[formattedType] || null;
|
57
|
+
|
52
58
|
if (downloadOption) {
|
53
|
-
const
|
59
|
+
const menuButtonText = this.isBookProtected ? menuBase[formattedType].type : publicMenuBase[formattedType];
|
60
|
+
const menuInfo = Object.assign({}, downloadOption, { url: link, type: menuButtonText});
|
54
61
|
found.push(menuInfo);
|
55
62
|
}
|
56
63
|
return found;
|
57
64
|
}, []);
|
58
65
|
|
59
|
-
downloads = menuData;
|
66
|
+
this.downloads = menuData;
|
60
67
|
}
|
61
68
|
|
62
|
-
|
63
69
|
get menu () {
|
64
|
-
return html`<ia-book-downloads .downloads=${downloads}></ia-book-downloads>`;
|
70
|
+
return html`<ia-book-downloads .downloads=${this.downloads}></ia-book-downloads>`;
|
65
71
|
}
|
66
72
|
}
|
@@ -1,11 +1,12 @@
|
|
1
|
-
import { css, html, LitElement } from 'lit
|
2
|
-
import
|
1
|
+
import { css, html, LitElement, nothing } from 'lit';
|
2
|
+
import buttonStyles from '../assets/button-base.js';
|
3
3
|
export class IABookDownloads extends LitElement {
|
4
4
|
static get properties() {
|
5
5
|
return {
|
6
6
|
downloads: { type: Array },
|
7
7
|
expiration: { type: Number },
|
8
8
|
renderHeader: { type: Boolean },
|
9
|
+
isBookProtected: { type: Boolean },
|
9
10
|
};
|
10
11
|
}
|
11
12
|
|
@@ -14,6 +15,7 @@ export class IABookDownloads extends LitElement {
|
|
14
15
|
this.downloads = [];
|
15
16
|
this.expiration = 0;
|
16
17
|
this.renderHeader = false;
|
18
|
+
this.isBookProtected = false;
|
17
19
|
}
|
18
20
|
|
19
21
|
get formatsCount() {
|
@@ -31,7 +33,7 @@ export class IABookDownloads extends LitElement {
|
|
31
33
|
return this.downloads.map(option => (
|
32
34
|
html`
|
33
35
|
<li>
|
34
|
-
<a class="button" href="${option.url}">Get ${option.type}</a>
|
36
|
+
<a class="ia-button link primary" href="${option.url}">Get ${option.type}</a>
|
35
37
|
${option.note ? html`<p>${option.note}</p>` : html``}
|
36
38
|
</li>
|
37
39
|
`
|
@@ -50,18 +52,24 @@ export class IABookDownloads extends LitElement {
|
|
50
52
|
`;
|
51
53
|
}
|
52
54
|
|
55
|
+
get accessProtectedBook() {
|
56
|
+
return html`
|
57
|
+
<p>To access downloaded books, you need Adobe-compliant software on your device. The Internet Archive will administer this loan, but Adobe may also collect some information.</p>
|
58
|
+
<a class="ia-button external primary" href="https://www.adobe.com/solutions/ebook/digital-editions/download.html" rel="noopener noreferrer" target="_blank">Install Adobe Digital Editions</a>
|
59
|
+
`;
|
60
|
+
}
|
61
|
+
|
53
62
|
render() {
|
54
63
|
return html`
|
55
64
|
${this.header}
|
56
65
|
${this.loanExpiryMessage}
|
57
66
|
<ul>${this.renderDownloadOptions()}</ul>
|
58
|
-
|
59
|
-
<a class="button external" href="https://www.adobe.com/solutions/ebook/digital-editions/download.html" rel="noopener noreferrer" target="_blank">Install Adobe Digital Editions</a>
|
67
|
+
${this.isBookProtected ? this.accessProtectedBook : nothing}
|
60
68
|
`;
|
61
69
|
}
|
62
70
|
|
63
71
|
static get styles() {
|
64
|
-
|
72
|
+
const mainCss = css`
|
65
73
|
:host {
|
66
74
|
display: block;
|
67
75
|
height: 100%;
|
@@ -79,24 +87,6 @@ export class IABookDownloads extends LitElement {
|
|
79
87
|
justify-self: end;
|
80
88
|
}
|
81
89
|
|
82
|
-
.button {
|
83
|
-
color: var(--primaryTextColor);
|
84
|
-
background: var(--primaryCTAFill);
|
85
|
-
border: 1px solid var(--primaryCTABorder);
|
86
|
-
display: inline-block;
|
87
|
-
padding: .6rem 1rem;
|
88
|
-
font-size: 1.4rem;
|
89
|
-
text-decoration: none;
|
90
|
-
text-shadow: 1px 1px #484848;
|
91
|
-
border-radius: 4px;
|
92
|
-
}
|
93
|
-
|
94
|
-
.button.external {
|
95
|
-
background: var(--secondaryCTAFill, transparent);
|
96
|
-
border: 1px solid var(--secondaryCTABorder, #999);
|
97
|
-
text-shadow: none;
|
98
|
-
}
|
99
|
-
|
100
90
|
header {
|
101
91
|
display: flex;
|
102
92
|
align-items: center;
|
@@ -109,7 +99,6 @@ export class IABookDownloads extends LitElement {
|
|
109
99
|
font-weight: bold;
|
110
100
|
font-style: italic;
|
111
101
|
}
|
112
|
-
|
113
102
|
header div {
|
114
103
|
display: flex;
|
115
104
|
align-items: baseline;
|
@@ -142,5 +131,8 @@ export class IABookDownloads extends LitElement {
|
|
142
131
|
line-height: 140%;
|
143
132
|
}
|
144
133
|
`;
|
134
|
+
|
135
|
+
return [buttonStyles, mainCss];
|
145
136
|
}
|
146
137
|
}
|
138
|
+
customElements.define('ia-book-downloads', IABookDownloads);
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import { nothing } from 'lit
|
2
|
-
import {
|
3
|
-
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
|
1
|
+
import { html, LitElement, nothing } from 'lit';
|
2
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
4
3
|
|
5
4
|
export class BookSearchResult extends LitElement {
|
6
5
|
static get properties() {
|
@@ -52,3 +51,4 @@ export class BookSearchResult extends LitElement {
|
|
52
51
|
`;
|
53
52
|
}
|
54
53
|
}
|
54
|
+
customElements.define('book-search-result', BookSearchResult);
|
@@ -1,9 +1,6 @@
|
|
1
|
-
import { html } from 'lit
|
2
|
-
import
|
3
|
-
|
4
|
-
/* instantiate web component */
|
5
|
-
import { IABookSearchResults } from './search-results';
|
6
|
-
customElements.define('ia-book-search-results', IABookSearchResults);
|
1
|
+
import { html, nothing } from 'lit';
|
2
|
+
import '@internetarchive/icon-search/icon-search';
|
3
|
+
import './search-results';
|
7
4
|
|
8
5
|
let searchState = {
|
9
6
|
query: '',
|
@@ -12,8 +9,11 @@ let searchState = {
|
|
12
9
|
queryInProgress: false,
|
13
10
|
errorMessage: '',
|
14
11
|
};
|
15
|
-
export default class {
|
16
|
-
constructor(
|
12
|
+
export default class SearchProvider {
|
13
|
+
constructor({
|
14
|
+
onProviderChange,
|
15
|
+
bookreader
|
16
|
+
}) {
|
17
17
|
/* search menu events */
|
18
18
|
this.onBookSearchInitiated = this.onBookSearchInitiated.bind(this);
|
19
19
|
/* bookreader search events */
|
@@ -22,6 +22,8 @@ export default class {
|
|
22
22
|
this.onSearchResultsClicked = this.onSearchResultsClicked.bind(this);
|
23
23
|
this.onSearchResultsChange = this.onSearchResultsChange.bind(this);
|
24
24
|
this.onSearchResultsCleared = this.onSearchResultsCleared.bind(this);
|
25
|
+
this.searchCanceledInMenu = this.searchCanceledInMenu.bind(this);
|
26
|
+
|
25
27
|
/* class methods */
|
26
28
|
this.bindEventListeners = this.bindEventListeners.bind(this);
|
27
29
|
this.getMenuDetails = this.getMenuDetails.bind(this);
|
@@ -29,9 +31,9 @@ export default class {
|
|
29
31
|
this.advanceToPage = this.advanceToPage.bind(this);
|
30
32
|
this.updateMenu = this.updateMenu.bind(this);
|
31
33
|
|
32
|
-
this.
|
33
|
-
this.bookreader =
|
34
|
-
this.icon = html`<ia-icon
|
34
|
+
this.onProviderChange = onProviderChange;
|
35
|
+
this.bookreader = bookreader;
|
36
|
+
this.icon = html`<ia-icon-search style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-search>`;
|
35
37
|
this.label = 'Search inside';
|
36
38
|
this.menuDetails = this.getMenuDetails();
|
37
39
|
this.id = 'search';
|
@@ -41,7 +43,7 @@ export default class {
|
|
41
43
|
|
42
44
|
getMenuDetails() {
|
43
45
|
const { resultsCount, query, queryInProgress } = searchState;
|
44
|
-
if (queryInProgress || !query) { return nothing }
|
46
|
+
if (queryInProgress || !query) { return nothing; }
|
45
47
|
const unit = resultsCount === 1 ? 'result' : 'results';
|
46
48
|
return html`(${resultsCount} ${unit})`;
|
47
49
|
}
|
@@ -49,14 +51,36 @@ export default class {
|
|
49
51
|
bindEventListeners() {
|
50
52
|
window.addEventListener('BookReader:SearchStarted', this.onSearchStarted);
|
51
53
|
window.addEventListener('BookReader:SearchCallback', this.onSearchResultsChange);
|
52
|
-
window.addEventListener('BookReader:SearchCallbackEmpty', (event) => { this.onSearchRequestError(event, 'noResults') });
|
53
|
-
window.addEventListener('BookReader:SearchCallbackNotIndexed', (event) => { this.onSearchRequestError(event, 'notIndexed') });
|
54
|
-
window.addEventListener('BookReader:SearchCallbackError', (event) => { this.onSearchRequestError(event) });
|
55
|
-
window.addEventListener('BookReader:SearchResultsCleared', () => { this.onSearchResultsCleared() });
|
54
|
+
window.addEventListener('BookReader:SearchCallbackEmpty', (event) => { this.onSearchRequestError(event, 'noResults'); });
|
55
|
+
window.addEventListener('BookReader:SearchCallbackNotIndexed', (event) => { this.onSearchRequestError(event, 'notIndexed'); });
|
56
|
+
window.addEventListener('BookReader:SearchCallbackError', (event) => { this.onSearchRequestError(event); });
|
57
|
+
window.addEventListener('BookReader:SearchResultsCleared', () => { this.onSearchResultsCleared(); });
|
58
|
+
window.addEventListener('BookReader:SearchCanceled', (e) => { this.onSearchCanceled(e); });
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Cancel search handler
|
63
|
+
* resets `searchState`
|
64
|
+
*/
|
65
|
+
onSearchCanceled() {
|
66
|
+
searchState = {
|
67
|
+
query: '',
|
68
|
+
results: [],
|
69
|
+
resultsCount: 0,
|
70
|
+
queryInProgress: false,
|
71
|
+
errorMessage: '',
|
72
|
+
};
|
73
|
+
const updateMenuFor = {
|
74
|
+
searchCanceled: true
|
75
|
+
};
|
76
|
+
this.updateMenu(updateMenuFor);
|
56
77
|
}
|
57
78
|
|
58
79
|
onSearchStarted(e) {
|
59
|
-
const { term = '' } = e.detail.props;
|
80
|
+
const { term = '', instance } = e.detail.props;
|
81
|
+
if (instance) {
|
82
|
+
this.bookreader = instance;
|
83
|
+
}
|
60
84
|
searchState.query = term;
|
61
85
|
searchState.results = [];
|
62
86
|
searchState.resultsCount = 0;
|
@@ -81,10 +105,11 @@ export default class {
|
|
81
105
|
noResults: '0 results',
|
82
106
|
notIndexed: `This book hasn't been indexed for searching yet. We've just started indexing it,
|
83
107
|
so search should be available soon. Please try again later. Thanks!`,
|
84
|
-
default: 'Sorry, there was an error with your search.
|
108
|
+
default: 'Sorry, there was an error with your search. Please try again.',
|
85
109
|
};
|
86
110
|
|
87
111
|
const messageToShow = errorMessages[errorType] ?? errorMessages.default;
|
112
|
+
searchState.query = instance?.searchResults?.q || '';
|
88
113
|
searchState.results = [];
|
89
114
|
searchState.resultsCount = 0;
|
90
115
|
searchState.queryInProgress = false;
|
@@ -106,6 +131,10 @@ export default class {
|
|
106
131
|
this.updateMenu();
|
107
132
|
}
|
108
133
|
|
134
|
+
searchCanceledInMenu() {
|
135
|
+
this.bookreader?.cancelSearchRequest();
|
136
|
+
}
|
137
|
+
|
109
138
|
onSearchResultsCleared() {
|
110
139
|
searchState = {
|
111
140
|
query: '',
|
@@ -113,15 +142,19 @@ export default class {
|
|
113
142
|
resultsCount: 0,
|
114
143
|
queryInProgress: false,
|
115
144
|
errorMessage: '',
|
116
|
-
}
|
117
|
-
this.updateMenu();
|
118
|
-
this.bookreader?.searchView?.clearSearchFieldAndResults();
|
145
|
+
};
|
146
|
+
this.updateMenu({ openMenu: false });
|
147
|
+
this.bookreader?.searchView?.clearSearchFieldAndResults(false);
|
119
148
|
}
|
120
149
|
|
121
|
-
|
150
|
+
/**
|
151
|
+
* Relays how to update side menu given the context of a search update
|
152
|
+
@param {{searchCanceled: boolean}} searchUpdates
|
153
|
+
*/
|
154
|
+
updateMenu(searchUpdates = {}) {
|
122
155
|
this.menuDetails = this.getMenuDetails();
|
123
156
|
this.component = this.getComponent();
|
124
|
-
this.
|
157
|
+
this.onProviderChange(this.bookreader, searchUpdates);
|
125
158
|
}
|
126
159
|
|
127
160
|
getComponent() {
|
@@ -136,6 +169,7 @@ export default class {
|
|
136
169
|
@resultSelected=${this.onSearchResultsClicked}
|
137
170
|
@bookSearchInitiated=${this.onBookSearchInitiated}
|
138
171
|
@bookSearchResultsCleared=${this.onSearchResultsCleared}
|
172
|
+
@bookSearchCanceled=${this.searchCanceledInMenu}
|
139
173
|
></ia-book-search-results>
|
140
174
|
`;
|
141
175
|
}
|
@@ -148,6 +182,5 @@ export default class {
|
|
148
182
|
advanceToPage(leaf) {
|
149
183
|
const page = this.bookreader.leafNumToIndex(leaf);
|
150
184
|
this.bookreader._searchPluginGoToResult(page);
|
151
|
-
this.bookreader.updateSearchHilites();
|
152
185
|
}
|
153
186
|
}
|