@internetarchive/bookreader 5.0.0-48 → 5.0.0-48-alpha1
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/BookReader/BookReader.js +1 -1
- package/BookReader/BookReader.js.map +1 -1
- package/BookReader/ia-bookreader-bundle.js +89 -89
- package/BookReader/ia-bookreader-bundle.js.map +1 -1
- package/BookReaderDemo/IADemoBr.js +0 -2
- package/CHANGELOG.md +0 -4
- package/package.json +1 -1
- package/src/BookNavigator/book-navigator.js +2 -2
- package/src/BookNavigator/downloads/downloads-provider.js +9 -41
- package/src/BookNavigator/downloads/downloads.js +83 -47
- package/src/BookNavigator/volumes/volumes-provider.js +1 -1
- package/tests/jest/BookNavigator/book-navigator.test.js +15 -19
- package/src/util/manifestGenerator.js +0 -0
@@ -82,8 +82,6 @@ const initializeBookReader = (brManifest) => {
|
|
82
82
|
// we expect this at the global level
|
83
83
|
BookReaderJSIAinit(brManifest.data, options);
|
84
84
|
|
85
|
-
const isRestricted = brManifest.data.isRestricted;
|
86
|
-
window.dispatchEvent(new CustomEvent('contextmenu', { detail: { isRestricted } }));
|
87
85
|
if (customAutoflipParams.autoflip) {
|
88
86
|
br.autoToggle(customAutoflipParams);
|
89
87
|
}
|
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
@@ -449,10 +449,10 @@ export class BookNavigator extends LitElement {
|
|
449
449
|
/** Display an element's context menu */
|
450
450
|
manageContextMenuVisibility(e) {
|
451
451
|
if (window.archive_analytics) {
|
452
|
-
window.archive_analytics?.
|
452
|
+
window.archive_analytics?.send_event_no_sampling(
|
453
453
|
'BookReader',
|
454
454
|
`contextmenu-${this.bookIsRestricted ? 'restricted' : 'unrestricted'}`,
|
455
|
-
e.target
|
455
|
+
e.target.classList.value
|
456
456
|
);
|
457
457
|
}
|
458
458
|
if (!this.bookIsRestricted) {
|
@@ -2,41 +2,11 @@ import { html } from 'lit';
|
|
2
2
|
import '@internetarchive/icon-dl/icon-dl';
|
3
3
|
import './downloads';
|
4
4
|
|
5
|
-
const menuBase = {
|
6
|
-
pdf: {
|
7
|
-
type: 'Encrypted Adobe PDF',
|
8
|
-
url: '#',
|
9
|
-
note: 'PDF files contain high quality images of pages.',
|
10
|
-
},
|
11
|
-
lcppdf: {
|
12
|
-
type: 'Get LCP PDF',
|
13
|
-
url: '#',
|
14
|
-
note: 'PDF files contain high quality images of pages.',
|
15
|
-
},
|
16
|
-
lcpepub: {
|
17
|
-
type: 'Get LCP ePub',
|
18
|
-
url: '#',
|
19
|
-
note: 'ePub files are smaller in size, but may contain errors.',
|
20
|
-
},
|
21
|
-
epub: {
|
22
|
-
type: 'Encrypted Adobe ePub',
|
23
|
-
url: '#',
|
24
|
-
note: 'ePub files are smaller in size, but may contain errors.',
|
25
|
-
},
|
26
|
-
};
|
27
|
-
|
28
|
-
const publicMenuBase = {
|
29
|
-
pdf: "PDF",
|
30
|
-
epub: "ePub",
|
31
|
-
lcppdf: "LCP PDF",
|
32
|
-
lcpepub: "LCP ePub",
|
33
|
-
};
|
34
|
-
|
35
5
|
export default class DownloadsProvider {
|
36
6
|
|
37
7
|
constructor({ bookreader }) {
|
38
8
|
this.icon = html`<ia-icon-dl style="width: var(--iconWidth); height: var(--iconHeight);"></ia-icon-dl>`;
|
39
|
-
this.label = '
|
9
|
+
this.label = 'Read offline';
|
40
10
|
this.menuDetails = '';
|
41
11
|
this.downloads = [];
|
42
12
|
this.id = 'downloads';
|
@@ -54,23 +24,21 @@ export default class DownloadsProvider {
|
|
54
24
|
}
|
55
25
|
|
56
26
|
/**
|
57
|
-
*
|
58
|
-
*
|
27
|
+
* Restructures available download type data for the renderer
|
28
|
+
* Sets global `downloads`
|
59
29
|
* @param availableTypes
|
60
30
|
*/
|
61
31
|
computeAvailableTypes(availableTypes = []) {
|
62
32
|
const menuData = availableTypes.reduce((found, incoming = []) => {
|
63
33
|
const [ type = '', link = '' ] = incoming;
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
const menuButtonText = this.isBookProtected ? menuBase[formattedType].type : publicMenuBase[formattedType];
|
69
|
-
const menuInfo = Object.assign({}, downloadOption, { url: link, type: menuButtonText});
|
70
|
-
found.push(menuInfo);
|
34
|
+
if (!type) return found;
|
35
|
+
let formattedType = type.toLowerCase();
|
36
|
+
if ((formattedType === 'pdf' || formattedType === 'epub') && this.isBookProtected) {
|
37
|
+
formattedType = `adobe${formattedType}`;
|
71
38
|
}
|
39
|
+
found[formattedType] = link;
|
72
40
|
return found;
|
73
|
-
},
|
41
|
+
}, {});
|
74
42
|
|
75
43
|
this.downloads = menuData;
|
76
44
|
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { css, html, LitElement, nothing } from 'lit';
|
2
2
|
import buttonStyles from '../assets/button-base.js';
|
3
|
+
|
3
4
|
export class IABookDownloads extends LitElement {
|
4
5
|
static get properties() {
|
5
6
|
return {
|
@@ -18,6 +19,26 @@ export class IABookDownloads extends LitElement {
|
|
18
19
|
this.isBookProtected = false;
|
19
20
|
}
|
20
21
|
|
22
|
+
render() {
|
23
|
+
return html`
|
24
|
+
${this.header}
|
25
|
+
${this.loanExpiryMessage}
|
26
|
+
${this.renderDownloadOptions()}
|
27
|
+
`;
|
28
|
+
}
|
29
|
+
|
30
|
+
get header() {
|
31
|
+
if (!this.renderHeader) {
|
32
|
+
return nothing;
|
33
|
+
}
|
34
|
+
return html`
|
35
|
+
<header>
|
36
|
+
<h3>Read offline</h3>
|
37
|
+
${this.formatsCount}
|
38
|
+
</header>
|
39
|
+
`;
|
40
|
+
}
|
41
|
+
|
21
42
|
get formatsCount() {
|
22
43
|
const count = this.downloads.length;
|
23
44
|
return count ? html`<p>${count} format${count > 1 ? 's' : ''}</p>` : html``;
|
@@ -30,65 +51,80 @@ export class IABookDownloads extends LitElement {
|
|
30
51
|
}
|
31
52
|
|
32
53
|
renderDownloadOptions() {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
`
|
40
|
-
));
|
41
|
-
}
|
42
|
-
|
43
|
-
/**
|
44
|
-
* checks if downloads list contains an LCP option
|
45
|
-
* @return {boolean}
|
46
|
-
*/
|
47
|
-
get hasLCPOption() {
|
48
|
-
const regex = /^(LCP)/g;
|
49
|
-
const lcpAvailable = this.downloads.some(option => option.type?.match(regex));
|
50
|
-
return lcpAvailable;
|
51
|
-
}
|
52
|
-
|
53
|
-
get header() {
|
54
|
-
if (!this.renderHeader) {
|
55
|
-
return nothing;
|
56
|
-
}
|
54
|
+
const downloadOptions = [];
|
55
|
+
['pdf', 'epub', 'lcppdf', 'lcpepub', 'adobepdf', 'adobeepub'].forEach(format => {
|
56
|
+
if (this.downloads[format]) {
|
57
|
+
downloadOptions.push(this.downloadOption(format, this.downloads[format]));
|
58
|
+
}
|
59
|
+
});
|
57
60
|
return html`
|
58
|
-
<
|
59
|
-
|
60
|
-
|
61
|
-
</header>
|
61
|
+
<ul>
|
62
|
+
${downloadOptions}
|
63
|
+
</ul>
|
62
64
|
`;
|
63
65
|
}
|
64
66
|
|
65
|
-
|
67
|
+
downloadOption(format, link) {
|
68
|
+
if (/^adobe/.test(format)) {
|
69
|
+
return html`
|
70
|
+
<li>
|
71
|
+
<a
|
72
|
+
href="${link}"
|
73
|
+
data-event-click-tracking="BookReader|Download-${format}"
|
74
|
+
>${this.menuText[format].linkText}</a>
|
75
|
+
${this.menuText[format].message ?? nothing}
|
76
|
+
</li>
|
77
|
+
`;
|
78
|
+
}
|
66
79
|
return html`
|
67
|
-
<
|
68
|
-
|
80
|
+
<li>
|
81
|
+
<a class="ia-button link primary"
|
82
|
+
href="${link}"
|
83
|
+
data-event-click-tracking="BookReader|Download-${format}"
|
84
|
+
>${this.menuText[format].linkText}</a>
|
85
|
+
${this.menuText[format].message ? html`<p>${this.menuText[format].message}</p>` : nothing}
|
86
|
+
</li>
|
69
87
|
`;
|
70
88
|
}
|
71
89
|
|
72
|
-
get
|
90
|
+
get menuText() {
|
91
|
+
return {
|
92
|
+
pdf: {
|
93
|
+
linkText: 'Get high-resolution PDF',
|
94
|
+
message: html``,
|
95
|
+
},
|
96
|
+
epub: {
|
97
|
+
linkText: 'Get text-based ebook',
|
98
|
+
message: html`Smaller size. May contain some errors.`,
|
99
|
+
},
|
100
|
+
lcppdf: {
|
101
|
+
linkText: 'Get high-resolution PDF',
|
102
|
+
message: this.lcpNote,
|
103
|
+
},
|
104
|
+
lcpepub: {
|
105
|
+
linkText: 'Get text-based ebook',
|
106
|
+
message: html`Smaller size. May contain some errors. ${this.lcpNote}`,
|
107
|
+
},
|
108
|
+
adobepdf: {
|
109
|
+
linkText:'Get legacy Adobe DRM PDF version here.',
|
110
|
+
message: this.adobeNote,
|
111
|
+
},
|
112
|
+
adobeepub: {
|
113
|
+
linkText: 'Get legacy Adobe DRM EPUB version here.',
|
114
|
+
message: this.adobeNote,
|
115
|
+
},
|
116
|
+
};
|
117
|
+
};
|
118
|
+
|
119
|
+
get lcpNote() {
|
73
120
|
return html`
|
74
|
-
|
75
|
-
|
76
|
-
<li><a href="https://librarysimplified.org/simplye/" rel="noopener noreferrer nofollow" target="_blank">Install SimplyE</a></li>
|
77
|
-
<li><a href="https://www.demarque.com/en-aldiko" rel="noopener noreferrer nofollow" target="_blank">Install Aldiko</a></li>
|
78
|
-
<li><a href="https://www.edrlab.org/software/thorium-reader/" rel="noopener noreferrer nofollow" target="_blank">Install Thorium</a></li>
|
79
|
-
</ul>
|
80
|
-
`;
|
121
|
+
Requires having an LCP-compatible e-reader installed like Aldiko Next (<a href="https://apps.apple.com/us/app/aldiko-next/id1476410111">iOS</a>, <a href="https://play.google.com/store/apps/details?id=com.aldiko.android">Android</a>) or <a href="https://www.edrlab.org/software/thorium-reader/">Thorium</a>.
|
122
|
+
`;
|
81
123
|
}
|
82
124
|
|
83
|
-
|
125
|
+
get adobeNote() {
|
84
126
|
return html`
|
85
|
-
|
86
|
-
${this.loanExpiryMessage}
|
87
|
-
<ul>${this.renderDownloadOptions()}</ul>
|
88
|
-
${this.hasLCPOption
|
89
|
-
? this.installSimplyEAldikoThoriumMsg
|
90
|
-
: (this.isBookProtected ? this.accessProtectedBook : nothing)
|
91
|
-
}
|
127
|
+
Requires a compatible e-reader like <a hef="https://www.adobe.com/solutions/ebook/digital-editions.html">Adobe Digital Editions</a>.
|
92
128
|
`;
|
93
129
|
}
|
94
130
|
|
@@ -104,7 +104,7 @@ export default class VolumesProvider {
|
|
104
104
|
if (!window.archive_analytics) {
|
105
105
|
return;
|
106
106
|
}
|
107
|
-
window.archive_analytics?.
|
107
|
+
window.archive_analytics?.send_event_no_sampling(
|
108
108
|
'BookReader',
|
109
109
|
`VolumesSort|${orderBy}`,
|
110
110
|
window.location.path,
|
@@ -46,13 +46,6 @@ window.ResizeObserver = class ResizeObserver {
|
|
46
46
|
disconnect = sinon.fake()
|
47
47
|
};
|
48
48
|
|
49
|
-
beforeEach(() => {
|
50
|
-
window.archive_analytics = {
|
51
|
-
send_event_no_sampling: sinon.fake(),
|
52
|
-
send_event: sinon.fake()
|
53
|
-
};
|
54
|
-
});
|
55
|
-
|
56
49
|
afterEach(() => {
|
57
50
|
window.br = null;
|
58
51
|
fixtureCleanup();
|
@@ -523,6 +516,8 @@ describe('<book-navigator>', () => {
|
|
523
516
|
describe('Handles Restricted Books', () => {
|
524
517
|
describe('contextMenu is prevented when book is restricted', () => {
|
525
518
|
it('watches on `div.BRscreen`', async () => {
|
519
|
+
window.archive_analytics = { send_event_no_sampling: sinon.fake() };
|
520
|
+
|
526
521
|
const el = fixtureSync(container());
|
527
522
|
const brStub = {
|
528
523
|
options: { restricted: true },
|
@@ -534,8 +529,9 @@ describe('<book-navigator>', () => {
|
|
534
529
|
const elSpy = sinon.spy(el.manageContextMenuVisibility);
|
535
530
|
await el.elementUpdated;
|
536
531
|
|
537
|
-
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
538
|
-
|
532
|
+
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
533
|
+
false
|
534
|
+
);
|
539
535
|
expect(elSpy.called).toEqual(false);
|
540
536
|
|
541
537
|
const body = document.querySelector('body');
|
@@ -554,13 +550,14 @@ describe('<book-navigator>', () => {
|
|
554
550
|
|
555
551
|
// analytics fires
|
556
552
|
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
557
|
-
|
553
|
+
true
|
558
554
|
);
|
559
|
-
expect(window.archive_analytics.send_event.called).toEqual(true);
|
560
555
|
// we prevent default
|
561
556
|
expect(preventDefaultSpy.called).toEqual(true);
|
562
557
|
});
|
563
558
|
it('watches on `img.BRpageimage`', async () => {
|
559
|
+
window.archive_analytics = { send_event_no_sampling: sinon.fake() };
|
560
|
+
|
564
561
|
const el = fixtureSync(container());
|
565
562
|
const brStub = {
|
566
563
|
options: { restricted: true },
|
@@ -571,8 +568,9 @@ describe('<book-navigator>', () => {
|
|
571
568
|
|
572
569
|
await el.elementUpdated;
|
573
570
|
|
574
|
-
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
575
|
-
|
571
|
+
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
572
|
+
false
|
573
|
+
);
|
576
574
|
|
577
575
|
const body = document.querySelector('body');
|
578
576
|
// const element stub for img.BRpageimage
|
@@ -588,13 +586,14 @@ describe('<book-navigator>', () => {
|
|
588
586
|
imgBRpageimage.dispatchEvent(contextMenuEvent);
|
589
587
|
|
590
588
|
// analytics fires
|
591
|
-
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
592
|
-
expect(window.archive_analytics.send_event.called).toEqual(true);
|
589
|
+
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(true);
|
593
590
|
// we prevent default
|
594
591
|
expect(preventDefaultSpy.called).toEqual(true);
|
595
592
|
});
|
596
593
|
});
|
597
594
|
it('Allows unrestricted books access to context menu', async () => {
|
595
|
+
window.archive_analytics = { send_event_no_sampling: sinon.fake() };
|
596
|
+
|
598
597
|
const el = fixtureSync(container());
|
599
598
|
const brStub = {
|
600
599
|
options: { restricted: false },
|
@@ -608,8 +607,6 @@ describe('<book-navigator>', () => {
|
|
608
607
|
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
609
608
|
false
|
610
609
|
);
|
611
|
-
expect(window.archive_analytics.send_event.called).toEqual(false);
|
612
|
-
|
613
610
|
|
614
611
|
const body = document.querySelector('body');
|
615
612
|
// const element stub for img.BRpageimage
|
@@ -625,8 +622,7 @@ describe('<book-navigator>', () => {
|
|
625
622
|
imgBRpageimage.dispatchEvent(contextMenuEvent);
|
626
623
|
|
627
624
|
// analytics fires
|
628
|
-
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(
|
629
|
-
expect(window.archive_analytics.send_event.called).toEqual(true);
|
625
|
+
expect(window.archive_analytics.send_event_no_sampling.called).toEqual(true);
|
630
626
|
// we do not prevent default
|
631
627
|
expect(preventDefaultSpy.called).toEqual(false);
|
632
628
|
});
|
File without changes
|