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/reader.js | 1050 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 1014 insertions(+), 36 deletions(-) (limited to 'js/reader.js') diff --git a/js/reader.js b/js/reader.js index 1f6509a..d98e867 100644 --- a/js/reader.js +++ b/js/reader.js @@ -1,58 +1,1036 @@ 'use strict'; -/* global EpubeApp */ +/* global localforage, EpubeApp */ -function enable_swipes() { - $(window).off("swipeleft swiperight"); +const DEFAULT_FONT_SIZE = 16; +const DEFAULT_FONT_FAMILY = "Georgia"; +const DEFAULT_LINE_HEIGHT = 140; - $(window).on("swipeleft", function() { - parent.next_page(); - }); +const Reader = { + init: function() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker + .register('worker.js') + .then(function() { + console.log("service worker registered"); - $(window).on("swiperight", function() { - parent.prev_page(); - }); -} + Reader.Loader.init(); + }); + } else { + alert("Service worker support missing in browser (are you using plain HTTP?)."); + } -$(document).ready(function() { + $(document).on("keyup", function(e) { + Reader.hotkeyHandler(e); + }); + + $("#left").on("mouseup", function() { + Reader.Page.prev(); + }); + + $("#right").on("mouseup", function() { + Reader.Page.next(); + }); + }, + initSecondStage: function() { + + if (typeof EpubeApp != "undefined") { + EpubeApp.setPage("PAGE_READER"); + } + + Reader.applyTheme(); + + /* 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) { + Reader.Page._last_position_sync = new Date().getTime()/1000; + } + }) + .fail(function(e) { + if (e && e.status == 401) { + window.location = "index.php"; + } + }); + }); + + localforage.getItem(Reader.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(Reader.cacheId()).then(function(info) { + if (!info) { + $.post("backend.php", {op: "getinfo", id: bookId }, function(data) { + if (data) { + localforage.setItem(Reader.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(Reader.cacheId('cover'), resp.blob()); + } + }); + } + } + }); + } + }); + + const fileReader = new FileReader(); + + fileReader.onload = function() { + book.open(this.result).then(() => { + + // let's store this for later + localforage.setItem(Reader.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 + }); + + rendition.hooks.content.register(function() { + Reader.applyStyles(); + }); + + /*rendition.display().then(function() { + Reader.applyStyles(); + });*/ + + // 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_iframe.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 = Reader.Loader._res_data[base_url + res_names[i]]; + + doc.head.appendChild(elem); + } + + $(contents.document.head) + .append($("