diff --git a/client/components/ExternalLibs/ExternalLibs.vue b/client/components/ExternalLibs/ExternalLibs.vue
index 9054a401..e12fa314 100644
--- a/client/components/ExternalLibs/ExternalLibs.vue
+++ b/client/components/ExternalLibs/ExternalLibs.vue
@@ -408,7 +408,7 @@ class ExternalLibs extends Vue {
}
get header() {
- let result = (this.ready ? 'Библиотека' : 'Загрузка...');
+ let result = (this.ready ? 'Сетевая библиотека' : 'Загрузка...');
if (this.ready && this.selectedLink) {
result += ` | ${(this.libs.comment ? this.libs.comment + ' ': '') + lu.removeProtocol(this.libs.startLink)}`;
}
@@ -787,12 +787,17 @@ class ExternalLibs extends Vue {
showHelp() {
this.$root.stdDialog.alert(`
-
Окно 'Библиотека' позволяет открывать ссылки в читалке без переключения между окнами,
-что особенно актуально для мобильных устройств.
-
-'Библиотека' разрешает свободный доступ к сайту flibusta.is. Имеется возможность управлять закладками
+
Окно 'Сетевая библиотека' позволяет открывать ссылки в читалке без переключения между окнами,
+что особенно актуально для мобильных устройств. Имеется возможность управлять закладками
на понравившиеся ресурсы, книги или страницы авторов. Открытие ссылок и навигация происходят во фрейме, но,
-к сожалению, в нем открываются не все страницы.
+к сожалению, в нем открываются не все страницы.
+
+Доступ к сайтам http://flibusta.is и http://fantasy-worlds.org работает через прокси.
+
+
ПРЕДУПРЕЖДЕНИЕ!
+Доступ предназначен только для просмотра и скачивания книг. Авторизоваться на этих сайтах
+из фрейма категорически не рекомендуется, т.к. ваше подключение не защищено и данные могут попасть
+к третьим лицам.
Из-за проблем с безопасностью, навигация 'вперед-назад' во фрейме осуществляется с помощью контекстного меню правой кнопкой мыши.
diff --git a/client/components/Reader/ContentsPage/ContentsPage.vue b/client/components/Reader/ContentsPage/ContentsPage.vue
index 8144fdfa..9a34364a 100644
--- a/client/components/Reader/ContentsPage/ContentsPage.vue
+++ b/client/components/Reader/ContentsPage/ContentsPage.vue
@@ -50,6 +50,9 @@
+
+ Оглавление отсутствует
+
diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue
index 9dc3a02f..f2b1d395 100644
--- a/client/components/Reader/Reader.vue
+++ b/client/components/Reader/Reader.vue
@@ -250,11 +250,11 @@ class Reader extends Vue {
await this.$nextTick();
this.paramPosIgnore = false;
}
- }, 500, {'maxWait':5000});
+ }, 500, {maxWait: 5000});
this.scrollingSetRecentBook = _.debounce((newValue) => {
this.debouncedSetRecentBook(newValue);
- }, 15000, {'maxWait':20000});
+ }, 15000, {maxWait: 20000});
document.addEventListener('fullscreenchange', () => {
this.fullScreenActive = (document.fullscreenElement !== null);
diff --git a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue
index 96f677b0..c7eec977 100644
--- a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue
+++ b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue
@@ -59,7 +59,7 @@
@@ -87,7 +87,7 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import path from 'path';
-import _ from 'lodash';
+//import _ from 'lodash';
import * as utils from '../../../share/utils';
import Window from '../../share/Window.vue';
@@ -222,30 +222,11 @@ class RecentBooksPage extends Vue {
textLen = ` ${Math.round(book.textLength/1000)}k`;
}
- const fb2 = (book.fb2 ? book.fb2 : {});
+ const bt = utils.getBookTitle(book.fb2);
- let title = fb2.bookTitle;
- if (title)
- title = `"${title}"`;
- else
- title = '';
-
- let author = '';
- if (fb2.author) {
- const authorNames = fb2.author.map(a => _.compact([
- a.lastName,
- a.firstName,
- a.middleName
- ]).join(' '));
- author = authorNames.join(', ');
- } else {//TODO: убрать в будущем
- author = _.compact([
- fb2.lastName,
- fb2.firstName,
- fb2.middleName
- ]).join(' ');
- }
- author = (author ? author : (fb2.bookTitle ? fb2.bookTitle : book.url));
+ let title = bt.bookTitle;
+ title = (title ? `"${title}"`: '');
+ const author = (bt.author ? bt.author : (bt.bookTitle ? bt.bookTitle : book.url));
result.push({
num,
@@ -256,9 +237,10 @@ class RecentBooksPage extends Vue {
author,
title: `${title}${perc}${textLen}`,
},
- descString: `${author}${title}${perc}${textLen}`,
+ descString: `${author}${title}${perc}${textLen}`,//для сортировки
url: book.url,
path: book.path,
+ fullTitle: bt.fullTitle,
key: book.key,
});
}
@@ -291,13 +273,18 @@ class RecentBooksPage extends Vue {
return `${(this.search ? 'Найдено' : 'Всего')} ${len} книг${this.wordEnding(len)}`;
}
- async downloadBook(fb2path) {
+ async downloadBook(fb2path, fullTitle) {
try {
await readerApi.checkCachedBook(fb2path);
const d = this.$refs.download;
d.href = fb2path;
- d.download = path.basename(fb2path).substr(0, 10) + '.fb2';
+ try {
+ const fn = utils.makeValidFilename(fullTitle);
+ d.download = fn.substring(0, 100) + '.fb2';
+ } catch(e) {
+ d.download = path.basename(fb2path).substr(0, 10) + '.fb2';
+ }
d.click();
} catch (e) {
@@ -308,14 +295,6 @@ class RecentBooksPage extends Vue {
}
}
- openOriginal(url) {
- window.open(url, '_blank');
- }
-
- openFb2(path) {
- window.open(path, '_blank');
- }
-
async handleDel(key) {
await bookManager.delRecentBook({key});
//this.updateTableData();//обновление уже происходит Reader.bookManagerEvent
diff --git a/client/components/Reader/ServerStorage/ServerStorage.vue b/client/components/Reader/ServerStorage/ServerStorage.vue
index 7a17af30..0bd9cb8b 100644
--- a/client/components/Reader/ServerStorage/ServerStorage.vue
+++ b/client/components/Reader/ServerStorage/ServerStorage.vue
@@ -507,10 +507,10 @@ class ServerStorage extends Vue {
if (md.key && result[md.key])
result[md.key] = utils.applyObjDiff(result[md.key], md.mod, {isAddChanged: true});
- if (!bookManager.loaded) {
+ /*if (!bookManager.loaded) {
this.warning('Ожидание загрузки списка книг перед синхронизацией');
while (!bookManager.loaded) await utils.sleep(100);
- }
+ }*/
if (newRecent.rev != this.cachedRecent.rev)
await this.setCachedRecent(newRecent);
diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue
index 04c3d897..7685e294 100644
--- a/client/components/Reader/TextPage/TextPage.vue
+++ b/client/components/Reader/TextPage/TextPage.vue
@@ -40,7 +40,7 @@ import Component from 'vue-class-component';
import {loadCSS} from 'fg-loadcss';
import _ from 'lodash';
-import {sleep} from '../../../share/utils';
+import * as utils from '../../../share/utils';
import bookManager from '../share/bookManager';
import DrawHelper from './DrawHelper';
import rstore from '../../../store/modules/reader';
@@ -134,7 +134,7 @@ class TextPage extends Vue {
this.$root.$on('resize', async() => {
this.$nextTick(this.onResize);
- await sleep(500);
+ await utils.sleep(500);
this.$nextTick(this.onResize);
});
}
@@ -285,7 +285,7 @@ class TextPage extends Vue {
let close = null;
(async() => {
- await sleep(500);
+ await utils.sleep(500);
if (this.fontsLoading)
close = this.$root.notify.info('Загрузка шрифта ');
})();
@@ -342,7 +342,7 @@ class TextPage extends Vue {
let i = 0;
const t = this.parsed.testText;
while (i++ < 50 && this.parsed === parsed && this.drawHelper.measureText(t, {}) === this.parsed.testWidth)
- await sleep(100);
+ await utils.sleep(100);
if (this.parsed === parsed) {
this.parsed.testWidth = this.drawHelper.measureText(t, {});
@@ -366,7 +366,6 @@ class TextPage extends Vue {
this.updateLayout();
this.book = null;
this.meta = null;
- this.fb2 = null;
this.parsed = null;
this.linesUp = null;
@@ -383,7 +382,7 @@ class TextPage extends Vue {
try {
//подождем ленивый парсинг
this.stopLazyParse = true;
- while (this.doingLazyParse) await sleep(10);
+ while (this.doingLazyParse) await utils.sleep(10);
const isParsed = await bookManager.hasBookParsed(this.lastBook);
if (!isParsed) {
@@ -392,21 +391,9 @@ class TextPage extends Vue {
this.book = await bookManager.getBook(this.lastBook);
this.meta = bookManager.metaOnly(this.book);
- this.fb2 = this.meta.fb2;
+ const bt = utils.getBookTitle(this.meta.fb2);
- let authorNames = [];
- if (this.fb2.author) {
- authorNames = this.fb2.author.map(a => _.compact([
- a.lastName,
- a.firstName,
- a.middleName
- ]).join(' '));
- }
-
- this.title = _.compact([
- authorNames.join(', '),
- this.fb2.bookTitle
- ]).join(' - ');
+ this.title = bt.fullTitle;
this.$root.$emit('set-app-title', this.title);
@@ -493,7 +480,7 @@ class TextPage extends Vue {
let wait = (timeout + 201)/100;
while (wait > 0 && !this[stopPropertyName]) {
wait--;
- await sleep(100);
+ await utils.sleep(100);
}
resolve();
})().catch(reject); });
@@ -509,7 +496,7 @@ class TextPage extends Vue {
}
//ждем анимацию
- while (this.inAnimation) await sleep(10);
+ while (this.inAnimation) await utils.sleep(10);
this.stopScrolling = false;
this.doingScrolling = true;
@@ -520,7 +507,7 @@ class TextPage extends Vue {
this.page1 = this.page2;
this.toggleLayout = true;
await this.$nextTick();
- await sleep(50);
+ await utils.sleep(50);
this.cachedPos = -1;
this.draw();
@@ -557,7 +544,7 @@ class TextPage extends Vue {
page.style.transform = 'none';
page.offsetHeight;
- while (this.doingScrolling) await sleep(10);
+ while (this.doingScrolling) await utils.sleep(10);
}
draw() {
@@ -766,7 +753,7 @@ class TextPage extends Vue {
for (let i = 0; i < this.parsed.para.length; i++) {
j++;
if (j > 1) {
- await sleep(1);
+ await utils.sleep(1);
j = 0;
}
if (this.stopLazyParse)
@@ -788,7 +775,7 @@ class TextPage extends Vue {
async refreshTime() {
if (!this.timeRefreshing) {
this.timeRefreshing = true;
- await sleep(60*1000);
+ await utils.sleep(60*1000);
if (this.book && this.parsed.textLength) {
this.debouncedDrawStatusBar();
@@ -905,7 +892,7 @@ class TextPage extends Vue {
this.settingsChanging = true;
const newSize = (this.settings.fontSize + 1 < 200 ? this.settings.fontSize + 1 : 100);
this.commit('reader/setSettings', {fontSize: newSize});
- await sleep(50);
+ await utils.sleep(50);
this.settingsChanging = false;
}
}
@@ -915,7 +902,7 @@ class TextPage extends Vue {
this.settingsChanging = true;
const newSize = (this.settings.fontSize - 1 > 5 ? this.settings.fontSize - 1 : 5);
this.commit('reader/setSettings', {fontSize: newSize});
- await sleep(50);
+ await utils.sleep(50);
this.settingsChanging = false;
}
}
@@ -925,7 +912,7 @@ class TextPage extends Vue {
this.settingsChanging = true;
const newDelay = (this.settings.scrollingDelay - 50 > 1 ? this.settings.scrollingDelay - 50 : 1);
this.commit('reader/setSettings', {scrollingDelay: newDelay});
- await sleep(50);
+ await utils.sleep(50);
this.settingsChanging = false;
}
}
@@ -935,7 +922,7 @@ class TextPage extends Vue {
this.settingsChanging = true;
const newDelay = (this.settings.scrollingDelay + 50 < 10000 ? this.settings.scrollingDelay + 50 : 10000);
this.commit('reader/setSettings', {scrollingDelay: newDelay});
- await sleep(50);
+ await utils.sleep(50);
this.settingsChanging = false;
}
}
@@ -949,7 +936,7 @@ class TextPage extends Vue {
let delay = 400;
while (this.repDoing) {
this.handleClick(pointX, pointY);
- await sleep(delay);
+ await utils.sleep(delay);
if (delay > 15)
delay *= 0.8;
}
diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js
index f368b6be..7c11260f 100644
--- a/client/components/Reader/share/BookParser.js
+++ b/client/components/Reader/share/BookParser.js
@@ -216,12 +216,32 @@ export default class BookParser {
}
}
- if (tag == 'author' && path.indexOf('/fictionbook/description/title-info/author') == 0) {
+ if (path == '/fictionbook/description/title-info/author') {
if (!fb2.author)
fb2.author = [];
+
fb2.author.push({});
}
+ const isPublishSequence = (path == '/fictionbook/description/publish-info/sequence');
+ if (path == '/fictionbook/description/title-info/sequence' || isPublishSequence) {
+ if (!fb2.sequence)
+ fb2.sequence = [];
+
+ if (!isPublishSequence || !fb2.sequence.length) {
+ const attrs = sax.getAttrsSync(tail);
+ const seq = {};
+ if (attrs.name && attrs.name.value) {
+ seq.name = attrs.name.value;
+ }
+ if (attrs.number && attrs.number.value) {
+ seq.number = attrs.number.value;
+ }
+
+ fb2.sequence.push(seq);
+ }
+ }
+
if (path.indexOf('/fictionbook/body') == 0) {
if (tag == 'body') {
if (isFirstBody && fb2.annotation) {
@@ -233,6 +253,14 @@ export default class BookParser {
newParagraph(' ', 1);
}
+ if (isFirstBody && fb2.sequence && fb2.sequence.length) {
+ const bt = utils.getBookTitle(fb2);
+ if (bt.sequence) {
+ newParagraph(bt.sequence, bt.sequence.length);
+ newParagraph(' ', 1);
+ }
+ }
+
if (!isFirstBody)
newParagraph(' ', 1);
isFirstBody = false;
diff --git a/client/components/Reader/share/bookManager.js b/client/components/Reader/share/bookManager.js
index 71c77381..abfe8cdc 100644
--- a/client/components/Reader/share/bookManager.js
+++ b/client/components/Reader/share/bookManager.js
@@ -6,17 +6,23 @@ import BookParser from './BookParser';
const maxDataSize = 300*1024*1024;//compressed bytes
+//локальный кэш метаданных книг, ограничение maxDataSize
const bmMetaStore = localForage.createInstance({
name: 'bmMetaStore'
});
+//локальный кэш самих книг, ограничение maxDataSize
const bmDataStore = localForage.createInstance({
name: 'bmDataStore'
});
-const bmRecentStore = localForage.createInstance({
+//список недавно открытых книг
+const bmRecentStoreOld = localForage.createInstance({
name: 'bmRecentStore'
});
+const bmRecentStoreNew = localForage.createInstance({
+ name: 'bmRecentStoreNew'
+});
class BookManager {
async init(settings) {
@@ -25,15 +31,74 @@ class BookManager {
this.eventListeners = [];
this.books = {};
- this.recent = {};
- this.recentLast = await bmRecentStore.getItem('recent-last');
- if (this.recentLast) {
- this.recent[this.recentLast.key] = this.recentLast;
- const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLast.key}`);
- if (_.isObject(meta)) {
- this.books[meta.key] = meta;
+ this.recent = {};
+ this.saveRecent = _.debounce(() => {
+ bmRecentStoreNew.setItem('recent', this.recent);
+ }, 300, {maxWait: 800});
+
+ this.saveRecentItem = _.debounce(() => {
+ bmRecentStoreNew.setItem('recent-item', this.recentItem);
+ this.recentRev++;
+ bmRecentStoreNew.setItem('rev', this.recentRev);
+ }, 200, {maxWait: 300});
+
+ //загрузка bmRecentStore
+ this.recentRev = await bmRecentStoreNew.getItem('rev') || 0;
+ if (this.recentRev) {
+ this.recent = await bmRecentStoreNew.getItem('recent');
+ if (!this.recent)
+ this.recent = {};
+
+ this.recentItem = await bmRecentStoreNew.getItem('recent-item');
+ if (this.recentItem)
+ this.recent[this.recentItem.key] = this.recentItem;
+
+ this.recentLastKey = await bmRecentStoreNew.getItem('recent-last-key');
+ if (this.recentLastKey) {
+ const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLastKey}`);
+ if (_.isObject(meta)) {
+ this.books[meta.key] = meta;
+ }
}
+
+ await this.cleanRecentBooks();
+
+ } else {//TODO: убрать после 06.2021, когда bmRecentStoreOld устареет
+ this.recentLast = await bmRecentStoreOld.getItem('recent-last');
+ if (this.recentLast) {
+ this.recent[this.recentLast.key] = this.recentLast;
+ const meta = await bmMetaStore.getItem(`bmMeta-${this.recentLast.key}`);
+ if (_.isObject(meta)) {
+ this.books[meta.key] = meta;
+ }
+ }
+
+ let key = null;
+ const len = await bmRecentStoreOld.length();
+ for (let i = len - 1; i >= 0; i--) {
+ key = await bmRecentStoreOld.key(i);
+ if (key) {
+ let r = await bmRecentStoreOld.getItem(key);
+ if (_.isObject(r) && r.key) {
+ this.recent[r.key] = r;
+ }
+ } else {
+ await bmRecentStoreOld.removeItem(key);
+ }
+ }
+
+ //размножение для дебага
+ /*if (key) {
+ for (let i = 0; i < 1000; i++) {
+ const k = this.keyFromUrl(i.toString());
+ this.recent[k] = Object.assign({}, _.cloneDeep(this.recent[key]), {key: k, touchTime: Date.now() - 1000000, url: utils.randomHexString(300)});
+ }
+ }*/
+
+ await bmRecentStoreNew.setItem('recent', this.recent);
+ this.recentRev = 1;
+ await bmRecentStoreNew.setItem('rev', this.recentRev);
}
this.recentChanged = true;
@@ -41,9 +106,7 @@ class BookManager {
this.loadStored();//no await
}
- //Долгая асинхронная загрузка из хранилища.
- //Хранение в отдельных записях дает относительно
- //нормальное поведение при нескольких вкладках с читалкой в браузере.
+ //Ленивая асинхронная загрузка bmMetaStore
async loadStored() {
//даем время для загрузки последней читаемой книги, чтобы не блокировать приложение
await utils.sleep(2000);
@@ -70,32 +133,7 @@ class BookManager {
}
}
- let key = null;
- len = await bmRecentStore.length();
- for (let i = len - 1; i >= 0; 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) {
- for (let i = 0; i < 1000; i++) {
- const k = this.keyFromUrl(i.toString());
- this.recent[k] = Object.assign({}, _.cloneDeep(this.recent[key]), {key: k, touchTime: Date.now() - 1000000, url: utils.randomHexString(300)});
- }
- }*/
-
await this.cleanBooks();
- await this.cleanRecentBooks();
-
- this.recentChanged = true;
this.loaded = true;
this.emit('load-stored-finish');
}
@@ -238,7 +276,7 @@ class BookManager {
let book = this.books[meta.key];
if (!book && !this.loaded) {
- book = await bmDataStore.getItem(`bmMeta-${meta.key}`);
+ book = await bmMetaStore.getItem(`bmMeta-${meta.key}`);
if (book)
this.books[meta.key] = book;
}
@@ -254,7 +292,7 @@ class BookManager {
result = this.books[meta.key];
if (!result) {
- result = await bmDataStore.getItem(`bmMeta-${meta.key}`);
+ result = await bmMetaStore.getItem(`bmMeta-${meta.key}`);
if (result)
this.books[meta.key] = result;
}
@@ -328,6 +366,43 @@ class BookManager {
}
//-- recent --------------------------------------------------------------
+ async recentSetItem(item = null, skipCheck = false) {
+ const rev = await bmRecentStoreNew.getItem('rev');
+ if (rev != this.recentRev && !skipCheck) {
+ const newRecent = await bmRecentStoreNew.getItem('recent');
+ Object.assign(this.recent, newRecent);
+ this.recentItem = await bmRecentStoreNew.getItem('recent-item');
+ this.recentRev = rev;
+ }
+
+ const prevKey = (this.recentItem ? this.recentItem.key : '');
+ if (item) {
+ this.recent[item.key] = item;
+ this.recentItem = item;
+ } else {
+ this.recentItem = null;
+ }
+
+ this.saveRecentItem();
+
+ if (!item || prevKey != item.key) {
+ this.saveRecent();
+ }
+
+ this.recentChanged = true;
+
+ if (item) {
+ this.emit('recent-changed', item.key);
+ } else {
+ this.emit('recent-changed');
+ }
+ }
+
+ async recentSetLastKey(key) {
+ this.recentLastKey = key;
+ await bmRecentStoreNew.setItem('recent-last-key', this.recentLastKey);
+ }
+
async setRecentBook(value) {
const result = this.metaOnly(value);
result.touchTime = Date.now();
@@ -341,38 +416,25 @@ class BookManager {
result.bookPosSeen = this.recent[result.key].bookPosSeen;
}
- this.recent[result.key] = result;
-
- await bmRecentStore.setItem(result.key, result);
-
- this.recentLast = result;
- await bmRecentStore.setItem('recent-last', this.recentLast);
-
- this.recentChanged = true;
- this.emit('recent-changed', result.key);
+ await this.recentSetLastKey(result.key);
+ await this.recentSetItem(result);
return result;
}
async getRecentBook(value) {
- let result = this.recent[value.key];
- if (!result) {
- result = await bmRecentStore.getItem(value.key);
- if (result)
- this.recent[value.key] = result;
- }
- return result;
+ return this.recent[value.key];
}
async delRecentBook(value) {
- this.recent[value.key].deleted = 1;
- await bmRecentStore.setItem(value.key, this.recent[value.key]);
+ const item = this.recent[value.key];
+ item.deleted = 1;
- if (this.recentLast.key == value.key) {
- this.recentLast = null;
- await bmRecentStore.setItem('recent-last', this.recentLast);
+ if (this.recentLastKey == value.key) {
+ await this.recentSetLastKey(null);
}
+
+ await this.recentSetItem(item);
this.emit('recent-deleted', value.key);
- this.emit('recent-changed', value.key);
}
async cleanRecentBooks() {
@@ -380,24 +442,22 @@ class BookManager {
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;
if (isDel)
- this.emit('recent-changed');
+ await this.recentSetItem();
return isDel;
}
mostRecentBook() {
- if (this.recentLast) {
- return this.recentLast;
+ if (this.recentLastKey) {
+ return this.recent[this.recentLastKey];
}
- const oldRecentLast = this.recentLast;
+ const oldKey = this.recentLastKey;
let max = 0;
let result = null;
@@ -408,10 +468,11 @@ class BookManager {
result = book;
}
}
- this.recentLast = result;
- bmRecentStore.setItem('recent-last', this.recentLast);//no await
+
+ const newRecentLastKey = (result ? result.key : null);
+ this.recentSetLastKey(newRecentLastKey);//no await
- if (this.recentLast !== oldRecentLast)
+ if (newRecentLastKey !== oldKey)
this.emit('recent-changed');
return result;
@@ -442,24 +503,12 @@ class BookManager {
delete mergedRecent[i];
}
- //"ленивое" обновление хранилища
- (async() => {
- for (const rec of Object.values(mergedRecent)) {
- if (rec.key) {
- await bmRecentStore.setItem(rec.key, rec);
- await utils.sleep(1);
- }
- }
- })();
-
this.recent = mergedRecent;
- this.recentLast = null;
- await bmRecentStore.setItem('recent-last', this.recentLast);
+ await this.recentSetLastKey(null);
+ await this.recentSetItem(null, true);
- this.recentChanged = true;
this.emit('set-recent');
- this.emit('recent-changed');
}
addEventListener(listener) {
diff --git a/client/components/Reader/versionHistory.js b/client/components/Reader/versionHistory.js
index 3df6ae1c..57394587 100644
--- a/client/components/Reader/versionHistory.js
+++ b/client/components/Reader/versionHistory.js
@@ -1,4 +1,15 @@
export const versionHistory = [
+{
+ showUntil: '2020-11-20',
+ header: '0.9.9 (2020-11-21)',
+ content:
+`
+
+ - оптимизации, исправления багов
+
+`
+},
+
{
showUntil: '2020-11-12',
header: '0.9.8 (2020-11-13)',
diff --git a/client/share/utils.js b/client/share/utils.js
index c773159b..c68d48a7 100644
--- a/client/share/utils.js
+++ b/client/share/utils.js
@@ -308,3 +308,51 @@ export function userHotKeysObjectSwap(userHotKeys) {
export function removeHtmlTags(s) {
return s.replace(/(<([^>]+)>)/ig, '');
}
+
+export function makeValidFilename(filename, repl = '_') {
+ let f = filename.replace(/[\x00\\/:*"<>|]/g, repl); // eslint-disable-line no-control-regex
+ f = f.trim();
+ while (f.length && (f[f.length - 1] == '.' || f[f.length - 1] == '_')) {
+ f = f.substring(0, f.length - 1);
+ }
+
+ if (f)
+ return f;
+ else
+ throw new Error('Invalid filename');
+}
+
+export function getBookTitle(fb2) {
+ fb2 = (fb2 ? fb2 : {});
+ const result = {};
+
+ if (fb2.author) {
+ const authorNames = fb2.author.map(a => _.compact([
+ a.lastName,
+ a.firstName,
+ a.middleName
+ ]).join(' '));
+
+ result.author = authorNames.join(', ');
+ }
+
+ if (fb2.sequence) {
+ const seqs = fb2.sequence.map(s => _.compact([
+ s.name,
+ (s.number ? `#${s.number}` : null),
+ ]).join(' '));
+
+ result.sequence = seqs.join(', ');
+ if (result.sequence)
+ result.sequenceTitle = `(${result.sequence})`;
+ }
+
+ result.bookTitle = _.compact([result.sequenceTitle, fb2.bookTitle]).join(' ');
+
+ result.fullTitle = _.compact([
+ result.author,
+ result.bookTitle
+ ]).join(' - ');
+
+ return result;
+}
\ No newline at end of file
diff --git a/client/store/modules/reader.js b/client/store/modules/reader.js
index 59eb206c..f99d79c8 100644
--- a/client/store/modules/reader.js
+++ b/client/store/modules/reader.js
@@ -16,7 +16,7 @@ const readerActions = {
'refresh': 'Принудительно обновить книгу',
'offlineMode': 'Автономный режим (без интернета)',
'contents': 'Оглавление/закладки',
- 'libs': 'Библиотека',
+ 'libs': 'Сетевая библиотека',
'recentBooks': 'Открыть недавние',
'switchToolbar': 'Показать/скрыть панель управления',
'donate': '',
diff --git a/package-lock.json b/package-lock.json
index ebebb4ef..8919bab9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "Liberama",
- "version": "0.9.8",
+ "version": "0.9.9",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index 655745d3..3174b1ba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "Liberama",
- "version": "0.9.8",
+ "version": "0.9.9",
"author": "Book Pauk ",
"license": "CC0-1.0",
"repository": "bookpauk/liberama",
diff --git a/server/core/Reader/ReaderWorker.js b/server/core/Reader/ReaderWorker.js
index 3e76f8aa..76ca0bfe 100644
--- a/server/core/Reader/ReaderWorker.js
+++ b/server/core/Reader/ReaderWorker.js
@@ -171,6 +171,7 @@ class ReaderWorker {
} catch (e) {
log(LM_ERR, e.stack);
+ log(LM_ERR, `downloadedFilename: ${downloadedFilename}`);
if (e.message == 'abort')
e.message = overLoadMes;
wState.set({state: 'error', error: e.message});