diff --git a/client/components/Reader/LibsPage/LibsPage.vue b/client/components/Reader/LibsPage/LibsPage.vue index 91e97ef3..32cf73f4 100644 --- a/client/components/Reader/LibsPage/LibsPage.vue +++ b/client/components/Reader/LibsPage/LibsPage.vue @@ -34,8 +34,8 @@ class LibsPage { if (!this.mode) return; - //TODO: убрать второе условие в 24г - if (!this.libs || (this.mode === 'omnireader' && this.libs.mode !== this.mode)) { + //TODO: убрать условие с mode в 24г + if (!this.libs || !this.libs.groups || (this.mode === 'omnireader' && this.libs.mode !== this.mode)) { const defaults = rstore.getLibsDefaults(this.mode); this.commit('reader/setLibs', defaults); } diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index a91c4754..fbea462c 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -393,6 +393,9 @@ class Reader { this.recentItemKeys = []; //сохранение в удаленном хранилище await this.$refs.serverStorage.saveRecent(itemKeys); + + //periodicTasks + this.periodicTasks();//no await } catch (e) { if (!this.offlineModeActive) this.$root.notify.error(e.message); @@ -442,26 +445,15 @@ class Reader { this.$refs.recentBooksPage.init(); })(); - //проверки обновлений читалки + //единственный запуск periodicTasks при инициализации + //дальнейшие запуски periodicTasks выполняются из debouncedSaveRecent + //т.е. только по действию пользователя (async() => { + await utils.sleep(15*1000); this.isFirstNeedUpdateNotify = true; - //вечный цикл, запрашиваем периодически конфиг для проверки выхода новой версии читалки - while (1) {// eslint-disable-line no-constant-condition - await this.checkNewVersionAvailable(); - await utils.sleep(60*60*1000); //каждый час - } - //дальше хода нет - })(); - //проверки обновлений книг - (async() => { - await utils.sleep(15*1000); //подождем неск. секунд перед первым запросом - //вечный цикл, запрашиваем периодически обновления - while (1) {// eslint-disable-line no-constant-condition - await this.checkBuc(); - await utils.sleep(70*60*1000); //каждые 70 минут - } - //дальше хода нет + this.allowPeriodicTasks = true; + this.periodicTasks();//no await })(); } @@ -560,26 +552,56 @@ class Reader { } } - async checkNewVersionAvailable() { - if (!this.checkingNewVersion && this.showNeedUpdateNotify) { - this.checkingNewVersion = true; - try { - await utils.sleep(15*1000); //подождем 15 секунд, чтобы прогрузился ServiceWorker при выходе новой версии - const config = await miscApi.loadConfig(); - this.commit('config/setConfig', config); + async periodicTasks() { + if (!this.allowPeriodicTasks || this.doingPeriodicTasks) + return; - let againMes = ''; - if (this.isFirstNeedUpdateNotify) { - againMes = ' еще один раз'; + this.doingPeriodicTasks = true; + try { + if (!this.taskList) { + const taskArr = [ + [this.checkNewVersionAvailable, 60], //проверки обновлений читалки, каждый час + [this.checkBuc, 70], //проверки обновлений книг, каждые 70 минут + ]; + + this.taskList = []; + for (const task of taskArr) { + const [method, period] = task; + this.taskList.push({method, period, lastRunTime: 0}); } + } + + for (const task of this.taskList) { + if (Date.now() - task.lastRunTime >= task.period*60*1000) { + try { + //console.log('task run', task.method.name); + await task.method(); + } catch (e) { + console.error(e); + } + task.lastRunTime = Date.now(); + } + } + } catch (e) { + console.error(e); + } finally { + this.doingPeriodicTasks = false; + } + } + + async checkNewVersionAvailable() { + if (this.showNeedUpdateNotify) { + const config = await miscApi.loadConfig(); + this.commit('config/setConfig', config); + + let againMes = ''; + if (this.isFirstNeedUpdateNotify) { + againMes = ' еще один раз'; + } + + if (this.version != this.clientVersion) + this.$root.notify.info(`Вышла новая версия (v${this.version}) читалки.
Пожалуйста, обновите страницу${againMes}.`, 'Обновление'); - if (this.version != this.clientVersion) - this.$root.notify.info(`Вышла новая версия (v${this.version}) читалки.
Пожалуйста, обновите страницу${againMes}.`, 'Обновление'); - } catch(e) { - console.error(e); - } finally { - this.checkingNewVersion = false; - } this.isFirstNeedUpdateNotify = false; } } @@ -588,82 +610,78 @@ class Reader { if (!this.bothBucEnabled) return; - try { - const sorted = bookManager.getSortedRecent(); + const sorted = bookManager.getSortedRecent(); - //выберем все кандидиаты на обновление - const updateUrls = new Set(); - for (const book of sorted) { - if (!book.deleted && book.checkBuc && book.url && book.url.indexOf('disk://') !== 0) - updateUrls.add(book.url); + //выберем все кандидиаты на обновление + const updateUrls = new Set(); + for (const book of sorted) { + if (!book.deleted && book.checkBuc && book.url && book.url.indexOf('disk://') !== 0) + updateUrls.add(book.url); + } + + //теперь по кусочкам запросим сервер + const arr = Array.from(updateUrls); + const bucSize = {}; + const chunkSize = 100; + for (let i = 0; i < arr.length; i += chunkSize) { + const chunk = arr.slice(i, i + chunkSize); + + const data = await readerApi.checkBuc(chunk); + + for (const item of data) { + bucSize[item.id] = item.size; } - //теперь по кусочкам запросим сервер - const arr = Array.from(updateUrls); - const bucSize = {}; - const chunkSize = 100; - for (let i = 0; i < arr.length; i += chunkSize) { - const chunk = arr.slice(i, i + chunkSize); + await utils.sleep(1000);//чтобы не ддосить сервер + } - const data = await readerApi.checkBuc(chunk); - - for (const item of data) { - bucSize[item.id] = item.size; - } - - await utils.sleep(1000);//чтобы не ддосить сервер + const checkSetTime = {}; + //проставим новые размеры у книг + for (const book of sorted) { + if (book.deleted) + continue; + + //размер 0 считаем отсутствующим + if (book.url && bucSize[book.url] && bucSize[book.url] !== book.bucSize) { + book.bucSize = bucSize[book.url]; + await bookManager.recentSetItem(book); } - const checkSetTime = {}; - //проставим новые размеры у книг - for (const book of sorted) { - if (book.deleted) - continue; - - //размер 0 считаем отсутствующим - if (book.url && bucSize[book.url] && bucSize[book.url] !== book.bucSize) { - book.bucSize = bucSize[book.url]; - await bookManager.recentSetItem(book); - } + //подготовка к следующему шагу, ищем книгу по url с максимальной датой установки checkBucTime/loadTime + //от этой даты будем потом отсчитывать bucCancelDays + if (updateUrls.has(book.url)) { + let rec = checkSetTime[book.url] || {time: 0, loadTime: 0}; - //подготовка к следующему шагу, ищем книгу по url с максимальной датой установки checkBucTime/loadTime - //от этой даты будем потом отсчитывать bucCancelDays - if (updateUrls.has(book.url)) { - let rec = checkSetTime[book.url] || {time: 0, loadTime: 0}; + const time = (book.checkBucTime ? book.checkBucTime : (rec.loadTime || 0)); + if (time > rec.time || (time == rec.time && (book.loadTime > rec.loadTime))) + rec = {time, loadTime: book.loadTime, key: book.key}; - const time = (book.checkBucTime ? book.checkBucTime : (rec.loadTime || 0)); - if (time > rec.time || (time == rec.time && (book.loadTime > rec.loadTime))) - rec = {time, loadTime: book.loadTime, key: book.key}; - - checkSetTime[book.url] = rec; - } + checkSetTime[book.url] = rec; } + } - //bucCancelEnabled и bucCancelDays - //снимем флаг checkBuc у необновлявшихся bucCancelDays - if (this.bucCancelEnabled) { - for (const rec of Object.values(checkSetTime)) { - if (rec.time && Date.now() - rec.time > this.bucCancelDays*24*3600*1000) { - const book = await bookManager.getRecentBook({key: rec.key}); - const needBookUpdate = - book.checkBuc - && book.bucSize - && utils.hasProp(book, 'downloadSize') - && book.bucSize !== book.downloadSize - && (book.bucSize - book.downloadSize >= this.bucSizeDiff) - ; + //bucCancelEnabled и bucCancelDays + //снимем флаг checkBuc у необновлявшихся bucCancelDays + if (this.bucCancelEnabled) { + for (const rec of Object.values(checkSetTime)) { + if (rec.time && Date.now() - rec.time > this.bucCancelDays*24*3600*1000) { + const book = await bookManager.getRecentBook({key: rec.key}); + const needBookUpdate = + book.checkBuc + && book.bucSize + && utils.hasProp(book, 'downloadSize') + && book.bucSize !== book.downloadSize + && (book.bucSize - book.downloadSize >= this.bucSizeDiff) + ; - if (book && !needBookUpdate) { - await bookManager.setCheckBuc(book, undefined);//!!! - } + if (book && !needBookUpdate) { + await bookManager.setCheckBuc(book, undefined);//!!! } } } - - await this.$refs.recentBooksPage.updateTableData(); - } catch (e) { - console.error(e); } + + await this.$refs.recentBooksPage.updateTableData(); } updateCountChanged(event) { @@ -1409,8 +1427,6 @@ class Reader { if (!this.showHelpOnErrorIfNeeded(url)) { this.$root.stdDialog.alert(e.message, 'Ошибка', {color: 'negative'}); } - } finally { - this.checkNewVersionAvailable(); } } diff --git a/client/components/Reader/ServerStorage/ServerStorage.vue b/client/components/Reader/ServerStorage/ServerStorage.vue index 24f4b78b..a2eba6b5 100644 --- a/client/components/Reader/ServerStorage/ServerStorage.vue +++ b/client/components/Reader/ServerStorage/ServerStorage.vue @@ -22,10 +22,12 @@ const ssCacheStore = localForage.createInstance({ const componentOptions = { watch: { serverSyncEnabled: function() { - this.serverSyncEnabledChanged(); + if (this.inited) + this.serverSyncEnabledChanged(); }, serverStorageKey: function() { - this.serverStorageKeyChanged(true); + if (this.inited) + this.serverStorageKeyChanged(true); }, settings: function() { this.debouncedSaveSettings(); @@ -85,6 +87,13 @@ class ServerStorage { if (!this.cachedRecentMod) await this.cleanCachedRecent('cachedRecentMod'); + //подстраховка хранения ключа, восстановим из IndexedDB при проблемах в localStorage + if (!this.serverStorageKey) { + const key = await ssCacheStore.getItem('storageKey'); + if (key) + this.commit('reader/setServerStorageKey', key); + } + if (!this.serverStorageKey) { //генерируем новый ключ await this.generateNewServerStorageKey(); @@ -123,6 +132,7 @@ class ServerStorage { async generateNewServerStorageKey() { const key = utils.toBase58(utils.randomArray(32)); this.commit('reader/setServerStorageKey', key); + //дождемся serverStorageKeyChanged, событие по watch не работает при this.inited == false await this.serverStorageKeyChanged(true); } @@ -141,6 +151,10 @@ class ServerStorage { async serverStorageKeyChanged(force) { if (this.prevServerStorageKey != this.serverStorageKey) { this.prevServerStorageKey = this.serverStorageKey; + + //сохраним ключ также в IndexedDB, чтобы была возможность восстановить при проблемах с localStorage + await ssCacheStore.setItem('storageKey', this.serverStorageKey); + this.hashedStorageKey = utils.toBase58(cryptoUtils.sha256(this.serverStorageKey)); this.keyInited = true; diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js index 9f4a9211..cfceea3e 100644 --- a/client/components/Reader/share/BookParser.js +++ b/client/components/Reader/share/BookParser.js @@ -438,61 +438,63 @@ export default class BookParser { }; const onEndNode = (elemName) => {// eslint-disable-line no-unused-vars - if (tag == elemName) { - if (tag == 'binary') { - binaryId = ''; - } - - if (path.indexOf('/fictionbook/body') == 0) { - if (tag == 'title') { - isFirstTitlePara = false; - bold = false; - center = false; - inTitle = false; - } + tag = elemName; - if (tag == 'section') { - sectionLevel--; - } - - if (tag == 'emphasis' || tag == 'strong' || tag == 'sup' || tag == 'sub') { - growParagraph(``, 0); - } - - if (tag == 'p') { - inPara = false; - } - - if (tag == 'subtitle') { - isFirstTitlePara = false; - bold = false; - center = false; - inSubtitle = false; - } - - if (tag == 'epigraph' || tag == 'annotation') { - italic = false; - space -= 1; - newParagraph(); - } - - if (tag == 'stanza') { - newParagraph(); - } - - if (tag == 'text-author') { - bold = false; - space -= 1; - } + if (tag == 'binary') { + binaryId = ''; + } + + if (path.indexOf('/fictionbook/body') == 0) { + if (tag == 'title') { + isFirstTitlePara = false; + bold = false; + center = false; + inTitle = false; } - path = path.substr(0, path.length - tag.length - 1); - let i = path.lastIndexOf('/'); - if (i >= 0) { - tag = path.substr(i + 1); - } else { + if (tag == 'section') { + sectionLevel--; + } + + if (tag == 'emphasis' || tag == 'strong' || tag == 'sup' || tag == 'sub') { + growParagraph(``, 0); + } + + if (tag == 'p') { + inPara = false; + } + + if (tag == 'subtitle') { + isFirstTitlePara = false; + bold = false; + center = false; + inSubtitle = false; + } + + if (tag == 'epigraph' || tag == 'annotation') { + italic = false; + space -= 1; + newParagraph(); + } + + if (tag == 'stanza') { + newParagraph(); + } + + if (tag == 'text-author') { + bold = false; + space -= 1; + } + } + + let i = path.lastIndexOf(tag); + if (i >= 0) { + path = path.substring(0, i - 1); + i = path.lastIndexOf('/'); + if (i >= 0) + tag = path.substring(i + 1); + else tag = path; - } } }; diff --git a/client/components/Reader/versionHistory.js b/client/components/Reader/versionHistory.js index 000ebbe4..8592f3c4 100644 --- a/client/components/Reader/versionHistory.js +++ b/client/components/Reader/versionHistory.js @@ -1,4 +1,17 @@ export const versionHistory = [ +{ + version: '1.1.3', + releaseDate: '2023-02-06', + showUntil: '2023-02-05', + content: +` + + +` +}, + { version: '1.1.2', releaseDate: '2023-01-22', diff --git a/client/store/modules/reader.js b/client/store/modules/reader.js index e8a5cc4c..95b1d79a 100644 --- a/client/store/modules/reader.js +++ b/client/store/modules/reader.js @@ -325,7 +325,7 @@ const state = { currentProfile: '', settings: _.cloneDeep(settingDefaults), settingsRev: {}, - libs: false, + libs: {}, libsRev: 0, }; diff --git a/package-lock.json b/package-lock.json index f1e6613a..bb4f30c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "liberama", - "version": "1.1.2", + "version": "1.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "liberama", - "version": "1.1.2", + "version": "1.1.3", "hasInstallScript": true, "license": "CC0-1.0", "dependencies": { diff --git a/package.json b/package.json index 5110a6df..11b4d339 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "liberama", - "version": "1.1.2", + "version": "1.1.3", "author": "Book Pauk ", "license": "CC0-1.0", "repository": "bookpauk/liberama",