@readium/navigator 2.4.0-beta.8 → 2.4.0-beta.9
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/dist/index.js +851 -943
- package/dist/index.umd.cjs +22 -22
- package/package.json +1 -1
- package/src/audio/AudioNavigator.ts +25 -12
- package/src/audio/index.ts +1 -2
- package/src/index.ts +0 -1
- package/types/src/audio/AudioNavigator.d.ts +5 -4
- package/types/src/audio/index.d.ts +0 -1
- package/types/src/index.d.ts +0 -1
- package/src/Timeline.ts +0 -58
- package/src/audio/AudioTimeline.ts +0 -156
- package/types/src/Timeline.d.ts +0 -48
- package/types/src/audio/AudioTimeline.d.ts +0 -34
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Link, Locator, LocatorLocations, Publication } from "@readium/shared";
|
|
1
|
+
import { Link, Locator, LocatorLocations, Publication, Timeline, TimelineItem } from "@readium/shared";
|
|
2
2
|
import { MediaNavigator, IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../Navigator";
|
|
3
3
|
import { Configurable } from "../preferences";
|
|
4
4
|
import { WebAudioEngine, PlaybackState } from "./engine";
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
IAudioDefaults
|
|
12
12
|
} from "./preferences";
|
|
13
13
|
import { AudioPoolManager } from "./AudioPoolManager";
|
|
14
|
-
import { AudioTimeline } from "./AudioTimeline";
|
|
15
14
|
import { ContextMenuEvent, KeyboardEventData, SuspiciousActivityEvent } from "@readium/navigator-html-injectables";
|
|
16
15
|
import { AudioNavigatorProtector } from "./protection/AudioNavigatorProtector";
|
|
17
16
|
import { NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT } from "../protection/NavigatorProtector";
|
|
@@ -20,6 +19,7 @@ import { KeyboardPeripherals, NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT } from "../per
|
|
|
20
19
|
export interface AudioNavigatorListeners {
|
|
21
20
|
trackLoaded: (media: HTMLMediaElement) => void;
|
|
22
21
|
positionChanged: (locator: Locator) => void;
|
|
22
|
+
timelineItemChanged: (item: TimelineItem | undefined) => void;
|
|
23
23
|
error: (error: any, locator: Locator) => void;
|
|
24
24
|
trackEnded: (locator: Locator) => void;
|
|
25
25
|
play: (locator: Locator) => void;
|
|
@@ -36,6 +36,7 @@ export interface AudioNavigatorListeners {
|
|
|
36
36
|
const defaultListeners = (listeners: Partial<AudioNavigatorListeners>): AudioNavigatorListeners => ({
|
|
37
37
|
trackLoaded: listeners.trackLoaded ?? (() => {}),
|
|
38
38
|
positionChanged: listeners.positionChanged ?? (() => {}),
|
|
39
|
+
timelineItemChanged: listeners.timelineItemChanged ?? (() => {}),
|
|
39
40
|
error: listeners.error ?? (() => {}),
|
|
40
41
|
trackEnded: listeners.trackEnded ?? (() => {}),
|
|
41
42
|
play: listeners.play ?? (() => {}),
|
|
@@ -71,7 +72,7 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
71
72
|
private _mediaSessionEnabled: boolean = false;
|
|
72
73
|
private pool: AudioPoolManager;
|
|
73
74
|
private readonly _navigatorProtector: AudioNavigatorProtector | null = null;
|
|
74
|
-
private
|
|
75
|
+
private _currentTimelineItem: TimelineItem | undefined;
|
|
75
76
|
private readonly _keyboardPeripheralsManager: KeyboardPeripherals | null = null;
|
|
76
77
|
private readonly _suspiciousActivityListener: ((event: Event) => void) | null = null;
|
|
77
78
|
private readonly _keyboardPeripheralListener: ((event: Event) => void) | null = null;
|
|
@@ -82,7 +83,6 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
82
83
|
}) {
|
|
83
84
|
super();
|
|
84
85
|
this.pub = publication;
|
|
85
|
-
this._timeline = new AudioTimeline(publication);
|
|
86
86
|
this.listeners = defaultListeners(listeners);
|
|
87
87
|
|
|
88
88
|
this._preferences = new AudioPreferences(configuration.preferences);
|
|
@@ -167,7 +167,7 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
167
167
|
this.waitForLoadedAndSeeked(initialTime)
|
|
168
168
|
.then(() => {
|
|
169
169
|
this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement());
|
|
170
|
-
this.
|
|
170
|
+
this._notifyTimelineChange(this.currentLocator);
|
|
171
171
|
this.listeners.positionChanged(this.currentLocator);
|
|
172
172
|
})
|
|
173
173
|
.catch(() => {
|
|
@@ -214,8 +214,16 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
214
214
|
return this.pub;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
get timeline():
|
|
218
|
-
return this.
|
|
217
|
+
get timeline(): Timeline {
|
|
218
|
+
return this.pub.timeline;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private _notifyTimelineChange(locator: Locator): void {
|
|
222
|
+
const item = this.pub.timeline.locate(locator);
|
|
223
|
+
if (item !== this._currentTimelineItem) {
|
|
224
|
+
this._currentTimelineItem = item;
|
|
225
|
+
this.listeners.timelineItemChanged(item);
|
|
226
|
+
}
|
|
219
227
|
}
|
|
220
228
|
|
|
221
229
|
private ensureLocatorLocations(locator: Locator): Locator {
|
|
@@ -365,7 +373,7 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
365
373
|
progression,
|
|
366
374
|
fragments: [`t=${currentTime}`]
|
|
367
375
|
}));
|
|
368
|
-
this.
|
|
376
|
+
this._notifyTimelineChange(this.currentLocation);
|
|
369
377
|
this.listeners.positionChanged(this.currentLocation);
|
|
370
378
|
}
|
|
371
379
|
});
|
|
@@ -373,6 +381,7 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
373
381
|
this.pool.audioEngine.on("seeking", () => this.listeners.seeking(true));
|
|
374
382
|
this.pool.audioEngine.on("waiting", () => this.listeners.seeking(true));
|
|
375
383
|
this.pool.audioEngine.on("stalled", () => this.listeners.stalled(true));
|
|
384
|
+
this.pool.audioEngine.on("canplaythrough", () => this.listeners.stalled(false));
|
|
376
385
|
this.pool.audioEngine.on("progress", (seekable: TimeRanges) => this.listeners.seekable(seekable));
|
|
377
386
|
|
|
378
387
|
this.pool.audioEngine.on("loadedmetadata", () => {
|
|
@@ -417,7 +426,7 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
417
426
|
progression,
|
|
418
427
|
fragments: [`t=${currentTime}`]
|
|
419
428
|
}));
|
|
420
|
-
this.
|
|
429
|
+
this._notifyTimelineChange(this.currentLocation);
|
|
421
430
|
this.listeners.positionChanged(this.currentLocation);
|
|
422
431
|
}, this._settings.pollInterval);
|
|
423
432
|
}
|
|
@@ -455,10 +464,13 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
455
464
|
|
|
456
465
|
await this.waitForLoadedAndSeeked(time, id);
|
|
457
466
|
|
|
458
|
-
if (id !== this.navigationId)
|
|
467
|
+
if (id !== this.navigationId) {
|
|
468
|
+
cb(false);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
459
471
|
|
|
460
472
|
this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement());
|
|
461
|
-
this.
|
|
473
|
+
this._notifyTimelineChange(this.currentLocator);
|
|
462
474
|
this.listeners.positionChanged(this.currentLocator);
|
|
463
475
|
|
|
464
476
|
if (this._settings.enableMediaSession) {
|
|
@@ -466,12 +478,13 @@ export class AudioNavigator extends MediaNavigator implements Configurable<Audio
|
|
|
466
478
|
}
|
|
467
479
|
|
|
468
480
|
if (wasPlaying) this.play();
|
|
469
|
-
this._playIntent = false;
|
|
470
481
|
|
|
471
482
|
cb(true);
|
|
472
483
|
} catch (error) {
|
|
473
484
|
console.error("Failed to go to locator:", error);
|
|
474
485
|
cb(false);
|
|
486
|
+
} finally {
|
|
487
|
+
this._playIntent = false;
|
|
475
488
|
}
|
|
476
489
|
}
|
|
477
490
|
|
package/src/audio/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { Link, Locator, Publication } from "@readium/shared";
|
|
1
|
+
import { Link, Locator, Publication, Timeline, TimelineItem } from "@readium/shared";
|
|
2
2
|
import { MediaNavigator, IContentProtectionConfig, IKeyboardPeripheralsConfig } from "../Navigator";
|
|
3
3
|
import { Configurable } from "../preferences";
|
|
4
4
|
import { AudioPreferences, AudioSettings, AudioPreferencesEditor, IAudioPreferences, IAudioDefaults } from "./preferences";
|
|
5
|
-
import { AudioTimeline } from "./AudioTimeline";
|
|
6
5
|
import { ContextMenuEvent, KeyboardEventData, SuspiciousActivityEvent } from "@readium/navigator-html-injectables";
|
|
7
6
|
export interface AudioNavigatorListeners {
|
|
8
7
|
trackLoaded: (media: HTMLMediaElement) => void;
|
|
9
8
|
positionChanged: (locator: Locator) => void;
|
|
9
|
+
timelineItemChanged: (item: TimelineItem | undefined) => void;
|
|
10
10
|
error: (error: any, locator: Locator) => void;
|
|
11
11
|
trackEnded: (locator: Locator) => void;
|
|
12
12
|
play: (locator: Locator) => void;
|
|
@@ -39,7 +39,7 @@ export declare class AudioNavigator extends MediaNavigator implements Configurab
|
|
|
39
39
|
private _mediaSessionEnabled;
|
|
40
40
|
private pool;
|
|
41
41
|
private readonly _navigatorProtector;
|
|
42
|
-
private
|
|
42
|
+
private _currentTimelineItem;
|
|
43
43
|
private readonly _keyboardPeripheralsManager;
|
|
44
44
|
private readonly _suspiciousActivityListener;
|
|
45
45
|
private readonly _keyboardPeripheralListener;
|
|
@@ -49,7 +49,8 @@ export declare class AudioNavigator extends MediaNavigator implements Configurab
|
|
|
49
49
|
submitPreferences(preferences: AudioPreferences): Promise<void>;
|
|
50
50
|
private applyPreferences;
|
|
51
51
|
get publication(): Publication;
|
|
52
|
-
get timeline():
|
|
52
|
+
get timeline(): Timeline;
|
|
53
|
+
private _notifyTimelineChange;
|
|
53
54
|
private ensureLocatorLocations;
|
|
54
55
|
/** Resolves a bare href (no fragment) to its index in the reading order. Returns -1 if not found. */
|
|
55
56
|
private hrefToTrackIndex;
|
package/types/src/index.d.ts
CHANGED
package/src/Timeline.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents a single entry in the publication's timeline.
|
|
3
|
-
* The timeline contextualizes the reading order, table of contents,
|
|
4
|
-
* positions list, and guided navigation document (GND) so that
|
|
5
|
-
* consuming apps can, for instance, display position numbers
|
|
6
|
-
* for TOC items, select the current TOC entry when
|
|
7
|
-
* it has a fragment, or display previous/next as chapter titles while
|
|
8
|
-
* pointing to the actual resources.
|
|
9
|
-
*
|
|
10
|
-
* Properties vary by format — not all will be populated for every format.
|
|
11
|
-
*/
|
|
12
|
-
export interface TimelineItem {
|
|
13
|
-
/** Title of this timeline entry (e.g. chapter or section name). */
|
|
14
|
-
title: string;
|
|
15
|
-
/** References as hrefs with optional fragments, e.g. ["chapter1.html"], ["track1.mp3#t=60"], ["#page=6"]. */
|
|
16
|
-
references: string[];
|
|
17
|
-
/** Roles of this entry, e.g. ["chapter"], ["section"], ["part"]. */
|
|
18
|
-
role?: string[];
|
|
19
|
-
/** Position number in the reading order context. */
|
|
20
|
-
position?: number;
|
|
21
|
-
/** Scroll progression within the resource (0 to 1), for entries that start mid-way in a resource. */
|
|
22
|
-
scroll?: number;
|
|
23
|
-
/** Nested timeline entries. */
|
|
24
|
-
children?: TimelineItem[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type TimelineChangeCallback = (current: TimelineItem | undefined, previous: TimelineItem | undefined, next: TimelineItem | undefined) => void;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* A timeline built from a publication's structure.
|
|
31
|
-
* Format-specific subclasses are responsible for building the items
|
|
32
|
-
* from the publication's reading order, table of contents, positions list and GND.
|
|
33
|
-
*/
|
|
34
|
-
export abstract class Timeline {
|
|
35
|
-
abstract readonly items: TimelineItem[];
|
|
36
|
-
|
|
37
|
-
/** The current timeline item matching the navigator's position. */
|
|
38
|
-
abstract get current(): TimelineItem | undefined;
|
|
39
|
-
|
|
40
|
-
/** The previous entry relative to current, based on resource boundaries in the TOC tree. */
|
|
41
|
-
abstract get previous(): TimelineItem | undefined;
|
|
42
|
-
|
|
43
|
-
/** The next entry relative to current, based on resource boundaries in the TOC tree. */
|
|
44
|
-
abstract get next(): TimelineItem | undefined;
|
|
45
|
-
|
|
46
|
-
/** Returns the previous and next entries relative to current. */
|
|
47
|
-
get adjacent(): { previous: TimelineItem | undefined; next: TimelineItem | undefined } {
|
|
48
|
-
return { previous: this.previous, next: this.next };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
protected changeCallback: TimelineChangeCallback | null = null;
|
|
52
|
-
|
|
53
|
-
/** Register a callback invoked when the current timeline item changes. */
|
|
54
|
-
onChange(callback: TimelineChangeCallback): void {
|
|
55
|
-
this.changeCallback = callback;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { Link, Locator, Publication } from "@readium/shared";
|
|
2
|
-
import { Timeline, TimelineItem } from "../Timeline";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Audio-specific timeline built from the publication's table of contents,
|
|
6
|
-
* falling back to the reading order when no TOC is available.
|
|
7
|
-
*/
|
|
8
|
-
export class AudioTimeline extends Timeline {
|
|
9
|
-
readonly items: TimelineItem[];
|
|
10
|
-
|
|
11
|
-
private _current: TimelineItem | undefined;
|
|
12
|
-
private _previous: TimelineItem | undefined;
|
|
13
|
-
private _next: TimelineItem | undefined;
|
|
14
|
-
private readonly flat: TimelineItem[];
|
|
15
|
-
|
|
16
|
-
constructor(publication: Publication) {
|
|
17
|
-
super();
|
|
18
|
-
const toc = publication.toc;
|
|
19
|
-
this.items = toc && toc.items.length > 0
|
|
20
|
-
? AudioTimeline.itemsFromToc(toc.items)
|
|
21
|
-
: AudioTimeline.itemsFromReadingOrder(publication.readingOrder.items);
|
|
22
|
-
this.flat = this.flatten(this.items);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get current(): TimelineItem | undefined {
|
|
26
|
-
return this._current;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get previous(): TimelineItem | undefined {
|
|
30
|
-
return this._previous;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get next(): TimelineItem | undefined {
|
|
34
|
-
return this._next;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
update(locator: Locator): void {
|
|
38
|
-
const href = locator.href.split("#")[0];
|
|
39
|
-
const time = locator.locations?.time() ?? 0;
|
|
40
|
-
|
|
41
|
-
const matched = this.findCurrent(this.items, href, time);
|
|
42
|
-
|
|
43
|
-
// Only fire callback when timeline values actually change
|
|
44
|
-
if (matched !== this._current) {
|
|
45
|
-
this._current = matched;
|
|
46
|
-
this._previous = matched ? this.findPrevious(matched) : undefined;
|
|
47
|
-
this._next = matched ? this.findNext(matched) : undefined;
|
|
48
|
-
this.changeCallback?.(this._current, this._previous, this._next);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Finds the deepest timeline item whose reference matches the given
|
|
54
|
-
* href and whose time offset is at or before the current time.
|
|
55
|
-
*/
|
|
56
|
-
private findCurrent(_items: TimelineItem[], href: string, time: number): TimelineItem | undefined {
|
|
57
|
-
// Search for time-based match first
|
|
58
|
-
let match: TimelineItem | undefined;
|
|
59
|
-
|
|
60
|
-
for (const item of this.flat) {
|
|
61
|
-
if (this.itemMatchesPosition(item, href, time)) {
|
|
62
|
-
match = item;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// If no time-based match, fallback to base href match
|
|
67
|
-
if (!match) {
|
|
68
|
-
for (const item of this.flat) {
|
|
69
|
-
if (this.bareHref(item) === href) {
|
|
70
|
-
match = item;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return match;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** First preceding entry in the flat list */
|
|
80
|
-
private findPrevious(target: TimelineItem): TimelineItem | undefined {
|
|
81
|
-
const index = this.flat.indexOf(target);
|
|
82
|
-
if (index > 0) {
|
|
83
|
-
return this.flat[index - 1];
|
|
84
|
-
}
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** First following entry in the flat list */
|
|
89
|
-
private findNext(target: TimelineItem): TimelineItem | undefined {
|
|
90
|
-
const index = this.flat.indexOf(target);
|
|
91
|
-
if (index < this.flat.length - 1) {
|
|
92
|
-
return this.flat[index + 1];
|
|
93
|
-
}
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private bareHref(item: TimelineItem): string {
|
|
98
|
-
const ref = item.references[0];
|
|
99
|
-
if (!ref) return "";
|
|
100
|
-
return ref.split("#")[0];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private flatten(items: TimelineItem[]): TimelineItem[] {
|
|
104
|
-
const result: TimelineItem[] = [];
|
|
105
|
-
for (const item of items) {
|
|
106
|
-
result.push(item);
|
|
107
|
-
if (item.children) {
|
|
108
|
-
result.push(...this.flatten(item.children));
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return result;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private itemMatchesPosition(item: TimelineItem, href: string, time: number): boolean {
|
|
115
|
-
for (const ref of item.references) {
|
|
116
|
-
const [refHref, refFragment] = ref.split("#");
|
|
117
|
-
const refBare = refHref || href; // empty refHref means same resource (e.g. "#t=60")
|
|
118
|
-
if (refBare !== href) continue;
|
|
119
|
-
const refTime = this.parseTimeFragment(refFragment);
|
|
120
|
-
if (time >= refTime) return true;
|
|
121
|
-
}
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private parseTimeFragment(fragment: string | undefined): number {
|
|
126
|
-
if (!fragment) return 0;
|
|
127
|
-
const match = fragment.match(/(?:^|&)t=(\d+(?:\.\d+)?)/);
|
|
128
|
-
return match ? parseFloat(match[1]) : 0;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
private static itemsFromToc(links: Link[]): TimelineItem[] {
|
|
132
|
-
return links
|
|
133
|
-
.map(link => AudioTimeline.linkToItem(link))
|
|
134
|
-
.filter(Boolean) as TimelineItem[];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private static itemsFromReadingOrder(links: Link[]): TimelineItem[] {
|
|
138
|
-
return links
|
|
139
|
-
.map(link => AudioTimeline.linkToItem(link))
|
|
140
|
-
.filter(Boolean) as TimelineItem[];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private static linkToItem(link: Link): TimelineItem | undefined {
|
|
144
|
-
if (!link.title) return undefined;
|
|
145
|
-
|
|
146
|
-
const children = link.children?.items
|
|
147
|
-
.map(child => AudioTimeline.linkToItem(child))
|
|
148
|
-
.filter(Boolean) as TimelineItem[] | undefined;
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
title: link.title,
|
|
152
|
-
references: [link.href],
|
|
153
|
-
children: children && children.length > 0 ? children : undefined,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
}
|
package/types/src/Timeline.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents a single entry in the publication's timeline.
|
|
3
|
-
* The timeline contextualizes the reading order, table of contents,
|
|
4
|
-
* positions list, and guided navigation document (GND) so that
|
|
5
|
-
* consuming apps can, for instance, display position numbers
|
|
6
|
-
* for TOC items, select the current TOC entry when
|
|
7
|
-
* it has a fragment, or display previous/next as chapter titles while
|
|
8
|
-
* pointing to the actual resources.
|
|
9
|
-
*
|
|
10
|
-
* Properties vary by format — not all will be populated for every format.
|
|
11
|
-
*/
|
|
12
|
-
export interface TimelineItem {
|
|
13
|
-
/** Title of this timeline entry (e.g. chapter or section name). */
|
|
14
|
-
title: string;
|
|
15
|
-
/** References as hrefs with optional fragments, e.g. ["chapter1.html"], ["track1.mp3#t=60"], ["#page=6"]. */
|
|
16
|
-
references: string[];
|
|
17
|
-
/** Roles of this entry, e.g. ["chapter"], ["section"], ["part"]. */
|
|
18
|
-
role?: string[];
|
|
19
|
-
/** Position number in the reading order context. */
|
|
20
|
-
position?: number;
|
|
21
|
-
/** Scroll progression within the resource (0 to 1), for entries that start mid-way in a resource. */
|
|
22
|
-
scroll?: number;
|
|
23
|
-
/** Nested timeline entries. */
|
|
24
|
-
children?: TimelineItem[];
|
|
25
|
-
}
|
|
26
|
-
export type TimelineChangeCallback = (current: TimelineItem | undefined, previous: TimelineItem | undefined, next: TimelineItem | undefined) => void;
|
|
27
|
-
/**
|
|
28
|
-
* A timeline built from a publication's structure.
|
|
29
|
-
* Format-specific subclasses are responsible for building the items
|
|
30
|
-
* from the publication's reading order, table of contents, positions list and GND.
|
|
31
|
-
*/
|
|
32
|
-
export declare abstract class Timeline {
|
|
33
|
-
abstract readonly items: TimelineItem[];
|
|
34
|
-
/** The current timeline item matching the navigator's position. */
|
|
35
|
-
abstract get current(): TimelineItem | undefined;
|
|
36
|
-
/** The previous entry relative to current, based on resource boundaries in the TOC tree. */
|
|
37
|
-
abstract get previous(): TimelineItem | undefined;
|
|
38
|
-
/** The next entry relative to current, based on resource boundaries in the TOC tree. */
|
|
39
|
-
abstract get next(): TimelineItem | undefined;
|
|
40
|
-
/** Returns the previous and next entries relative to current. */
|
|
41
|
-
get adjacent(): {
|
|
42
|
-
previous: TimelineItem | undefined;
|
|
43
|
-
next: TimelineItem | undefined;
|
|
44
|
-
};
|
|
45
|
-
protected changeCallback: TimelineChangeCallback | null;
|
|
46
|
-
/** Register a callback invoked when the current timeline item changes. */
|
|
47
|
-
onChange(callback: TimelineChangeCallback): void;
|
|
48
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Locator, Publication } from "@readium/shared";
|
|
2
|
-
import { Timeline, TimelineItem } from "../Timeline";
|
|
3
|
-
/**
|
|
4
|
-
* Audio-specific timeline built from the publication's table of contents,
|
|
5
|
-
* falling back to the reading order when no TOC is available.
|
|
6
|
-
*/
|
|
7
|
-
export declare class AudioTimeline extends Timeline {
|
|
8
|
-
readonly items: TimelineItem[];
|
|
9
|
-
private _current;
|
|
10
|
-
private _previous;
|
|
11
|
-
private _next;
|
|
12
|
-
private readonly flat;
|
|
13
|
-
constructor(publication: Publication);
|
|
14
|
-
get current(): TimelineItem | undefined;
|
|
15
|
-
get previous(): TimelineItem | undefined;
|
|
16
|
-
get next(): TimelineItem | undefined;
|
|
17
|
-
update(locator: Locator): void;
|
|
18
|
-
/**
|
|
19
|
-
* Finds the deepest timeline item whose reference matches the given
|
|
20
|
-
* href and whose time offset is at or before the current time.
|
|
21
|
-
*/
|
|
22
|
-
private findCurrent;
|
|
23
|
-
/** First preceding entry in the flat list */
|
|
24
|
-
private findPrevious;
|
|
25
|
-
/** First following entry in the flat list */
|
|
26
|
-
private findNext;
|
|
27
|
-
private bareHref;
|
|
28
|
-
private flatten;
|
|
29
|
-
private itemMatchesPosition;
|
|
30
|
-
private parseTimeFragment;
|
|
31
|
-
private static itemsFromToc;
|
|
32
|
-
private static itemsFromReadingOrder;
|
|
33
|
-
private static linkToItem;
|
|
34
|
-
}
|