Browse Source

Merge branch 'release/0.7.2'

Book Pauk 5 years ago
parent
commit
f7eb576d0d

+ 2 - 3
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)});
             }
         }
         //загрузка

+ 7 - 3
client/components/Reader/HelpPage/CommonHelpPage/CommonHelpPage.vue

@@ -24,10 +24,14 @@
 
         <div v-show="mode == 'omnireader'">
             <p>Вы можете добавить в свой браузер закладку, указав в ее свойствах вместо адреса следующий код:
-                <br><span class="clickable" @click="copyText('javascript:location.href=\'https://omnireader.ru/?url=\'+location.href;', 'Код для адреса закладки успешно скопирован в буфер обмена')">
-                    <strong>javascript:location.href='https://omnireader.ru/?url='+location.href;</strong>
+                <br><strong>javascript:location.href='https://omnireader.ru/?url='+location.href;</strong>
+                &nbsp;
+                <span class="clickable" @click="copyText('javascript:location.href=\'https://omnireader.ru/?url=\'+location.href;', 'Код для адреса закладки успешно скопирован в буфер обмена')">
+                    (скопировать)
                 </span>
-                <br>Тогда, активировав получившуюся закладку на любой странице интернета, вы автоматически откроете ее в Omni Reader.
+                <br>или перетащив на панель закладок следующую ссылку:
+                <br><a style="margin-left: 50px" href="javascript:location.href='https://omnireader.ru/?url='+location.href;">Omni Reader</a>
+                <br>Тогда, активировав получившуюся закладку на любой странице интернета, вы автоматически загрузите эту страницу в Omni Reader.
                 <br>В Chrome для Android можно вызывать такую закладку по имени прямо в адресной строке браузера (имя стоит сделать попроще).
             </p>
         </div>

+ 5 - 0
client/components/Reader/LoaderPage/LoaderPage.vue

@@ -31,6 +31,7 @@
             </div>
             <div class="space"></div>
             <span v-if="mode == 'omnireader'" class="bottom-span clickable" @click="openComments">Отзывы о читалке</span>
+            <span v-if="mode == 'omnireader'" class="bottom-span clickable" @click="openOldVersion">Старая версия</span>
         </div>
 
         <div class="part bottom">
@@ -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);

+ 24 - 14
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');
             });
         }

+ 1 - 0
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;
     }

+ 1 - 1
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;

+ 11 - 0
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() => {

+ 11 - 0
client/components/Reader/versionHistory.js

@@ -1,4 +1,15 @@
 export const versionHistory = [
+{
+    showUntil: '2019-10-17',
+    header: '0.7.2 (2019-10-18)',
+    content:
+`
+<ul>
+    <li>исправления багов</li>
+</ul>
+`
+},
+
 {
     showUntil: '2019-09-19',
     header: '0.7.1 (2019-09-20)',

+ 8 - 74
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",

+ 2 - 2
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",

+ 1 - 1
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';

+ 7 - 16
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);
         });
     }