summaryrefslogtreecommitdiff
path: root/reader.js
diff options
context:
space:
mode:
Diffstat (limited to 'reader.js')
-rwxr-xr-xreader.js267
1 files changed, 251 insertions, 16 deletions
diff --git a/reader.js b/reader.js
index 852664d..112d430 100755
--- a/reader.js
+++ b/reader.js
@@ -1,36 +1,271 @@
-function ComicArchive(file) {
+const TCRSYNC_SERVER = "https://tt-rss.org/tcrsync/";
+
+function Model() {
const self = this;
- self.zip = new AdmZip(file);
+ self.fileName = ko.observable("");
+ self._zip = null;
+ self._zipEntries = ko.observableArray();
+ self.syncAccount = ko.observable("");
+
+ self.cacheKey = function(suffix) {
+ const sha1 = require('js-sha1');
+
+ return sha1(self.fileName()) + ":" + suffix;
+ };
+
+ self.syncClient = {
+ _sha1_compat: function(str) {
+ const sha1 = require('js-sha1');
+ const hash = sha1.create();
+ hash.update(str);
+
+ const chars = hash.array('');
+ let rv = "";
+
+ for (let i = 0; i < chars.length; i++) {
+ rv += Number(chars[i]).toString(16);
+ }
+
+ return rv;
+ },
+ set: function(page) {
+ if (!self.syncAccount() || !self.fileName())
+ return;
+
+ const owner = this._sha1_compat(self.syncAccount());
+ const hash = this._sha1_compat(self.fileName());
+
+ console.log('syncClient, set', owner, hash, page)
+ },
+ get: function() {
+ if (!self.syncAccount() || !self.fileName())
+ return;
+
+ const owner = this._sha1_compat(self.syncAccount());
+ const hash = this._sha1_compat(self.fileName());
+
+ console.log('syncClient, get', owner, hash);
+
+ return new Promise((resolve, reject) => {
+ $.post(TCRSYNC_SERVER, {op: "get", version: 2, owner: owner, hash: hash}).then((resp) => {
+ console.log('tcrsync_get', resp);
+
+ const page = isNaN(resp) ? -1 : parseInt(resp);
+
+ resolve(page);
+ });
+ });
+ },
+ };
+
+ self.openFile = function (file) {
+ console.log('openFile', file);
+
+ self._zipEntries.removeAll();
+ self.currentPage(-2);
+
+ const AdmZip = require('adm-zip');
+ self._zip = new AdmZip(file);
+
+ const zipEntries = self._zip.getEntries();
-};
+ for (let i = 0; i < zipEntries.length; i++) {
+ const ze = zipEntries[i];
-$(document).ready(function() {
- const { remote, ipcRenderer } = require('electron');
- const { BrowserWindow } = remote;
+ if (ze.entryName.match(/\.(jpe?g|gif|bmp|png|webp)$/i)) {
+ self._zipEntries.push(ze);
+ }
+ }
- console.log("document ready", BrowserWindow, remote, ipcRenderer);
+ self._zipEntries.sort(function(a, b) {
+ return a.entryName.localeCompare(b.entryName);
+ });
+
+ self.fileName(file.split(/[\\/]/).pop());
+
+
+ localforage.getItem(self.cacheKey("POSITION")).then((page) => {
+ if (page)
+ self.currentPage(page);
+ else
+ self.currentPage(0);
+ });
+
+ };
+
+ self.documentTitle = ko.computed(function () {
+ if (self.fileName())
+ return "Pow! Comics Reader: " + self.fileName();
+ else
+ return "Pow! Comics Reader";
+ });
+
+ self.totalPages = ko.computed(function () {
+ return self._zipEntries().length;
+ });
+
+ self._currentPage = ko.observable(-2);
+
+ self.currentPage = ko.computed({
+ read: function() {
+ return self._currentPage();
+ },
+ write: function(page) {
+ self._currentPage(page);
+
+ localforage.getItem(model.cacheKey("POSITION")).then((stored) => {
+ if (stored < page) {
+ localforage.setItem(model.cacheKey("POSITION"), page).then(() => {
+ console.log('saved position', page);
+
+ if (page % 10 == 0) {
+ model.syncClient.set(page);
+ }
+ });
+ }
+ });
+ },
+ });
+
+ self.currentPageDisp = ko.computed(function () {
+ const page = self.currentPage();
+
+ if (page < 0)
+ return 0;
+ else
+ return page + 1;
+ });
- ipcRenderer.on("test-event", (event, args) => {
- console.log('test-event', event, args);
+ self.progressPct = ko.computed(function () {
+ if (self.totalPages() > 0) {
+ return parseInt(self.currentPage() / self.totalPages() * 100) + "%";
+ } else {
+ return "";
+ }
+ });
+
+ self.getLeftPage = ko.computed(function () {
+ const page = self.currentPage();
+
+ if (self._zip && page >= 0 && page < self._zipEntries().length) {
+ const ze = self._zipEntries()[page];
+
+ if (ze) {
+ return 'data:image/jpeg;base64,' + ze.getData().toString("base64");
+ }
+ }
+ });
+
+ self.getRightPage = ko.computed(function () {
+ const page = self.currentPage() + 1;
+
+ if (self._zip && page >= 0 && page < self._zipEntries().length) {
+ const ze = self._zipEntries()[page];
+
+ if (ze) {
+ return 'data:image/jpeg;base64,' + ze.getData().toString("base64");
+ }
+ }
+ });
+}
+
+const model = new Model();
+
+$(document).ready(function () {
+ const {remote, ipcRenderer} = require('electron');
+ const {BrowserWindow} = remote;
+
+ localforage.getItem("TTC:SYNC-ACCOUNT").then((acct) => {
+ if (acct)
+ model.syncAccount(acct);
+ });
+
+ ko.applyBindings(model, document.querySelector('html'));
+
+ ipcRenderer.on("open-settings", () => {
+ $('#settings-modal').modal('show');
});
ipcRenderer.on("open-file", (event, args) => {
- console.log('open-file', event, args);
+ model.openFile(args[0]);
+ });
- const file = args[0];
+ ipcRenderer.on("sync-to-last", (event, args) => {
+ model.syncClient.get().then((page) => {
+ if (confirm("You are currently on page %p. Furthest read page stored on the server is %r. Open it instead?"
+ .replace("%p", model.currentPageDisp())
+ .replace("%r", page + 1))) {
- const AdmZip = require('adm-zip');
- const zip = new AdmZip(file);
+ model.currentPage(page);
+
+ }
+ });
+ });
+
+ $(".location").click(function() {
+ const current = model.currentPageDisp();
+ const total = model.totalPages();
- const zip_entries = zip.getEntries();
+ const page = prompt("Jump to location [1-" + total + "]", parseInt(current));
+
+ if (page) {
+ $("#reader img").attr("data-page", parseInt(page - 1));
+ }
+ });
- $.each(zip_entries, (i, ze) => {
- console.log(ze);
+ $(".sync-account").on("change", function() {
+ const acct = $(this).val();
+ console.log('sa', acct);
+ localforage.setItem("TTC:SYNC-ACCOUNT", acct).then(() => {
+ model.syncAccount(acct);
});
+ });
+
+ $("#left").on("click", (e) => {
+ e.stopPropagation();
+
+ let page = model.currentPage();
+
+ if ($(".right-page").is(":visible") && page > 1)
+ page = page - 1;
+
+ if (page > 0)
+ model.currentPage(page - 1);
+
+ });
+
+ $("#right").on("click", (e) => {
+ e.stopPropagation();
+
+ let page = model.currentPage();
+
+ if ($(".right-page").is(":visible") && page < total_pages - 2)
+ page = page + 1;
+
+ if (page < model.totalPages()) {
+ model.currentPage(page + 1);
+ }
+ });
+
+ $(document).on("keydown", (e) => {
+ if ($(".modal").is(":visible"))
+ return;
+ switch (e.which) {
+ case 27:
+ $(".header,.footer").fadeIn();
+ break;
+ case 37:
+ $("#left").click();
+ break;
+ case 32:
+ case 39:
+ $("#right").click();
+ break;
+ }
});
});