@readium/navigator 1.2.0
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/LICENSE +28 -0
- package/README.MD +11 -0
- package/dist/assets/AccessibleDfA.otf +0 -0
- package/dist/assets/iAWriterDuospace-Regular.ttf +0 -0
- package/dist/index.js +6263 -0
- package/dist/index.umd.cjs +107 -0
- package/package.json +65 -0
- package/src/Navigator.ts +66 -0
- package/src/audio/engine/AudioEngine.ts +136 -0
- package/src/audio/engine/WebAudioEngine.ts +286 -0
- package/src/audio/engine/index.ts +2 -0
- package/src/audio/index.ts +1 -0
- package/src/epub/EpubNavigator.ts +507 -0
- package/src/epub/frame/FrameBlobBuilder.ts +211 -0
- package/src/epub/frame/FrameComms.ts +142 -0
- package/src/epub/frame/FrameManager.ts +134 -0
- package/src/epub/frame/FramePoolManager.ts +179 -0
- package/src/epub/frame/index.ts +3 -0
- package/src/epub/fxl/FXLCoordinator.ts +152 -0
- package/src/epub/fxl/FXLFrameManager.ts +286 -0
- package/src/epub/fxl/FXLFramePoolManager.ts +632 -0
- package/src/epub/fxl/FXLPeripherals.ts +587 -0
- package/src/epub/fxl/FXLPeripheralsDebug.ts +46 -0
- package/src/epub/fxl/FXLSpreader.ts +95 -0
- package/src/epub/fxl/index.ts +5 -0
- package/src/epub/index.ts +3 -0
- package/src/helpers/sML.ts +120 -0
- package/src/index.ts +3 -0
- package/types/src/Navigator.d.ts +41 -0
- package/types/src/audio/engine/AudioEngine.d.ts +114 -0
- package/types/src/audio/engine/WebAudioEngine.d.ts +107 -0
- package/types/src/audio/engine/index.d.ts +2 -0
- package/types/src/audio/index.d.ts +1 -0
- package/types/src/epub/EpubNavigator.d.ts +66 -0
- package/types/src/epub/frame/FrameBlobBuilder.d.ts +13 -0
- package/types/src/epub/frame/FrameComms.d.ts +26 -0
- package/types/src/epub/frame/FrameManager.d.ts +21 -0
- package/types/src/epub/frame/FramePoolManager.d.ts +17 -0
- package/types/src/epub/frame/index.d.ts +3 -0
- package/types/src/epub/fxl/FXLCoordinator.d.ts +37 -0
- package/types/src/epub/fxl/FXLFrameManager.d.ts +41 -0
- package/types/src/epub/fxl/FXLFramePoolManager.d.ts +93 -0
- package/types/src/epub/fxl/FXLPeripherals.d.ts +97 -0
- package/types/src/epub/fxl/FXLPeripheralsDebug.d.ts +13 -0
- package/types/src/epub/fxl/FXLSpreader.d.ts +12 -0
- package/types/src/epub/fxl/index.d.ts +5 -0
- package/types/src/epub/index.d.ts +3 -0
- package/types/src/helpers/sML.d.ts +51 -0
- package/types/src/index.d.ts +3 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Link, Links, Orientation, Page, Publication, ReadingProgression, Spread } from "@readium/shared";
|
|
2
|
+
|
|
3
|
+
export class FXLSpreader {
|
|
4
|
+
shift = true; // TODO getter
|
|
5
|
+
private spreads: Link[][] = [];
|
|
6
|
+
nLandscape: number = 0; // TODO getter
|
|
7
|
+
|
|
8
|
+
constructor(publication: Publication) {
|
|
9
|
+
this.index(publication);
|
|
10
|
+
this.testShift(publication);
|
|
11
|
+
console.log(`Indexed ${this.spreads.length} spreads for ${publication.readingOrder.items.length} items`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private index(publication: Publication, redo = false) {
|
|
15
|
+
this.nLandscape = 0;
|
|
16
|
+
publication.readingOrder.items.forEach((item, index) => {
|
|
17
|
+
// item.Properties.Spread = item.Properties.Spread ? item.Properties.Spread : "landscape"; // TODO Maybe default to auto instead
|
|
18
|
+
if(!redo) {
|
|
19
|
+
publication.readingOrder.items[index] = item.addProperties({
|
|
20
|
+
"number": index + 1,
|
|
21
|
+
"isImage": item.type?.indexOf("image/") === 0,
|
|
22
|
+
});
|
|
23
|
+
// if(!orientation) item.Properties.Orientation = item.Width > item.Height ? "landscape" : "portrait";
|
|
24
|
+
}
|
|
25
|
+
const isLandscape = item.properties?.getOrientation() === Orientation.landscape ? true : false;
|
|
26
|
+
if((!item.properties?.getPage() || redo)) item.properties = item.properties?.add({
|
|
27
|
+
"page": isLandscape ? // If a landscape image
|
|
28
|
+
"center" : // Center it
|
|
29
|
+
((((this.shift ? 0 : 1) + index - this.nLandscape) % 2) ?
|
|
30
|
+
(publication.metadata.readingProgression === ReadingProgression.rtl ? "right" : "left") :
|
|
31
|
+
(publication.metadata.readingProgression === ReadingProgression.rtl ? "left" : "right"))
|
|
32
|
+
})
|
|
33
|
+
if(isLandscape || item.properties?.otherProperties["addBlank"])
|
|
34
|
+
this.nLandscape++;
|
|
35
|
+
});
|
|
36
|
+
if(redo)
|
|
37
|
+
this.spreads = [];
|
|
38
|
+
this.buildSpreads(publication.readingOrder);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private testShift(publication: Publication) {
|
|
42
|
+
let wasLastSingle = false;
|
|
43
|
+
this.spreads.forEach((item, index) => {
|
|
44
|
+
if(item.length > 1)
|
|
45
|
+
return; // Only left with single-page "spreads"
|
|
46
|
+
const single = item[0];
|
|
47
|
+
const orientation = single.properties?.getOrientation();
|
|
48
|
+
|
|
49
|
+
// First page is landscape/spread means no shift
|
|
50
|
+
if(index === 0 && (orientation === Orientation.landscape || (orientation !== Orientation.portrait && ((single.width || 0) > (single.height || 0) || single.properties?.getSpread() === Spread.both))))
|
|
51
|
+
this.shift = false;
|
|
52
|
+
|
|
53
|
+
// If last was a true single, and this spread is a center page (that's not special), something's wrong
|
|
54
|
+
if(wasLastSingle && single.properties?.getPage() === Page.center) {
|
|
55
|
+
this.spreads[index - 1][0].addProperties({"addBlank": true});
|
|
56
|
+
/*if(single.findFlag("final"))
|
|
57
|
+
this.nLandscape++;*/
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// If this single page spread is an orphaned component of a double page spread (and it's not the first page)
|
|
61
|
+
if(orientation === Orientation.portrait && single.properties?.getPage() !== "center" && single.properties?.otherProperties["number"] > 1)
|
|
62
|
+
wasLastSingle = true;
|
|
63
|
+
else
|
|
64
|
+
wasLastSingle = false;
|
|
65
|
+
});
|
|
66
|
+
if(!this.shift)
|
|
67
|
+
this.index(publication, true); // Re-index spreads
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private buildSpreads(spine: Links) {
|
|
71
|
+
let currentSet: Link[] = [];
|
|
72
|
+
spine.items.forEach((item, index) => {
|
|
73
|
+
if(!index && this.shift) {
|
|
74
|
+
this.spreads.push([item]);
|
|
75
|
+
} else if(item.properties?.getPage() === Page.center) { // If a center (single) page spread, push immediately and reset current set
|
|
76
|
+
if(currentSet.length > 0) this.spreads.push(currentSet);
|
|
77
|
+
this.spreads.push([item]);
|
|
78
|
+
currentSet = [];
|
|
79
|
+
} else if (currentSet.length >= 2) { // Spread has max 2 pages
|
|
80
|
+
this.spreads.push(currentSet);
|
|
81
|
+
currentSet = [item];
|
|
82
|
+
} else // Add this item to current set
|
|
83
|
+
currentSet.push(item);
|
|
84
|
+
});
|
|
85
|
+
if(currentSet.length > 0) this.spreads.push(currentSet);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
currentSpread(currentSlide: number, perPage: number): Link[] {
|
|
89
|
+
return this.spreads[Math.min(Math.floor(currentSlide / perPage), this.spreads.length - 1)];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
findByLink(link: Link): Link[] | undefined {
|
|
93
|
+
return this.spreads.find((spread) => spread.includes(link)) || undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* (℠)
|
|
3
|
+
* # sML.js | I'm a Simple and Middling Library.
|
|
4
|
+
*
|
|
5
|
+
* * Copyright (c) Satoru MATSUSHIMA - https://github.com/satorumurmur/sML
|
|
6
|
+
* * Licensed under the MIT license. - http://www.opensource.org/licenses/mit-license.php
|
|
7
|
+
*
|
|
8
|
+
* Portions of this code come from the sML library
|
|
9
|
+
* Current version: 1.0.36
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
declare interface OSFlags {
|
|
13
|
+
iOS: number[];
|
|
14
|
+
macOS: number[];
|
|
15
|
+
iPadOS: number[];
|
|
16
|
+
WindowsPhone: number[];
|
|
17
|
+
ChromeOS: number[];
|
|
18
|
+
Windows: number[];
|
|
19
|
+
Android: number[];
|
|
20
|
+
Linux: number[];
|
|
21
|
+
Firefox: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare interface UAFlags {
|
|
25
|
+
Gecko: number[];
|
|
26
|
+
Firefox: number[];
|
|
27
|
+
Waterfox: number[];
|
|
28
|
+
Opera: number[];
|
|
29
|
+
Silk: number[];
|
|
30
|
+
Blink: number[];
|
|
31
|
+
EdgeHTML: number[];
|
|
32
|
+
Chrome: number[];
|
|
33
|
+
Chromium: number[];
|
|
34
|
+
Phoebe: number[];
|
|
35
|
+
UCBrowser: number[];
|
|
36
|
+
Vivaldi: number[];
|
|
37
|
+
Safari: number[];
|
|
38
|
+
Edge: number[];
|
|
39
|
+
WebKit: number[];
|
|
40
|
+
Trident: number[];
|
|
41
|
+
InternetExplorer: number[];
|
|
42
|
+
Flash: number[];
|
|
43
|
+
Facebook: number[];
|
|
44
|
+
LINE: number[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class sML {
|
|
48
|
+
OS: OSFlags;
|
|
49
|
+
UA: UAFlags;
|
|
50
|
+
Env!: string[];
|
|
51
|
+
|
|
52
|
+
constructor() {
|
|
53
|
+
const NUAD = (navigator as any).userAgentData, NUA = navigator.userAgent;
|
|
54
|
+
|
|
55
|
+
const _sV = (V?: string | number) => (typeof V === "string" || typeof V === "number") && V ? String(V).replace(/_/g, ".").split(".").map(I => parseInt(I) || 0) : [];
|
|
56
|
+
const _dV = (Pre="") => {
|
|
57
|
+
if(!Pre) return [];
|
|
58
|
+
const RE = new RegExp("^.*" + Pre + "[ :\\/]?(\\d+([\\._]\\d+)*).*$");
|
|
59
|
+
if(!RE.test(NUA)) return [];
|
|
60
|
+
return _sV(NUA.replace(RE, "$1"));
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
this.OS = ((OS: OSFlags) => {
|
|
64
|
+
if( /(macOS|Mac OS X)/.test(NUA)) {
|
|
65
|
+
if(/\(iP(hone|od touch);/.test(NUA)) OS.iOS = _dV("CPU (?:iPhone )?OS ");
|
|
66
|
+
if( /\(iPad;/.test(NUA)) OS.iOS = OS.iPadOS = _dV("CPU (?:iPhone )?OS ");
|
|
67
|
+
else if( /(macOS|Mac OS X) \d/.test(NUA)) document.ontouchend !== undefined ? OS.iOS = OS.iPadOS = _dV() : OS.macOS = _dV("(?:macOS|Mac OS X) ");
|
|
68
|
+
} else if( /Windows( NT)? \d/.test(NUA)) OS.Windows = (V => V[0] !== 6 || !V[1] ? V : V[1] === 1 ? [7] : V[1] === 2 ? [8] : [8, 1])(_dV("Windows(?: NT)?"));
|
|
69
|
+
else if( /Android \d/.test(NUA)) OS.Android = _dV("Android");
|
|
70
|
+
else if( /CrOS/.test(NUA)) OS.ChromeOS = _dV();
|
|
71
|
+
else if( /X11;/.test(NUA)) OS.Linux = _dV();
|
|
72
|
+
return OS;
|
|
73
|
+
})({} as OSFlags); if(NUAD) NUAD.getHighEntropyValues(["architecture", "model", "platform", "platformVersion", "uaFullVersion"]).then((HEUAD: any) => (OS => { const Pf = HEUAD.platform, PfV = HEUAD.platformVersion; if(!Pf || !PfV) return;
|
|
74
|
+
if( /^i(OS|P(hone|od touch))$/.test(Pf)) OS.iOS = _sV(PfV);
|
|
75
|
+
else if( /^iPad(OS)?$/.test(Pf)) OS.iOS = OS.iPadOS = _sV(PfV);
|
|
76
|
+
else if(/^(macOS|(Mac )?OS X|Mac(Intel)?)$/.test(Pf)) document.ontouchend !== undefined ? OS.iOS = OS.iPadOS = _sV() : OS.macOS = _sV(PfV);
|
|
77
|
+
else if( /^(Microsoft )?Windows$/.test(Pf)) OS.Windows = _sV(PfV);
|
|
78
|
+
else if( /^(Google )?Android$/.test(Pf)) OS.Android = _sV(PfV);
|
|
79
|
+
else if( /^((Google )?Chrome OS|CrOS)$/.test(Pf)) OS.ChromeOS = _sV(PfV);
|
|
80
|
+
else if( /^(Linux|Ubuntu|X11)$/.test(Pf)) OS.Linux = _sV(PfV);
|
|
81
|
+
else return; /**/ Object.keys(this.OS).forEach(Key => delete (this.OS as any)[Key]), Object.assign(this.OS, OS);
|
|
82
|
+
})({} as OSFlags));
|
|
83
|
+
|
|
84
|
+
this.UA = ((UA: UAFlags) => { let _OK = false;
|
|
85
|
+
if(NUAD && Array.isArray(NUAD.brands)) { const BnV = NUAD.brands.reduce((BnV: string[], _: any) => { (BnV[_.brand] as any) = [_.version * 1]; return BnV; }, {});
|
|
86
|
+
if(BnV["Google Chrome"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Chrome = BnV["Google Chrome"];
|
|
87
|
+
else if(BnV["Microsoft Edge"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Edge = BnV["Microsoft Edge"];
|
|
88
|
+
else if(BnV["Opera"]) _OK = true, UA.Blink = UA.Chromium = BnV["Chromium"] || [], UA.Opera = BnV["Opera"];
|
|
89
|
+
} if(!_OK) {
|
|
90
|
+
if( / Gecko\/\d/.test(NUA)) { UA.Gecko = _dV("rv");
|
|
91
|
+
if( / Waterfox\/\d/.test(NUA)) UA.Waterfox = _dV("Waterfox");
|
|
92
|
+
else if( / Firefox\/\d/.test(NUA)) UA.Firefox = _dV("Firefox");
|
|
93
|
+
} else if( / Edge\/\d/.test(NUA)) { UA.EdgeHTML = _dV("Edge");
|
|
94
|
+
UA.Edge = UA.EdgeHTML;
|
|
95
|
+
} else if(/ Chrom(ium|e)\/\d/.test(NUA)) { UA.Blink = UA.Chromium = (V => V[0] ? V : _dV("Chrome"))(_dV("Chromium"));
|
|
96
|
+
if( / EdgA?\/\d/.test(NUA)) UA.Edge = (V => V[0] ? V : _dV("Edg"))(_dV("EdgA"));
|
|
97
|
+
else if( / OPR\/\d/.test(NUA)) UA.Opera = _dV("OPR");
|
|
98
|
+
else if( / Vivaldi\/\d/.test(NUA)) UA.Vivaldi = _dV("Vivaldi");
|
|
99
|
+
else if( / Silk\/\d/.test(NUA)) UA.Silk = _dV("Silk");
|
|
100
|
+
else if( / UCBrowser\/\d/.test(NUA)) UA.UCBrowser = _dV("UCBrowser");
|
|
101
|
+
else if( / Phoebe\/\d/.test(NUA)) UA.Phoebe = _dV("Phoebe");
|
|
102
|
+
else UA.Chrome = (V => V[0] ? V : UA.Chromium)(_dV("Chrome"));
|
|
103
|
+
} else if( / AppleWebKit\/\d/.test(NUA)) { UA.WebKit = _dV("AppleWebKit");
|
|
104
|
+
if( / CriOS \d/.test(NUA)) UA.Chrome = _dV("CriOS");
|
|
105
|
+
else if( / FxiOS \d/.test(NUA)) UA.Firefox = _dV("FxiOS");
|
|
106
|
+
else if( / EdgiOS\/\d/.test(NUA)) UA.Edge = _dV("EdgiOS");
|
|
107
|
+
else if( / Version\/\d/.test(NUA)) UA.Safari = _dV("Version");
|
|
108
|
+
} else if( / Trident\/\d/.test(NUA)) { UA.Trident = _dV("Trident");
|
|
109
|
+
UA.InternetExplorer = (V => V[0] ? V : _dV("MSIE"))(_dV("rv"));
|
|
110
|
+
}
|
|
111
|
+
} /*+*/ if( /[\[; ]FB(AN|_IAB)\//.test(NUA)) UA.Facebook = _dV("FBAV");
|
|
112
|
+
/*+*/ if( / Line\/\d/.test(NUA)) UA.LINE = _dV("Line");
|
|
113
|
+
return UA;
|
|
114
|
+
})({} as UAFlags);
|
|
115
|
+
|
|
116
|
+
(this.Env as any) = { get: () => [this.OS, this.UA].reduce((Env: string[], OS_UA) => { for(const Par in OS_UA) if((OS_UA as any)[Par]) Env.push(Par); return Env; }, []) };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default (new sML);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Link, Locator, Publication, ReadingProgression } from "@readium/shared";
|
|
2
|
+
type cbb = (ok: boolean) => void;
|
|
3
|
+
export declare abstract class Navigator {
|
|
4
|
+
abstract get publication(): Publication;
|
|
5
|
+
abstract get currentLocator(): Locator;
|
|
6
|
+
/**
|
|
7
|
+
* Moves to the position in the publication corresponding to the given {Locator}.
|
|
8
|
+
*/
|
|
9
|
+
abstract go(locator: Locator, animated: boolean, cb: cbb): void;
|
|
10
|
+
/**
|
|
11
|
+
* Moves to the position in the publication targeted by the given link.
|
|
12
|
+
*/
|
|
13
|
+
abstract goLink(link: Link, animated: boolean, cb: cbb): void;
|
|
14
|
+
/**
|
|
15
|
+
* Moves to the next content portion (eg. page) in the reading progression direction.
|
|
16
|
+
*/
|
|
17
|
+
abstract goForward(animated: boolean, cb: cbb): void;
|
|
18
|
+
/**
|
|
19
|
+
* Moves to the previous content portion (eg. page) in the reading progression direction.
|
|
20
|
+
*/
|
|
21
|
+
abstract goBackward(animated: boolean, cb: cbb): void;
|
|
22
|
+
/**
|
|
23
|
+
* Destroy all resources associated with this navigator. Synonymous with "unmount"
|
|
24
|
+
*/
|
|
25
|
+
abstract destroy(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare abstract class VisualNavigator extends Navigator {
|
|
28
|
+
/**
|
|
29
|
+
* Current reading progression direction.
|
|
30
|
+
*/
|
|
31
|
+
abstract get readingProgression(): ReadingProgression;
|
|
32
|
+
/**
|
|
33
|
+
* Moves to the left content portion (eg. page) relative to the reading progression direction.
|
|
34
|
+
*/
|
|
35
|
+
goLeft(animated: boolean | undefined, completion: cbb): void;
|
|
36
|
+
/**
|
|
37
|
+
* Moves to the right content portion (eg. page) relative to the reading progression direction.
|
|
38
|
+
*/
|
|
39
|
+
goRight(animated: boolean | undefined, completion: cbb): void;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Locator } from '@readium/shared';
|
|
2
|
+
import { Publication } from '@readium/shared';
|
|
3
|
+
/**
|
|
4
|
+
* Initial state of the audio engine playback.
|
|
5
|
+
*/
|
|
6
|
+
export interface PlaybackState {
|
|
7
|
+
/**
|
|
8
|
+
* The current time of the audio resource.
|
|
9
|
+
*/
|
|
10
|
+
currentTime: number;
|
|
11
|
+
/**
|
|
12
|
+
* The duration of the audio resource.
|
|
13
|
+
*/
|
|
14
|
+
duration: number;
|
|
15
|
+
/**
|
|
16
|
+
* The volume of the audio resource.
|
|
17
|
+
*/
|
|
18
|
+
volume: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Playback interface for an audio engine state
|
|
22
|
+
* @state The initial [PlaybackState].
|
|
23
|
+
* @playWhenReady Indicates if the navigator should play as soon as the state is Ready.
|
|
24
|
+
* @index Index of the reading order item currently being played.
|
|
25
|
+
* @offset Position of the playback in the current item.
|
|
26
|
+
* @buffered Position in the current item until which the content is buffered.
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
export interface Playback {
|
|
30
|
+
state: PlaybackState;
|
|
31
|
+
playWhenReady: boolean;
|
|
32
|
+
index: number;
|
|
33
|
+
offset?: number;
|
|
34
|
+
buffered?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* An audio engine that plays audio resources from a publication.
|
|
38
|
+
* @playback - The current [Playback] state.
|
|
39
|
+
*/
|
|
40
|
+
export interface AudioEngine {
|
|
41
|
+
/**
|
|
42
|
+
* The current playback state.
|
|
43
|
+
*/
|
|
44
|
+
playback: Playback;
|
|
45
|
+
/**
|
|
46
|
+
* Plays the audio resource at the given locator.
|
|
47
|
+
*/
|
|
48
|
+
playLocator(publication: Publication, locator: Locator): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Adds an event listener to the audio engine.
|
|
51
|
+
* @param event The event name to listen.
|
|
52
|
+
* @param callback Callback function to be called when the event is triggered.
|
|
53
|
+
*/
|
|
54
|
+
on(event: string, callback: (data: any) => void): void;
|
|
55
|
+
/**
|
|
56
|
+
* Removes an event listener from the audio engine.
|
|
57
|
+
* @param event The event name to remove the listener.
|
|
58
|
+
* @param callback Callback function to be removed.
|
|
59
|
+
*/
|
|
60
|
+
off(event: string, callback: (data: any) => void): void;
|
|
61
|
+
/**
|
|
62
|
+
* Loads the audio resource at the given URL.
|
|
63
|
+
* @param url The URL of the audio resource.
|
|
64
|
+
*/
|
|
65
|
+
loadAudio(url: string): void;
|
|
66
|
+
/**
|
|
67
|
+
* Plays the current audio resource.
|
|
68
|
+
*/
|
|
69
|
+
play(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Pauses the currently playing audio resource.
|
|
72
|
+
*/
|
|
73
|
+
pause(): void;
|
|
74
|
+
/**
|
|
75
|
+
* Stops the currently playing audio resource.
|
|
76
|
+
*/
|
|
77
|
+
stop(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Skips [duration] either forward or backward if [duration] is negative.
|
|
80
|
+
*/
|
|
81
|
+
skip(duration: number): void;
|
|
82
|
+
/**
|
|
83
|
+
* Returns the duration of the audio resource.
|
|
84
|
+
*/
|
|
85
|
+
duration(): number;
|
|
86
|
+
/**
|
|
87
|
+
* Returns whether the audio resource is currently playing.
|
|
88
|
+
*/
|
|
89
|
+
isPlaying(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Returns whether the audio resource is currently paused.
|
|
92
|
+
*/
|
|
93
|
+
isPaused(): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Returns whether the audio resource is currently stopped.
|
|
96
|
+
*/
|
|
97
|
+
isStopped(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Returns whether the audio resource is currently loading.
|
|
100
|
+
*/
|
|
101
|
+
isLoading(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Returns whether the audio resource is currently loaded.
|
|
104
|
+
*/
|
|
105
|
+
isLoaded(): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Returns whether the audio resource is currently ended.
|
|
108
|
+
*/
|
|
109
|
+
isEnded(): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Returns whether the audio resource is currently muted.
|
|
112
|
+
*/
|
|
113
|
+
isMuted(): boolean;
|
|
114
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { AudioEngine, Playback } from "./AudioEngine";
|
|
2
|
+
import { Publication } from "@readium/shared";
|
|
3
|
+
import { Locator } from "@readium/shared";
|
|
4
|
+
type EventCallback = (data: any) => void;
|
|
5
|
+
export declare class WebAudioEngine implements AudioEngine {
|
|
6
|
+
readonly playback: Playback;
|
|
7
|
+
private audioContext;
|
|
8
|
+
private mediaElement;
|
|
9
|
+
private sourceNode;
|
|
10
|
+
private gainNode;
|
|
11
|
+
private listeners;
|
|
12
|
+
private isMutedValue;
|
|
13
|
+
private isPlayingValue;
|
|
14
|
+
private isPausedValue;
|
|
15
|
+
private isLoadingValue;
|
|
16
|
+
private isLoadedValue;
|
|
17
|
+
private isEndedValue;
|
|
18
|
+
constructor(values: {
|
|
19
|
+
playback: Playback;
|
|
20
|
+
audioContext: AudioContext;
|
|
21
|
+
});
|
|
22
|
+
/**
|
|
23
|
+
* Adds an event listener to the audio engine.
|
|
24
|
+
* @param event - event name to be listened.
|
|
25
|
+
* @param callback - callback function to be called when the event is triggered.
|
|
26
|
+
*/
|
|
27
|
+
on(event: string, callback: EventCallback): void;
|
|
28
|
+
/**
|
|
29
|
+
* Removes an event listener from the audio engine.
|
|
30
|
+
* @param event - event name to be removed from the listeners.
|
|
31
|
+
* @param callback - callback function to be removed.
|
|
32
|
+
*/
|
|
33
|
+
off(event: string, callback: EventCallback): void;
|
|
34
|
+
/**
|
|
35
|
+
* Load the audio resource at the given URL.
|
|
36
|
+
* @param url The URL of the audio resource.
|
|
37
|
+
* */
|
|
38
|
+
loadAudio(url: string): void;
|
|
39
|
+
private ensureAudioContextRunning;
|
|
40
|
+
private onTimeUpdate;
|
|
41
|
+
private onCanPlayThrough;
|
|
42
|
+
private onError;
|
|
43
|
+
private onEnded;
|
|
44
|
+
private emit;
|
|
45
|
+
/**
|
|
46
|
+
* Plays the audio resource at the given locator.
|
|
47
|
+
*/
|
|
48
|
+
playLocator(_publication: Publication, _locator: Locator): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Plays the current audio resource.
|
|
51
|
+
*/
|
|
52
|
+
play(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Pauses the currently playing audio resource.
|
|
55
|
+
*/
|
|
56
|
+
pause(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Stops the currently playing audio resource.
|
|
59
|
+
*/
|
|
60
|
+
stop(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Adjusts the [volume] of the audio resource.
|
|
63
|
+
* @volume The volume to set, in the range [0, 1].
|
|
64
|
+
*/
|
|
65
|
+
setVolume(volume: number): void;
|
|
66
|
+
/**
|
|
67
|
+
* Skips [seconds] either forward or backward if [seconds] is negative.
|
|
68
|
+
*/
|
|
69
|
+
skip(seconds: number): void;
|
|
70
|
+
/**
|
|
71
|
+
* Returns de current time in the audio resource.
|
|
72
|
+
*/
|
|
73
|
+
currentTime(): number;
|
|
74
|
+
/**
|
|
75
|
+
* Returns the duration in seconds of the current media element resource.
|
|
76
|
+
*/
|
|
77
|
+
duration(): number;
|
|
78
|
+
/**
|
|
79
|
+
* Returns whether the audio resource is currently playing.
|
|
80
|
+
*/
|
|
81
|
+
isPlaying(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Returns whether the audio resource is currently paused.
|
|
84
|
+
*/
|
|
85
|
+
isPaused(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Returns whether the audio resource is currently stopped.
|
|
88
|
+
*/
|
|
89
|
+
isStopped(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Returns whether the audio resource is currently loading.
|
|
92
|
+
*/
|
|
93
|
+
isLoading(): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Returns whether the audio resource is currently loaded.
|
|
96
|
+
*/
|
|
97
|
+
isLoaded(): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Returns whether the audio resource is currently ended.
|
|
100
|
+
*/
|
|
101
|
+
isEnded(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Returns whether the audio resource is currently muted.
|
|
104
|
+
*/
|
|
105
|
+
isMuted(): boolean;
|
|
106
|
+
}
|
|
107
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './engine';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { EPUBLayout, Link, Locator, Publication, ReadingProgression } from "@readium/shared";
|
|
2
|
+
import { VisualNavigator } from "../";
|
|
3
|
+
import { FramePoolManager } from "./frame/FramePoolManager";
|
|
4
|
+
import { FXLFramePoolManager } from "./fxl/FXLFramePoolManager";
|
|
5
|
+
import { CommsEventKey } from "@readium/navigator-html-injectables";
|
|
6
|
+
import { BasicTextSelection, FrameClickEvent } from "@readium/navigator-html-injectables";
|
|
7
|
+
import { FXLFrameManager } from "./fxl/FXLFrameManager";
|
|
8
|
+
import { FrameManager } from "./frame/FrameManager";
|
|
9
|
+
export type ManagerEventKey = "zoom";
|
|
10
|
+
export interface EpubNavigatorListeners {
|
|
11
|
+
frameLoaded: (wnd: Window) => void;
|
|
12
|
+
positionChanged: (locator: Locator) => void;
|
|
13
|
+
tap: (e: FrameClickEvent) => boolean;
|
|
14
|
+
click: (e: FrameClickEvent) => boolean;
|
|
15
|
+
zoom: (scale: number) => void;
|
|
16
|
+
miscPointer: (amount: number) => void;
|
|
17
|
+
customEvent: (key: string, data: unknown) => void;
|
|
18
|
+
handleLocator: (locator: Locator) => boolean;
|
|
19
|
+
textSelected: (selection: BasicTextSelection) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare class EpubNavigator extends VisualNavigator {
|
|
22
|
+
private readonly pub;
|
|
23
|
+
private readonly container;
|
|
24
|
+
private readonly listeners;
|
|
25
|
+
private framePool;
|
|
26
|
+
private positions;
|
|
27
|
+
private currentLocation;
|
|
28
|
+
private currentProgression;
|
|
29
|
+
readonly layout: EPUBLayout;
|
|
30
|
+
constructor(container: HTMLElement, pub: Publication, listeners: EpubNavigatorListeners, positions?: Locator[], initialPosition?: Locator | undefined);
|
|
31
|
+
static determineLayout(pub: Publication): EPUBLayout;
|
|
32
|
+
load(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Exposed to the public to compensate for lack of implemented readium conveniences
|
|
35
|
+
* TODO remove when settings management is incorporated
|
|
36
|
+
*/
|
|
37
|
+
get _cframes(): (FXLFrameManager | FrameManager | undefined)[];
|
|
38
|
+
/**
|
|
39
|
+
* Exposed to the public to compensate for lack of implemented readium conveniences
|
|
40
|
+
* TODO remove when settings management is incorporated
|
|
41
|
+
*/
|
|
42
|
+
get pool(): FramePoolManager | FXLFramePoolManager;
|
|
43
|
+
/**
|
|
44
|
+
* Left intentionally public so you can pass in your own events here
|
|
45
|
+
* to trigger the navigator when user's mouse/keyboard focus is
|
|
46
|
+
* outside the readium-controller navigator. Be careful!
|
|
47
|
+
*/
|
|
48
|
+
eventListener(key: CommsEventKey | ManagerEventKey, data: unknown): void;
|
|
49
|
+
private determineModules;
|
|
50
|
+
private attachListener;
|
|
51
|
+
private apply;
|
|
52
|
+
destroy(): Promise<void>;
|
|
53
|
+
private changeResource;
|
|
54
|
+
private findNearestPosition;
|
|
55
|
+
private syncLocation;
|
|
56
|
+
goBackward(_: boolean, cb: (ok: boolean) => void): void;
|
|
57
|
+
goForward(_: boolean, cb: (ok: boolean) => void): void;
|
|
58
|
+
get currentLocator(): Locator;
|
|
59
|
+
get currentPositionNumbers(): number[];
|
|
60
|
+
get readingProgression(): ReadingProgression;
|
|
61
|
+
setReadingProgression(newProgression: ReadingProgression): Promise<void>;
|
|
62
|
+
get publication(): Publication;
|
|
63
|
+
private loadLocator;
|
|
64
|
+
go(locator: Locator, _: boolean, cb: (ok: boolean) => void): void;
|
|
65
|
+
goLink(link: Link, animated: boolean, cb: (ok: boolean) => void): void;
|
|
66
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Link, Publication } from "@readium/shared";
|
|
2
|
+
export default class FrameBlobBuider {
|
|
3
|
+
private readonly item;
|
|
4
|
+
private readonly burl;
|
|
5
|
+
private readonly pub;
|
|
6
|
+
constructor(pub: Publication, baseURL: string, item: Link);
|
|
7
|
+
build(fxl?: boolean): Promise<string>;
|
|
8
|
+
private buildHtmlFrame;
|
|
9
|
+
private buildImageFrame;
|
|
10
|
+
private hasExecutable;
|
|
11
|
+
private hasStyle;
|
|
12
|
+
private finalizeDOM;
|
|
13
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CommsCommandKey, CommsAck, CommsEventKey } from "@readium/navigator-html-injectables";
|
|
2
|
+
import { ManagerEventKey } from "../EpubNavigator";
|
|
3
|
+
export type FrameCommsListener = (key: CommsEventKey | ManagerEventKey, value: unknown) => void;
|
|
4
|
+
export declare class FrameComms {
|
|
5
|
+
private readonly wnd;
|
|
6
|
+
private readonly registry;
|
|
7
|
+
private readonly gc;
|
|
8
|
+
private readonly origin;
|
|
9
|
+
readonly channelId: string;
|
|
10
|
+
private _ready;
|
|
11
|
+
private _listener;
|
|
12
|
+
private listenerBuffer;
|
|
13
|
+
set listener(listener: FrameCommsListener);
|
|
14
|
+
clearListener(): void;
|
|
15
|
+
constructor(wnd: Window, origin: string);
|
|
16
|
+
halt(): void;
|
|
17
|
+
resume(): void;
|
|
18
|
+
private handle;
|
|
19
|
+
private handler;
|
|
20
|
+
get ready(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Send a message to the window using postMessage-based comms communication
|
|
23
|
+
* @returns Identifier associated with the message
|
|
24
|
+
*/
|
|
25
|
+
send(key: CommsCommandKey, data: unknown, callback?: CommsAck, strict?: boolean, transfer?: Transferable[]): string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Loader, ModuleName } from "@readium/navigator-html-injectables";
|
|
2
|
+
import { FrameComms } from "./FrameComms";
|
|
3
|
+
export declare class FrameManager {
|
|
4
|
+
private frame;
|
|
5
|
+
private loader;
|
|
6
|
+
readonly source: string;
|
|
7
|
+
private comms;
|
|
8
|
+
private currModules;
|
|
9
|
+
constructor(source: string);
|
|
10
|
+
load(modules: ModuleName[]): Promise<Window>;
|
|
11
|
+
destroy(): Promise<void>;
|
|
12
|
+
hide(): Promise<void>;
|
|
13
|
+
show(atProgress?: number): Promise<void>;
|
|
14
|
+
get iframe(): HTMLIFrameElement;
|
|
15
|
+
get realSize(): DOMRect;
|
|
16
|
+
get window(): Window;
|
|
17
|
+
get atLeft(): boolean;
|
|
18
|
+
get atRight(): boolean;
|
|
19
|
+
get msg(): FrameComms | undefined;
|
|
20
|
+
get ldr(): Loader<ModuleName> | undefined;
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ModuleName } from "@readium/navigator-html-injectables";
|
|
2
|
+
import { Locator, Publication } from "@readium/shared";
|
|
3
|
+
import { FrameManager } from "./FrameManager";
|
|
4
|
+
export declare class FramePoolManager {
|
|
5
|
+
private readonly container;
|
|
6
|
+
private readonly positions;
|
|
7
|
+
private _currentFrame;
|
|
8
|
+
private readonly pool;
|
|
9
|
+
private readonly blobs;
|
|
10
|
+
private readonly inprogress;
|
|
11
|
+
private currentBaseURL;
|
|
12
|
+
constructor(container: HTMLElement, positions: Locator[]);
|
|
13
|
+
destroy(): Promise<void>;
|
|
14
|
+
update(pub: Publication, locator: Locator, modules: ModuleName[], force?: boolean): Promise<void>;
|
|
15
|
+
get currentFrames(): (FrameManager | undefined)[];
|
|
16
|
+
get currentBounds(): DOMRect;
|
|
17
|
+
}
|