diff --git a/client/api/reader.js b/client/api/reader.js index b8081bd8..7d45eada 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -1,6 +1,4 @@ -import _ from 'lodash'; import axios from 'axios'; -import {Buffer} from 'safe-buffer'; import * as utils from '../share/utils'; @@ -66,12 +64,13 @@ class Reader { estSize = response.headers['content-length']; } + callback({state: 'loading', progress: 0}); const options = { onDownloadProgress: progress => { while (progress.loaded > estSize) estSize *= 1.5; if (callback) - callback({state: 'loading', progress: Math.round((progress.loaded*100)/estSize)}); + callback({progress: Math.round((progress.loaded*100)/estSize)}); } } //загрузка diff --git a/client/components/Reader/HelpPage/CommonHelpPage/CommonHelpPage.vue b/client/components/Reader/HelpPage/CommonHelpPage/CommonHelpPage.vue index 2ea212c6..28ebd44c 100644 --- a/client/components/Reader/HelpPage/CommonHelpPage/CommonHelpPage.vue +++ b/client/components/Reader/HelpPage/CommonHelpPage/CommonHelpPage.vue @@ -24,10 +24,14 @@

Вы можете добавить в свой браузер закладку, указав в ее свойствах вместо адреса следующий код: -
- javascript:location.href='https://omnireader.ru/?url='+location.href; +
javascript:location.href='https://omnireader.ru/?url='+location.href; +   + + (скопировать) -
Тогда, активировав получившуюся закладку на любой странице интернета, вы автоматически откроете ее в Omni Reader. +
или перетащив на панель закладок следующую ссылку: +
Omni Reader +
Тогда, активировав получившуюся закладку на любой странице интернета, вы автоматически загрузите эту страницу в Omni Reader.
В Chrome для Android можно вызывать такую закладку по имени прямо в адресной строке браузера (имя стоит сделать попроще).

diff --git a/client/components/Reader/LoaderPage/LoaderPage.vue b/client/components/Reader/LoaderPage/LoaderPage.vue index 1bf6475c..673909de 100644 --- a/client/components/Reader/LoaderPage/LoaderPage.vue +++ b/client/components/Reader/LoaderPage/LoaderPage.vue @@ -31,6 +31,7 @@
Отзывы о читалке + Старая версия
@@ -137,6 +138,10 @@ class LoaderPage extends Vue { window.open('http://samlib.ru/comment/b/bookpauk/bookpauk_reader', '_blank'); } + openOldVersion() { + window.open('http://old.omnireader.ru', '_blank'); + } + keyHook(event) { if (this.pasteTextActive) { return this.$refs.pasteTextPage.keyHook(event); diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 90428c15..b3055709 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -510,29 +510,35 @@ class Reader extends Vue { } async bookManagerEvent(eventName) { - if (eventName == 'recent-changed') { - if (this.recentBooksActive) { - await this.$refs.recentBooksPage.updateTableData(); - } - } - if (eventName == 'set-recent' || eventName == 'recent-deleted') { - const oldBook = this.mostRecentBookReactive; + const oldBook = (this.textPage ? this.textPage.lastBook : null); + const oldPos = (this.textPage ? this.textPage.bookPos : null); const newBook = bookManager.mostRecentBook(); + + if (!(oldBook && newBook && oldBook.key == newBook.key)) { + this.mostRecentBook(); + } + if (oldBook && newBook) { - if (oldBook.key != newBook.key) { + if (oldBook.key != newBook.key || oldBook.path != newBook.path) { this.loadingBook = true; try { await this.loadBook(newBook); } finally { this.loadingBook = false; } - } else if (oldBook.bookPos != newBook.bookPos) { + } else if (oldPos != newBook.bookPos) { while (this.loadingBook) await utils.sleep(100); this.bookPosChanged({bookPos: newBook.bookPos}); } } } + + if (eventName == 'recent-changed') { + if (this.recentBooksActive) { + await this.$refs.recentBooksPage.updateTableData(); + } + } } get toolBarActive() { @@ -903,6 +909,7 @@ class Reader extends Vue { this.updateRoute(); const textPage = this.$refs.page; if (textPage.showBook) { + this.textPage = textPage; textPage.lastBook = last; textPage.bookPos = (last.bookPos !== undefined ? last.bookPos : 0); @@ -927,8 +934,10 @@ class Reader extends Vue { url = 'http://' + url; // уже просматривается сейчас - const lastBook = (this.$refs.page ? this.$refs.page.lastBook : null); - if (!opts.force && lastBook && lastBook.url == url && await bookManager.hasBookParsed(lastBook)) { + const lastBook = (this.textPage ? this.textPage.lastBook : null); + if (!opts.force && lastBook && lastBook.url == url && + (!opts.path || opts.path == lastBook.path) && + await bookManager.hasBookParsed(lastBook)) { this.loaderActive = false; return; } @@ -957,7 +966,7 @@ class Reader extends Vue { if (!opts.force) { // пытаемся загрузить и распарсить книгу в менеджере из локального кэша - const bookParsed = await bookManager.getBook({url}, (prog) => { + const bookParsed = await bookManager.getBook({url, path: opts.path}, (prog) => { progress.setState({progress: prog}); }); @@ -978,6 +987,7 @@ class Reader extends Vue { // иначе идем на сервер // пытаемся загрузить готовый файл с сервера if (wasOpened.path) { + progress.setState({totalSteps: 5}); try { const resp = await readerApi.loadCachedBook(wasOpened.path, (state) => { progress.setState(state); @@ -1063,7 +1073,7 @@ class Reader extends Vue { let page = this.$refs.page; while (this.blinkCount) { this.showRefreshIcon = !this.showRefreshIcon; - if (page.blinkCachedLoadMessage) + if (page && page.blinkCachedLoadMessage) page.blinkCachedLoadMessage(this.showRefreshIcon); await utils.sleep(500); if (this.stopBlink) @@ -1073,7 +1083,7 @@ class Reader extends Vue { } this.showRefreshIcon = true; this.inBlink = false; - if (page.blinkCachedLoadMessage) + if (page && page.blinkCachedLoadMessage) page.blinkCachedLoadMessage('finish'); }); } diff --git a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue index 444dbc3e..200dc9c1 100644 --- a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue +++ b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue @@ -251,6 +251,7 @@ class RecentBooksPage extends Vue { } if (this.tableData.length > result.length) this.tableData.splice(result.length);*/ + this.tableData = result; this.updating = false; } diff --git a/client/components/Reader/ServerStorage/ServerStorage.vue b/client/components/Reader/ServerStorage/ServerStorage.vue index 21667b62..9c55ec3b 100644 --- a/client/components/Reader/ServerStorage/ServerStorage.vue +++ b/client/components/Reader/ServerStorage/ServerStorage.vue @@ -455,7 +455,7 @@ class ServerStorage extends Vue { const l = Object.keys(this.recentDelta).length - (1*(!!this.recentDelta.diff)); this.makeDeltaDiff = (l == 1 && this.prevItemKey == itemKey ? this.makeDeltaDiff : false); - const forceSaveRecent = l > 10 || (this.sameKeyCount > 5 && (l > 1)) || (l == 1 && this.sameKeyCount > 10 && !this.makeDeltaDiff); + const forceSaveRecent = l > 20 || (this.sameKeyCount > 5 && (l > 1)) || (l == 1 && this.sameKeyCount > 10 && !this.makeDeltaDiff); this.sameKeyCount = (!forceSaveRecent ? this.sameKeyCount : 0); this.prevItemKey = itemKey; diff --git a/client/components/Reader/share/bookManager.js b/client/components/Reader/share/bookManager.js index 06342f78..e58a2e0b 100644 --- a/client/components/Reader/share/bookManager.js +++ b/client/components/Reader/share/bookManager.js @@ -262,6 +262,11 @@ class BookManager { this.books[meta.key] = result; } + //Если файл на сервере изменился, считаем, что в кеше его нету + if (meta.path && result && meta.path != result.path) { + return; + } + if (result && !result.parsed) { let data = await bmDataStore.getItem(`bmData-${meta.key}`); callback(5); @@ -434,6 +439,12 @@ class BookManager { const mergedRecent = _.cloneDeep(this.recent); Object.assign(mergedRecent, value); + + //подстраховка + for (let i of Object.keys(mergedRecent)) { + if (!mergedRecent[i].key || mergedRecent[i].key !== i) + delete mergedRecent[i]; + } //"ленивое" обновление хранилища (async() => { diff --git a/client/components/Reader/versionHistory.js b/client/components/Reader/versionHistory.js index df6acf20..3cdb9d90 100644 --- a/client/components/Reader/versionHistory.js +++ b/client/components/Reader/versionHistory.js @@ -1,4 +1,15 @@ export const versionHistory = [ +{ + showUntil: '2019-10-17', + header: '0.7.2 (2019-10-18)', + content: +` + +` +}, + { showUntil: '2019-09-19', header: '0.7.1 (2019-09-20)', diff --git a/package-lock.json b/package-lock.json index 8970897b..8c703a87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Liberama", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -541,6 +541,11 @@ "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", "dev": true }, + "adm-zip": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==" + }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", @@ -1645,15 +1650,6 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -1883,11 +1879,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -2071,14 +2062,6 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -3196,20 +3179,6 @@ "mimic-response": "^1.0.0" } }, - "decompress-zip": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decompress-zip/-/decompress-zip-0.2.2.tgz", - "integrity": "sha512-v+Na3Ck86Px7s2ix+f77pMQC3GlkxHHN+YyvnkEW7+xX5F39pcDpIV/VFvGYk8MznTFcMoPjL3XNWEJLXWoSPw==", - "requires": { - "binary": "^0.3.0", - "graceful-fs": "^4.1.3", - "mkpath": "^0.1.0", - "nopt": "^3.0.1", - "q": "^1.1.2", - "readable-stream": "^1.1.8", - "touch": "0.0.3" - } - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -6751,11 +6720,6 @@ } } }, - "mkpath": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-0.1.0.tgz", - "integrity": "sha1-dVSm+Nhxg0zJe1RisSLEwSTW3pE=" - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -7047,14 +7011,6 @@ "semver": "^5.3.0" } }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -9953,7 +9909,8 @@ "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true }, "qs": { "version": "6.7.0", @@ -11785,24 +11742,6 @@ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", "dev": true }, - "touch": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", - "integrity": "sha1-Ua7z1ElXHU8oel2Hyci0kYGg2x0=", - "requires": { - "nopt": "~1.0.10" - }, - "dependencies": { - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "requires": { - "abbrev": "1" - } - } - } - }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -11819,11 +11758,6 @@ } } }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" - }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", diff --git a/package.json b/package.json index e5ca04a4..ef406575 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Liberama", - "version": "0.7.1", + "version": "0.7.2", "engines": { "node": ">=10.0.0" }, @@ -55,12 +55,12 @@ "webpack-merge": "^4.2.2" }, "dependencies": { + "adm-zip": "^0.4.13", "appcache-webpack-plugin": "^1.4.0", "axios": "^0.18.1", "base-x": "^3.0.6", "chardet": "^0.7.0", "compression": "^1.7.4", - "decompress-zip": "^0.2.2", "element-ui": "^2.12.0", "express": "^4.17.1", "fg-loadcss": "^2.1.0", diff --git a/server/core/BookConverter/textUtils.js b/server/core/BookConverter/textUtils.js index 6ee5169d..80ee401e 100644 --- a/server/core/BookConverter/textUtils.js +++ b/server/core/BookConverter/textUtils.js @@ -74,7 +74,7 @@ function getEncoding(buf, returnAll) { if (returnAll) return sorted; - else if (sorted[0].c > 0) + else if (sorted[0].c > 0 && sorted[0].c > sorted[0].totalChecked/2) return sorted[0].codePage; else return 'ISO-8859-5'; diff --git a/server/core/FileDecompressor.js b/server/core/FileDecompressor.js index 99305207..95a4a46b 100644 --- a/server/core/FileDecompressor.js +++ b/server/core/FileDecompressor.js @@ -4,7 +4,7 @@ const crypto = require('crypto'); const path = require('path'); const unbzip2Stream = require('unbzip2-stream'); const tar = require('tar-fs'); -const DecompressZip = require('decompress-zip'); +const AdmZip = require('adm-zip'); const utils = require('./utils'); const FileDetector = require('./FileDetector'); @@ -112,26 +112,17 @@ class FileDecompressor { } async unZip(filename, outputDir) { - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const files = []; - const unzipper = new DecompressZip(filename); + const zip = new AdmZip(filename); - unzipper.on('error', function(err) { - reject(err); + zip.getEntries().forEach(function(zipEntry) { + files.push({path: zipEntry.entryName, size: zipEntry.header.size}); }); - unzipper.on('extract', function() { - resolve(files); - }); + zip.extractAllTo(outputDir, true); - unzipper.extract({ - path: outputDir, - filter: function(file) { - if (file.type == 'File') - files.push({path: file.path, size: file.uncompressedSize}); - return true; - } - }); + resolve(files); }); }