summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2024-01-13 20:45:09 +0300
committerAndrew Dolgov <[email protected]>2024-01-13 20:45:09 +0300
commit4cd967ec87da352ad2b792dc4b41995cdb5e2df4 (patch)
treef60291c979e608122b87d91f780ad0f76a7f3d15
parent98e2ece85a03c8d4991bd0fbca61976d9732c53e (diff)
bring back downloading notice
-rw-r--r--dist/app.min.js2
-rw-r--r--js/reader.js2
2 files changed, 3 insertions, 1 deletions
diff --git a/dist/app.min.js b/dist/app.min.js
index e5b086b..88b8b3f 100644
--- a/dist/app.min.js
+++ b/dist/app.min.js
@@ -1 +1 @@
-"use strict";$.urlParam=function(t){try{const e=new RegExp("[?&]"+t+"=([^&#]*)").exec(window.location.href);return decodeURIComponent(e[1].replace(/\+/g," "))||0}catch(t){return 0}};const Cookie={set:function(t,e,o){const n=new Date;n.setTime(n.getTime()+1e3*o);const a="expires="+n.toUTCString();document.cookie=t+"="+encodeURIComponent(e)+"; "+a},get:function(t){t+="=";const e=document.cookie.split(";");for(let o=0;o<e.length;o++){let n=e[o];for(;" "==n.charAt(0);)n=n.substring(1);if(0==n.indexOf(t))return decodeURIComponent(n.substring(t.length,n.length))}return""},delete:function(t){document.cookie=t+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT"}},App={_dl_progress_timeout:!1,index_mode:"",last_mtime:-1,cached_urls:[],version:"UNKNOWN",csrf_token:"",init:function(){let t=0;this.csrf_token=Cookie.get("epube_csrf_token"),console.log("setting prefilter for token",this.csrf_token),$.ajaxPrefilter((function(t,e,o){if("post"!==e.type||"post"!==t.type)return;const n=typeof e.data;"object"==n?t.data=$.param($.extend(e.data,{csrf_token:App.csrf_token})):"string"==n&&(t.data=e.data+"&csrf_token="+encodeURIComponent(App.srf_token)),console.log(">>>",t)})),"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),$(".separate-search").show(),"favorites"==$.urlParam("mode")?EpubeApp.setPage("PAGE_FAVORITES"):EpubeApp.setPage("PAGE_LIBRARY")),App.initNightMode(),"serviceWorker"in navigator?(navigator.serviceWorker.addEventListener("message",(function(e){"refresh-started"==e.data&&(console.log("cache refresh started"),t=0,$(".dl-progress").fadeIn().text("Loading, please wait...")),e.data&&0==e.data.indexOf("refreshed:")&&(++t,$(".dl-progress").fadeIn().text("Updated "+t+" files...")),"refresh-finished"==e.data&&(localforage.setItem("epube.cache-timestamp",App.last_mtime),localforage.setItem("epube.cache-version",App.version),window.location.reload())})),App.showCovers(),App.Offline.markBooks(),App.refreshCache()):$(".container-main").addClass("alert alert-danger").html("Service worker support missing in browser (are you using plain HTTP?).")},logout:function(){$.post("backend.php",{op:"logout"}).then(()=>{window.location.reload()})},showSummary:function(t){const e=t.getAttribute("data-book-id");return $.post("backend.php",{op:"getinfo",id:e},(function(t){const e=t.comment?t.comment:"No description available";$("#summary-modal .modal-title").html(t.title),$("#summary-modal .book-summary").html(e),$("#summary-modal").modal()})),!1},showCovers:function(){$("img[data-book-id]").each((t,e)=>{if((e=$(e)).attr("data-cover-link")){const t=$("<img>").on("load",(function(){e.css("background-image","url("+e.attr("data-cover-link")+")").fadeIn(),t.attr("src",null)})).attr("src",e.attr("data-cover-link"))}})},toggleFavorite:function(t){const e=t.getAttribute("data-book-id");return("0"==t.getAttribute("data-is-fav")||confirm("Remove favorite?"))&&$.post("backend.php",{op:"togglefav",id:e},(function(o){if(o){let n="[Error]";0==o.status?n="Add to favorites":1==o.status&&(n="Remove from favorites"),$(t).html(n).attr("data-is-fav",o.status),"favorites"==App.index_mode&&0==o.status&&$("#cell-"+e).remove()}})),!1},refreshCache:function(t){"serviceWorker"in navigator?localforage.getItem("epube.cache-timestamp").then((function(e){console.log("stamp",e,"last mtime",App.last_mtime,"version",App.version),(t||e!=App.last_mtime)&&(console.log("asking worker to refresh cache"),navigator.serviceWorker.controller?navigator.serviceWorker.controller.postMessage({msg:"refresh-cache",urls:App.cached_urls}):localforage.getItem("epube.initial-load-done").then((function(t){console.log("initial load done",t),t?$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page."):localforage.setItem("epube.initial-load-done",!0).then((function(){$(".dl-progress").show().addClass("alert-info").html("Page will reload to activate service worker..."),window.setTimeout((function(){window.location.reload()}),3e3)}))})))})):$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page.")},isOnline:function(){return"undefined"!=typeof EpubeApp&&void 0!==EpubeApp.isOnline?EpubeApp.isOnline():navigator.onLine},appCheckOffline:function(){EpubeApp.setOffline(!App.isOnline)},initNightMode:function(){if("undefined"==typeof EpubeApp){if(window.matchMedia){const t=window.matchMedia("(prefers-color-scheme: dark)");t.addEventListener("change",()=>{App.applyNightMode(t.matches)}),App.applyNightMode(t.matches)}}else App.applyNightMode(EpubeApp.isNightMode())},applyNightMode:function(t){console.log("night mode changed to",t),$("#theme_css").attr("href","lib/bootstrap/v3/css/"+(t?"theme-dark.min.css":"bootstrap-theme.min.css"))},Offline:{init:function(){"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),EpubeApp.setPage("PAGE_OFFLINE")),App.initNightMode();const t=$.urlParam("query");t&&$(".search_query").val(t),App.Offline.populateList()},get:function(t,e){console.log("offline cache: "+t),$.post("backend.php",{op:"getinfo",id:t},(function(o){if(o){const n="epube-book."+t;localforage.setItem(n,o).then((function(o){console.log(n+" got data");const a=[];a.push(fetch("backend.php?op=download&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got book"),e(),localforage.setItem(n+".book",t.blob()))}))),a.push(fetch("backend.php?op=getpagination&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got pagination"),t.text().then((function(t){localforage.setItem(n+".locations",JSON.parse(t))})))}))),a.push(fetch("backend.php?op=getlastread&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got lastread"),t.text().then((function(t){localforage.setItem(n+".lastread",JSON.parse(t))})))}))),o.has_cover&&a.push(fetch("backend.php?op=cover&id="+t,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got cover"),localforage.setItem(n+".cover",t.blob()))}))),Promise.all(a).then((function(){$(".dl-progress").show().html("Finished downloading <b>"+o.title+"</b>"),window.clearTimeout(App._dl_progress_timeout),App._dl_progress_timeout=window.setTimeout((function(){$(".dl-progress").fadeOut()}),5e3)}))}))}}))},getAll:function(){confirm("Download all books on this page?")&&$(".row > div").each((function(t,e){const o=$(e).attr("id").replace("cell-",""),n=$(e).find(".offline_dropitem")[0];if(o){const t="epube-book."+o;localforage.getItem(t).then((function(t){t||App.Offline.get(o,(function(){App.Offline.mark(n)}))}))}}))},markBooks:function(){const t=$(".offline_dropitem");$.each(t,(function(t,e){App.Offline.mark(e)}))},mark:function(t){const e=t.getAttribute("data-book-id"),o="epube-book."+e;localforage.getItem(o).then((function(o){o?(t.onclick=function(){return App.Offline.remove(e,(function(){App.Offline.mark(t)})),!1},t.innerHTML="Remove offline data"):(t.onclick=function(){return App.Offline.get(e,(function(){App.Offline.mark(t)})),!1},t.innerHTML="Make available offline")}))},removeFromList:function(t){const e=t.getAttribute("data-book-id");return App.Offline.remove(e,(function(){$("#cell-"+e).remove()}))},remove:function(t,e){if(confirm("Remove download?")){const o="epube-book."+t,n=[];console.log("offline remove: "+t),localforage.iterate((function(t,e){e.match(o)&&n.push(localforage.removeItem(e))})),Promise.all(n).then((function(){window.setTimeout((function(){e()}),500)}))}},search:function(){const t=$(".search_query").val();return localforage.setItem("epube.search-query",t).then((function(){App.Offline.populateList()})),!1},removeAll:function(){if(confirm("Remove all downloaded books?")){const t=[];localforage.iterate((function(e,o){o.match("epube-book")&&t.push(localforage.removeItem(o))})),Promise.all(t).then((function(){window.setTimeout((function(){App.Offline.populateList()}),500)}))}},showSummary:function(t){const e=t.getAttribute("data-book-id");return localforage.getItem("epube-book."+e).then((function(t){const e=t.comment?t.comment:"No description available";$("#summary-modal .modal-title").html(t.title),$("#summary-modal .book-summary").html(e),$("#summary-modal").modal()})),!1},populateList:function(){let t=$.urlParam("query");t&&(t=t.toLowerCase());const e=$("#books_container");e.html(""),localforage.iterate((function(o,n){n.match(/epube-book\.\d{1,}$/)&&Promise.all([localforage.getItem(n),localforage.getItem(n+".cover"),localforage.getItem(n+".lastread"),localforage.getItem(n+".book")]).then((function(o){if(o[0]&&o[3]){const n=o[0];if(t){if(!(n.series_name&&n.series_name.toLowerCase().match(t)||n.title&&n.title.toLowerCase().match(t)||n.author_sort&&n.author_sort.toLowerCase().match(t)))return}let a=!1;o&&o[1]&&(a=URL.createObjectURL(o[1]));let i=!1,l=!1;const r=o[2];r&&(i=r.page>0,l=r.total>0&&r.total-r.page<5);const s=l?"read":"",c=i?"in_progress":"",d=n.series_name?`<div><a class="series_link" href="#">${n.series_name+" ["+n.series_index+"]"}</a></div>`:"",f=$(`<div class="col-xxs-6 col-xs-4 col-sm-3 col-md-2" id="cell-${n.id}">\n\t\t\t\t\t\t\t<a class="thumbnail ${s}" href="read.html?id=${n.epub_id}&b=${n.id}">\n\t\t\t\t\t\t\t\t<img style="display : none">\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<div class="caption">\n\t\t\t\t\t\t\t\t<div><a class="${c}" href="read.html?id=${n.epub_id}&b=${n.id}">${n.title}</a></div>\n\t\t\t\t\t\t\t\t<div><a class="author_link" href="#">${n.author_sort}</a></div>\n\t\t\t\t\t\t\t\t${d}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class="dropdown" style="white-space : nowrap">\n\t\t\t\t\t\t\t\t<a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>\n\t\t\t\t\t\t\t\t<ul class="dropdown-menu">\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="return App.Offline.showSummary(this)">Summary</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="App.Offline.removeFromList(this)">Remove offline data</a></li>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>`);a?f.find("img").css("background-image","url("+a+")").fadeIn():f.fadeIn(),f.find(".series_link").attr("title",n.series_name+" ["+n.series_index+"]").attr("href","offline.html?query="+encodeURIComponent(n.series_name)),f.find(".author_link").attr("title",n.author_sort).attr("href","offline.html?query="+encodeURIComponent(n.author_sort)),e.append(f)}}))}))}}},DEFAULT_FONT_SIZE=16,DEFAULT_FONT_FAMILY="Arial",DEFAULT_LINE_HEIGHT=140,MIN_LENGTH_TO_JUSTIFY=32,LOCATION_DIVISOR=10,PAGE_RESET_PROGRESS=-1,CACHE_PREFIX="epube",CACHE_NAME="epube-v3";Promise.allSettled=Promise.allSettled||(t=>Promise.all(t.map(t=>t.then(t=>({status:"fulfilled",value:t})).catch(t=>({status:"rejected",reason:t})))));const Reader={csrf_token:"",last_stored_cfi:"",prevent_lastread_update:!1,hyphenate:{},init:function(){this.csrf_token=Cookie.get("epube_csrf_token"),console.log("setting prefilter for token",this.csrf_token),$.ajaxPrefilter((function(t,e){if("post"!==e.type||"post"!==t.type)return;const o=typeof e.data;"object"==o?t.data=$.param($.extend(e.data,{csrf_token:Reader.csrf_token})):"string"==o&&(t.data=e.data+"&csrf_token="+encodeURIComponent(Reader.srf_token)),console.log(">>>",t)})),$(document).on("keyup",(function(t){Reader.hotkeyHandler(t)})),$("#left").on("mouseup",(function(){Reader.Page.prev()})),$("#right").on("mouseup",(function(){Reader.Page.next()})),Reader.Loader.init()},onOfflineModeChanged:function(t){if(console.log("onOfflineModeChanged",t),!t&&window.book){const t=window.book;console.log("we're online, storing lastread");const e=t.rendition.currentLocation().start.cfi,o=parseInt(100*t.locations.percentageFromCfi(e));$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:o,cfi:e,timestamp:(new Date).getTime()},(function(){})).fail((function(t){t&&401==t.status&&(window.location="index.php")}))}},initSecondStage:async function(){"undefined"!=typeof EpubeApp?EpubeApp.setPage("PAGE_READER"):($(window).on("online",(function(){Reader.onOfflineModeChanged(!1)})),$(window).on("offline",(function(){Reader.onOfflineModeChanged(!0)}))),Reader.applyTheme();if(await localforage.getItem(Reader.cacheId()))console.log("bookinfo already stored");else{const t=$.urlParam("b");console.log("requesting bookinfo for book",t);try{const e=await $.post("backend.php",{op:"getinfo",id:t});if(e.has_cover){const e=await fetch("backend.php?op=cover&id="+t);e.ok&&await localforage.setItem(Reader.cacheId("cover"),e.blob())}await localforage.setItem(Reader.cacheId(),e),console.log("bookinfo saved")}catch(t){return void $(".loading-message").html(`Unable to load book info.<br/><small>${t.responseText}</small>`)}}console.log("trying to load book...");let t=await localforage.getItem(Reader.cacheId("book"));if(t)console.log("local data already present for book");else{console.log("local data not found, loading from network...");const e=await fetch("backend.php?op=download&id="+$.urlParam("id"));if(!e.ok)return void $(".loading-message").html("Unable to download book: "+e.status);if(t=await e.blob(),!t)return void $(".loading-message").html("Unable to get book blob data.");await localforage.setItem(Reader.cacheId("book"),t),console.log("saved local data for book")}const e=new FileReader;e.onload=function(){try{Reader.openBookData(this.result)}catch(t){console.error(t),$(".loading-message").html("Unable to load book blob: "+t)}},e.onerror=t=>{console.log("filereader error",t),$(".loading-message").html("Unable to open book.<br/><small>"+t+"</small>")},e.readAsArrayBuffer(t)},openBookData:async function(t){const e=ePub();window.book=e;try{await e.open(t)}catch(t){return console.error(t),void $(".loading-message").html("Unable to open book.<br/><small>"+t.message+"</small>")}await e.ready,console.log("book is ready"),await Reader.showBookInfo(e),await Reader.loadLocations(e);const o=e.renderTo("reader",{width:"100%",height:"100%",allowScriptedContent:!0,minSpreadWidth:961});$(".location").click((async function(){const t=Math.floor(o.currentLocation().start.location/10),n=Math.floor(e.locations.length()/10),a=prompt("Jump to location [1-"+n+"]",t);a&&await o.display(e.locations._locations[10*a])}));await localforage.getItem("epube.enable-hyphens")&&(Reader.hyphenate.en=createHyphenator(hyphenationPatternsEnUs,{html:!0}),Reader.hyphenate.ru=createHyphenator(hyphenationPatternsRu,{html:!0})),Reader.applyStyles(!0),console.log("book displayed"),Reader.initRenditionHooks(e,o),Reader.initModals(),Reader.initToc(e),Reader.initStyleHooks(e),Reader.Page.openLastRead(o)},showBookInfo:async function(t){const e=await localforage.getItem(Reader.cacheId());let o,n;if(e)o=e.title,n=e.author_sort;else{const e=t.package.metadata;o=e.title,n=e.creator}document.title=o+" – "+n+" – The Epube",$(".title").text(o).attr("title",o+" – "+n),"undefined"!=typeof EpubeApp&&(EpubeApp.setTitle(o),EpubeApp.showActionBar(!1))},loadLocations:async function(t){console.log("init locations...");let e=await localforage.getItem(Reader.cacheId("locations"));if(e&&"string"==typeof e[0])return console.log("loading local locations..."),t.locations.load(e);{console.log("requesting locations...");const o=await fetch("backend.php?op=getpagination&id="+$.urlParam("id"));if(o.ok&&(console.log("got locations from server"),e=await o.json(),e&&"string"==typeof e[0]))return console.log("saving locations locally..."),await localforage.setItem(Reader.cacheId("locations"),e),t.locations.load(e);$(".loading-message").html("Preparing locations…"),e=await t.locations.generate(100),$.post("backend.php",{op:"storepagination",id:$.urlParam("id"),payload:JSON.stringify(e),total:100}),await localforage.setItem(Reader.cacheId("locations"),e)}},initRenditionHooks:function(t,e){e.hooks.content.register(async t=>{t.on("linkClicked",t=>{console.log("linkClicked",t),Reader.prevent_lastread_update=!0,-1==t.indexOf("://")&&($(".prev_location_btn").attr("data-location-cfi",e.currentLocation().start.cfi).show(),window.setTimeout((function(){Reader.showUI(!0)}),50))});const o=window.location.href.match(/^.*\//)[0];"undefined"!=typeof EpubeApp?$(t.document.head).append($('<link type="text/css" rel="stylesheet" media="screen" href="/assets/android.css" />')):$(t.document.head).append($("<style type='text/css'>").text(Reader.generateFontsCss(o)));const n=["dist/app-libs.min.js","dist/reader_iframe.min.js"];for(let e=0;e<n.length;e++){const a=t.document.createElement("script");a.type="text/javascript",a.text=Reader.Loader._res_data[o+n[e]],t.document.head.appendChild(a)}$(t.document.head).append($("<style type='text/css'>").text(Reader.Loader._res_data[o+"dist/reader_iframe.min.css"]));const a=await localforage.getItem("epube.theme")||"default";$(t.document).find("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("theme-"+a)}),e.on("keyup",t=>{Reader.hotkeyHandler(t)}),e.on("rendered",(function(){$(".chapter").html($("<span>").addClass("glyphicon glyphicon-th-list")),setTimeout(()=>{Reader.Page._moved_next=0},150),Reader.applyTheme(),Reader.resizeSideColumns();try{const o=e.currentLocation();if(o.start){const e=t.canonical(o.start.href);let n=!1;$.each(Reader.flattenToc(t),(function(o,a){t.spine.get(a.href).canonical!=e||(n=a)})),n&&n.label&&$(".chapter").append("&nbsp;"+n.label.trim()+" | "),Reader.generateTocBar(t,Reader.flattenToc(t))}}catch(t){console.warn(t)}})),e.on("relocated",async o=>{if(0==t.locations.length())return;localforage.getItem("epube.enable-column-hacks").then(t=>{t&&Reader.Page._moved_next>=20&&(console.log("forcing re-render because of column hacks"),e.onResized($("#reader").width()),Reader.Page._moved_next=0)});const n=o.start.cfi,a=parseInt(100*t.locations.percentageFromCfi(n));$("#cur_page").text(Math.floor(o.start.location/10)),$("#total_pages").text(Math.floor(t.locations.length()/10)),$("#page_pct").text(parseInt(100*t.locations.percentageFromCfi(n))+"%"),Reader.updateTocBarPosition(t,o);const i=o.start.displayed;if(i&&($("#chapter_cur_page").text(i.page),$("#chapter_total_pages").text(i.total),i.total>0&&$("#chapter_pct").text(parseInt(i.page/i.total*100)+"%")),Reader.last_stored_cfi!=n&&!Reader.prevent_lastread_update){const t=(new Date).getTime();console.log("storing lastread",a,n,t),await localforage.setItem(Reader.cacheId("lastread"),{cfi:n,page:a,total:100,timestamp:t}),App.isOnline()&&(console.log("updating remote lastread",n),Reader.last_stored_cfi=n,$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:a,cfi:n,timestamp:t}))}Reader.prevent_lastread_update=!1})},initModals:function(){console.log("initializing modals..."),$("#settings-modal").on("shown.bs.modal",(async function(){const t=await localforage.getItem(Reader.cacheId("lastread"));t&&t.cfi&&$(".lastread_input").val(t.page+"%").attr("title","[local] "+t.cfi),navigator.onLine&&$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},t=>{$(".lastread_input").val(t.page+"%").attr("title","[remote] "+t.cfi)}),$(".enable_hyphens_checkbox").attr("checked",await localforage.getItem("epube.enable-hyphens")).off("click").on("click",(function(t){localforage.setItem("epube.enable-hyphens",t.target.checked),confirm("Toggling hyphens requires page reload. Reload now?")&&window.location.reload()})),"undefined"!=typeof EpubeApp?$(".keep_ui_checkbox").parent().parent().hide():$(".keep_ui_checkbox").attr("checked",await localforage.getItem("epube.keep-ui-visible")).off("click").on("click",(function(t){localforage.setItem("epube.keep-ui-visible",t.target.checked)}));const e=await localforage.getItem("epube.enable-column-hacks");$(".enable_column_hacks_checkbox").attr("checked",e).off("click").on("click",(function(t){localforage.setItem("epube.enable-column-hacks",t.target.checked)}));const o=await localforage.getItem("epube.cache-timestamp"),n=await localforage.getItem("epube.cache-version");$(".last-mod-timestamp").html(`${n}\n\t\t\t\t&mdash; ${parseInt(o)?new Date(1e3*o).toLocaleString("en-GB"):"Unknown"}\n\t\t\t\t(${App.isOnline()?"<span class='text-success'>Online</span>":"<span class='text-danger'>Offline</span>"})\n\t\t\t\t`),$(".font_family").val(await localforage.getItem("epube.fontFamily")||"Arial"),$(".theme_name").val(await localforage.getItem("epube.theme"));const a=$(".font_size").html("");for(let t=10;t<=32;t++){const e=$("<option>").val(t).html(t+" px");a.append(e)}a.val(await localforage.getItem("epube.fontSize")||16);const i=$(".line_height").html("");for(let t=100;t<=220;t+=10){const e=$("<option>").val(t).html(t+"%");i.append(e)}i.val(await localforage.getItem("epube.lineHeight")||140)})),$("#dict-modal").on("shown.bs.modal",(function(){$(".dict_result").scrollTop(0)})),$(".dict_search_btn").on("click",(function(){$("#dict-modal").modal("hide"),window.open("https://duckduckgo.com/?q="+$(".dict_query").val())})),$(".wiki_search_btn").on("click",(function(){$(".dict_result").html("Loading, please wait..."),$.post("backend.php",{op:"wikisearch",query:$(".dict_query").val()}).then(t=>{try{console.log("wikisearch resp",t);let e="";$.each(t.query.pages,(t,o)=>{e+=o.extract}),$(".dict_result").html(e&&"undefined"!=e?e:"No definition found for "+$(".dict_query").val()+".")}catch(t){console.error(t),$(".dict_result").text("Error while processing data: "+t)}}).fail(t=>{console.error(t),$(".dict_result").text("Error while retrieving data.")})}))},initToc:function(t){function e(e){try{const o=t.spine.get(e).cfiBase,n=t.locations._locations.find((function(t){return-1!=t.indexOf(o)}));return parseInt(window.book.locations.locationFromCfi(n)/10)}catch(t){console.warn(t)}return""}console.log("initializing toc modal..."),$("#toc-modal").on("shown.bs.modal",(function(){const o=t.navigation.toc,n=$(".toc_list");n.html(""),$.each(o,(function(o,a){try{const o=$("<a>").attr("href","#").html("<b class='pull-right'>"+e(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){t.rendition.display(o.attr("data-href"))}));n.append($("<li>").append(o)),function o(n,a,i){if(3==i)return!1;if(n.subitems){const l=$("<ul class='toc_sublist list-unstyled'>");$.each(n.subitems,(function(n,a){const r=$("<a>").attr("href","#").html("<b class='pull-right'>"+e(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){t.rendition.display(r.attr("data-href"))}));l.append($("<li>").append(r)),o(a,l,i+1)})),a.append(l)}}(a,n,0)}catch(t){console.warn(t)}})),n.children().length<=1&&(n.html(""),$.each(t.spine.items,(function(e,o){const a=$("<a>").attr("href","#").attr("title",o.url).html("Section "+(e+1)).attr("data-href",o.href).click((function(){t.rendition.display(a.attr("data-href"))}));n.append($("<li>").append(a))})))}))},initStyleHooks:function(t){console.log("registering style hooks..."),t.spine.hooks.content.register((function(t){$(t).find("p").filter((t,e)=>$(e).text().length>=32?e:null).css("text-align","justify"),$(t).find("html").attr("class",""),$(t).find("pre").css("white-space","pre-wrap"),$(t).find("a, p, span, em, i, strong, b, body, header, section, div, big, small, table, tr, td, ul, ol, li").attr("class","").css("font-family","inherit").css("font-size","inherit").css("line-height","inherit").css("color","").css("border","none ! important").css("background","").css("background-color","").attr("width","").attr("height",""),$(t).find("h1, h2, h3, h4, h5").attr("class","").css("font-family","inherit").css("color","").css("border","none ! important").css("background","").css("background-color",""),void 0!==Reader.hyphenate.en&&$(t).find("p, div").each((t,e)=>{(e=$(e)).html(Reader.hyphenate.en(e.html())),e.html(Reader.hyphenate.ru(e.html()))})}))},generateFontsCss:function(t){return`\n\t\t\t/** Calibri */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibriz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibrib.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibrii.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibri.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Cambria */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriaz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambria.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Caecilia */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caecilia.ttf"]});\n\t\t\t\tfont-weight : normal;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caeciliab.ttf"]});\n\t\t\t\tfont-weight : bold;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caeciliai.ttf"]});\n\t\t\t\tfont-style : italic;\n\t\t\t}\n\n\t\t\t/** Palatino */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palabi.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/pala.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Consolas */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolaz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consola.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** IBM Plex Mono */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-Bold.otf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-BoldItalic.otf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-TextItalic.otf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-Text.otf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\t\t\t`},flattenTocSubItems:function(t,e){let o=[];return 3!=e&&(t.subitems&&$.each(t.subitems,(function(t,n){n._nest=e,o.push(n),o=o.concat(Reader.flattenTocSubItems(n,e+1))})),o)},flattenToc:function(t){if(this._flattened_toc)return this._flattened_toc;{let e=[];return $.each(t.navigation.toc,(function(t,o){o._nest=0,e.push(o),e=e.concat(Reader.flattenTocSubItems(o,1))})),this._flattened_toc=e,e}},generateTocBar:function(t,e){$(".spacer").html(""),$.each(e,(function(e,o){try{const e=t.spine.get(o.href).cfiBase,n=t.locations._locations.find((function(t){return-1!=t.indexOf(e)}));if(n){const e=Math.round(100*t.locations.percentageFromCfi(n));$(".spacer").append($("<div class='toc-bar-entry'>").attr("data-nest-level",o._nest).css("left",e+"%").css("_width",3-o._nest+"px").attr("title",o.label))}}catch(t){console.warn(t)}})),$(".spacer").append($("<div class='toc-bar-entry current-position'>")),Reader.updateTocBarPosition(t,t.rendition.currentLocation())},updateTocBarPosition:function(t,e){const o=Math.round(e.start.location/t.locations.length()*100);$(".toc-bar-entry.current-position").css("left",o+"%")},applyStyles:function(t){Promise.all([localforage.getItem("epube.fontSize"),localforage.getItem("epube.fontFamily"),localforage.getItem("epube.lineHeight"),localforage.getItem("epube.theme")]).then((function(e){const o=e[0]?e[0]+"px":"16px",n=e[1]?e[1]:"Arial",a=e[2]?e[2]+"%":"140%";console.log("style",n,o,a),console.log("applying default theme..."),window.book.rendition.themes.default({html:{"font-size":o,"font-family":"'"+n+"'","line-height":a,"text-align":"justify","text-indent":"1em"}}),t||(console.log("applying rendition themes..."),$.each(window.book.rendition.getContents(),(function(t,e){e.css("font-size",o),e.css("font-family","'"+n+"'"),e.css("line-height",a),e.css("text-align","justify")}))),Reader.applyTheme()}))},applyTheme:function(){localforage.getItem("epube.theme").then((function(t){t||(t="default"),console.log("called for theme",t),"default"==t&&"undefined"!=typeof EpubeApp&&EpubeApp.isNightMode()&&(t="night"),console.log("setting main UI theme",t),$("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("epube-reader theme-"+t).attr("data-is-loading","false"),"undefined"!=typeof EpubeApp&&window.setTimeout((function(){const t=window.getComputedStyle(document.querySelector("body"),null).getPropertyValue("background-color").match(/rgb\((\d{1,}), (\d{1,}), (\d{1,})\)/);t&&(console.log("sending bgcolor",t),EpubeApp.setStatusBarColor(parseInt(t[1]),parseInt(t[2]),parseInt(t[3])))}),250),window.book&&$.each(window.book.rendition.getContents(),(function(e,o){console.log("applying rendition theme",t,"to",o,o.document),$(o.document).find("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("theme-"+t)}))}))},hotkeyHandler:function(t){try{if($(".modal").is(":visible"))return;39!=t.which&&32!=t.which&&34!=t.which||(t.preventDefault(),Reader.Page.next()),37!=t.which&&33!=t.which||(t.preventDefault(),Reader.Page.prev()),27==t.which&&(t.preventDefault(),Reader.showUI(!0))}catch(t){console.warn(t)}},resizeSideColumns:function(){let t=$("#reader").position().left;const e=$("#reader iframe")[0];e&&e.contentWindow.$&&(t+=parseInt(e.contentWindow.$("body").css("padding-left"))),$("#left, #right").width(t)},markAsRead:function(){if(confirm("Mark book as read?")){const t=100,e=window.book.locations.cfiFromPercentage(1),o=(new Date).getTime();App.isOnline()&&$.post("backend.php",{op:"storelastread",page:t,cfi:e,id:$.urlParam("id"),timestamp:o},(function(t){$(".lastread_input").val(t.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:e,page:t,total:t,timestamp:o})}},close:function(){const t=window.book.rendition.currentLocation().start.cfi,e=parseInt(100*window.book.locations.percentageFromCfi(t)),o=(new Date).getTime();localforage.setItem(Reader.cacheId("lastread"),{cfi:t,page:e,total:100,timestamp:o}),App.isOnline()?$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:e,cfi:t,timestamp:o},(function(){window.location=$.urlParam("rt")?"index.php?mode="+$.urlParam("rt"):"index.php"})).fail((function(){window.location="index.php"})):window.location="index.php"},cacheId:function(t){return"epube-book."+$.urlParam("b")+(t?"."+t:"")},toggleFullscreen:function(){if("undefined"!=typeof EpubeApp);else{const t=document.documentElement,e=document.webkitIsFullScreen||document.mozFullScreen||!1;t.requestFullScreen=t.requestFullScreen||t.webkitRequestFullScreen||t.mozRequestFullScreen||function(){return!1},document.cancelFullScreen=document.cancelFullScreen||document.webkitCancelFullScreen||document.mozCancelFullScreen||function(){return!1},e?document.cancelFullScreen():t.requestFullScreen()}},showUI:function(t){t?$(".header,.footer").fadeIn():$(".header,.footer").fadeOut()},toggleUI:function(){$(".header").is(":visible")?$(".header,.footer").fadeOut():$(".header,.footer").fadeIn()},lookupWord:function(t,e){t=t.replace(/­/g,""),$(".dict_result").html("Loading, please wait..."),$("#dict-modal").modal("show"),$.post("backend.php",{op:"define",word:t},(function(o){o&&($(".dict_result").html(o.result.join("<br/>")),$(".dict_query").val(t),e&&e())})).fail((function(t){console.warn(t),$(".dict_result").html("Network error while looking up word: "+t.statusText)}))},search:function(){const t=$(".search_input").val(),e=$(".search_results");e.html(""),t&&Promise.all(window.book.spine.spineItems.map(e=>e.load(window.book.load.bind(window.book)).then(e.find.bind(e,t)).finally(e.unload.bind(e)))).then(t=>Promise.resolve([].concat.apply([],t))).then((function(t){$.each(t,(function(t,o){const n=$("<a>").attr("href","#").html("<b class='pull-right'>"+window.book.locations.locationFromCfi(o.cfi)+"</b>"+o.excerpt).attr("data-cfi",o.cfi).attr("data-id",o.id).click((function(){window.book.rendition.display(n.attr("data-cfi"))}));e.append($("<li>").append(n))}))}))},Loader:{_res_data:[],init:async function(){const t=[];let e=!1;const o=await caches.open("epube-v3");(await o.keys()).forEach(o=>{if(!o.url.match("backend.php")){console.log("[loader] loading resource",o.url);const n=fetch(o.url).then(async t=>{if(t.ok){const e=new URL(t.url);if(e.searchParams.delete("ts"),t.url.match("\\.ttf|\\.otf")){const o=await t.blob();console.log("[loader] storing blob",e.href),Reader.Loader._res_data[e.toString()]=URL.createObjectURL(o)}else{const o=await t.text();console.log("[loader] storing text",e.href),Reader.Loader._res_data[e.toString()]=o}}else console.warn("[loader] failed for resource",o.url,t),$(".loading-message").html(`Unable to load resource.<br/><small>${o.url}</small>`),e=!0});t.push(n)}}),await Promise.allSettled(t),console.log("[loader] resource load complete, failed: ",e),e?Reader.applyTheme():Reader.initSecondStage()}},Page:{_moved_next:0,next:function(){window.book.rendition.next(),Reader.Page._moved_next+=1,"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(t){t||Reader.showUI(!1)}))},prev:function(){window.book.rendition.prev(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(t){t||Reader.showUI(!1)}))},openPrevious:async function(t){const e=$(t).attr("data-location-cfi");e&&await window.book.rendition.display(e),$(t).fadeOut()},clearLastRead:async function(){if(confirm("Clear stored last read location?")){const t=window.book.locations.length(),e=(new Date).getTime();if(App.isOnline()){const t=await $.post("backend.php",{op:"storelastread",page:-1,cfi:"",id:$.urlParam("id"),timestamp:e});$(".lastread_input").val(t.page+"%")}await localforage.setItem(Reader.cacheId("lastread"),{cfi:"",page:0,total:t,timestamp:e}),await window.book.rendition.display(window.book.locations.cfiFromPercentage(0))}},openLastRead:async function(t){const e=await localforage.getItem(Reader.cacheId("lastread"))||{};if(e&&e.cfi){console.log("using local lastread cfi",e.cfi);try{await t.display(e.cfi)}catch(t){console.warn(t)}}if(App.isOnline()){const o=await $.post("backend.php",{op:"getlastread",id:$.urlParam("id")});console.log("got remote lastread",o,e),o&&o.cfi&&e.cfi!=o.cfi&&(!e.timestamp||o.timestamp<=e.timestamp)&&(console.log("using remote lastread (timestamp is newer or local timestamp is missing)"),await localforage.setItem(Reader.cacheId("lastread"),{cfi:o.cfi,page:o.page,total:o.total,timestamp:o.timestamp}),await t.display(o.cfi))}$(".loading").hide()}},Settings:{onThemeChanged:function(t){const e=$(t).val();localforage.setItem("epube.theme",e).then((function(){Reader.applyTheme()}))},onLineHeightChanged:function(t){const e=$(t).val();localforage.setItem("epube.lineHeight",e).then((function(){Reader.applyStyles()}))},onTextSizeChanged:function(t){const e=$(t).val();localforage.setItem("epube.fontSize",e).then((function(){Reader.applyStyles()}))},onFontChanged:function(t){const e=$(t).val();localforage.setItem("epube.fontFamily",e).then((function(){Reader.applyStyles()}))}}};function __get_reader(){return Reader}function __get_app(){return App} \ No newline at end of file
+"use strict";$.urlParam=function(t){try{const e=new RegExp("[?&]"+t+"=([^&#]*)").exec(window.location.href);return decodeURIComponent(e[1].replace(/\+/g," "))||0}catch(t){return 0}};const Cookie={set:function(t,e,o){const n=new Date;n.setTime(n.getTime()+1e3*o);const a="expires="+n.toUTCString();document.cookie=t+"="+encodeURIComponent(e)+"; "+a},get:function(t){t+="=";const e=document.cookie.split(";");for(let o=0;o<e.length;o++){let n=e[o];for(;" "==n.charAt(0);)n=n.substring(1);if(0==n.indexOf(t))return decodeURIComponent(n.substring(t.length,n.length))}return""},delete:function(t){document.cookie=t+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT"}},App={_dl_progress_timeout:!1,index_mode:"",last_mtime:-1,cached_urls:[],version:"UNKNOWN",csrf_token:"",init:function(){let t=0;this.csrf_token=Cookie.get("epube_csrf_token"),console.log("setting prefilter for token",this.csrf_token),$.ajaxPrefilter((function(t,e,o){if("post"!==e.type||"post"!==t.type)return;const n=typeof e.data;"object"==n?t.data=$.param($.extend(e.data,{csrf_token:App.csrf_token})):"string"==n&&(t.data=e.data+"&csrf_token="+encodeURIComponent(App.srf_token)),console.log(">>>",t)})),"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),$(".separate-search").show(),"favorites"==$.urlParam("mode")?EpubeApp.setPage("PAGE_FAVORITES"):EpubeApp.setPage("PAGE_LIBRARY")),App.initNightMode(),"serviceWorker"in navigator?(navigator.serviceWorker.addEventListener("message",(function(e){"refresh-started"==e.data&&(console.log("cache refresh started"),t=0,$(".dl-progress").fadeIn().text("Loading, please wait...")),e.data&&0==e.data.indexOf("refreshed:")&&(++t,$(".dl-progress").fadeIn().text("Updated "+t+" files...")),"refresh-finished"==e.data&&(localforage.setItem("epube.cache-timestamp",App.last_mtime),localforage.setItem("epube.cache-version",App.version),window.location.reload())})),App.showCovers(),App.Offline.markBooks(),App.refreshCache()):$(".container-main").addClass("alert alert-danger").html("Service worker support missing in browser (are you using plain HTTP?).")},logout:function(){$.post("backend.php",{op:"logout"}).then(()=>{window.location.reload()})},showSummary:function(t){const e=t.getAttribute("data-book-id");return $.post("backend.php",{op:"getinfo",id:e},(function(t){const e=t.comment?t.comment:"No description available";$("#summary-modal .modal-title").html(t.title),$("#summary-modal .book-summary").html(e),$("#summary-modal").modal()})),!1},showCovers:function(){$("img[data-book-id]").each((t,e)=>{if((e=$(e)).attr("data-cover-link")){const t=$("<img>").on("load",(function(){e.css("background-image","url("+e.attr("data-cover-link")+")").fadeIn(),t.attr("src",null)})).attr("src",e.attr("data-cover-link"))}})},toggleFavorite:function(t){const e=t.getAttribute("data-book-id");return("0"==t.getAttribute("data-is-fav")||confirm("Remove favorite?"))&&$.post("backend.php",{op:"togglefav",id:e},(function(o){if(o){let n="[Error]";0==o.status?n="Add to favorites":1==o.status&&(n="Remove from favorites"),$(t).html(n).attr("data-is-fav",o.status),"favorites"==App.index_mode&&0==o.status&&$("#cell-"+e).remove()}})),!1},refreshCache:function(t){"serviceWorker"in navigator?localforage.getItem("epube.cache-timestamp").then((function(e){console.log("stamp",e,"last mtime",App.last_mtime,"version",App.version),(t||e!=App.last_mtime)&&(console.log("asking worker to refresh cache"),navigator.serviceWorker.controller?navigator.serviceWorker.controller.postMessage({msg:"refresh-cache",urls:App.cached_urls}):localforage.getItem("epube.initial-load-done").then((function(t){console.log("initial load done",t),t?$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page."):localforage.setItem("epube.initial-load-done",!0).then((function(){$(".dl-progress").show().addClass("alert-info").html("Page will reload to activate service worker..."),window.setTimeout((function(){window.location.reload()}),3e3)}))})))})):$(".dl-progress").show().addClass("alert-danger").html("Could not communicate with service worker. Try reloading the page.")},isOnline:function(){return"undefined"!=typeof EpubeApp&&void 0!==EpubeApp.isOnline?EpubeApp.isOnline():navigator.onLine},appCheckOffline:function(){EpubeApp.setOffline(!App.isOnline)},initNightMode:function(){if("undefined"==typeof EpubeApp){if(window.matchMedia){const t=window.matchMedia("(prefers-color-scheme: dark)");t.addEventListener("change",()=>{App.applyNightMode(t.matches)}),App.applyNightMode(t.matches)}}else App.applyNightMode(EpubeApp.isNightMode())},applyNightMode:function(t){console.log("night mode changed to",t),$("#theme_css").attr("href","lib/bootstrap/v3/css/"+(t?"theme-dark.min.css":"bootstrap-theme.min.css"))},Offline:{init:function(){"undefined"!=typeof EpubeApp&&($(".navbar").hide(),$(".epube-app-filler").show(),EpubeApp.setPage("PAGE_OFFLINE")),App.initNightMode();const t=$.urlParam("query");t&&$(".search_query").val(t),App.Offline.populateList()},get:function(t,e){console.log("offline cache: "+t),$.post("backend.php",{op:"getinfo",id:t},(function(o){if(o){const n="epube-book."+t;localforage.setItem(n,o).then((function(o){console.log(n+" got data");const a=[];a.push(fetch("backend.php?op=download&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got book"),e(),localforage.setItem(n+".book",t.blob()))}))),a.push(fetch("backend.php?op=getpagination&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got pagination"),t.text().then((function(t){localforage.setItem(n+".locations",JSON.parse(t))})))}))),a.push(fetch("backend.php?op=getlastread&id="+o.epub_id,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got lastread"),t.text().then((function(t){localforage.setItem(n+".lastread",JSON.parse(t))})))}))),o.has_cover&&a.push(fetch("backend.php?op=cover&id="+t,{credentials:"same-origin"}).then((function(t){200==t.status&&(console.log(n+" got cover"),localforage.setItem(n+".cover",t.blob()))}))),Promise.all(a).then((function(){$(".dl-progress").show().html("Finished downloading <b>"+o.title+"</b>"),window.clearTimeout(App._dl_progress_timeout),App._dl_progress_timeout=window.setTimeout((function(){$(".dl-progress").fadeOut()}),5e3)}))}))}}))},getAll:function(){confirm("Download all books on this page?")&&$(".row > div").each((function(t,e){const o=$(e).attr("id").replace("cell-",""),n=$(e).find(".offline_dropitem")[0];if(o){const t="epube-book."+o;localforage.getItem(t).then((function(t){t||App.Offline.get(o,(function(){App.Offline.mark(n)}))}))}}))},markBooks:function(){const t=$(".offline_dropitem");$.each(t,(function(t,e){App.Offline.mark(e)}))},mark:function(t){const e=t.getAttribute("data-book-id"),o="epube-book."+e;localforage.getItem(o).then((function(o){o?(t.onclick=function(){return App.Offline.remove(e,(function(){App.Offline.mark(t)})),!1},t.innerHTML="Remove offline data"):(t.onclick=function(){return App.Offline.get(e,(function(){App.Offline.mark(t)})),!1},t.innerHTML="Make available offline")}))},removeFromList:function(t){const e=t.getAttribute("data-book-id");return App.Offline.remove(e,(function(){$("#cell-"+e).remove()}))},remove:function(t,e){if(confirm("Remove download?")){const o="epube-book."+t,n=[];console.log("offline remove: "+t),localforage.iterate((function(t,e){e.match(o)&&n.push(localforage.removeItem(e))})),Promise.all(n).then((function(){window.setTimeout((function(){e()}),500)}))}},search:function(){const t=$(".search_query").val();return localforage.setItem("epube.search-query",t).then((function(){App.Offline.populateList()})),!1},removeAll:function(){if(confirm("Remove all downloaded books?")){const t=[];localforage.iterate((function(e,o){o.match("epube-book")&&t.push(localforage.removeItem(o))})),Promise.all(t).then((function(){window.setTimeout((function(){App.Offline.populateList()}),500)}))}},showSummary:function(t){const e=t.getAttribute("data-book-id");return localforage.getItem("epube-book."+e).then((function(t){const e=t.comment?t.comment:"No description available";$("#summary-modal .modal-title").html(t.title),$("#summary-modal .book-summary").html(e),$("#summary-modal").modal()})),!1},populateList:function(){let t=$.urlParam("query");t&&(t=t.toLowerCase());const e=$("#books_container");e.html(""),localforage.iterate((function(o,n){n.match(/epube-book\.\d{1,}$/)&&Promise.all([localforage.getItem(n),localforage.getItem(n+".cover"),localforage.getItem(n+".lastread"),localforage.getItem(n+".book")]).then((function(o){if(o[0]&&o[3]){const n=o[0];if(t){if(!(n.series_name&&n.series_name.toLowerCase().match(t)||n.title&&n.title.toLowerCase().match(t)||n.author_sort&&n.author_sort.toLowerCase().match(t)))return}let a=!1;o&&o[1]&&(a=URL.createObjectURL(o[1]));let i=!1,l=!1;const r=o[2];r&&(i=r.page>0,l=r.total>0&&r.total-r.page<5);const s=l?"read":"",c=i?"in_progress":"",d=n.series_name?`<div><a class="series_link" href="#">${n.series_name+" ["+n.series_index+"]"}</a></div>`:"",f=$(`<div class="col-xxs-6 col-xs-4 col-sm-3 col-md-2" id="cell-${n.id}">\n\t\t\t\t\t\t\t<a class="thumbnail ${s}" href="read.html?id=${n.epub_id}&b=${n.id}">\n\t\t\t\t\t\t\t\t<img style="display : none">\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t<div class="caption">\n\t\t\t\t\t\t\t\t<div><a class="${c}" href="read.html?id=${n.epub_id}&b=${n.id}">${n.title}</a></div>\n\t\t\t\t\t\t\t\t<div><a class="author_link" href="#">${n.author_sort}</a></div>\n\t\t\t\t\t\t\t\t${d}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class="dropdown" style="white-space : nowrap">\n\t\t\t\t\t\t\t\t<a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>\n\t\t\t\t\t\t\t\t<ul class="dropdown-menu">\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="return App.Offline.showSummary(this)">Summary</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href="#" data-book-id="${n.id}" onclick="App.Offline.removeFromList(this)">Remove offline data</a></li>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>`);a?f.find("img").css("background-image","url("+a+")").fadeIn():f.fadeIn(),f.find(".series_link").attr("title",n.series_name+" ["+n.series_index+"]").attr("href","offline.html?query="+encodeURIComponent(n.series_name)),f.find(".author_link").attr("title",n.author_sort).attr("href","offline.html?query="+encodeURIComponent(n.author_sort)),e.append(f)}}))}))}}},DEFAULT_FONT_SIZE=16,DEFAULT_FONT_FAMILY="Arial",DEFAULT_LINE_HEIGHT=140,MIN_LENGTH_TO_JUSTIFY=32,LOCATION_DIVISOR=10,PAGE_RESET_PROGRESS=-1,CACHE_PREFIX="epube",CACHE_NAME="epube-v3";Promise.allSettled=Promise.allSettled||(t=>Promise.all(t.map(t=>t.then(t=>({status:"fulfilled",value:t})).catch(t=>({status:"rejected",reason:t})))));const Reader={csrf_token:"",last_stored_cfi:"",prevent_lastread_update:!1,hyphenate:{},init:function(){this.csrf_token=Cookie.get("epube_csrf_token"),console.log("setting prefilter for token",this.csrf_token),$.ajaxPrefilter((function(t,e){if("post"!==e.type||"post"!==t.type)return;const o=typeof e.data;"object"==o?t.data=$.param($.extend(e.data,{csrf_token:Reader.csrf_token})):"string"==o&&(t.data=e.data+"&csrf_token="+encodeURIComponent(Reader.srf_token)),console.log(">>>",t)})),$(document).on("keyup",(function(t){Reader.hotkeyHandler(t)})),$("#left").on("mouseup",(function(){Reader.Page.prev()})),$("#right").on("mouseup",(function(){Reader.Page.next()})),Reader.Loader.init()},onOfflineModeChanged:function(t){if(console.log("onOfflineModeChanged",t),!t&&window.book){const t=window.book;console.log("we're online, storing lastread");const e=t.rendition.currentLocation().start.cfi,o=parseInt(100*t.locations.percentageFromCfi(e));$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:o,cfi:e,timestamp:(new Date).getTime()},(function(){})).fail((function(t){t&&401==t.status&&(window.location="index.php")}))}},initSecondStage:async function(){"undefined"!=typeof EpubeApp?EpubeApp.setPage("PAGE_READER"):($(window).on("online",(function(){Reader.onOfflineModeChanged(!1)})),$(window).on("offline",(function(){Reader.onOfflineModeChanged(!0)}))),Reader.applyTheme();if(await localforage.getItem(Reader.cacheId()))console.log("bookinfo already stored");else{const t=$.urlParam("b");console.log("requesting bookinfo for book",t);try{const e=await $.post("backend.php",{op:"getinfo",id:t});if(e.has_cover){const e=await fetch("backend.php?op=cover&id="+t);e.ok&&await localforage.setItem(Reader.cacheId("cover"),e.blob())}await localforage.setItem(Reader.cacheId(),e),console.log("bookinfo saved")}catch(t){return void $(".loading-message").html(`Unable to load book info.<br/><small>${t.responseText}</small>`)}}console.log("trying to load book...");let t=await localforage.getItem(Reader.cacheId("book"));if(t)console.log("local data already present for book");else{console.log("local data not found, loading from network..."),$(".loading-message").html("Downloading book…");const e=await fetch("backend.php?op=download&id="+$.urlParam("id"));if(!e.ok)return void $(".loading-message").html("Unable to download book: "+e.status);if(t=await e.blob(),!t)return void $(".loading-message").html("Unable to get book blob data.");await localforage.setItem(Reader.cacheId("book"),t),console.log("saved local data for book")}const e=new FileReader;e.onload=function(){try{Reader.openBookData(this.result)}catch(t){console.error(t),$(".loading-message").html("Unable to load book blob: "+t)}},e.onerror=t=>{console.log("filereader error",t),$(".loading-message").html("Unable to open book.<br/><small>"+t+"</small>")},e.readAsArrayBuffer(t)},openBookData:async function(t){const e=ePub();window.book=e;try{await e.open(t)}catch(t){return console.error(t),void $(".loading-message").html("Unable to open book.<br/><small>"+t.message+"</small>")}await e.ready,console.log("book is ready"),await Reader.showBookInfo(e),await Reader.loadLocations(e);const o=e.renderTo("reader",{width:"100%",height:"100%",allowScriptedContent:!0,minSpreadWidth:961});$(".location").click((async function(){const t=Math.floor(o.currentLocation().start.location/10),n=Math.floor(e.locations.length()/10),a=prompt("Jump to location [1-"+n+"]",t);a&&await o.display(e.locations._locations[10*a])}));await localforage.getItem("epube.enable-hyphens")&&(Reader.hyphenate.en=createHyphenator(hyphenationPatternsEnUs,{html:!0}),Reader.hyphenate.ru=createHyphenator(hyphenationPatternsRu,{html:!0})),Reader.applyStyles(!0),console.log("book displayed"),Reader.initRenditionHooks(e,o),Reader.initModals(),Reader.initToc(e),Reader.initStyleHooks(e),Reader.Page.openLastRead(o)},showBookInfo:async function(t){const e=await localforage.getItem(Reader.cacheId());let o,n;if(e)o=e.title,n=e.author_sort;else{const e=t.package.metadata;o=e.title,n=e.creator}document.title=o+" – "+n+" – The Epube",$(".title").text(o).attr("title",o+" – "+n),"undefined"!=typeof EpubeApp&&(EpubeApp.setTitle(o),EpubeApp.showActionBar(!1))},loadLocations:async function(t){console.log("init locations...");let e=await localforage.getItem(Reader.cacheId("locations"));if(e&&"string"==typeof e[0])return console.log("loading local locations..."),t.locations.load(e);{console.log("requesting locations...");const o=await fetch("backend.php?op=getpagination&id="+$.urlParam("id"));if(o.ok&&(console.log("got locations from server"),e=await o.json(),e&&"string"==typeof e[0]))return console.log("saving locations locally..."),await localforage.setItem(Reader.cacheId("locations"),e),t.locations.load(e);$(".loading-message").html("Preparing locations…"),e=await t.locations.generate(100),$.post("backend.php",{op:"storepagination",id:$.urlParam("id"),payload:JSON.stringify(e),total:100}),await localforage.setItem(Reader.cacheId("locations"),e)}},initRenditionHooks:function(t,e){e.hooks.content.register(async t=>{t.on("linkClicked",t=>{console.log("linkClicked",t),Reader.prevent_lastread_update=!0,-1==t.indexOf("://")&&($(".prev_location_btn").attr("data-location-cfi",e.currentLocation().start.cfi).show(),window.setTimeout((function(){Reader.showUI(!0)}),50))});const o=window.location.href.match(/^.*\//)[0];"undefined"!=typeof EpubeApp?$(t.document.head).append($('<link type="text/css" rel="stylesheet" media="screen" href="/assets/android.css" />')):$(t.document.head).append($("<style type='text/css'>").text(Reader.generateFontsCss(o)));const n=["dist/app-libs.min.js","dist/reader_iframe.min.js"];for(let e=0;e<n.length;e++){const a=t.document.createElement("script");a.type="text/javascript",a.text=Reader.Loader._res_data[o+n[e]],t.document.head.appendChild(a)}$(t.document.head).append($("<style type='text/css'>").text(Reader.Loader._res_data[o+"dist/reader_iframe.min.css"]));const a=await localforage.getItem("epube.theme")||"default";$(t.document).find("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("theme-"+a)}),e.on("keyup",t=>{Reader.hotkeyHandler(t)}),e.on("rendered",(function(){$(".chapter").html($("<span>").addClass("glyphicon glyphicon-th-list")),setTimeout(()=>{Reader.Page._moved_next=0},150),Reader.applyTheme(),Reader.resizeSideColumns();try{const o=e.currentLocation();if(o.start){const e=t.canonical(o.start.href);let n=!1;$.each(Reader.flattenToc(t),(function(o,a){t.spine.get(a.href).canonical!=e||(n=a)})),n&&n.label&&$(".chapter").append("&nbsp;"+n.label.trim()+" | "),Reader.generateTocBar(t,Reader.flattenToc(t))}}catch(t){console.warn(t)}})),e.on("relocated",async o=>{if(0==t.locations.length())return;localforage.getItem("epube.enable-column-hacks").then(t=>{t&&Reader.Page._moved_next>=20&&(console.log("forcing re-render because of column hacks"),e.onResized($("#reader").width()),Reader.Page._moved_next=0)});const n=o.start.cfi,a=parseInt(100*t.locations.percentageFromCfi(n));$("#cur_page").text(Math.floor(o.start.location/10)),$("#total_pages").text(Math.floor(t.locations.length()/10)),$("#page_pct").text(parseInt(100*t.locations.percentageFromCfi(n))+"%"),Reader.updateTocBarPosition(t,o);const i=o.start.displayed;if(i&&($("#chapter_cur_page").text(i.page),$("#chapter_total_pages").text(i.total),i.total>0&&$("#chapter_pct").text(parseInt(i.page/i.total*100)+"%")),Reader.last_stored_cfi!=n&&!Reader.prevent_lastread_update){const t=(new Date).getTime();console.log("storing lastread",a,n,t),await localforage.setItem(Reader.cacheId("lastread"),{cfi:n,page:a,total:100,timestamp:t}),App.isOnline()&&(console.log("updating remote lastread",n),Reader.last_stored_cfi=n,$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:a,cfi:n,timestamp:t}))}Reader.prevent_lastread_update=!1})},initModals:function(){console.log("initializing modals..."),$("#settings-modal").on("shown.bs.modal",(async function(){const t=await localforage.getItem(Reader.cacheId("lastread"));t&&t.cfi&&$(".lastread_input").val(t.page+"%").attr("title","[local] "+t.cfi),navigator.onLine&&$.post("backend.php",{op:"getlastread",id:$.urlParam("id")},t=>{$(".lastread_input").val(t.page+"%").attr("title","[remote] "+t.cfi)}),$(".enable_hyphens_checkbox").attr("checked",await localforage.getItem("epube.enable-hyphens")).off("click").on("click",(function(t){localforage.setItem("epube.enable-hyphens",t.target.checked),confirm("Toggling hyphens requires page reload. Reload now?")&&window.location.reload()})),"undefined"!=typeof EpubeApp?$(".keep_ui_checkbox").parent().parent().hide():$(".keep_ui_checkbox").attr("checked",await localforage.getItem("epube.keep-ui-visible")).off("click").on("click",(function(t){localforage.setItem("epube.keep-ui-visible",t.target.checked)}));const e=await localforage.getItem("epube.enable-column-hacks");$(".enable_column_hacks_checkbox").attr("checked",e).off("click").on("click",(function(t){localforage.setItem("epube.enable-column-hacks",t.target.checked)}));const o=await localforage.getItem("epube.cache-timestamp"),n=await localforage.getItem("epube.cache-version");$(".last-mod-timestamp").html(`${n}\n\t\t\t\t&mdash; ${parseInt(o)?new Date(1e3*o).toLocaleString("en-GB"):"Unknown"}\n\t\t\t\t(${App.isOnline()?"<span class='text-success'>Online</span>":"<span class='text-danger'>Offline</span>"})\n\t\t\t\t`),$(".font_family").val(await localforage.getItem("epube.fontFamily")||"Arial"),$(".theme_name").val(await localforage.getItem("epube.theme"));const a=$(".font_size").html("");for(let t=10;t<=32;t++){const e=$("<option>").val(t).html(t+" px");a.append(e)}a.val(await localforage.getItem("epube.fontSize")||16);const i=$(".line_height").html("");for(let t=100;t<=220;t+=10){const e=$("<option>").val(t).html(t+"%");i.append(e)}i.val(await localforage.getItem("epube.lineHeight")||140)})),$("#dict-modal").on("shown.bs.modal",(function(){$(".dict_result").scrollTop(0)})),$(".dict_search_btn").on("click",(function(){$("#dict-modal").modal("hide"),window.open("https://duckduckgo.com/?q="+$(".dict_query").val())})),$(".wiki_search_btn").on("click",(function(){$(".dict_result").html("Loading, please wait..."),$.post("backend.php",{op:"wikisearch",query:$(".dict_query").val()}).then(t=>{try{console.log("wikisearch resp",t);let e="";$.each(t.query.pages,(t,o)=>{e+=o.extract}),$(".dict_result").html(e&&"undefined"!=e?e:"No definition found for "+$(".dict_query").val()+".")}catch(t){console.error(t),$(".dict_result").text("Error while processing data: "+t)}}).fail(t=>{console.error(t),$(".dict_result").text("Error while retrieving data.")})}))},initToc:function(t){function e(e){try{const o=t.spine.get(e).cfiBase,n=t.locations._locations.find((function(t){return-1!=t.indexOf(o)}));return parseInt(window.book.locations.locationFromCfi(n)/10)}catch(t){console.warn(t)}return""}console.log("initializing toc modal..."),$("#toc-modal").on("shown.bs.modal",(function(){const o=t.navigation.toc,n=$(".toc_list");n.html(""),$.each(o,(function(o,a){try{const o=$("<a>").attr("href","#").html("<b class='pull-right'>"+e(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){t.rendition.display(o.attr("data-href"))}));n.append($("<li>").append(o)),function o(n,a,i){if(3==i)return!1;if(n.subitems){const l=$("<ul class='toc_sublist list-unstyled'>");$.each(n.subitems,(function(n,a){const r=$("<a>").attr("href","#").html("<b class='pull-right'>"+e(a.href)+"</b>"+a.label).attr("data-href",a.href).click((function(){t.rendition.display(r.attr("data-href"))}));l.append($("<li>").append(r)),o(a,l,i+1)})),a.append(l)}}(a,n,0)}catch(t){console.warn(t)}})),n.children().length<=1&&(n.html(""),$.each(t.spine.items,(function(e,o){const a=$("<a>").attr("href","#").attr("title",o.url).html("Section "+(e+1)).attr("data-href",o.href).click((function(){t.rendition.display(a.attr("data-href"))}));n.append($("<li>").append(a))})))}))},initStyleHooks:function(t){console.log("registering style hooks..."),t.spine.hooks.content.register((function(t){$(t).find("p").filter((t,e)=>$(e).text().length>=32?e:null).css("text-align","justify"),$(t).find("html").attr("class",""),$(t).find("pre").css("white-space","pre-wrap"),$(t).find("a, p, span, em, i, strong, b, body, header, section, div, big, small, table, tr, td, ul, ol, li").attr("class","").css("font-family","inherit").css("font-size","inherit").css("line-height","inherit").css("color","").css("border","none ! important").css("background","").css("background-color","").attr("width","").attr("height",""),$(t).find("h1, h2, h3, h4, h5").attr("class","").css("font-family","inherit").css("color","").css("border","none ! important").css("background","").css("background-color",""),void 0!==Reader.hyphenate.en&&$(t).find("p, div").each((t,e)=>{(e=$(e)).html(Reader.hyphenate.en(e.html())),e.html(Reader.hyphenate.ru(e.html()))})}))},generateFontsCss:function(t){return`\n\t\t\t/** Calibri */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibriz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibrib.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibrii.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Calibri';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/calibri.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Cambria */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriaz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambriai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Cambria';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/cambria.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Caecilia */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caecilia.ttf"]});\n\t\t\t\tfont-weight : normal;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caeciliab.ttf"]});\n\t\t\t\tfont-weight : bold;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: Caecilia;\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/caeciliai.ttf"]});\n\t\t\t\tfont-style : italic;\n\t\t\t}\n\n\t\t\t/** Palatino */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palabi.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/palai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Palatino';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/pala.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** Consolas */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolab.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolaz.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consolai.ttf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'Consolas';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/consola.ttf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t/** IBM Plex Mono */\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-Bold.otf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-BoldItalic.otf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 700;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-TextItalic.otf"]});\n\t\t\t\tfont-style: italic;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\n\t\t\t@font-face {\n\t\t\t\tfont-family: 'IBM Plex Mono';\n\t\t\t\tsrc: url(${Reader.Loader._res_data[t+"lib/fonts/IBMPlexMono-Text.otf"]});\n\t\t\t\tfont-style: normal;\n\t\t\t\tfont-weight : 400;\n\t\t\t}\n\t\t\t`},flattenTocSubItems:function(t,e){let o=[];return 3!=e&&(t.subitems&&$.each(t.subitems,(function(t,n){n._nest=e,o.push(n),o=o.concat(Reader.flattenTocSubItems(n,e+1))})),o)},flattenToc:function(t){if(this._flattened_toc)return this._flattened_toc;{let e=[];return $.each(t.navigation.toc,(function(t,o){o._nest=0,e.push(o),e=e.concat(Reader.flattenTocSubItems(o,1))})),this._flattened_toc=e,e}},generateTocBar:function(t,e){$(".spacer").html(""),$.each(e,(function(e,o){try{const e=t.spine.get(o.href).cfiBase,n=t.locations._locations.find((function(t){return-1!=t.indexOf(e)}));if(n){const e=Math.round(100*t.locations.percentageFromCfi(n));$(".spacer").append($("<div class='toc-bar-entry'>").attr("data-nest-level",o._nest).css("left",e+"%").css("_width",3-o._nest+"px").attr("title",o.label))}}catch(t){console.warn(t)}})),$(".spacer").append($("<div class='toc-bar-entry current-position'>")),Reader.updateTocBarPosition(t,t.rendition.currentLocation())},updateTocBarPosition:function(t,e){const o=Math.round(e.start.location/t.locations.length()*100);$(".toc-bar-entry.current-position").css("left",o+"%")},applyStyles:function(t){Promise.all([localforage.getItem("epube.fontSize"),localforage.getItem("epube.fontFamily"),localforage.getItem("epube.lineHeight"),localforage.getItem("epube.theme")]).then((function(e){const o=e[0]?e[0]+"px":"16px",n=e[1]?e[1]:"Arial",a=e[2]?e[2]+"%":"140%";console.log("style",n,o,a),console.log("applying default theme..."),window.book.rendition.themes.default({html:{"font-size":o,"font-family":"'"+n+"'","line-height":a,"text-align":"justify","text-indent":"1em"}}),t||(console.log("applying rendition themes..."),$.each(window.book.rendition.getContents(),(function(t,e){e.css("font-size",o),e.css("font-family","'"+n+"'"),e.css("line-height",a),e.css("text-align","justify")}))),Reader.applyTheme()}))},applyTheme:function(){localforage.getItem("epube.theme").then((function(t){t||(t="default"),console.log("called for theme",t),"default"==t&&"undefined"!=typeof EpubeApp&&EpubeApp.isNightMode()&&(t="night"),console.log("setting main UI theme",t),$("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("epube-reader theme-"+t).attr("data-is-loading","false"),"undefined"!=typeof EpubeApp&&window.setTimeout((function(){const t=window.getComputedStyle(document.querySelector("body"),null).getPropertyValue("background-color").match(/rgb\((\d{1,}), (\d{1,}), (\d{1,})\)/);t&&(console.log("sending bgcolor",t),EpubeApp.setStatusBarColor(parseInt(t[1]),parseInt(t[2]),parseInt(t[3])))}),250),window.book&&$.each(window.book.rendition.getContents(),(function(e,o){console.log("applying rendition theme",t,"to",o,o.document),$(o.document).find("body").attr("class","undefined"!=typeof EpubeApp?"is-epube-app":"").addClass("theme-"+t)}))}))},hotkeyHandler:function(t){try{if($(".modal").is(":visible"))return;39!=t.which&&32!=t.which&&34!=t.which||(t.preventDefault(),Reader.Page.next()),37!=t.which&&33!=t.which||(t.preventDefault(),Reader.Page.prev()),27==t.which&&(t.preventDefault(),Reader.showUI(!0))}catch(t){console.warn(t)}},resizeSideColumns:function(){let t=$("#reader").position().left;const e=$("#reader iframe")[0];e&&e.contentWindow.$&&(t+=parseInt(e.contentWindow.$("body").css("padding-left"))),$("#left, #right").width(t)},markAsRead:function(){if(confirm("Mark book as read?")){const t=100,e=window.book.locations.cfiFromPercentage(1),o=(new Date).getTime();App.isOnline()&&$.post("backend.php",{op:"storelastread",page:t,cfi:e,id:$.urlParam("id"),timestamp:o},(function(t){$(".lastread_input").val(t.page+"%")})),localforage.setItem(Reader.cacheId("lastread"),{cfi:e,page:t,total:t,timestamp:o})}},close:function(){const t=window.book.rendition.currentLocation().start.cfi,e=parseInt(100*window.book.locations.percentageFromCfi(t)),o=(new Date).getTime();localforage.setItem(Reader.cacheId("lastread"),{cfi:t,page:e,total:100,timestamp:o}),App.isOnline()?$.post("backend.php",{op:"storelastread",id:$.urlParam("id"),page:e,cfi:t,timestamp:o},(function(){window.location=$.urlParam("rt")?"index.php?mode="+$.urlParam("rt"):"index.php"})).fail((function(){window.location="index.php"})):window.location="index.php"},cacheId:function(t){return"epube-book."+$.urlParam("b")+(t?"."+t:"")},toggleFullscreen:function(){if("undefined"!=typeof EpubeApp);else{const t=document.documentElement,e=document.webkitIsFullScreen||document.mozFullScreen||!1;t.requestFullScreen=t.requestFullScreen||t.webkitRequestFullScreen||t.mozRequestFullScreen||function(){return!1},document.cancelFullScreen=document.cancelFullScreen||document.webkitCancelFullScreen||document.mozCancelFullScreen||function(){return!1},e?document.cancelFullScreen():t.requestFullScreen()}},showUI:function(t){t?$(".header,.footer").fadeIn():$(".header,.footer").fadeOut()},toggleUI:function(){$(".header").is(":visible")?$(".header,.footer").fadeOut():$(".header,.footer").fadeIn()},lookupWord:function(t,e){t=t.replace(/­/g,""),$(".dict_result").html("Loading, please wait..."),$("#dict-modal").modal("show"),$.post("backend.php",{op:"define",word:t},(function(o){o&&($(".dict_result").html(o.result.join("<br/>")),$(".dict_query").val(t),e&&e())})).fail((function(t){console.warn(t),$(".dict_result").html("Network error while looking up word: "+t.statusText)}))},search:function(){const t=$(".search_input").val(),e=$(".search_results");e.html(""),t&&Promise.all(window.book.spine.spineItems.map(e=>e.load(window.book.load.bind(window.book)).then(e.find.bind(e,t)).finally(e.unload.bind(e)))).then(t=>Promise.resolve([].concat.apply([],t))).then((function(t){$.each(t,(function(t,o){const n=$("<a>").attr("href","#").html("<b class='pull-right'>"+window.book.locations.locationFromCfi(o.cfi)+"</b>"+o.excerpt).attr("data-cfi",o.cfi).attr("data-id",o.id).click((function(){window.book.rendition.display(n.attr("data-cfi"))}));e.append($("<li>").append(n))}))}))},Loader:{_res_data:[],init:async function(){const t=[];let e=!1;const o=await caches.open("epube-v3");(await o.keys()).forEach(o=>{if(!o.url.match("backend.php")){console.log("[loader] loading resource",o.url);const n=fetch(o.url).then(async t=>{if(t.ok){const e=new URL(t.url);if(e.searchParams.delete("ts"),t.url.match("\\.ttf|\\.otf")){const o=await t.blob();console.log("[loader] storing blob",e.href),Reader.Loader._res_data[e.toString()]=URL.createObjectURL(o)}else{const o=await t.text();console.log("[loader] storing text",e.href),Reader.Loader._res_data[e.toString()]=o}}else console.warn("[loader] failed for resource",o.url,t),$(".loading-message").html(`Unable to load resource.<br/><small>${o.url}</small>`),e=!0});t.push(n)}}),await Promise.allSettled(t),console.log("[loader] resource load complete, failed: ",e),e?Reader.applyTheme():Reader.initSecondStage()}},Page:{_moved_next:0,next:function(){window.book.rendition.next(),Reader.Page._moved_next+=1,"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(t){t||Reader.showUI(!1)}))},prev:function(){window.book.rendition.prev(),"undefined"!=typeof EpubeApp?EpubeApp.showActionBar(!1):localforage.getItem("epube.keep-ui-visible").then((function(t){t||Reader.showUI(!1)}))},openPrevious:async function(t){const e=$(t).attr("data-location-cfi");e&&await window.book.rendition.display(e),$(t).fadeOut()},clearLastRead:async function(){if(confirm("Clear stored last read location?")){const t=window.book.locations.length(),e=(new Date).getTime();if(App.isOnline()){const t=await $.post("backend.php",{op:"storelastread",page:-1,cfi:"",id:$.urlParam("id"),timestamp:e});$(".lastread_input").val(t.page+"%")}await localforage.setItem(Reader.cacheId("lastread"),{cfi:"",page:0,total:t,timestamp:e}),await window.book.rendition.display(window.book.locations.cfiFromPercentage(0))}},openLastRead:async function(t){const e=await localforage.getItem(Reader.cacheId("lastread"))||{};if(e&&e.cfi){console.log("using local lastread cfi",e.cfi);try{await t.display(e.cfi)}catch(t){console.warn(t)}}if(App.isOnline()){const o=await $.post("backend.php",{op:"getlastread",id:$.urlParam("id")});console.log("got remote lastread",o,e),o&&o.cfi&&e.cfi!=o.cfi&&(!e.timestamp||o.timestamp<=e.timestamp)&&(console.log("using remote lastread (timestamp is newer or local timestamp is missing)"),await localforage.setItem(Reader.cacheId("lastread"),{cfi:o.cfi,page:o.page,total:o.total,timestamp:o.timestamp}),await t.display(o.cfi))}$(".loading").hide()}},Settings:{onThemeChanged:function(t){const e=$(t).val();localforage.setItem("epube.theme",e).then((function(){Reader.applyTheme()}))},onLineHeightChanged:function(t){const e=$(t).val();localforage.setItem("epube.lineHeight",e).then((function(){Reader.applyStyles()}))},onTextSizeChanged:function(t){const e=$(t).val();localforage.setItem("epube.fontSize",e).then((function(){Reader.applyStyles()}))},onFontChanged:function(t){const e=$(t).val();localforage.setItem("epube.fontFamily",e).then((function(){Reader.applyStyles()}))}}};function __get_reader(){return Reader}function __get_app(){return App} \ No newline at end of file
diff --git a/js/reader.js b/js/reader.js
index 0981876..00afabc 100644
--- a/js/reader.js
+++ b/js/reader.js
@@ -140,6 +140,8 @@ const Reader = {
if (!book_data) {
console.log("local data not found, loading from network...");
+ $(".loading-message").html("Downloading book…");
+
const book_resp = await fetch("backend.php?op=download&id=" + $.urlParam("id"));
if (book_resp.ok) {