r2-navigator-js
Version:
Readium 2 'navigator' for NodeJS (TypeScript)
1,091 lines (1,059 loc) • 67.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setWebViewStyle = setWebViewStyle;
exports.keyboardFocusRequest = keyboardFocusRequest;
exports.locationHandleIpcMessage = locationHandleIpcMessage;
exports.shiftWebview = shiftWebview;
exports.navPreviousOrNext = navPreviousOrNext;
exports.navLeftOrRight = navLeftOrRight;
exports.handleLink = handleLink;
exports.handleLinkUrl = handleLinkUrl;
exports.handleLinkLocator = handleLinkLocator;
exports.reloadContent = reloadContent;
exports.getCurrentReadingLocation = getCurrentReadingLocation;
exports.setReadingLocationSaver = setReadingLocationSaver;
exports.isLocatorVisible = isLocatorVisible;
const tslib_1 = require("tslib");
const debug_ = require("debug");
const electron_1 = require("electron");
const path = require("path");
const url_1 = require("url");
const metadata_properties_1 = require("r2-shared-js/dist/es7-es2016/src/models/metadata-properties");
const UrlUtils_1 = require("r2-utils-js/dist/es7-es2016/src/_utils/http/UrlUtils");
const audiobook_1 = require("../common/audiobook");
const events_1 = require("../common/events");
const readium_css_inject_1 = require("../common/readium-css-inject");
const sessions_1 = require("../common/sessions");
const styles_1 = require("../common/styles");
const audiobook_2 = require("./audiobook");
const url_params_1 = require("./common/url-params");
const epubReadingSystem_1 = require("./epubReadingSystem");
const media_overlays_1 = require("./media-overlays");
const readium_css_1 = require("./readium-css");
const URI = require("urijs");
const debug = debug_("r2:navigator#electron/renderer/location");
const IS_DEV = (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "dev");
const win = global.window;
const webviewStyleCommon = "display: flex; border: 0; margin: 0; padding: 0; box-sizing: border-box; position: absolute; ";
const webviewStyleLeft = `opacity: ${styles_1.ENABLE_EXTRA_COLUMN_SHIFT_METHOD ? 0 : 1}; ` + webviewStyleCommon + "left: 0; width: 50%; bottom: 0; top: 0;";
const webviewStyleRight = `opacity: ${styles_1.ENABLE_EXTRA_COLUMN_SHIFT_METHOD ? 0 : 1}; ` + webviewStyleCommon + "left: 50%; right: 0; bottom: 0; top: 0;";
const webviewStyleCenter = `opacity: ${styles_1.ENABLE_EXTRA_COLUMN_SHIFT_METHOD ? 0 : 1}; ` + webviewStyleCommon + "left: 0; right: 0; bottom: 0; top: 0;";
const webviewStyleLeft_ = "opacity: 1; " + webviewStyleCommon +
"left: 0; top: calc(0 - max(var(--R2_FXL_Y_SHIFT), var(--R2_FXL_Y_SHIFT_)));";
const webviewStyleRight_ = "opacity: 1; " + webviewStyleCommon +
"left: calc(50% - var(--R2_FXL_X_SHIFT));" +
"top: calc(0 - max(var(--R2_FXL_Y_SHIFT), var(--R2_FXL_Y_SHIFT_)));";
const webviewStyleCenter_ = "opacity: 1; " + webviewStyleCommon +
"left: 0; top: calc(0 - var(--R2_FXL_Y_SHIFT));";
function setWebViewStyle(wv, wvSlot, fxl) {
const v = fxl ? JSON.stringify(fxl).replace(/{/g, "").replace(/}/g, "").replace(/"/g, "") : "NO FXL";
debug("setWebViewStyle fxl: " + v);
if (fxl) {
let wvSlot_ = wv.getAttribute("data-wv-slot");
if (!wvSlot_) {
wvSlot_ = wvSlot;
}
const tx = fxl.tx >= 0 ? fxl.tx : 0;
if (wvSlot_ === styles_1.WebViewSlotEnum.left || wvSlot_ === styles_1.WebViewSlotEnum.center) {
win.document.documentElement.style.setProperty("--R2_FXL_X_SHIFT", fxl.tx >= 0 ? "0px" : `${fxl.tx}px`);
}
const ty = fxl.ty >= 0 ? fxl.ty : 0;
win.document.documentElement.style.setProperty((wvSlot_ === styles_1.WebViewSlotEnum.left || wvSlot_ === styles_1.WebViewSlotEnum.center) ? "--R2_FXL_Y_SHIFT" : "--R2_FXL_Y_SHIFT_", fxl.ty >= 0 ? "0px" : `${fxl.ty}px`);
const cxx = ` width:${fxl.width * fxl.scale}px; height:${fxl.height * fxl.scale}px; transform-origin: 0 0; transform: translate(${tx}px, ${ty}px) scale(${"1"});`;
wv.setAttribute("style", wvSlot_ === styles_1.WebViewSlotEnum.center ? webviewStyleCenter_ + cxx :
(wvSlot_ === styles_1.WebViewSlotEnum.left ? webviewStyleLeft_ + cxx :
webviewStyleRight_ + cxx));
wv.setAttribute("data-wv-fxl", v);
}
else {
wv.setAttribute("style", wvSlot === styles_1.WebViewSlotEnum.center ? webviewStyleCenter :
(wvSlot === styles_1.WebViewSlotEnum.left ? webviewStyleLeft :
webviewStyleRight));
wv.removeAttribute("data-wv-fxl");
wv.setAttribute("data-wv-slot", wvSlot === styles_1.WebViewSlotEnum.center ? "center" :
(wvSlot === styles_1.WebViewSlotEnum.left ? "left" :
"right"));
}
}
function keyboardFocusRequest(deep, webview) {
var _a, _b, _c, _d;
if (!webview) {
const loc = getCurrentReadingLocation();
if (loc === null || loc === void 0 ? void 0 : loc.locator) {
const activeWebViews = win.READIUM2.getActiveWebViews();
for (const activeWebView of activeWebViews) {
if (activeWebView.READIUM2.DOMisReady &&
loc.locator.href === ((_a = activeWebView.READIUM2.link) === null || _a === void 0 ? void 0 : _a.Href)) {
webview = activeWebView;
debug("KEYBOARD FOCUS REQUEST (222) -- NO WEBVIEW => FOUND", loc.locator.href);
break;
}
}
}
}
if (!webview) {
debug("KEYBOARD FOCUS REQUEST (222) -- NO WEBVIEW??! ... FALLBACK");
webview = (_b = win.READIUM2) === null || _b === void 0 ? void 0 : _b.getFirstOrSecondWebView();
}
if (!webview || !webview.READIUM2.DOMisReady) {
debug("KEYBOARD FOCUS REQUEST (222) -- NO WEBVIEW??! FAIL :(", !!webview, webview === null || webview === void 0 ? void 0 : webview.READIUM2.DOMisReady);
return;
}
debug("KEYBOARD FOCUS REQUEST (222) ", webview.id, !!win.document.activeElement, (_c = win.document.activeElement) === null || _c === void 0 ? void 0 : _c.id);
if (win.document.activeElement && win.document.activeElement.blur) {
debug("KEYBOARD FOCUS REQUEST (222) ... BLUR");
win.document.activeElement.blur();
}
const iframe = (_d = webview.shadowRoot) === null || _d === void 0 ? void 0 : _d.querySelector("iframe");
if (iframe) {
debug("KEYBOARD FOCUS REQUEST (222) --> IFRAME");
iframe.focus();
}
else {
debug("KEYBOARD FOCUS REQUEST (222) --> WEBVIEW (no IFRAME)");
webview.focus();
}
if (deep) {
setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
if ((_a = webview.READIUM2) === null || _a === void 0 ? void 0 : _a.DOMisReady) {
yield webview.send(events_1.R2_EVENT_FOCUS_READING_LOC);
}
}), 0);
}
}
function locationHandleIpcMessage(eventChannel, eventArgs, eventCurrentTarget) {
const activeWebView = eventCurrentTarget;
if (eventChannel === events_1.R2_EVENT_LOCATOR_VISIBLE) {
}
else if (eventChannel === events_1.R2_EVENT_SHIFT_VIEW_X) {
if (!activeWebView.hasAttribute("data-wv-fxl")) {
shiftWebview(activeWebView, eventArgs[0].offset, eventArgs[0].backgroundColor);
}
}
else if (eventChannel === events_1.R2_EVENT_PAGE_TURN_RES) {
const payload = eventArgs[0];
if (payload.nav) {
navPreviousOrNext(payload.go === "PREVIOUS");
return true;
}
const publication = win.READIUM2.publication;
const publicationURL = win.READIUM2.publicationURL;
if (!publication) {
return true;
}
const doNothing = payload.go === "";
if (doNothing) {
return true;
}
const goPREVIOUS = payload.go === "PREVIOUS";
if (!activeWebView.READIUM2.link) {
debug("WEBVIEW READIUM2_LINK ??!!");
return true;
}
let nextOrPreviousSpineItem;
if (publication.Spine) {
for (let i = 0; i < publication.Spine.length; i++) {
if (publication.Spine[i] === activeWebView.READIUM2.link) {
if (goPREVIOUS && (i - 1) >= 0) {
nextOrPreviousSpineItem = publication.Spine[i - 1];
}
else if (!goPREVIOUS && (i + 1) < publication.Spine.length) {
nextOrPreviousSpineItem = publication.Spine[i + 1];
}
break;
}
}
}
if (!nextOrPreviousSpineItem) {
return true;
}
if (publicationURL) {
const uri = new url_1.URL(nextOrPreviousSpineItem.Href, publicationURL);
uri.hash = "";
uri.search = "";
const urlNoQueryParams = uri.toString();
debug(`locationHandleIpcMessage R2_EVENT_PAGE_TURN_RES: ${urlNoQueryParams}`);
handleLink(urlNoQueryParams, goPREVIOUS, false, activeWebView.READIUM2.readiumCss);
}
}
else if (eventChannel === events_1.R2_EVENT_READING_LOCATION_CLEAR_SELECTION) {
if (_lastSavedReadingLocation === null || _lastSavedReadingLocation === void 0 ? void 0 : _lastSavedReadingLocation.selectionInfo) {
_lastSavedReadingLocation.selectionInfo = undefined;
}
}
else if (eventChannel === events_1.R2_EVENT_READING_LOCATION) {
const payload = eventArgs[0];
if (activeWebView.READIUM2.link) {
_saveReadingLocation(activeWebView, payload);
}
}
else if (eventChannel === events_1.R2_EVENT_LINK) {
const payload = eventArgs[0];
debug(`locationHandleIpcMessage R2_EVENT_LINK: ${payload.url}`);
let href = payload.url;
if (!/^(https?|thoriumhttps):\/\//.test(href) &&
!href.startsWith((sessions_1.READIUM2_ELECTRON_HTTP_PROTOCOL + "://")) &&
activeWebView.READIUM2.link) {
const sourceUrl = new url_1.URL(activeWebView.READIUM2.link.Href, win.READIUM2.publicationURL);
const destUrl = new url_1.URL(href, sourceUrl);
href = destUrl.toString();
debug(`R2_EVENT_LINK ABSOLUTE-ized: ${href}`);
}
const eventPayload = {
url: href,
rcss: activeWebView.READIUM2.readiumCss,
};
electron_1.ipcRenderer.emit(events_1.R2_EVENT_LINK, eventPayload);
}
else if (eventChannel === events_1.R2_EVENT_AUDIO_PLAYBACK_RATE) {
const payload = eventArgs[0];
(0, audiobook_2.setCurrentAudioPlaybackRate)(payload.speed);
}
else {
return false;
}
return true;
}
electron_1.ipcRenderer.on(events_1.R2_EVENT_LINK, (event, payload) => {
if (!win.READIUM2) {
return;
}
debug("R2_EVENT_LINK (ipcRenderer.on)");
const pay = (!payload && event.url) ? event : payload;
debug(pay.url);
if (pay.url.indexOf("#" + url_params_1.FRAG_ID_CSS_SELECTOR) >= 0) {
debug("R2_EVENT_LINK (ipcRenderer.on) SKIP link activation [FRAG_ID_CSS_SELECTOR]");
return;
}
const activeWebView = pay.rcss ? undefined : win.READIUM2.getFirstOrSecondWebView();
handleLinkUrl(pay.url, pay.rcss ? pay.rcss :
(activeWebView ? activeWebView.READIUM2.readiumCss : undefined));
});
function shiftWebview(webview, offset, backgroundColor) {
if (!offset) {
webview.style.transform = "none";
}
else {
if (backgroundColor) {
const domSlidingViewport = win.READIUM2.domSlidingViewport;
domSlidingViewport.style.backgroundColor = backgroundColor;
}
webview.style.transform = `translateX(${offset}px)`;
}
}
function navPreviousOrNext(goPREVIOUS, spineNav, ignorePageSpreadHandling) {
const publication = win.READIUM2.publication;
const publicationURL = win.READIUM2.publicationURL;
if (!publication || !publicationURL) {
return undefined;
}
if (!publication.Spine) {
return undefined;
}
const loc = _lastSavedReadingLocation;
let href = loc ? loc.locator.href : undefined;
if (!ignorePageSpreadHandling) {
let linkFirst;
let linkSecond;
const firstWebView = win.READIUM2.getFirstWebView();
if (firstWebView) {
linkFirst = firstWebView.READIUM2.link;
}
const secondWebView = win.READIUM2.getSecondWebView(false);
if (secondWebView) {
linkSecond = secondWebView.READIUM2.link;
}
if (linkFirst && linkSecond) {
const indexFirst = publication.Spine.indexOf(linkFirst);
const indexSecond = publication.Spine.indexOf(linkSecond);
if (indexSecond >= 0 && indexFirst >= 0) {
const boundaryLink = indexSecond < indexFirst ?
(goPREVIOUS ? linkSecond : linkFirst) :
(goPREVIOUS ? linkFirst : linkSecond);
debug(`navLeftOrRight spineNav = true force ${href} => ${boundaryLink.Href}`);
spineNav = true;
href = boundaryLink.Href;
}
}
}
if (spineNav) {
if (!href) {
return undefined;
}
const offset = goPREVIOUS ? -1 : 1;
const currentSpineIndex = publication.Spine.findIndex((link) => {
return link.Href === href;
});
if (currentSpineIndex >= 0) {
const spineIndex = currentSpineIndex + offset;
if (spineIndex >= 0 && spineIndex <= (publication.Spine.length - 1)) {
const nextOrPreviousSpineItem = publication.Spine[spineIndex];
const uri = new url_1.URL(nextOrPreviousSpineItem.Href, publicationURL);
uri.hash = "";
uri.search = "";
const urlNoQueryParams = uri.toString();
const activeWebView = win.READIUM2.getFirstOrSecondWebView();
debug(`navLeftOrRight: ${urlNoQueryParams}`);
handleLink(urlNoQueryParams, goPREVIOUS, false, activeWebView ? activeWebView.READIUM2.readiumCss : undefined);
return nextOrPreviousSpineItem;
}
else {
electron_1.shell.beep();
}
}
(0, media_overlays_1.mediaOverlaysInterrupt)();
}
else {
(0, media_overlays_1.mediaOverlaysInterrupt)();
const payload = {
go: goPREVIOUS ? "PREVIOUS" : "NEXT",
};
const activeWebView = win.READIUM2.getFirstOrSecondWebView();
if (activeWebView) {
setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
if ((_a = activeWebView.READIUM2) === null || _a === void 0 ? void 0 : _a.DOMisReady) {
yield activeWebView.send(events_1.R2_EVENT_PAGE_TURN, payload);
}
}), 0);
}
}
return undefined;
}
function navLeftOrRight(left, spineNav, ignorePageSpreadHandling) {
var _a;
const loc = _lastSavedReadingLocation;
const rtl = (0, readium_css_1.isRTL_PackageMeta)() ||
(typeof ((_a = loc === null || loc === void 0 ? void 0 : loc.docInfo) === null || _a === void 0 ? void 0 : _a.isRightToLeft) !== "undefined" ?
loc.docInfo.isRightToLeft :
(0, readium_css_1.isRTL_PackageMeta)());
const goPREVIOUS = left ? !rtl : rtl;
return navPreviousOrNext(goPREVIOUS, spineNav, ignorePageSpreadHandling);
}
function handleLink(href, previous, useGoto, rcss) {
debug(`handleLink: ${href}`);
const special = href.startsWith(sessions_1.READIUM2_ELECTRON_HTTP_PROTOCOL + "://");
if (special) {
debug("handleLink R2 URL");
const okay = loadLink(href, previous, useGoto, rcss);
if (!okay) {
debug(`Readium link fail?! ${href}`);
}
}
else if (href.startsWith("file://")) {
debug(`Skip navigation/link to local filesystem: ${href}`);
}
else {
debug("handleLink non-R2 URL");
const okay = loadLink(href, previous, useGoto, rcss);
if (!okay) {
if (/^https?:\/\/127\.0\.0\.1/.test(href)) {
debug(`Internal link, fails to match publication document: ${href}`);
}
else if (href && /^https?:\/\//.test(href)) {
debug(`External link: ${href}`);
(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
try {
yield electron_1.shell.openExternal(href);
}
catch (err) {
debug(err);
}
}))();
}
}
}
}
function handleLinkUrl(href, rcss) {
debug(`handleLinkUrl: ${href}`);
handleLink(href, undefined, false, rcss);
}
function handleLinkLocator(location, rcss) {
var _a, _b;
const rangeInfo = (_b = (_a = location === null || location === void 0 ? void 0 : location.locations) === null || _a === void 0 ? void 0 : _a.caretInfo) === null || _b === void 0 ? void 0 : _b.rangeInfo;
const publication = win.READIUM2.publication;
const publicationURL = win.READIUM2.publicationURL;
if (!publication || !publicationURL) {
return;
}
let linkToLoad;
let linkToLoadGoto;
if (location && location.href) {
if (publication.Spine && publication.Spine.length) {
linkToLoad = publication.Spine.find((spineLink) => {
return spineLink.Href === location.href;
});
if (linkToLoad && location.locations) {
linkToLoadGoto = location.locations;
}
}
if (!linkToLoad &&
publication.Resources && publication.Resources.length) {
linkToLoad = publication.Resources.find((resLink) => {
return resLink.Href === location.href;
});
if (linkToLoad && location.locations) {
linkToLoadGoto = location.locations;
}
}
}
if (!linkToLoad) {
debug(`handleLinkLocator FAIL ${publicationURL} + ${location ? location.href : "NIL"}`);
}
if (!linkToLoad) {
if (publication.Spine && publication.Spine.length) {
const firstLinear = publication.Spine[0];
if (firstLinear) {
linkToLoad = firstLinear;
}
}
}
if (linkToLoad) {
const useGoto = typeof linkToLoadGoto !== "undefined";
const uri = new url_1.URL(linkToLoad.Href, publicationURL);
uri.hash = "";
uri.search = "";
const urlNoQueryParams = uri.toString();
const hrefToLoad = urlNoQueryParams +
(useGoto ? ("?" + url_params_1.URL_PARAM_GOTO + "=" +
(0, UrlUtils_1.encodeURIComponent_RFC3986)(Buffer.from(JSON.stringify(linkToLoadGoto, null, "")).toString("base64"))) :
"") +
((useGoto && rangeInfo) ? ("&" + url_params_1.URL_PARAM_GOTO_DOM_RANGE + "=" +
(0, UrlUtils_1.encodeURIComponent_RFC3986)(Buffer.from(JSON.stringify(rangeInfo, null, "")).toString("base64"))) :
"");
debug(`handleLinkLocator: ${hrefToLoad}`);
handleLink(hrefToLoad, undefined, useGoto, rcss);
}
}
let _reloadCounter = 0;
function reloadContent() {
const activeWebViews = win.READIUM2.getActiveWebViews();
for (const activeWebView of activeWebViews) {
reloadWebView(activeWebView);
}
}
function reloadWebView(activeWebView) {
setTimeout(() => {
activeWebView.READIUM2.forceRefresh = true;
if (activeWebView.READIUM2.link) {
const uri = new url_1.URL(activeWebView.READIUM2.link.Href, win.READIUM2.publicationURL);
uri.hash = "";
uri.search = "";
const urlNoQueryParams = uri.toString();
debug(`reloadContent: ${urlNoQueryParams}`);
handleLinkUrl(urlNoQueryParams, activeWebView.READIUM2.readiumCss);
}
}, 0);
}
function loadLink(hrefToLoad, previous, useGoto, rcss, secondWebView) {
var _a, _b, _c, _d, _e, _f, _g, _h;
if (typeof win.READIUM2.opacityMaskCounter === "undefined" || !secondWebView) {
win.READIUM2.opacityMaskCounter = 0;
}
const publication = win.READIUM2.publication;
const publicationURL = win.READIUM2.publicationURL;
if (!publication || !publicationURL) {
return false;
}
(0, media_overlays_1.mediaOverlaysInterrupt)();
if (!hrefToLoad.startsWith(sessions_1.READIUM2_ELECTRON_HTTP_PROTOCOL + "://")) {
debug(`LOAD LINK not internal? ${hrefToLoad} ... ${publicationURL}`);
return false;
}
const hrefToLoadHttp = (0, sessions_1.convertCustomSchemeToHttpUrl)(hrefToLoad);
const pubIsServedViaSpecialUrlProtocol = publicationURL.startsWith(sessions_1.READIUM2_ELECTRON_HTTP_PROTOCOL + "://");
const publicationURLHttp = pubIsServedViaSpecialUrlProtocol ?
(0, sessions_1.convertCustomSchemeToHttpUrl)(publicationURL) : publicationURL;
const hrefToLoadHttpObj = new url_1.URL(hrefToLoadHttp);
hrefToLoadHttpObj.hash = "";
hrefToLoadHttpObj.search = "";
const publicationURLHttpObj = new url_1.URL(publicationURLHttp);
publicationURLHttpObj.hash = "";
publicationURLHttpObj.search = "";
const rootPath = publicationURLHttpObj.pathname.replace(/manifest\.json$/, "");
let linkPath = hrefToLoadHttpObj.pathname.replace(rootPath, "");
linkPath = decodeURIComponent(linkPath);
debug(`R2LOADLINK: ${hrefToLoad} ... ${publicationURL} ==> ${linkPath}`);
let pubLink = publication.Spine ? publication.Spine.find((spineLink) => {
return spineLink.Href === linkPath;
}) : undefined;
if (!pubLink && publication.Resources) {
pubLink = publication.Resources.find((resLink) => {
return resLink.Href === linkPath;
});
}
if (!pubLink) {
let hrefToLoadHttpNoHash;
try {
const hrefToLoadHttpObjUri = new URI(hrefToLoadHttp);
hrefToLoadHttpObjUri.hash("").normalizeHash();
hrefToLoadHttpObjUri.search((data) => {
data[url_params_1.URL_PARAM_PREVIOUS] = undefined;
data[url_params_1.URL_PARAM_GOTO] = undefined;
data[url_params_1.URL_PARAM_GOTO_DOM_RANGE] = undefined;
data[url_params_1.URL_PARAM_CSS] = undefined;
data[url_params_1.URL_PARAM_EPUBMEDIAOVERLAYS] = undefined;
data[url_params_1.URL_PARAM_EPUBREADINGSYSTEM] = undefined;
data[url_params_1.URL_PARAM_DEBUG_VISUALS] = undefined;
data[url_params_1.URL_PARAM_A11Y_SUPPORT_ENABLED] = undefined;
data[url_params_1.URL_PARAM_CLIPBOARD_INTERCEPT] = undefined;
data[url_params_1.URL_PARAM_REFRESH] = undefined;
data[url_params_1.URL_PARAM_WEBVIEW_SLOT] = undefined;
data[url_params_1.URL_PARAM_SECOND_WEBVIEW] = undefined;
data[url_params_1.URL_PARAM_HIGHLIGHTS] = undefined;
});
hrefToLoadHttpNoHash = hrefToLoadHttpObjUri.toString();
}
catch (err) {
debug(err);
}
if (hrefToLoadHttpNoHash) {
pubLink = publication.Spine ? publication.Spine.find((spineLink) => {
return spineLink.Href === hrefToLoadHttpNoHash;
}) : undefined;
if (!pubLink && publication.Resources) {
pubLink = publication.Resources.find((resLink) => {
return resLink.Href === hrefToLoadHttpNoHash;
});
}
}
if (!pubLink) {
debug(`CANNOT LOAD EXT LINK ${hrefToLoad} ... ${publicationURL} --- (${hrefToLoadHttpNoHash}) ==> ${linkPath}`);
return false;
}
}
if (!pubLink) {
debug(`CANNOT LOAD LINK ${hrefToLoad} ... ${publicationURL} ==> ${linkPath}`);
return false;
}
if (!secondWebView) {
win.document.documentElement.style.setProperty("--R2_FXL_X_SHIFT", "0px");
win.document.documentElement.style.setProperty("--R2_FXL_Y_SHIFT", "0px");
win.document.documentElement.style.setProperty("--R2_FXL_Y_SHIFT_", "0px");
}
const webview1 = win.READIUM2.getFirstWebView();
const webview2 = win.READIUM2.getSecondWebView(false);
const webviewSpreadSwap = secondWebView ?
(webview2 && webview1 && webview1.READIUM2.link === pubLink) :
(webview2 && webview2.READIUM2.link === pubLink);
const secondWebViewWasJustCreated = secondWebView && !webviewSpreadSwap && !webview2;
const activeWebView = webviewSpreadSwap ?
(secondWebView ? webview1 : win.READIUM2.getSecondWebView(true)) :
(secondWebView ? win.READIUM2.getSecondWebView(true) : webview1);
const actualReadiumCss = (activeWebView && activeWebView.READIUM2.readiumCss) ?
activeWebView.READIUM2.readiumCss :
(0, readium_css_1.obtainReadiumCss)(rcss);
if (activeWebView) {
activeWebView.READIUM2.readiumCss = actualReadiumCss;
}
const fileName = path.basename(linkPath);
const ext = path.extname(fileName);
const isAudio = publication.Metadata &&
publication.Metadata.RDFType &&
/https?:\/\/schema\.org\/Audiobook$/.test(publication.Metadata.RDFType) &&
((pubLink.TypeLink && pubLink.TypeLink.startsWith("audio/")) ||
/\.mp[3|4]$/i.test(ext) ||
/\.wav$/i.test(ext) ||
/\.aac$/i.test(ext) ||
/\.og[g|b|a]$/i.test(ext) ||
/\.aiff$/i.test(ext) ||
/\.wma$/i.test(ext) ||
/\.flac$/i.test(ext));
let webViewSlot = styles_1.WebViewSlotEnum.center;
let loadingSecondWebView;
const linkIndex = publication.Spine ? publication.Spine.indexOf(pubLink) : -1;
if (publication.Spine &&
linkIndex >= 0 &&
(0, readium_css_1.isFixedLayout)(pubLink)) {
const rtl = (0, readium_css_1.isRTL_PackageMeta)();
const publicationSpreadNone = ((_b = (_a = publication.Metadata) === null || _a === void 0 ? void 0 : _a.Rendition) === null || _b === void 0 ? void 0 : _b.Spread) === metadata_properties_1.SpreadEnum.None;
const slotOfFirstPageInSpread = rtl ? metadata_properties_1.PageEnum.Right : metadata_properties_1.PageEnum.Left;
const slotOfSecondPageInSpread = slotOfFirstPageInSpread === metadata_properties_1.PageEnum.Right ? metadata_properties_1.PageEnum.Left : metadata_properties_1.PageEnum.Right;
const linkSpreadNoneForced = ((_c = rcss === null || rcss === void 0 ? void 0 : rcss.setCSS) === null || _c === void 0 ? void 0 : _c.colCount) === "1" ||
((_d = rcss === null || rcss === void 0 ? void 0 : rcss.setCSS) === null || _d === void 0 ? void 0 : _d.colCount) === "auto" &&
win.READIUM2.domSlidingViewport &&
win.READIUM2.domSlidingViewport.clientWidth !== 0 &&
win.READIUM2.domSlidingViewport.clientHeight !== 0 &&
win.READIUM2.domSlidingViewport.clientWidth < win.READIUM2.domSlidingViewport.clientHeight;
publication.Spine.forEach((spineLink, i) => {
var _a, _b, _c, _d, _e;
spineLink.__notInSpread = false;
spineLink.__notInSpreadForced = false;
if (!(0, readium_css_1.isFixedLayout)(spineLink)) {
spineLink.__notInSpread = true;
if (!spineLink.Properties) {
spineLink.Properties = new metadata_properties_1.Properties();
}
spineLink.Properties.Page = metadata_properties_1.PageEnum.Center;
return;
}
if (linkSpreadNoneForced) {
spineLink.__notInSpreadForced = true;
}
const linkSpreadNone = linkSpreadNoneForced || ((_a = spineLink.Properties) === null || _a === void 0 ? void 0 : _a.Spread) === metadata_properties_1.SpreadEnum.None;
const linkSpreadOther = !linkSpreadNone && ((_b = spineLink.Properties) === null || _b === void 0 ? void 0 : _b.Spread);
const notInSpread = linkSpreadNone || (publicationSpreadNone && !linkSpreadOther);
spineLink.__notInSpread = notInSpread;
if (((_c = spineLink.Properties) === null || _c === void 0 ? void 0 : _c.Page) &&
spineLink.Properties.Page !== metadata_properties_1.PageEnum.Left &&
spineLink.Properties.Page !== metadata_properties_1.PageEnum.Right) {
spineLink.__notInSpread = true;
}
if (!((_d = spineLink.Properties) === null || _d === void 0 ? void 0 : _d.Page)) {
if (!spineLink.Properties) {
spineLink.Properties = new metadata_properties_1.Properties();
}
if (i === 0) {
spineLink.__notInSpread = true;
spineLink.Properties.Page = notInSpread ? metadata_properties_1.PageEnum.Center : slotOfSecondPageInSpread;
}
else {
const firstPageInSpread = publication.Spine &&
((_e = publication.Spine[i - 1].Properties) === null || _e === void 0 ? void 0 : _e.Page) !== slotOfFirstPageInSpread;
spineLink.Properties.Page = notInSpread ? metadata_properties_1.PageEnum.Center :
(firstPageInSpread ? slotOfFirstPageInSpread : slotOfSecondPageInSpread);
}
}
});
const prev = previous ? true : false;
const page = pubLink.__notInSpreadForced ? metadata_properties_1.PageEnum.Center : (_e = pubLink.Properties) === null || _e === void 0 ? void 0 : _e.Page;
if (page === metadata_properties_1.PageEnum.Left) {
webViewSlot = styles_1.WebViewSlotEnum.left;
if (!secondWebView && !pubLink.__notInSpread) {
const otherIndex = linkIndex + (rtl ? -1 : 1);
const otherLink = publication.Spine[otherIndex];
if (otherLink && !otherLink.__notInSpread &&
((_f = otherLink.Properties) === null || _f === void 0 ? void 0 : _f.Page) === metadata_properties_1.PageEnum.Right) {
const needToInverse = !webviewSpreadSwap &&
prev && publication.Spine.indexOf(pubLink) > otherIndex;
const otherLinkURLObj = new url_1.URL(otherLink.Href, publicationURL);
otherLinkURLObj.hash = "";
otherLinkURLObj.search = "";
loadingSecondWebView = otherLink;
loadLink(otherLinkURLObj.toString(), undefined, false, rcss, needToInverse ? false : true);
if (needToInverse) {
return true;
}
}
}
if (activeWebView) {
debug("loadLink LEFT ... setWebViewStyle");
win.READIUM2.domRootElement.style.opacity = "0";
win.READIUM2.opacityMaskCounter++;
setWebViewStyle(activeWebView, styles_1.WebViewSlotEnum.left);
}
}
else if (page === metadata_properties_1.PageEnum.Right) {
webViewSlot = styles_1.WebViewSlotEnum.right;
if (!secondWebView && !pubLink.__notInSpread) {
const otherIndex = linkIndex + (!rtl ? -1 : 1);
const otherLink = publication.Spine[otherIndex];
if (otherLink && !otherLink.__notInSpread &&
((_g = otherLink.Properties) === null || _g === void 0 ? void 0 : _g.Page) === metadata_properties_1.PageEnum.Left) {
const needToInverse = !webviewSpreadSwap &&
prev && publication.Spine.indexOf(pubLink) > otherIndex;
const otherLinkURLObj = new url_1.URL(otherLink.Href, publicationURL);
otherLinkURLObj.hash = "";
otherLinkURLObj.search = "";
loadingSecondWebView = otherLink;
loadLink(otherLinkURLObj.toString(), undefined, false, rcss, needToInverse ? false : true);
if (needToInverse) {
return true;
}
}
}
if (activeWebView) {
debug("loadLink RIGHT ... setWebViewStyle");
win.READIUM2.domRootElement.style.opacity = "0";
win.READIUM2.opacityMaskCounter++;
setWebViewStyle(activeWebView, styles_1.WebViewSlotEnum.right);
}
}
else {
webViewSlot = styles_1.WebViewSlotEnum.center;
if (activeWebView) {
debug("loadLink CENTER ... setWebViewStyle");
win.READIUM2.domRootElement.style.opacity = "0";
win.READIUM2.opacityMaskCounter++;
setWebViewStyle(activeWebView, styles_1.WebViewSlotEnum.center);
}
}
}
if (!secondWebView && !loadingSecondWebView && !webviewSpreadSwap) {
win.READIUM2.destroySecondWebView();
}
const rcssJson = (0, readium_css_1.adjustReadiumCssJsonMessageForFixedLayout)(activeWebView, pubLink || (activeWebView === null || activeWebView === void 0 ? void 0 : activeWebView.READIUM2.link), actualReadiumCss);
const rcssJsonstr = JSON.stringify(rcssJson, null, "");
const rcssJsonstrBase64 = Buffer.from(rcssJsonstr).toString("base64");
const hrefToLoadHttpUri = new URI(hrefToLoadHttp);
if ((_h = hrefToLoadHttpUri.fragment()) === null || _h === void 0 ? void 0 : _h.startsWith(url_params_1.FRAG_ID_CSS_SELECTOR)) {
const cssSelector = decodeURIComponent(hrefToLoadHttpUri.fragment().substring(url_params_1.FRAG_ID_CSS_SELECTOR.length));
debug("FRAG_ID_CSS_SELECTOR: " + cssSelector);
hrefToLoadHttpUri.hash("").normalizeHash();
hrefToLoadHttpUri.search((data) => {
data[url_params_1.URL_PARAM_GOTO] = Buffer.from(JSON.stringify({ cssSelector }, null, "")).toString("base64");
});
useGoto = true;
}
if (isAudio) {
if (useGoto) {
hrefToLoadHttpUri.hash("").normalizeHash();
if (pubLink.Duration) {
const gotoBase64 = hrefToLoadHttpUri.search(true)[url_params_1.URL_PARAM_GOTO];
if (gotoBase64) {
const str = Buffer.from(gotoBase64, "base64").toString("utf8");
const json = JSON.parse(str);
const gotoProgression = json.progression;
if (typeof gotoProgression !== "undefined") {
const time = gotoProgression * pubLink.Duration;
hrefToLoadHttpUri.hash(`t=${time}`).normalizeHash();
}
}
}
}
hrefToLoadHttpUri.search((data) => {
data[url_params_1.URL_PARAM_PREVIOUS] = undefined;
data[url_params_1.URL_PARAM_GOTO] = undefined;
data[url_params_1.URL_PARAM_GOTO_DOM_RANGE] = undefined;
data[url_params_1.URL_PARAM_CSS] = undefined;
data[url_params_1.URL_PARAM_EPUBMEDIAOVERLAYS] = undefined;
data[url_params_1.URL_PARAM_EPUBREADINGSYSTEM] = undefined;
data[url_params_1.URL_PARAM_DEBUG_VISUALS] = undefined;
data[url_params_1.URL_PARAM_A11Y_SUPPORT_ENABLED] = undefined;
data[url_params_1.URL_PARAM_CLIPBOARD_INTERCEPT] = undefined;
data[url_params_1.URL_PARAM_REFRESH] = undefined;
data[url_params_1.URL_PARAM_WEBVIEW_SLOT] = undefined;
data[url_params_1.URL_PARAM_SECOND_WEBVIEW] = undefined;
data[url_params_1.URL_PARAM_HIGHLIGHTS] = undefined;
});
}
else {
hrefToLoadHttpUri.search((data) => {
if (typeof previous === "undefined") {
data[url_params_1.URL_PARAM_PREVIOUS] = undefined;
}
else {
data[url_params_1.URL_PARAM_PREVIOUS] = previous ? "true" : "false";
}
if (!useGoto) {
data[url_params_1.URL_PARAM_GOTO] = undefined;
data[url_params_1.URL_PARAM_GOTO_DOM_RANGE] = undefined;
}
});
if (useGoto) {
hrefToLoadHttpUri.hash("").normalizeHash();
}
const rersJson = (0, epubReadingSystem_1.getEpubReadingSystemInfo)();
const rersJsonstr = JSON.stringify(rersJson, null, "");
const rersJsonstrBase64 = Buffer.from(rersJsonstr).toString("base64");
hrefToLoadHttpUri.search((data) => {
data[url_params_1.URL_PARAM_CSS] = rcssJsonstrBase64;
data[url_params_1.URL_PARAM_EPUBMEDIAOVERLAYS] = win.READIUM2.publication ? ((0, media_overlays_1.publicationHasMediaOverlays)(win.READIUM2.publication) ? "1" : "0") : "0";
data[url_params_1.URL_PARAM_EPUBREADINGSYSTEM] = rersJsonstrBase64;
data[url_params_1.URL_PARAM_DEBUG_VISUALS] = (IS_DEV &&
win.READIUM2.DEBUG_VISUALS) ?
"true" : "false";
data[url_params_1.URL_PARAM_A11Y_SUPPORT_ENABLED] =
win.READIUM2.accessibilitySupportEnabled ?
"true" : "false";
data[url_params_1.URL_PARAM_CLIPBOARD_INTERCEPT] =
win.READIUM2.clipboardInterceptor ?
"true" : "false";
data[url_params_1.URL_PARAM_WEBVIEW_SLOT] = webViewSlot;
data[url_params_1.URL_PARAM_SECOND_WEBVIEW] = secondWebView ? "1" :
(loadingSecondWebView ? `0${loadingSecondWebView.Href}` : "0");
});
}
const webviewNeedsForcedRefresh = !isAudio && (win.READIUM2.ttsClickEnabled ||
activeWebView && activeWebView.READIUM2.forceRefresh);
if (activeWebView) {
activeWebView.READIUM2.forceRefresh = undefined;
}
const webviewNeedsHardRefresh = !isAudio &&
(win.READIUM2.enableScreenReaderAccessibilityWebViewHardRefresh
&& win.READIUM2.accessibilitySupportEnabled);
if (!isAudio && !webviewNeedsHardRefresh && !webviewNeedsForcedRefresh &&
activeWebView && activeWebView.READIUM2.link === pubLink && !(0, readium_css_1.isFixedLayout)(pubLink)) {
const goto = useGoto ? hrefToLoadHttpUri.search(true)[url_params_1.URL_PARAM_GOTO] : undefined;
const gotoDomRange = useGoto ? hrefToLoadHttpUri.search(true)[url_params_1.URL_PARAM_GOTO_DOM_RANGE] : undefined;
const hash = useGoto ? undefined : hrefToLoadHttpUri.fragment();
debug("WEBVIEW ALREADY LOADED: " + pubLink.Href);
const payload = {
goto,
gotoDomRange,
hash,
isSecondWebView: secondWebView ? true : false,
previous: previous ? true : false,
};
if (IS_DEV) {
const msgStr = JSON.stringify(payload);
debug(msgStr);
}
if (activeWebView) {
if (styles_1.ENABLE_EXTRA_COLUMN_SHIFT_METHOD &&
activeWebView.style.transform &&
activeWebView.style.transform !== "none" &&
!activeWebView.hasAttribute("data-wv-fxl")) {
activeWebView.style.opacity = "0";
setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
shiftWebview(activeWebView, 0, undefined);
if ((_a = activeWebView.READIUM2) === null || _a === void 0 ? void 0 : _a.DOMisReady) {
yield activeWebView.send(events_1.R2_EVENT_SCROLLTO, payload);
}
}), 10);
}
else {
setTimeout(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
var _a;
if ((_a = activeWebView.READIUM2) === null || _a === void 0 ? void 0 : _a.DOMisReady) {
yield activeWebView.send(events_1.R2_EVENT_SCROLLTO, payload);
}
}), 0);
}
}
return true;
}
if (activeWebView) {
if (webviewNeedsForcedRefresh) {
hrefToLoadHttpUri.search((data) => {
data[url_params_1.URL_PARAM_REFRESH] = `${++_reloadCounter}`;
});
}
if (win.READIUM2.sessionInfo) {
hrefToLoadHttpUri.search((data) => {
if (win.READIUM2.sessionInfo) {
const b64SessionInfo = Buffer.from(win.READIUM2.sessionInfo).toString("base64");
data[url_params_1.URL_PARAM_SESSION_INFO] = b64SessionInfo;
}
});
}
const uriStr = hrefToLoadHttpUri.toString();
const uriStr_ = uriStr.startsWith(sessions_1.READIUM2_ELECTRON_HTTP_PROTOCOL + "://") ? uriStr :
(pubIsServedViaSpecialUrlProtocol ? (0, sessions_1.convertHttpUrlToCustomScheme)(uriStr) : uriStr);
if (isAudio) {
if (IS_DEV) {
debug(`___HARD AUDIO___ WEBVIEW REFRESH: ${uriStr_}`);
}
const readiumCssBackup = activeWebView.READIUM2.readiumCss;
if (secondWebView) {
if (!secondWebViewWasJustCreated) {
win.READIUM2.destroySecondWebView();
win.READIUM2.createSecondWebView();
}
}
else {
win.READIUM2.destroyFirstWebView();
win.READIUM2.createFirstWebView();
}
const newActiveWebView = secondWebView ?
win.READIUM2.getSecondWebView(false) :
win.READIUM2.getFirstWebView();
if (newActiveWebView) {
newActiveWebView.READIUM2.readiumCss = readiumCssBackup;
newActiveWebView.READIUM2.link = pubLink;
const coverLink = publication.GetCover();
let title;
if (pubLink.Title) {
const regExp = /&(nbsp|amp|quot|lt|gt);/g;
const map = {
amp: "&",
gt: ">",
lt: "<",
nbsp: " ",
quot: "\"",
};
title = pubLink.Title.replace(regExp, (_match, entityName) => {
return map[entityName] ? map[entityName] : entityName;
});
}
const audioPlaybackRate = (0, audiobook_2.getCurrentAudioPlaybackRate)();
if (rcssJson.setCSS) {
rcssJson.setCSS.paged = false;
}
let htmlMarkup = `<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
<head>
<meta charset="utf-8" />
${title ? `<title>${title}</title>` : "<!-- NO TITLE -->"}
<base href="${publicationURLHttp}" id="${readium_css_inject_1.READIUM2_BASEURL_ID}" />
<style type="text/css">
/*<![CDATA[*/
/*]]>*/
</style>
<script>
//<![CDATA[
const DEBUG_AUDIO = ${IS_DEV};
const DEBUG_AUDIO_X = ${audiobook_1.DEBUG_AUDIO};
document.addEventListener("DOMContentLoaded", () => {
const _audioElement = document.getElementById("${styles_1.AUDIO_ID}");
_audioElement.playbackRate = ${audioPlaybackRate};
_audioElement.addEventListener("error", function()
{
console.debug("-1) error");
if (_audioElement.error) {
// 1 === MEDIA_ERR_ABORTED
// 2 === MEDIA_ERR_NETWORK
// 3 === MEDIA_ERR_DECODE
// 4 === MEDIA_ERR_SRC_NOT_SUPPORTED
console.log(_audioElement.error.code);
console.log(_audioElement.error.message);
}
}
);
if (DEBUG_AUDIO)
{
_audioElement.addEventListener("load", function()
{
console.debug("0) load");
}
);
_audioElement.addEventListener("loadstart", function()
{
console.debug("1) loadstart");
}
);
_audioElement.addEventListener("durationchange", function()
{
console.debug("2) durationchange");
}
);
_audioElement.addEventListener("loadedmetadata", function()
{
console.debug("3) loadedmetadata");
}
);
_audioElement.addEventListener("loadeddata", function()
{
console.debug("4) loadeddata");
}
);
_audioElement.addEventListener("progress", function()
{
console.debug("5) progress");
}
);
_audioElement.addEventListener("canplay", function()
{
console.debug("6) canplay");
}
);
_audioElement.addEventListener("canplaythrough", function()
{
console.debug("7) canplaythrough");
}
);
_audioElement.addEventListener("play", function()
{
console.debug("8) play");
}
);
_audioElement.addEventListener("pause", function()
{
console.debug("9) pause");
}
);
_audioElement.addEventListener("ended", function()
{
console.debug("10) ended");
}
);
_audioElement.addEventListener("seeked", function()
{
console.debug("11) seeked");
}
);
if (DEBUG_AUDIO_X) {
_audioElement.addEventListener("timeupdate", function()
{
console.debug("12) timeupdate");
}
);
}
_audioElement.addEventListener("seeking", function()
{
console.debug("13) seeking");
}
);
_audioElement.addEventListener("waiting", function()
{
console.debug("14) waiting");
}
);
_audioElement.addEventListener("volumechange", function()
{
console.debug("15) volumechange");
}
);
_audioElement.addEventListener("suspend", function()
{
console.debug("16) suspend");
}
);
_audioElement.addEventListener("stalled", function()
{
console.debug("17) stalled");
}
);
_audioElement.addEventListener("ratechange", function()
{
console.debug("18) ratechange");
}
);
_audioElement.addEventListener("playing", function()
{
console.debug("19) playing");
}
);
_audioElement.addEventListener("interruptend", function()
{
console.debug("20) interruptend");
}
);
_audioElement.addEventListener("interruptbegin", function()
{
console.debug("21) interruptbegin");
}
);
_audioElement.addEventListener("emptied", function()
{
console.debug("22) emptied");
}
);
_audioElement.addEventListener("abort", function()
{
console.debug("23) abort");
}
);
}
}, false);
//]]>
</script>
</head>
<body id="${styles_1.AUDIO_BODY_ID}">
<section id="${styles_1.AUDIO_SECTION_ID}">
${title ? `<h3 id="${styles_1.AUDIO_TITLE_ID}">${title}</h3>` : ""}
${coverLink ? `<img id="${styles_1.AUDIO_COVER_ID}" src="${coverLink.Href}" alt="" ${coverLink.Height ? `height="${coverLink.Height}"` : ""} ${coverLink.Width ? `width="${coverLink.Width}"` : ""} ${coverLink.Width || coverLink.Height ? `style="${coverLink.Height ? `height: ${coverLink.Height}px !important;` : ""} ${coverLink.Width ? `width: ${coverLink.Width}px !important;` : ""}"` : ""}/>` : ""}
<audio
id="${styles_1.AUDIO_ID}"
${audiobook_1.DEBUG_AUDIO ? "controlsx=\"controlsx\"" : ""}
autoplay="autoplay"
preload="metadata">
<source src="${uriStr}" type="${pubLink.TypeLink}" />
</audio>
${audiobook_1.DEBUG_AUDIO ?
`
<canvas id="${styles_1.AUDIO_BUFFER_CANVAS_ID}"> </canvas>
`
: ""}
<!-- SVG credits (tweaked sizing and coloring): https://material.io/resources/icons/?style=round -->
<div id="${styles_1.AUDIO_CONTROLS_ID}">
<button id="${styles_1.AUDIO_PREVIOUS_ID}" title="previous">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" width="48px" height="48px">
<path d="M7 6c.55 0 1 .45 1 1v10c0 .55-.45 1-1 1s-1-.45-1-1V7c0-.55.45-1 1-1zm3.66 6.82l5.77 4.07c.66.47 1.58-.01 1.58-.82V7.93c0-.81-.91-1.28-1.58-.82l-5.77 4.07c-.57.4-.57 1.24 0 1.64z"/></svg>
</button>
<button id="${styles_1.AUDIO_REWIND_ID}" title="rewind">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="48px" height="48px">
<path d="M12 5V2.21c0-.45-.54-.67-.85-.3