From a2c393b06b82b6676bd2aaa8780d7da0e90513d0 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 22 Aug 2019 15:37:15 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3,=20=D1=83=D0=BF=D1=80=D0=BE=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5,=20=D0=BD=D0=B0=D1=87=D0=B0=D0=BB?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8?= =?UTF-8?q?=20ServerStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Reader/HistoryPage/HistoryPage.vue | 46 +++- client/components/Reader/Reader.vue | 31 ++- client/components/Reader/share/bookManager.js | 244 +++++------------- 3 files changed, 123 insertions(+), 198 deletions(-) diff --git a/client/components/Reader/HistoryPage/HistoryPage.vue b/client/components/Reader/HistoryPage/HistoryPage.vue index e63b6ec6..a3432872 100644 --- a/client/components/Reader/HistoryPage/HistoryPage.vue +++ b/client/components/Reader/HistoryPage/HistoryPage.vue @@ -3,7 +3,8 @@
{ - this.$refs.input.focus(); + //this.$refs.input.focus(); }); + (async() => {//отбражение подгрузки списка + await utils.sleep(1000); + if (this.bookManagerLoaded) + this.updateTableData(); + else { + let i = 0; + let j = 5; + while (i < 500 && !this.bookManagerLoaded) { + if (i % j == 0) { + bookManager.sortedRecentCached = null; + this.updateTableData(100); + j *= 2; + } + + await utils.sleep(100); + i++; + } + } + })(); + } + + bookManagerEvent(eventName) { + if (eventName == 'load-stored-finish') { + this.updateTableData(); + this.bookManagerLoaded = true; + } } rowKey(row) { return row.key; } - updateTableData() { + updateTableData(limit) { let result = []; + this.loading = !!limit; const sorted = bookManager.getSortedRecent(); + for (let i = 0; i < sorted.length; i++) { const book = sorted[i]; if (book.deleted) continue; + if (limit && result.length >= limit) + break; + let d = new Date(); d.setTime(book.touchTime); - const t = formatDate(d).split(' '); + const t = utils.formatDate(d).split(' '); let perc = ''; let textLen = ''; diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 184e3c7d..cf8d1af7 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -73,7 +73,7 @@ - + { + const recent = this.mostRecentBook(); + if (!newValue && !this.loading && recent && !await bookManager.hasBookParsed(recent)) { + this.loadBook(recent); + } + })(); }, }, }) @@ -216,7 +218,7 @@ class Reader extends Vue { } }, 500); - this.debouncedSaveRecent = _.debounce(async() => { + /*this.debouncedSaveRecent = _.debounce(async() => { const serverStorage = this.$refs.serverStorage; while (!serverStorage.inited) await utils.sleep(1000); await serverStorage.saveRecent(); @@ -226,7 +228,7 @@ class Reader extends Vue { const serverStorage = this.$refs.serverStorage; while (!serverStorage.inited) await utils.sleep(1000); await serverStorage.saveRecentLast(); - }, 1000); + }, 1000);*/ document.addEventListener('fullscreenchange', () => { this.fullScreenActive = (document.fullscreenElement !== null); @@ -379,8 +381,8 @@ class Reader extends Vue { this.debouncedUpdateRoute(); } - async bookManagerEvent(eventName) { - const serverStorage = this.$refs.serverStorage; + async bookManagerEvent(/*eventName*/) { + /*const serverStorage = this.$refs.serverStorage; if (eventName == 'load-meta-finish') { serverStorage.init(); const result = await bookManager.cleanRecentBooks(); @@ -415,7 +417,7 @@ class Reader extends Vue { } else { this.debouncedSaveRecent(); } - } + }*/ } get toolBarActive() { @@ -759,7 +761,8 @@ class Reader extends Vue { //акивируем страницу с текстом this.$nextTick(async() => { const last = this.mostRecentBookReactive; - const isParsed = bookManager.hasBookParsed(last); + const isParsed = await bookManager.hasBookParsed(last); + if (!isParsed) { this.$root.$emit('set-app-title'); return; @@ -793,7 +796,7 @@ class Reader extends Vue { // уже просматривается сейчас const lastBook = (this.$refs.page ? this.$refs.page.lastBook : null); - if (!opts.force && lastBook && lastBook.url == url && bookManager.hasBookParsed(lastBook)) { + if (!opts.force && lastBook && lastBook.url == url && await bookManager.hasBookParsed(lastBook)) { this.loaderActive = false; return; } diff --git a/client/components/Reader/share/bookManager.js b/client/components/Reader/share/bookManager.js index 294bd624..7598c82a 100644 --- a/client/components/Reader/share/bookManager.js +++ b/client/components/Reader/share/bookManager.js @@ -18,46 +18,30 @@ const bmRecentStore = localForage.createInstance({ name: 'bmRecentStore' }); -const bmCacheStore = localForage.createInstance({ - name: 'bmCacheStore' -}); - class BookManager { async init(settings) { + this.loaded = false; this.settings = settings; this.eventListeners = []; + this.books = {}; + this.recent = {}; - //bmCacheStore нужен только для ускорения загрузки читалки - this.booksCached = await bmCacheStore.getItem('books'); - if (!this.booksCached) - this.booksCached = {}; - this.recent = await bmCacheStore.getItem('recent'); - this.recentLast = await bmCacheStore.getItem('recent-last'); + this.recentLast = await bmRecentStore.getItem('recent-last'); if (this.recentLast) this.recent[this.recentLast.key] = this.recentLast; - this.recentRev = await bmRecentStore.getItem('recent-rev') || 0; - this.recentLastRev = await bmRecentStore.getItem('recent-last-rev') || 0; - this.recentLastDiffRev = await bmRecentStore.getItem('recent-last-diff-rev') || 0; - this.books = Object.assign({}, this.booksCached); - this.recentChanged2 = true; + this.recentChanged = true; - if (!this.books || !this.recent) { - this.books = {}; - this.recent = {}; - await this.loadMeta(true); - } else { - this.loadMeta(false); - } + this.loadStored();//no await } - //долгая загрузка из хранилища, - //хранение в отдельных записях дает относительно - //нормальное поведение при нескольких вкладках с читалкой в браузере - async loadMeta(immediate) { - if (!immediate) - await utils.sleep(2000); + //Долгая асинхронная загрузка из хранилища. + //Хранение в отдельных записях дает относительно + //нормальное поведение при нескольких вкладках с читалкой в браузере. + async loadStored() { + //даем время для загрузки последней читаемой книги, чтобы не блокировать приложение + await utils.sleep(2000); let len = await bmMetaStore.length(); for (let i = 0; i < len; i++) { @@ -68,6 +52,7 @@ class BookManager { let meta = await bmMetaStore.getItem(key); if (_.isObject(meta)) { + //уже может быть распарсена книга const oldBook = this.books[meta.key]; this.books[meta.key] = meta; @@ -80,22 +65,19 @@ class BookManager { } } - //"ленивая" загрузка - (async() => { - let key = null; - len = await bmRecentStore.length(); - for (let i = 0; i < len; i++) { - key = await bmRecentStore.key(i); - if (key) { - let r = await bmRecentStore.getItem(key); - if (_.isObject(r) && r.key) { - this.recent[r.key] = r; - } - } else { - await bmRecentStore.removeItem(key); + let key = null; + len = await bmRecentStore.length(); + for (let i = 0; i < len; i++) { + key = await bmRecentStore.key(i); + if (key) { + let r = await bmRecentStore.getItem(key); + if (_.isObject(r) && r.key) { + this.recent[r.key] = r; } + } else { + await bmRecentStore.removeItem(key); } - })(); + } //размножение для дебага /*if (key) { @@ -106,17 +88,10 @@ class BookManager { }*/ await this.cleanBooks(); + await this.cleanRecentBooks(); - //очистка позже - //await this.cleanRecentBooks(); - - this.booksCached = {}; - for (const key in this.books) { - this.booksCached[key] = this.metaOnly(this.books[key]); - } - await bmCacheStore.setItem('books', this.booksCached); - await bmCacheStore.setItem('recent', this.recent); - this.emit('load-meta-finish'); + this.loaded = true; + this.emit('load-stored-finish'); } async cleanBooks() { @@ -136,7 +111,7 @@ class BookManager { } if (size > maxDataSize && toDel) { - await this._delBook(toDel); + await this.delBook(toDel); } else { break; } @@ -211,9 +186,7 @@ class BookManager { return inflator.result; } - async addBook(newBook, callback) { - if (!this.books) - await this.init(); + async addBook(newBook, callback) { let meta = {url: newBook.url, path: newBook.path}; meta.key = this.keyFromUrl(meta.url); meta.addTime = Date.now(); @@ -233,43 +206,53 @@ class BookManager { let data = newBook.data; if (result.dataCompressed) { - //data = utils.pako.deflate(data, {level: 9}); + //data = utils.pako.deflate(data, {level: 5}); data = await this.deflateWithProgress(data, cb2); result.dataCompressedLength = data.byteLength; } callback(95); this.books[meta.key] = result; - this.booksCached[meta.key] = this.metaOnly(result); await bmMetaStore.setItem(`bmMeta-${meta.key}`, this.metaOnly(result)); await bmDataStore.setItem(`bmData-${meta.key}`, data); - await bmCacheStore.setItem('books', this.booksCached); callback(100); return result; } - hasBookParsed(meta) { + async hasBookParsed(meta) { if (!this.books) return false; if (!meta.url) return false; if (!meta.key) meta.key = this.keyFromUrl(meta.url); + let book = this.books[meta.key]; + + if (!book && !this.loaded) { + book = await bmDataStore.getItem(`bmMeta-${meta.key}`); + if (book) + this.books[meta.key] = book; + } + return !!(book && book.parsed); } async getBook(meta, callback) { - if (!this.books) - await this.init(); let result = undefined; if (!meta.key) meta.key = this.keyFromUrl(meta.url); result = this.books[meta.key]; + if (!result) { + result = await bmDataStore.getItem(`bmMeta-${meta.key}`); + if (result) + this.books[meta.key] = result; + } + if (result && !result.parsed) { let data = await bmDataStore.getItem(`bmData-${meta.key}`); callback(5); @@ -303,27 +286,14 @@ class BookManager { return result; } - async _delBook(meta) { + async delBook(meta) { await bmMetaStore.removeItem(`bmMeta-${meta.key}`); await bmDataStore.removeItem(`bmData-${meta.key}`); delete this.books[meta.key]; - delete this.booksCached[meta.key]; - } - - async delBook(meta) { - if (!this.books) - await this.init(); - - await this._delBook(meta); - - await bmCacheStore.setItem('books', this.booksCached); } async parseBook(meta, data, callback) { - if (!this.books) - await this.init(); - const parsed = new BookParser(this.settings); const parsedMeta = await parsed.parse(data, callback); @@ -347,9 +317,8 @@ class BookManager { return utils.stringToHex(url); } + //-- recent -------------------------------------------------------------- async setRecentBook(value) { - if (!this.recent) - await this.init(); const result = this.metaOnly(value); result.touchTime = Date.now(); result.deleted = 0; @@ -366,66 +335,51 @@ class BookManager { await bmRecentStore.setItem(result.key, result); - //кэшируем, аккуратно - let saveRecent = false; - if (!(this.recentLast && this.recentLast.key == result.key)) { - await bmCacheStore.setItem('recent', this.recent); - saveRecent = true; - } this.recentLast = result; - await bmCacheStore.setItem('recent-last', this.recentLast); + await bmRecentStore.setItem('recent-last', this.recentLast); - this.mostRecentCached = result; - this.recentChanged2 = true; - - if (saveRecent) - this.emit('save-recent'); - this.emit('recent-changed'); + this.recentChanged = true; return result; } async getRecentBook(value) { - if (!this.recent) - await this.init(); - return this.recent[value.key]; + let result = this.recent[value.key]; + if (!result) { + result = await bmRecentStore.getItem(value.key); + this.recent[value.key] = result; + } + return result; } async delRecentBook(value) { - if (!this.recent) - await this.init(); - this.recent[value.key].deleted = 1; await bmRecentStore.setItem(value.key, this.recent[value.key]); - await bmCacheStore.setItem('recent', this.recent); - this.mostRecentCached = null; - this.recentChanged2 = true; + this.recentLast = null; + await bmRecentStore.setItem('recent-last', this.recentLast); - this.emit('save-recent'); + this.recentChanged = true; } async cleanRecentBooks() { - if (!this.recent) - await this.init(); - const sorted = this.getSortedRecent(); let isDel = false; for (let i = 1000; i < sorted.length; i++) { await bmRecentStore.removeItem(sorted[i].key); delete this.recent[sorted[i].key]; + await bmRecentStore.removeItem(sorted[i].key); isDel = true; } this.sortedRecentCached = null; - await bmCacheStore.setItem('recent', this.recent); return isDel; } mostRecentBook() { - if (this.mostRecentCached) { - return this.mostRecentCached; + if (this.recentLast) { + return this.recentLast; } let max = 0; @@ -437,12 +391,14 @@ class BookManager { result = book; } } - this.mostRecentCached = result; + this.recentLast = result; + bmRecentStore.setItem('recent-last', this.recentLast);//no await + return result; } getSortedRecent() { - if (!this.recentChanged2 && this.sortedRecentCached) { + if (!this.recentChanged && this.sortedRecentCached) { return this.sortedRecentCached; } @@ -451,78 +407,10 @@ class BookManager { result.sort((a, b) => b.touchTime - a.touchTime); this.sortedRecentCached = result; - this.recentChanged2 = false; + this.recentChanged = false; return result; } - async setRecent(value) { - const mergedRecent = _.cloneDeep(this.recent); - - Object.assign(mergedRecent, value); - const newRecent = {}; - - //"ленивое" обновление хранилища - (async() => { - for (const rec of Object.values(mergedRecent)) { - if (rec.key) { - await bmRecentStore.setItem(rec.key, rec); - await utils.sleep(1); - } - } - })(); - - for (const rec of Object.values(mergedRecent)) { - if (rec.key) { - newRecent[rec.key] = rec; - } - } - - this.recent = newRecent; - await bmCacheStore.setItem('recent', this.recent); - - this.recentLast = null; - await bmCacheStore.setItem('recent-last', this.recentLast); - - this.mostRecentCached = null; - this.emit('recent-changed'); - } - - async setRecentRev(value) { - await bmRecentStore.setItem('recent-rev', value); - this.recentRev = value; - } - - async setRecentLast(value) { - if (!value.key) - value = null; - - this.recentLast = value; - await bmCacheStore.setItem('recent-last', this.recentLast); - if (value && value.key) { - //гарантия переключения книги - const mostRecent = this.mostRecentBook(); - if (mostRecent) - this.recent[mostRecent.key].touchTime = value.touchTime - 1; - - this.recent[value.key] = value; - await bmRecentStore.setItem(value.key, value); - await bmCacheStore.setItem('recent', this.recent); - } - - this.mostRecentCached = null; - this.emit('recent-changed'); - } - - async setRecentLastRev(value) { - await bmRecentStore.setItem('recent-last-rev', value); - this.recentLastRev = value; - } - - async setRecentLastDiffRev(value) { - await bmRecentStore.setItem('recent-last-diff-rev', value); - this.recentLastDiffRev = value; - } - addEventListener(listener) { if (this.eventListeners.indexOf(listener) < 0) this.eventListeners.push(listener);