From dcc41c8200af4ed95c281a604c33c631ca5ff01b Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 21 Apr 2020 10:51:19 +0300 Subject: rework reader to use global Reader object various theme-related fixes --- js/app.js | 2 +- js/dict.js | 2 +- js/read.js | 1055 --------------------------------------------------- js/reader.js | 1050 ++++++++++++++++++++++++++++++++++++++++++++++++-- js/reader_iframe.js | 61 +++ read.html | 24 +- worker.js | 2 +- 7 files changed, 1090 insertions(+), 1106 deletions(-) delete mode 100644 js/read.js create mode 100644 js/reader_iframe.js diff --git a/js/app.js b/js/app.js index 2aacebf..585726a 100644 --- a/js/app.js +++ b/js/app.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; /* global localforage, EpubeApp */ diff --git a/js/dict.js b/js/dict.js index 88bd154..f8336d2 100644 --- a/js/dict.js +++ b/js/dict.js @@ -7,7 +7,7 @@ $(document).ready(function() { const sel = getSelection().toString().trim(); if (sel.match(/^\w+$/)) { - parent.dict_lookup(sel, function() { + parent.Reader.lookupWord(sel, function() { getSelection().removeAllRanges(); }); } diff --git a/js/read.js b/js/read.js deleted file mode 100644 index c22b4d0..0000000 --- a/js/read.js +++ /dev/null @@ -1,1055 +0,0 @@ -'use strict'; - -/* globals ePub, localforage, book, cacheId, EpubeApp */ - -let _pagination_stored = 0; -let _last_position_sync = 0; -let _store_position = 0; - -//const _is_ios = (/iPad|iPhone|iPod/).test(navigator.userAgent) && !window.MSStream; -const _res_data = []; - -const DEFAULT_FONT_SIZE = 16; -const DEFAULT_FONT_FAMILY = "Georgia"; -const DEFAULT_LINE_HEIGHT = 140; - -function cacheId(suffix) { - return "epube-book." + $.urlParam("b") + (suffix ? "." + suffix : ""); -} - -function init_loader() { - // we need to preload resources for reader iframe because it can't utilize our - // service worker because while offline it is created outside our base server context - const res_names = [ "lib/bootstrap/v3/js/jquery.js", "lib/jquery.mobile-events.min.js", - "css/transitions.css", - "js/reader.js", "css/reader.css", "js/dict.js", - "themes/default.css", "themes/light.css", "themes/mocca.css", "themes/night.css", - "themes/plan9.css", "themes/gray.css", "themes/sepia.css" ]; - - for (let i = 0; i < res_names.length; i++) { - fetch(res_names[i], {credentials: 'same-origin'}).then(function(resp) { - if (resp.status == 200) { - resp.text().then(function(data) { - const url = new URL(resp.url); - url.searchParams.delete("ts"); - - _res_data[url.toString()] = data; - }) - } else { - console.warn('loader failed for resource', res_names[i], resp); - } - }); - } - - check_resource_load(res_names, _res_data, 0); -} - -function check_resource_load(res_names, res_data, attempt) { - console.log("check_resource_load", attempt, res_names.length, Object.keys(res_data).length); - - if (attempt == 5) { - $(".loading_message").html("Unable to load resources."); - return; - } - - if (res_names.length != Object.keys(res_data).length) { - window.setTimeout(function() { - check_resource_load(res_names, res_data, attempt+1); - }, 250); - } else { - init_reader(); - } -} - -function init_reader() { - if (typeof EpubeApp != "undefined") { - EpubeApp.setPage("PAGE_READER"); - } - - apply_theme(); - - /* global Cookie */ - - if (Cookie.get("is-epube-app") == "true") { - $("body").addClass("is-epube-app"); - } - - $(window).on('online', function() { - console.log("we're online, storing lastread"); - - const currentCfi = book.rendition.currentLocation().start.cfi; - const currentPage = parseInt(book.locations.percentageFromCfi(currentCfi) * 100); - - $.post("backend.php", { op: "storelastread", id: $.urlParam("id"), page: currentPage, - cfi: currentCfi }, function(data) { - - if (data.cfi) { - _last_position_sync = new Date().getTime()/1000; - } - }) - .fail(function(e) { - if (e && e.status == 401) { - window.location = "index.php"; - } - }); - }); - - localforage.getItem(cacheId("book")).then(function(item) { - - // ios doesn't work with FileReader for whatever reason - if (/*!_is_ios &&*/ item) { - - console.log("loading from local storage"); - - const fileReader = new FileReader(); - - fileReader.onload = function() { - try { - book.open(this.result); - } catch (e) { - $(".loading_message").html("Unable to load book (local)."); - console.log(e); - } - }; - - fileReader.readAsArrayBuffer(item); - - } else { - - console.log("loading from network"); - - if (navigator.onLine) { - const book_url = "backend.php?op=download&id=" + $.urlParam("id"); - - $(".loading_message").html("Downloading..."); - - fetch(book_url, {credentials: 'same-origin'}).then(function(resp) { - - if (resp.status == 200) { - const bookId = $.urlParam("b"); - - resp.blob().then(function(blob) { - - // if there's no base information cached yet, let's do that too - localforage.getItem(cacheId()).then(function(info) { - if (!info) { - $.post("backend.php", {op: "getinfo", id: bookId }, function(data) { - if (data) { - localforage.setItem(cacheId(), data); - - if (data.has_cover) { - fetch("backend.php?op=cover&id=" + bookId, {credentials: 'same-origin'}).then(function(resp) { - if (resp.status == 200) { - localforage.setItem(cacheId('cover'), resp.blob()); - } - }); - } - } - }); - } - }); - - const fileReader = new FileReader(); - - fileReader.onload = function() { - book.open(this.result).then(() => { - - // let's store this for later - localforage.setItem(cacheId('book'), blob); - - }).catch((e) => { - $(".loading_message").html("Unable to open book.
" + e + ""); - }); - }; - - fileReader.onerror = function(e) { - console.log('filereader error', e); - $(".loading_message").html("Unable to open book.
" + e + ""); - } - - fileReader.readAsArrayBuffer(blob); - - }).catch((e) => { - console.log('blob error', e); - $(".loading_message").html("Unable to download book.
" + e + ""); - }); - } else { - $(".loading_message").html("Unable to download book: " + resp.status + "."); - } - }).catch(function(e) { - console.warn(e); - - if ($(".loading").is(":visible")) { - $(".loading_message").html("Unable to load book (remote).
" + e + ""); - } - }); - - } else { - $(".loading_message").html("This book is not available offline."); - } - } - }); - - const book = ePub(); - window.book = book; - - const rendition = book.renderTo("reader", { - width: '100%', - height: '100%', - minSpreadWidth: 961 - }); - - const displayed = rendition.display(); - - // this sets default theme, then we apply CSS to already rendered content - // with apply_styles() - displayed.then(function () { - - let fontSize; - let fontFamily; - let lineHeight; - //let themeName; - - Promise.all([ - localforage.getItem("epube.fontSize"), - localforage.getItem("epube.fontFamily"), - localforage.getItem("epube.lineHeight"), - localforage.getItem("epube.theme") - ]).then(function(res) { - fontSize = res[0] ? res[0] + "px" : DEFAULT_FONT_SIZE + "px"; - fontFamily = res[1] ? res[1] : DEFAULT_FONT_FAMILY; - lineHeight = res[2] ? res[2] + "%" : DEFAULT_LINE_HEIGHT + "%"; - //themeName = res[3] ? res[3] : 'default'; - - rendition.themes.default({ - html: { - 'font-size': fontSize, - 'font-family': "'" + fontFamily + "'", - 'line-height': lineHeight, - 'text-align': 'justify' - } - }); - - }); - }); - - rendition.hooks.content.register(function(contents) { - - contents.on("linkClicked", function(href) { - console.log('linkClicked', href); - - if (href.indexOf("://") == -1) { - $(".prev_location_btn") - .attr("data-location-cfi", book.rendition.currentLocation().start.cfi) - .show(); - - window.setTimeout(function() { - show_ui(true); - }, 50); - } - - }); - - const base_url = window.location.href.match(/^.*\//)[0]; - const res_names = [ "lib/bootstrap/v3/js/jquery.js", "lib/jquery.mobile-events.min.js", - "js/reader.js", "js/dict.js" ]; - const doc = contents.document; - - for (let i = 0; i < res_names.length; i++) { - - // we need to create script element with proper context, that is inside the iframe - const elem = doc.createElement("script"); - elem.type = 'text/javascript'; - elem.text = _res_data[base_url + res_names[i]]; - - doc.head.appendChild(elem); - } - - $(contents.document.head) - .append($("