summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2020-04-21 08:34:24 +0300
committerAndrew Dolgov <[email protected]>2020-04-21 08:34:24 +0300
commit0a80c7a89cbe092d4ec6591b1ce0ab68479323d6 (patch)
tree0da476cbacdb3c33b86ccd078d863c6bde2a7b2b
parentbb0bbfb1ed76bb9c429b92d3769c19adef553e43 (diff)
combine index-related JS code into one App object
-rw-r--r--.gitignore1
-rw-r--r--index.php72
-rw-r--r--js/app.js545
-rw-r--r--js/common.js75
-rw-r--r--js/index.js260
-rw-r--r--js/offline.js163
-rw-r--r--login.php2
-rw-r--r--offline.html31
-rw-r--r--read.html3
-rw-r--r--worker.js3
10 files changed, 559 insertions, 596 deletions
diff --git a/.gitignore b/.gitignore
index 43691ba..99e0722 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ sessions/*
/tags
/.tags*
/.gutentags
+.idea/*
diff --git a/index.php b/index.php
index bc9419c..1e4f523 100644
--- a/index.php
+++ b/index.php
@@ -64,8 +64,7 @@
<link rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
- <script src="js/index.js?<?php echo time() ?>"></script>
- <script src="js/common.js?<?php echo time() ?>"></script>
+ <script src="js/app.js?<?php echo time() ?>"></script>
</head>
<body>
@@ -112,7 +111,7 @@
</form>
<ul class="nav navbar-nav navbar-right">
- <li><a href="#" title="Refresh script cache" onclick="return cache_refresh(true)">
+ <li><a href="#" title="Refresh script cache" onclick="return App.refreshCache(true)">
<span class="glyphicon glyphicon-refresh"></span> <span class='hidden-sm hidden-md hidden-lg'>Refresh script cache</span></a></li>
</li>
<?php if ($mode !== "favorites") { ?>
@@ -121,7 +120,7 @@
</a></li>
<?php } ?>
<?php if ($mode == "favorites") { ?>
- <li><a href="#" onclick="offline_get_all()" title="Download all">
+ <li><a href="#" onclick="App.offlineGetAll()" title="Download all">
<span class="glyphicon glyphicon-download-alt text-primary"></span> <span class='hidden-sm hidden-md hidden-lg'>Download all</span>
</a></li>
<?php } ?>
@@ -134,66 +133,9 @@
<div class="epube-app-filler"></div>
<script type="text/javascript">
- var index_mode = "<?php echo $mode ?>";
-
$(document).ready(function() {
- let refreshed_files = 0;
-
- if (typeof EpubeApp != "undefined") {
- $(".navbar").hide();
- $(".epube-app-filler").show();
-
- if ($.urlParam("mode") == "favorites")
- EpubeApp.setPage("PAGE_FAVORITES");
- else
- EpubeApp.setPage("PAGE_LIBRARY");
- }
-
- init_night_mode();
-
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker
- .register('worker.js?<?php echo time() ?>')
- .then(function() {
- console.log("service worker registered");
- });
-
- navigator.serviceWorker.addEventListener('message', function(event) {
-
- if (event.data == 'refresh-started') {
- console.log('cache refresh started');
- refreshed_files = 0;
-
- $(".dl-progress")
- .fadeIn()
- .text("Loading, please wait...");
- }
-
- if (event.data && event.data.indexOf("refreshed:") == 0) {
- ++refreshed_files;
-
- $(".dl-progress")
- .fadeIn()
- .text("Updated " + refreshed_files + " files...");
- }
-
- if (event.data == 'client-reload') {
- const ts = parseInt(new Date().getTime()/1000);
- localforage.setItem("epube.cache-timestamp", ts);
- window.location.reload()
- }
-
- });
- } else {
- $(".container-main")
- .addClass("alert alert-danger")
- .html("Service worker support missing in browser (are you using plain HTTP?).");
- }
-
- show_covers();
- mark_offline_books();
- cache_refresh();
-
+ App.index_mode = "<?php echo $mode ?>";
+ App.init();
});
</script>
@@ -380,10 +322,10 @@
}
?>
- <li><a href="#" onclick="return show_summary(this)"
+ <li><a href="#" onclick="return App.showSummary(this)"
data-book-id="<?php echo $line["id"] ?>">Summary</a></li>
- <li><a href="#" onclick="return toggle_fav(this)"
+ <li><a href="#" onclick="return App.toggleFavorite(this)"
data-is-fav="<?php echo $fav_attr ?>"
class="fav_item" data-book-id="<?php echo $line["id"] ?>">
<?php echo $toggle_fav_prompt ?></a></li>
diff --git a/js/app.js b/js/app.js
new file mode 100644
index 0000000..885bfb2
--- /dev/null
+++ b/js/app.js
@@ -0,0 +1,545 @@
+'use strict'
+
+/* global localforage, EpubeApp */
+
+$.urlParam = function(name){
+ try {
+ const results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
+ return decodeURIComponent(results[1].replace(/\+/g, " ")) || 0;
+ } catch (e) {
+ return 0;
+ }
+};
+
+const Cookie = {
+ set: function (name, value, lifetime) {
+ const d = new Date();
+ d.setTime(d.getTime() + lifetime * 1000);
+ const expires = "expires=" + d.toUTCString();
+ document.cookie = name + "=" + encodeURIComponent(value) + "; " + expires;
+ },
+ get: function (name) {
+ name = name + "=";
+ const ca = document.cookie.split(';');
+ for (let i=0; i < ca.length; i++) {
+ let c = ca[i];
+ while (c.charAt(0) == ' ') c = c.substring(1);
+ if (c.indexOf(name) == 0) return decodeURIComponent(c.substring(name.length, c.length));
+ }
+ return "";
+ },
+ delete: function(name) {
+ const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
+ document.cookie = name + "=" + "" + "; " + expires;
+ }
+};
+
+const App = {
+ _dl_progress_timeout: false,
+ index_mode: "",
+ init: function() {
+ let refreshed_files = 0;
+
+ if (typeof EpubeApp != "undefined") {
+ $(".navbar").hide();
+ $(".epube-app-filler").show();
+
+ if ($.urlParam("mode") == "favorites")
+ EpubeApp.setPage("PAGE_FAVORITES");
+ else
+ EpubeApp.setPage("PAGE_LIBRARY");
+ }
+
+ App.initNightMode();
+
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker
+ .register('worker.js?<?php echo time() ?>')
+ .then(function() {
+ console.log("service worker registered");
+ });
+
+ navigator.serviceWorker.addEventListener('message', function(event) {
+
+ if (event.data == 'refresh-started') {
+ console.log('cache refresh started');
+ refreshed_files = 0;
+
+ $(".dl-progress")
+ .fadeIn()
+ .text("Loading, please wait...");
+ }
+
+ if (event.data && event.data.indexOf("refreshed:") == 0) {
+ ++refreshed_files;
+
+ $(".dl-progress")
+ .fadeIn()
+ .text("Updated " + refreshed_files + " files...");
+ }
+
+ if (event.data == 'client-reload') {
+ const ts = parseInt(new Date().getTime()/1000);
+ localforage.setItem("epube.cache-timestamp", ts);
+ window.location.reload()
+ }
+
+ });
+ } else {
+ $(".container-main")
+ .addClass("alert alert-danger")
+ .html("Service worker support missing in browser (are you using plain HTTP?).");
+ }
+
+ App.showCovers();
+ App.Offline.markBooks();
+ App.refreshCache();
+
+ },
+ showSummary: function(elem) {
+ const id = elem.getAttribute("data-book-id");
+
+ $.post("backend.php", {op: 'getinfo', id: id}, function(data) {
+
+ const comment = data.comment ? data.comment : 'No description available';
+
+ $("#summary-modal .modal-title").html(data.title);
+ $("#summary-modal .book-summary").html(comment);
+
+ $("#summary-modal").modal();
+
+ });
+
+ return false;
+ },
+ offlineGetAll: function() {
+ if (confirm("Download all books on this page?")) {
+
+ $(".row > div").each(function (i, row) {
+ const bookId = $(row).attr("id").replace("cell-", "");
+ const dropitem = $(row).find(".offline_dropitem")[0];
+
+ if (bookId) {
+
+ const cacheId = 'epube-book.' + bookId;
+ localforage.getItem(cacheId).then(function(book) {
+
+ if (!book) {
+ App.offlineCache(bookId, function() {
+ App.Offline.mark(dropitem);
+ });
+ }
+
+ });
+
+ }
+ });
+ }
+ },
+ offlineCache: function(bookId, callback) {
+ console.log("offline cache: " + bookId);
+
+ $.post("backend.php", {op: "getinfo", id: bookId}, function(data) {
+
+ if (data) {
+ const cacheId = 'epube-book.' + bookId;
+
+ localforage.setItem(cacheId, data).then(function(data) {
+
+ console.log(cacheId + ' got data');
+
+ const promises = [];
+
+ promises.push(fetch('backend.php?op=download&id=' + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
+ if (resp.status == 200) {
+ console.log(cacheId + ' got book');
+
+ callback();
+
+ localforage.setItem(cacheId + '.book', resp.blob());
+ }
+ }));
+
+ promises.push(fetch("backend.php?op=getpagination&id=" + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
+ if (resp.status == 200) {
+ console.log(cacheId + ' got pagination');
+
+ resp.text().then(function(text) {
+ localforage.setItem(cacheId + '.locations', JSON.parse(text));
+ });
+ }
+ }));
+
+ promises.push(fetch("backend.php?op=getlastread&id=" + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
+ if (resp.status == 200) {
+ console.log(cacheId + ' got lastread');
+ resp.text().then(function(text) {
+ localforage.setItem(cacheId + '.lastread', JSON.parse(text));
+ });
+ }
+ }));
+
+ if (data.has_cover) {
+
+ promises.push(fetch("backend.php?op=cover&id=" + bookId, {credentials: 'same-origin'}).then(function(resp) {
+
+ if (resp.status == 200) {
+ console.log(cacheId + ' got cover');
+ localforage.setItem(cacheId + '.cover', resp.blob());
+ }
+
+ }));
+
+ }
+
+ Promise.all(promises).then(function() {
+ $(".dl-progress")
+ .show()
+ .html("Finished downloading <b>" + data.title + "</b>");
+
+ window.clearTimeout(App._dl_progress_timeout);
+
+ App._dl_progress_timeout = window.setTimeout(function() {
+ $(".dl-progress").fadeOut();
+ }, 5*1000);
+ });
+ });
+ }
+ });
+ },
+ showCovers: function() {
+ $("img[data-book-id]").each((i,e) => {
+ e = $(e);
+
+ if (e.attr('data-cover-link')) {
+ const img = $("<img>")
+ .on("load", function() {
+ e.css("background-image", "url(" + e.attr('data-cover-link') + ")")
+ .fadeIn();
+
+ img.attr("src", null);
+ })
+ .attr("src", e.attr('data-cover-link'));
+ } else {
+ e.attr('src', 'holder.js/130x190?auto=yes').fadeIn();
+ }
+ });
+
+ Holder.run();
+ },
+ toggleFavorite: function(elem) {
+ const bookId = elem.getAttribute("data-book-id");
+
+ if (elem.getAttribute("data-is-fav") == "0" || confirm("Remove favorite?")) {
+
+ $.post("backend.php", {op: "togglefav", id: bookId}, function(data) {
+ if (data) {
+ let msg = "[Error]";
+
+ if (data.status == 0) {
+ msg = "Add to favorites";
+ } else if (data.status == 1) {
+ msg = "Remove from favorites";
+ }
+
+ $(elem).html(msg).attr('data-is-fav', data.status);
+
+ if (App.index_mode == "favorites" && data.status == 0) {
+ $("#cell-" + bookId).remove();
+ }
+ }
+ });
+ }
+
+ return false;
+ },
+ refreshCache: function(force) {
+ if ('serviceWorker' in navigator) {
+ localforage.getItem("epube.cache-timestamp").then(function(stamp) {
+ const ts = parseInt(new Date().getTime()/1000);
+
+ if (force || !stamp || ts - stamp > 3600 * 24 * 7) {
+ console.log('asking worker to refresh cache');
+
+ if (navigator.serviceWorker.controller) {
+ navigator.serviceWorker.controller.postMessage("refresh-cache");
+ } else {
+ localforage.getItem("epube.initial-load-done").then(function(done) {
+
+ console.log("initial load done", done);
+
+ if (done) {
+ $(".dl-progress")
+ .show()
+ .addClass("alert-danger")
+ .html("Could not communicate with service worker. Try reloading the page.");
+ } else {
+ localforage.setItem("epube.initial-load-done", true).then(function() {
+ $(".dl-progress")
+ .show()
+ .addClass("alert-info")
+ .html("Page will reload to activate service worker...");
+
+ window.setTimeout(function() {
+ window.location.reload();
+ }, 3*1000);
+
+ });
+ }
+
+ });
+ }
+ }
+
+ });
+ }
+ },
+
+ initNightMode: function() {
+ if (window.matchMedia) {
+ const mql = window.matchMedia('(prefers-color-scheme: dark)');
+
+ mql.addEventListener("change", () => {
+ App.applyNightMode(mql.matches);
+ });
+
+ App.applyNightMode(mql.matches);
+ }
+ },
+ applyNightMode: function(is_night) {
+ console.log("night mode changed to", is_night);
+
+ $("#theme_css").attr("href",
+ "lib/bootstrap/v3/css/" + (is_night ? "theme-dark.min.css" : "bootstrap-theme.min.css"));
+ },
+ Offline: {
+ init: function() {
+ if (typeof EpubeApp != "undefined") {
+ $(".navbar").hide();
+ $(".epube-app-filler").show();
+
+ EpubeApp.setPage("PAGE_OFFLINE");
+ }
+
+ App.initNightMode();
+
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker
+ .register('worker.js')
+ .then(function() {
+ console.log("service worker registered");
+ });
+ }
+
+ const query = $.urlParam("query");
+
+ if (query)
+ $(".search_query").val(query);
+
+ App.Offline.populateList();
+ },
+ markBooks: function() {
+ const elems = $(".offline_dropitem");
+
+ $.each(elems, function (i, elem) {
+ App.Offline.mark(elem);
+ });
+ },
+ mark: function(elem) {
+ const bookId = elem.getAttribute("data-book-id");
+ const cacheId = "epube-book." + bookId;
+
+ localforage.getItem(cacheId).then(function(book) {
+ if (book) {
+ elem.onclick = function() {
+ App.Offline.remove(bookId, function() {
+ App.Offline.mark(elem);
+ });
+ return false;
+ };
+
+ elem.innerHTML = "Remove offline data";
+
+ } else {
+ elem.onclick = function() {
+ App.offlineCache(bookId, function() {
+ App.Offline.mark(elem);
+ });
+ return false;
+ };
+
+ elem.innerHTML = "Make available offline";
+ }
+ });
+ },
+
+ removeFromList: function(elem) {
+ const bookId = elem.getAttribute("data-book-id");
+
+ /* global offline_remove */
+ return App.Offline.remove(bookId, function() {
+ $("#cell-" + bookId).remove();
+ });
+ },
+ remove: function(id, callback) {
+ if (confirm("Remove download?")) {
+
+ const cacheId = "epube-book." + id;
+ const promises = [];
+
+ console.log("offline remove: " + id);
+
+ localforage.iterate(function(value, key, i) {
+ if (key.match(cacheId)) {
+ promises.push(localforage.removeItem(key));
+ }
+ });
+
+ Promise.all(promises).then(function() {
+ window.setTimeout(function() {
+ callback();
+ }, 500);
+ });
+ }
+ },
+ search: function() {
+ const query = $(".search_query").val();
+
+ localforage.setItem("epube.search-query", query).then(function() {
+ App.Offline.populateList();
+ });
+
+ return false;
+ },
+ removeAll: function() {
+ if (confirm("Remove all downloaded books?")) {
+
+ const promises = [];
+
+ localforage.iterate(function(value, key/*, i*/) {
+
+ if (key.match("epube-book")) {
+ promises.push(localforage.removeItem(key));
+ }
+ });
+
+ Promise.all(promises).then(function() {
+ window.setTimeout(function() {
+ App.Offline.populateList();
+ }, 500);
+ });
+ }
+ },
+ showSummary: function(elem) {
+ const bookId = elem.getAttribute("data-book-id");
+
+ localforage.getItem("epube-book." + bookId).then(function(data) {
+
+ const comment = data.comment ? data.comment : 'No description available';
+
+ $("#summary-modal .modal-title").html(data.title);
+ $("#summary-modal .book-summary").html(comment);
+
+ $("#summary-modal").modal();
+
+ });
+
+ return false;
+ },
+ populateList: function() {
+ let query = $.urlParam("query");
+
+ if (query) query = query.toLowerCase();
+
+ const books = $("#books_container");
+ books.html("");
+
+ localforage.iterate(function(value, key/*, i*/) {
+ if (key.match(/epube-book\.\d{1,}$/)) {
+
+ Promise.all([
+ localforage.getItem(key),
+ localforage.getItem(key + ".cover"),
+ localforage.getItem(key + ".lastread"),
+ localforage.getItem(key + ".book")
+ ]).then(function(results) {
+
+ if (results[0] && results[3]) {
+ const info = results[0];
+
+ if (query) {
+ const match =
+ (info.series_name && info.series_name.toLowerCase().match(query)) ||
+ (info.title && info.title.toLowerCase().match(query)) ||
+ (info.author_sort && info.author_sort.toLowerCase().match(query));
+
+ if (!match) return;
+ }
+
+
+ let cover = false;
+
+ if (results && results[1]) {
+ cover = URL.createObjectURL(results[1]);
+ }
+
+ let in_progress = false;
+ let is_read = false;
+
+ const lastread = results[2];
+ if (lastread) {
+ in_progress = lastread.page > 0;
+ is_read = lastread.total > 0 && lastread.total - lastread.page < 5;
+ }
+
+ const thumb_class = is_read ? "read" : "";
+ const title_class = in_progress ? "in_progress" : "";
+
+ const series_link = info.series_name ? `<div><a class="series_link" href="#">${info.series_name + " [" + info.series_index + "]"}</a></div>` : "";
+
+ const cell = $(`<div class="col-xs-6 col-sm-3 col-md-2" id="cell-${info.id}">
+ <a class="thumbnail ${thumb_class}" href="read.html?id=${info.epub_id}&b=${info.id}">
+ <img style="display : none">
+ </a>
+ <div class="caption">
+ <div><a class="${title_class}" href="read.html?id=${info.epub_id}&b=${info.id}">${info.title}</a></div>
+ <div><a class="author_link" href="#">${info.author_sort}</a></div>
+ ${series_link}
+ </div>
+ <div class="dropdown" style="white-space : nowrap">
+ <a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>
+ <ul class="dropdown-menu">
+ <li><a href="#" data-book-id="${info.id}" onclick="return App.Offline.showSummary(this)">Summary</a></li>
+ <li><a href="#" data-book-id="${info.id}" onclick="App.Offline.removeFromList(this)">Remove offline data</a></li>
+ </ul>
+ </div>
+ </div>`);
+
+ if (cover) {
+ cell.find("img")
+ .css("background-image", "url(" + cover + ")")
+ .fadeIn();
+ } else {
+ cell
+ .find("img").attr("data-src", 'holder.js/130x190?auto=yes')
+ .fadeIn();
+ }
+
+ cell.find(".series_link")
+ .attr("title", info.series_name + " [" + info.series_index + "]")
+ .attr("href", "offline.html?query=" + encodeURIComponent(info.series_name));
+
+ cell.find(".author_link")
+ .attr("title", info.author_sort)
+ .attr("href", "offline.html?query=" + encodeURIComponent(info.author_sort));
+
+ books.append(cell);
+
+ Holder.run();
+ }
+ });
+ }
+ });
+ }
+ },
+};
diff --git a/js/common.js b/js/common.js
deleted file mode 100644
index 45851a7..0000000
--- a/js/common.js
+++ /dev/null
@@ -1,75 +0,0 @@
-'use strict';
-
-$.urlParam = function(name){
- try {
- const results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
- return decodeURIComponent(results[1].replace(/\+/g, " ")) || 0;
- } catch (e) {
- return 0;
- }
-}
-
-function offline_remove(id, callback) {
-
- if (confirm("Remove download?")) {
-
- const cacheId = "epube-book." + id;
- const promises = [];
-
- console.log("offline remove: " + id);
-
- localforage.iterate(function(value, key, i) {
- if (key.match(cacheId)) {
- promises.push(localforage.removeItem(key));
- }
- });
-
- Promise.all(promises).then(function() {
- window.setTimeout(function() {
- callback();
- }, 500);
- });
- }
-}
-
-function init_night_mode() {
- if (window.matchMedia) {
- const mql = window.matchMedia('(prefers-color-scheme: dark)');
-
- mql.addEventListener("change", () => {
- apply_night_mode(mql.matches);
- });
-
- apply_night_mode(mql.matches);
- }
-}
-
-function apply_night_mode(is_night) {
- console.log("night mode changed to", is_night);
-
- $("#theme_css").attr("href",
- "lib/bootstrap/v3/css/" + (is_night ? "theme-dark.min.css" : "bootstrap-theme.min.css"));
-}
-
-const Cookie = {
- set: function (name, value, lifetime) {
- const d = new Date();
- d.setTime(d.getTime() + lifetime * 1000);
- const expires = "expires=" + d.toUTCString();
- document.cookie = name + "=" + encodeURIComponent(value) + "; " + expires;
- },
- get: function (name) {
- name = name + "=";
- const ca = document.cookie.split(';');
- for (let i=0; i < ca.length; i++) {
- let c = ca[i];
- while (c.charAt(0) == ' ') c = c.substring(1);
- if (c.indexOf(name) == 0) return decodeURIComponent(c.substring(name.length, c.length));
- }
- return "";
- },
- delete: function(name) {
- const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT";
- document.cookie = name + "=" + "" + "; " + expires;
- }
-};
diff --git a/js/index.js b/js/index.js
deleted file mode 100644
index 983db0b..0000000
--- a/js/index.js
+++ /dev/null
@@ -1,260 +0,0 @@
-'use strict';
-
-/* global localforage */
-
-let _dl_progress_timeout;
-
-/* exported cache_refresh */
-function cache_refresh(force) {
- if ('serviceWorker' in navigator) {
- localforage.getItem("epube.cache-timestamp").then(function(stamp) {
- const ts = parseInt(new Date().getTime()/1000);
-
- if (force || !stamp || ts - stamp > 3600 * 24 * 7) {
- console.log('asking worker to refresh cache');
-
- if (navigator.serviceWorker.controller) {
- navigator.serviceWorker.controller.postMessage("refresh-cache");
- } else {
- localforage.getItem("epube.initial-load-done").then(function(done) {
-
- console.log("initial load done", done);
-
- if (done) {
- $(".dl-progress")
- .show()
- .addClass("alert-danger")
- .html("Could not communicate with service worker. Try reloading the page.");
- } else {
- localforage.setItem("epube.initial-load-done", true).then(function() {
- $(".dl-progress")
- .show()
- .addClass("alert-info")
- .html("Page will reload to activate service worker...");
-
- window.setTimeout(function() {
- window.location.reload();
- }, 3*1000);
-
- });
- }
-
- });
- }
- }
-
- });
- }
-
- return false;
-}
-
-/* exported toggle_fav */
-function toggle_fav(elem) {
- const bookId = elem.getAttribute("data-book-id");
-
- if (elem.getAttribute("data-is-fav") == "0" || confirm("Remove favorite?")) {
-
- $.post("backend.php", {op: "togglefav", id: bookId}, function(data) {
- if (data) {
- let msg = "[Error]";
-
- if (data.status == 0) {
- msg = "Add to favorites";
- } else if (data.status == 1) {
- msg = "Remove from favorites";
- }
-
- $(elem).html(msg).attr('data-is-fav', data.status);
-
- /* global index_mode */
- if (index_mode == "favorites" && data.status == 0) {
- $("#cell-" + bookId).remove();
- }
- }
- });
- }
-
- return false;
-}
-
-/* global offline_remove */
-function mark_offline(elem) {
-
- const bookId = elem.getAttribute("data-book-id");
- const cacheId = "epube-book." + bookId;
-
- localforage.getItem(cacheId).then(function(book) {
- if (book) {
- elem.onclick = function() {
- offline_remove(bookId, function() {
- mark_offline(elem);
- });
- return false;
- };
-
- elem.innerHTML = "Remove offline data";
-
-
- } else {
- elem.onclick = function() {
- offline_cache(bookId, function() {
- mark_offline(elem);
- });
- return false;
- };
-
- elem.innerHTML = "Make available offline";
- }
- });
-}
-
-/* exported mark_offline_books */
-function mark_offline_books() {
- const elems = $(".offline_dropitem");
-
- $.each(elems, function (i, elem) {
- mark_offline(elem);
- });
-}
-
-/* exported show_covers */
-function show_covers() {
- $("img[data-book-id]").each((i,e) => {
- e = $(e);
-
- if (e.attr('data-cover-link')) {
- const img = $("<img>")
- .on("load", function() {
- e.css("background-image", "url(" + e.attr('data-cover-link') + ")")
- .fadeIn();
-
- img.attr("src", null);
- })
- .attr("src", e.attr('data-cover-link'));
- } else {
- e.attr('src', 'holder.js/130x190?auto=yes').fadeIn();
- }
- });
-
- Holder.run();
-}
-
-function offline_cache(bookId, callback) {
- console.log("offline cache: " + bookId);
-
- $.post("backend.php", {op: "getinfo", id: bookId}, function(data) {
-
- if (data) {
- const cacheId = 'epube-book.' + bookId;
-
- localforage.setItem(cacheId, data).then(function(data) {
-
- console.log(cacheId + ' got data');
-
- const promises = [];
-
- promises.push(fetch('backend.php?op=download&id=' + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
- if (resp.status == 200) {
- console.log(cacheId + ' got book');
-
- callback();
-
- localforage.setItem(cacheId + '.book', resp.blob());
- }
- }));
-
- promises.push(fetch("backend.php?op=getpagination&id=" + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
- if (resp.status == 200) {
- console.log(cacheId + ' got pagination');
-
- resp.text().then(function(text) {
- localforage.setItem(cacheId + '.locations', JSON.parse(text));
- });
- }
- }));
-
- promises.push(fetch("backend.php?op=getlastread&id=" + data.epub_id, {credentials: 'same-origin'}).then(function(resp) {
- if (resp.status == 200) {
- console.log(cacheId + ' got lastread');
- resp.text().then(function(text) {
- localforage.setItem(cacheId + '.lastread', JSON.parse(text));
- });
- }
- }));
-
- if (data.has_cover) {
-
- promises.push(fetch("backend.php?op=cover&id=" + bookId, {credentials: 'same-origin'}).then(function(resp) {
-
- if (resp.status == 200) {
- console.log(cacheId + ' got cover');
- localforage.setItem(cacheId + '.cover', resp.blob());
- }
-
- }));
-
- }
-
- Promise.all(promises).then(function() {
- $(".dl-progress")
- .show()
- .html("Finished downloading <b>" + data.title + "</b>");
-
- window.clearTimeout(_dl_progress_timeout);
-
- _dl_progress_timeout = window.setTimeout(function() {
- $(".dl-progress").fadeOut();
- }, 5*1000);
- });
- });
- }
-
- });
-}
-
-/* exported show_summary */
-function show_summary(elem) {
- const id = elem.getAttribute("data-book-id");
-
- $.post("backend.php", {op: 'getinfo', id: id}, function(data) {
-
- const comment = data.comment ? data.comment : 'No description available';
-
- $("#summary-modal .modal-title").html(data.title);
- $("#summary-modal .book-summary").html(comment);
-
- $("#summary-modal").modal();
-
- });
-
- return false;
-}
-
-/* exported offline_get_all */
-function offline_get_all() {
-
- if (confirm("Download all books on this page?")) {
-
- $(".row > div").each(function (i, row) {
- const bookId = $(row).attr("id").replace("cell-", "");
- const dropitem = $(row).find(".offline_dropitem")[0];
-
- if (bookId) {
-
- const cacheId = 'epube-book.' + bookId;
- localforage.getItem(cacheId).then(function(book) {
-
- if (!book) {
- offline_cache(bookId, function() {
- mark_offline(dropitem);
- });
- }
-
- });
-
- }
- });
- }
-
-}
diff --git a/js/offline.js b/js/offline.js
deleted file mode 100644
index 5ad5088..0000000
--- a/js/offline.js
+++ /dev/null
@@ -1,163 +0,0 @@
-'use strict';
-
-/* global localforage, Holder */
-
-/* exported offline_search */
-function offline_search() {
- const query = $(".search_query").val();
-
- localforage.setItem("epube.search-query", query).then(function() {
- populate_list();
- });
-
- return false;
-}
-
-/* exported offline_remove2 */
-function offline_remove2(elem) {
- const bookId = elem.getAttribute("data-book-id");
-
- /* global offline_remove */
- return offline_remove(bookId, function() {
- $("#cell-" + bookId).remove();
- });
-}
-
-/* exported offline_clear */
-function offline_clear() {
-
- if (confirm("Remove all downloaded books?")) {
-
- const promises = [];
-
- localforage.iterate(function(value, key/*, i*/) {
-
- if (key.match("epube-book")) {
- promises.push(localforage.removeItem(key));
- }
- });
-
- Promise.all(promises).then(function() {
- window.setTimeout(function() {
- populate_list();
- }, 500);
- });
- }
-}
-
-
-function populate_list() {
-
- let query = $.urlParam("query");
-
- if (query) query = query.toLowerCase();
-
- const books = $("#books_container");
- books.html("");
-
- localforage.iterate(function(value, key/*, i*/) {
- if (key.match(/epube-book\.\d{1,}$/)) {
-
- Promise.all([
- localforage.getItem(key),
- localforage.getItem(key + ".cover"),
- localforage.getItem(key + ".lastread"),
- localforage.getItem(key + ".book")
- ]).then(function(results) {
-
- if (results[0] && results[3]) {
- const info = results[0];
-
- if (query) {
- const match =
- (info.series_name && info.series_name.toLowerCase().match(query)) ||
- (info.title && info.title.toLowerCase().match(query)) ||
- (info.author_sort && info.author_sort.toLowerCase().match(query));
-
- if (!match) return;
- }
-
-
- let cover = false;
-
- if (results && results[1]) {
- cover = URL.createObjectURL(results[1]);
- }
-
- let in_progress = false;
- let is_read = false;
-
- const lastread = results[2];
- if (lastread) {
- in_progress = lastread.page > 0;
- is_read = lastread.total > 0 && lastread.total - lastread.page < 5;
- }
-
- const thumb_class = is_read ? "read" : "";
- const title_class = in_progress ? "in_progress" : "";
-
- const series_link = info.series_name ? `<div><a class="series_link" href="#">${info.series_name + " [" + info.series_index + "]"}</a></div>` : "";
-
- const cell = $(`<div class="col-xs-6 col-sm-3 col-md-2" id="cell-${info.id}">
- <a class="thumbnail ${thumb_class}" href="read.html?id=${info.epub_id}&b=${info.id}">
- <img style="display : none">
- </a>
- <div class="caption">
- <div><a class="${title_class}" href="read.html?id=${info.epub_id}&b=${info.id}">${info.title}</a></div>
- <div><a class="author_link" href="#">${info.author_sort}</a></div>
- ${series_link}
- </div>
- <div class="dropdown" style="white-space : nowrap">
- <a href="#" data-toggle="dropdown" role="button">More...<span class="caret"></span></a>
- <ul class="dropdown-menu">
- <li><a href="#" data-book-id="${info.id}" onclick="return show_summary(this)">Summary</a></li>
- <li><a href="#" data-book-id="${info.id}" onclick="offline_remove2(this)">Remove offline data</a></li>
- </ul>
- </div>
- </div>`);
-
- if (cover) {
- cell.find("img")
- .css("background-image", "url(" + cover + ")")
- .fadeIn();
- } else {
- cell
- .find("img").attr("data-src", 'holder.js/130x190?auto=yes')
- .fadeIn();
- }
-
- cell.find(".series_link")
- .attr("title", info.series_name + " [" + info.series_index + "]")
- .attr("href", "offline.html?query=" + encodeURIComponent(info.series_name));
-
- cell.find(".author_link")
- .attr("title", info.author_sort)
- .attr("href", "offline.html?query=" + encodeURIComponent(info.author_sort));
-
- books.append(cell);
-
- Holder.run();
- }
- });
- }
- });
-
-}
-
-/* exported show_summary */
-function show_summary(elem) {
- const bookId = elem.getAttribute("data-book-id");
-
- localforage.getItem("epube-book." + bookId).then(function(data) {
-
- const comment = data.comment ? data.comment : 'No description available';
-
- $("#summary-modal .modal-title").html(data.title);
- $("#summary-modal .book-summary").html(comment);
-
- $("#summary-modal").modal();
-
- });
-
- return false;
-}
diff --git a/login.php b/login.php
index 79f2c1f..844862d 100644
--- a/login.php
+++ b/login.php
@@ -46,8 +46,6 @@
<link rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
- <script src="js/index.js"></script>
- <script src="js/common.js"></script>
</head>
<body>
diff --git a/offline.html b/offline.html
index 6d315b5..8fe8907 100644
--- a/offline.html
+++ b/offline.html
@@ -14,8 +14,7 @@
<link rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link rel="manifest" href="manifest.json">
<meta name="mobile-web-app-capable" content="yes">
- <script src="js/offline.js"></script>
- <script src="js/common.js"></script>
+ <script src="js/app.js"></script>
</head>
<body>
@@ -52,7 +51,7 @@
</form>
<ul class="nav navbar-nav navbar-right">
- <li><a href="#" onclick="offline_clear()" title="Remove all downloads">
+ <li><a href="#" onclick="App.Offline.removeAll()" title="Remove all downloads">
<span class="glyphicon glyphicon-remove-circle text-danger"></span> <span class='hidden-sm hidden-md hidden-lg'>Remove all downloads</span>
</a></li>
</ul>
@@ -68,31 +67,7 @@
'use strict';
$(document).ready(function() {
-
- if (typeof EpubeApp != "undefined") {
- $(".navbar").hide();
- $(".epube-app-filler").show();
-
- EpubeApp.setPage("PAGE_OFFLINE");
- }
-
- init_night_mode();
-
- if ('serviceWorker' in navigator) {
- navigator.serviceWorker
- .register('worker.js')
- .then(function() {
- console.log("service worker registered");
- });
- }
-
- var query = $.urlParam("query");
-
- if (query)
- $(".search_query").val(query);
-
- populate_list();
-
+ App.Offline.init();
});
</script>
diff --git a/read.html b/read.html
index 4244d09..330c543 100644
--- a/read.html
+++ b/read.html
@@ -14,8 +14,9 @@
<script src="lib/zip.min.js"></script>
<script src="lib/localforage.min.js"></script>
<script src="lib/epub.js"></script>
+
+ <script src="js/app.js"></script>
<script src="js/read.js"></script>
- <script src="js/common.js"></script>
<link id="favicon" rel="shortcut icon" type="image/png" href="img/favicon.png" />
<link type="text/css" rel="stylesheet" media="screen" href="css/read.css" />
diff --git a/worker.js b/worker.js
index ea568c8..b1d1aee 100644
--- a/worker.js
+++ b/worker.js
@@ -7,9 +7,8 @@ const CACHE_URLS = [
'img/ic_launcher_web.png',
'img/favicon.png',
'read.html',
- 'js/common.js',
+ 'js/app.js',
'js/read.js',
- 'js/offline.js',
'js/reader.js',
'js/dict.js',
'css/read.css',