UNPKG

r2-navigator-js

Version:

Readium 2 'navigator' for NodeJS (TypeScript)

1,091 lines (1,059 loc) 67.1 kB
"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