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 @@
- Последние 100 открытых книг
+ Последние {{tableData ? tableData.length : 0}} открытых книг
+ Список загружается
{
- 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);