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(`${tag}>`, 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(`${tag}>`, 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:
+`
+