Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f650124428 | ||
|
|
795d109c76 | ||
|
|
6868b3effc | ||
|
|
26747b7013 | ||
|
|
5198f8aa60 | ||
|
|
552da48a32 | ||
|
|
db8a688620 | ||
|
|
3088028d05 | ||
|
|
fd62ef865d | ||
|
|
ed74ed00ed | ||
|
|
741317aaaf | ||
|
|
9b6ecd4e6b | ||
|
|
7863b3358e | ||
|
|
e1be68ec3d | ||
|
|
a054186d4b | ||
|
|
2d5c549c83 | ||
|
|
9f6072dfe1 | ||
|
|
69c44fe1ab | ||
|
|
4fa7b2443e | ||
|
|
25a69592bb | ||
|
|
44e0b26990 | ||
|
|
c4496f8dc8 | ||
|
|
9e296231d9 | ||
|
|
49b3f05d65 | ||
|
|
f124b9c050 | ||
|
|
63a86f7c06 | ||
|
|
fd0f523c64 | ||
|
|
487e605520 | ||
|
|
9e169e1f4b | ||
|
|
9612e7ebcd |
@@ -24,8 +24,8 @@ async function main() {
|
||||
await fs.ensureDir(tempDownloadDir);
|
||||
|
||||
//sqlite3
|
||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.1.0/node-v72-linux-x64.tar.gz';
|
||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v72-linux-x64/node_sqlite3.node`;
|
||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.4/node-v64-linux-x64.tar.gz';
|
||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v64-linux-x64/node_sqlite3.node`;
|
||||
|
||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||
|
||||
@@ -55,6 +55,6 @@ module.exports = merge(baseWpConfig, {
|
||||
filename: `${publicDir}/index.html`
|
||||
}),
|
||||
new CopyWebpackPlugin([{from: `${clientDir}/assets/*`, to: `${publicDir}/`, flatten: true}]),
|
||||
new AppCachePlugin({})
|
||||
new AppCachePlugin({exclude: ['../index.html']})
|
||||
]
|
||||
});
|
||||
|
||||
@@ -24,8 +24,8 @@ async function main() {
|
||||
await fs.ensureDir(tempDownloadDir);
|
||||
|
||||
//sqlite3
|
||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.1.0/node-v72-win32-x64.tar.gz';
|
||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v72-win32-x64/node_sqlite3.node`;
|
||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.4/node-v64-win32-x64.tar.gz';
|
||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v64-win32-x64/node_sqlite3.node`;
|
||||
|
||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
<el-tooltip v-show="showToolButton['recentBooks']" content="Открыть недавние" :open-delay="1000" effect="light">
|
||||
<el-button ref="recentBooks" class="tool-button" :class="buttonActiveClass('recentBooks')" @click="buttonClick('recentBooks')"><i class="el-icon-document"></i></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip v-show="showToolButton['offlineMode']" content="Автономный режим (без интернета)" :open-delay="1000" effect="light">
|
||||
<el-button ref="offlineMode" class="tool-button" :class="buttonActiveClass('offlineMode')" @click="buttonClick('offlineMode')"><i class="el-icon-connection"></i></el-button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<el-tooltip content="Настроить" :open-delay="1000" effect="light">
|
||||
@@ -257,6 +260,7 @@ class Reader extends Vue {
|
||||
searchActive = false;
|
||||
copyTextActive = false;
|
||||
recentBooksActive = false;
|
||||
offlineModeActive = false;
|
||||
settingsActive = false;
|
||||
helpActive = false;
|
||||
clickMapActive = false;
|
||||
@@ -510,7 +514,9 @@ class Reader extends Vue {
|
||||
if (this.recentBooksActive) {
|
||||
await this.$refs.recentBooksPage.updateTableData();
|
||||
}
|
||||
}
|
||||
|
||||
if (eventName == 'set-recent' || eventName == 'recent-deleted') {
|
||||
const oldBook = this.mostRecentBookReactive;
|
||||
const newBook = bookManager.mostRecentBook();
|
||||
if (oldBook && newBook) {
|
||||
@@ -694,6 +700,11 @@ class Reader extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
offlineModeToggle() {
|
||||
this.offlineModeActive = !this.offlineModeActive;
|
||||
this.$refs.serverStorage.offlineModeActive = this.offlineModeActive;
|
||||
}
|
||||
|
||||
settingsToggle() {
|
||||
this.settingsActive = !this.settingsActive;
|
||||
if (this.settingsActive) {
|
||||
@@ -779,11 +790,14 @@ class Reader extends Vue {
|
||||
case 'copyText':
|
||||
this.copyTextToggle();
|
||||
break;
|
||||
case 'refresh':
|
||||
this.refreshBook();
|
||||
break;
|
||||
case 'recentBooks':
|
||||
this.recentBooksToggle();
|
||||
break;
|
||||
case 'refresh':
|
||||
this.refreshBook();
|
||||
case 'offlineMode':
|
||||
this.offlineModeToggle();
|
||||
break;
|
||||
case 'settings':
|
||||
this.settingsToggle();
|
||||
@@ -804,6 +818,7 @@ class Reader extends Vue {
|
||||
case 'search':
|
||||
case 'copyText':
|
||||
case 'recentBooks':
|
||||
case 'offlineMode':
|
||||
case 'settings':
|
||||
if (this[`${button}Active`])
|
||||
classResult = classActive;
|
||||
@@ -975,7 +990,6 @@ class Reader extends Vue {
|
||||
}
|
||||
|
||||
progress.setState({totalSteps: 5});
|
||||
|
||||
// не удалось, скачиваем книгу полностью с конвертацией
|
||||
let loadCached = true;
|
||||
if (!book) {
|
||||
|
||||
@@ -71,8 +71,24 @@ class ServerStorage extends Vue {
|
||||
}
|
||||
|
||||
async bookManagerEvent(eventName, itemKey) {
|
||||
if (!this.serverSyncEnabled)
|
||||
return;
|
||||
|
||||
if (eventName == 'recent-changed') {
|
||||
this.debouncedSaveRecent(itemKey);
|
||||
if (itemKey) {
|
||||
if (!this.recentDeltaInited) {
|
||||
await this.loadRecent();
|
||||
this.warning('Функции сохранения на сервер пока недоступны');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.recentDelta)
|
||||
this.recentDelta = {};
|
||||
|
||||
this.recentDelta[itemKey] = _.cloneDeep(bookManager.recent[itemKey]);
|
||||
|
||||
this.debouncedSaveRecent(itemKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +119,7 @@ class ServerStorage extends Vue {
|
||||
await this.loadProfiles(force);
|
||||
this.checkCurrentProfile();
|
||||
await this.currentProfileChanged(force);
|
||||
await this.loadRecent(force);
|
||||
await this.loadRecent();
|
||||
if (force)
|
||||
await this.saveRecent();
|
||||
}
|
||||
@@ -160,12 +176,12 @@ class ServerStorage extends Vue {
|
||||
}
|
||||
|
||||
warning(message) {
|
||||
if (this.showServerStorageMessages)
|
||||
if (this.showServerStorageMessages && !this.offlineModeActive)
|
||||
this.$notify.warning({message});
|
||||
}
|
||||
|
||||
error(message) {
|
||||
if (this.showServerStorageMessages)
|
||||
if (this.showServerStorageMessages && !this.offlineModeActive)
|
||||
this.$notify.error({message});
|
||||
}
|
||||
|
||||
@@ -324,55 +340,85 @@ class ServerStorage extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
async loadRecent(force = false, doNotifySuccess = true) {
|
||||
if (!this.keyInited || !this.serverSyncEnabled)
|
||||
async initRecentDelta() {
|
||||
let recentDelta = null;
|
||||
try {
|
||||
recentDelta = await this.storageGet({recentDelta: {}});
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером: ${e.message}`);
|
||||
return;
|
||||
|
||||
const oldRecentRev = bookManager.recentRev;
|
||||
const oldRecentDiffRev = bookManager.recentDiffRev;
|
||||
//проверим ревизию на сервере
|
||||
let revs = null;
|
||||
if (!force) {
|
||||
try {
|
||||
revs = await this.storageCheck({recent: {}, recentDiff: {}});
|
||||
if (revs.state == 'success' && revs.items.recent.rev == oldRecentRev &&
|
||||
revs.items.recentDiff.rev == oldRecentDiffRev) {
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером: ${e.message}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let recent = null;
|
||||
if (force || revs.items.recent.rev != oldRecentRev || revs.items.recentDiff.rev != oldRecentDiffRev) {
|
||||
if (recentDelta.state == 'success') {
|
||||
recentDelta = recentDelta.items.recentDelta;
|
||||
|
||||
if (recentDelta.rev == 0)
|
||||
recentDelta.data = {};
|
||||
|
||||
this.recentDelta = recentDelta.data;
|
||||
this.recentDeltaInited = true;
|
||||
} else {
|
||||
this.warning(`Неверный ответ сервера: ${recentDelta.state}`);
|
||||
}
|
||||
}
|
||||
|
||||
async loadRecent(skipRevCheck = false, doNotifySuccess = true) {
|
||||
if (!this.keyInited || !this.serverSyncEnabled || this.loadingRecent)
|
||||
return;
|
||||
|
||||
this.loadingRecent = true;
|
||||
try {
|
||||
const oldRecentRev = bookManager.recentRev;
|
||||
const oldRecentDeltaRev = bookManager.recentDeltaRev;
|
||||
//проверим ревизию на сервере
|
||||
let revs = null;
|
||||
if (!skipRevCheck) {
|
||||
try {
|
||||
revs = await this.storageCheck({recent: {}, recentDelta: {}});
|
||||
if (revs.state == 'success' && revs.items.recent.rev == oldRecentRev &&
|
||||
revs.items.recentDelta.rev == oldRecentDeltaRev) {
|
||||
if (!this.recentDeltaInited)
|
||||
await this.initRecentDelta();
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером: ${e.message}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let recent = null;
|
||||
try {
|
||||
recent = await this.storageGet({recent: {}, recentDiff: {}});
|
||||
recent = await this.storageGet({recent: {}, recentDelta: {}});
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером: ${e.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (recent.state == 'success') {
|
||||
let recentDiff = recent.items.recentDiff;
|
||||
let recentDelta = recent.items.recentDelta;
|
||||
recent = recent.items.recent;
|
||||
|
||||
if (recent.rev == 0)
|
||||
recent.data = {};
|
||||
|
||||
this.oldRecent = _.cloneDeep(recent.data);
|
||||
let newRecent = {};
|
||||
if (recentDiff && recentDiff.data) {
|
||||
newRecent = utils.applyObjDiff(recent.data, recentDiff.data);
|
||||
this.recentDiff = _.cloneDeep(recentDiff.data);
|
||||
if (!utils.isObjDiff(this.recentDiff))
|
||||
this.recentDiff = null;
|
||||
if (recentDelta && recentDelta.data) {
|
||||
if (recentDelta.data.diff) {
|
||||
newRecent = recent.data;
|
||||
const key = recentDelta.data.diff.key;
|
||||
if (newRecent[key])
|
||||
newRecent[key] = utils.applyObjDiff(newRecent[key], recentDelta.data.diff);
|
||||
} else {
|
||||
newRecent = Object.assign(recent.data, recentDelta.data);
|
||||
}
|
||||
this.recentDelta = recentDelta.data;
|
||||
} else {
|
||||
newRecent = recent.data;
|
||||
this.recentDiff = null;
|
||||
this.recentDelta = {};
|
||||
}
|
||||
|
||||
this.recentDeltaInited = true;
|
||||
|
||||
if (!bookManager.loaded) {
|
||||
this.warning('Ожидание загрузки списка книг перед синхронизацией');
|
||||
@@ -380,114 +426,108 @@ class ServerStorage extends Vue {
|
||||
}
|
||||
await bookManager.setRecent(newRecent);
|
||||
await bookManager.setRecentRev(recent.rev);
|
||||
await bookManager.setRecentDiffRev(recentDiff.rev);
|
||||
await bookManager.setRecentDeltaRev(recentDelta.rev);
|
||||
} else {
|
||||
this.warning(`Неверный ответ сервера: ${recent.state}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (doNotifySuccess)
|
||||
this.debouncedNotifySuccess();
|
||||
if (doNotifySuccess)
|
||||
this.debouncedNotifySuccess();
|
||||
} finally {
|
||||
this.loadingRecent = false;
|
||||
}
|
||||
}
|
||||
|
||||
async saveRecent(itemKey) {
|
||||
async saveRecent(itemKey, recurse) {
|
||||
if (!this.keyInited || !this.serverSyncEnabled || this.savingRecent)
|
||||
return;
|
||||
|
||||
const bm = bookManager;
|
||||
|
||||
/*if (!bookManager.loaded) {
|
||||
this.warning('Функции сохранения на сервер пока недоступны');
|
||||
return;
|
||||
}*/
|
||||
|
||||
//несколько замудреная инициализация oldRecent
|
||||
if (!this.oldRecent) {
|
||||
this.oldRecent = _.cloneDeep(bookManager.recent);
|
||||
}
|
||||
|
||||
if (bookManager.loaded && !this.oldRecentInited) {
|
||||
this.oldRecent = _.cloneDeep(bookManager.recent);
|
||||
this.oldRecentInited = true;
|
||||
}
|
||||
|
||||
//вычисляем дифф
|
||||
let diff = null;
|
||||
if (itemKey) {//ускоренное вычисления диффа
|
||||
let itemDiff;
|
||||
if (this.oldRecent[itemKey]) {
|
||||
itemDiff = utils.getObjDiff({[itemKey]: (this.oldRecentInited ? this.oldRecent[itemKey] : {})}, {[itemKey]: bm.recent[itemKey]});
|
||||
} else {
|
||||
itemDiff = utils.getObjDiff({}, {[itemKey]: bm.recent[itemKey]});
|
||||
}
|
||||
if (this.recentDiff) {
|
||||
diff = this.recentDiff;
|
||||
if (itemDiff.change[itemKey])
|
||||
diff.change[itemKey] = itemDiff.change[itemKey];
|
||||
if (itemDiff.add[itemKey])
|
||||
diff.add[itemKey] = itemDiff.add[itemKey];
|
||||
} else {
|
||||
diff = itemDiff;
|
||||
}
|
||||
} else {//медленное вычисление диффа
|
||||
if (this.oldRecentInited) {
|
||||
diff = utils.getObjDiff(this.oldRecent, bm.recent);
|
||||
} else
|
||||
return;
|
||||
}
|
||||
|
||||
if (utils.isEmptyObjDiff(diff))
|
||||
return;
|
||||
|
||||
//вычисление критерия сохранения целиком
|
||||
let forceSaveRecent = JSON.stringify(diff).length > 2000;
|
||||
if (!forceSaveRecent && itemKey) {
|
||||
if (!this.sameKeyCount)
|
||||
this.sameKeyCount = 0;
|
||||
if (this.prevItemKey == itemKey)
|
||||
this.sameKeyCount++;
|
||||
|
||||
forceSaveRecent = this.sameKeyCount > 5 && (Object.keys(diff.change).length > 1);
|
||||
|
||||
this.sameKeyCount = (!forceSaveRecent ? this.sameKeyCount : 0);
|
||||
this.prevItemKey = itemKey;
|
||||
if (!this.sameKeyCount)
|
||||
this.sameKeyCount = 0;
|
||||
if (this.prevItemKey == itemKey) {
|
||||
this.sameKeyCount++;
|
||||
} else {
|
||||
this.sameKeyCount = 0;
|
||||
}
|
||||
|
||||
this.recentDiff = diff;
|
||||
const l = Object.keys(this.recentDelta).length - (1*(!!this.recentDelta.diff));
|
||||
this.makeDeltaDiff = (l == 1 && this.prevItemKey == itemKey ? this.makeDeltaDiff : false);
|
||||
const forceSaveRecent = l > 10 || (this.sameKeyCount > 5 && (l > 1)) || (l == 1 && this.sameKeyCount > 10 && !this.makeDeltaDiff);
|
||||
|
||||
this.sameKeyCount = (!forceSaveRecent ? this.sameKeyCount : 0);
|
||||
this.prevItemKey = itemKey;
|
||||
|
||||
//дифф от дельты для уменьшения размера передаваемых данных в частном случае
|
||||
if (this.makeDeltaDiff) {
|
||||
this.recentDelta.diff = utils.getObjDiff(this.prevSavedItem, bm.recent[itemKey]);
|
||||
this.recentDelta.diff.key = itemKey;
|
||||
delete this.recentDelta[itemKey];
|
||||
} else if (this.recentDelta.diff) {
|
||||
const key = this.recentDelta.diff.key;
|
||||
if (!this.prevSavedItem && bm.recent[key])
|
||||
this.prevSavedItem = _.cloneDeep(bm.recent[key]);
|
||||
if (this.prevSavedItem) {
|
||||
this.recentDelta[key] = utils.applyObjDiff(this.prevSavedItem, this.recentDelta.diff);
|
||||
}
|
||||
delete this.recentDelta.diff;
|
||||
}
|
||||
|
||||
//сохранение
|
||||
this.savingRecent = true;
|
||||
try {
|
||||
if (forceSaveRecent) {//сохраняем recent целиком
|
||||
let result = {state: ''};
|
||||
|
||||
try {
|
||||
result = await this.storageSet({recent: {rev: bm.recentRev + 1, data: bm.recent}, recentDiff: {rev: bm.recentDiffRev + 1, data: {}}});
|
||||
result = await this.storageSet({recent: {rev: bm.recentRev + 1, data: bm.recent}, recentDelta: {rev: bm.recentDeltaRev + 1, data: {}}});
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером (${e.message}). Данные не сохранены и могут быть перезаписаны.`);
|
||||
}
|
||||
|
||||
if (result.state == 'reject') {
|
||||
|
||||
await this.loadRecent(true, false);
|
||||
|
||||
this.warning(`Последние изменения отменены. Данные синхронизированы с сервером.`);
|
||||
if (!recurse) {
|
||||
this.savingRecent = false;
|
||||
this.recentDelta[itemKey] = _.cloneDeep(bm.recent[itemKey]);
|
||||
this.saveRecent(itemKey, true);
|
||||
return;
|
||||
}
|
||||
} else if (result.state == 'success') {
|
||||
this.oldRecent = _.cloneDeep(bm.recent);
|
||||
this.recentDiff = null;
|
||||
this.makeDeltaDiff = true;
|
||||
this.prevSavedItem = _.cloneDeep(bm.recent[itemKey]);
|
||||
|
||||
this.recentDelta = {};
|
||||
await bm.setRecentRev(bm.recentRev + 1);
|
||||
await bm.setRecentDiffRev(bm.recentDiffRev + 1);
|
||||
await bm.setRecentDeltaRev(bm.recentDeltaRev + 1);
|
||||
}
|
||||
} else {//сохраняем только дифф
|
||||
let result = {state: ''};
|
||||
|
||||
try {
|
||||
result = await this.storageSet({recentDiff: {rev: bm.recentDiffRev + 1, data: this.recentDiff}});
|
||||
result = await this.storageSet({recentDelta: {rev: bm.recentDeltaRev + 1, data: this.recentDelta}});
|
||||
} catch(e) {
|
||||
this.error(`Ошибка соединения с сервером (${e.message}). Данные не сохранены и могут быть перезаписаны.`);
|
||||
}
|
||||
|
||||
if (result.state == 'reject') {
|
||||
|
||||
await this.loadRecent(true, false);
|
||||
|
||||
this.warning(`Последние изменения отменены. Данные синхронизированы с сервером.`);
|
||||
if (!recurse) {
|
||||
this.savingRecent = false;
|
||||
this.recentDelta[itemKey] = _.cloneDeep(bm.recent[itemKey]);
|
||||
this.saveRecent(itemKey, true);
|
||||
return;
|
||||
}
|
||||
} else if (result.state == 'success') {
|
||||
await bm.setRecentDiffRev(bm.recentDiffRev + 1);
|
||||
await bm.setRecentDeltaRev(bm.recentDeltaRev + 1);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -37,7 +37,7 @@ class BookManager {
|
||||
}
|
||||
|
||||
this.recentRev = await bmRecentStore.getItem('recent-rev') || 0;
|
||||
this.recentDiffRev = await bmRecentStore.getItem('recent-diff-rev') || 0;
|
||||
this.recentDeltaRev = await bmRecentStore.getItem('recent-delta-rev') || 0;
|
||||
|
||||
this.recentChanged = true;
|
||||
|
||||
@@ -356,7 +356,8 @@ class BookManager {
|
||||
let result = this.recent[value.key];
|
||||
if (!result) {
|
||||
result = await bmRecentStore.getItem(value.key);
|
||||
this.recent[value.key] = result;
|
||||
if (result)
|
||||
this.recent[value.key] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -369,6 +370,7 @@ class BookManager {
|
||||
this.recentLast = null;
|
||||
await bmRecentStore.setItem('recent-last', this.recentLast);
|
||||
}
|
||||
this.emit('recent-deleted', value.key);
|
||||
this.emit('recent-changed', value.key);
|
||||
}
|
||||
|
||||
@@ -410,6 +412,7 @@ class BookManager {
|
||||
|
||||
if (this.recentLast !== oldRecentLast)
|
||||
this.emit('recent-changed');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -448,6 +451,7 @@ class BookManager {
|
||||
await bmRecentStore.setItem('recent-last', this.recentLast);
|
||||
|
||||
this.recentChanged = true;
|
||||
this.emit('set-recent');
|
||||
this.emit('recent-changed');
|
||||
}
|
||||
|
||||
@@ -456,12 +460,11 @@ class BookManager {
|
||||
this.recentRev = value;
|
||||
}
|
||||
|
||||
async setRecentDiffRev(value) {
|
||||
await bmRecentStore.setItem('recent-diff-rev', value);
|
||||
this.recentDiffRev = value;
|
||||
async setRecentDeltaRev(value) {
|
||||
await bmRecentStore.setItem('recent-delta-rev', value);
|
||||
this.recentDeltaRev = value;
|
||||
}
|
||||
|
||||
|
||||
addEventListener(listener) {
|
||||
if (this.eventListeners.indexOf(listener) < 0)
|
||||
this.eventListeners.push(listener);
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
showUntil: '2019-09-19',
|
||||
header: '0.7.1 (2019-09-20)',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправления багов</li>
|
||||
<li>на панель управления добавлена кнопка "Автономный режим"</li>
|
||||
</ul>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
showUntil: '2019-10-01',
|
||||
header: '0.7.0 (2019-09-07)',
|
||||
|
||||
@@ -9,6 +9,7 @@ const toolButtons = [
|
||||
{name: 'copyText', show: false, text: 'Скопировать текст со страницы'},
|
||||
{name: 'refresh', show: true, text: 'Принудительно обновить книгу'},
|
||||
{name: 'recentBooks', show: true, text: 'Открыть недавние'},
|
||||
{name: 'offlineMode', show: false, text: 'Автономный режим (без интернета)'},
|
||||
];
|
||||
|
||||
const fonts = [
|
||||
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
2167
package-lock.json
generated
2167
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Liberama",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.1",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@@ -41,7 +41,7 @@
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"null-loader": "^0.1.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"pkg": "^4.4.0",
|
||||
"pkg": "4.3.7",
|
||||
"terser-webpack-plugin": "^1.4.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue-class-component": "^6.3.2",
|
||||
@@ -77,7 +77,7 @@
|
||||
"safe-buffer": "^5.2.0",
|
||||
"sjcl": "^1.0.8",
|
||||
"sql-template-strings": "^2.2.2",
|
||||
"sqlite": "^3.0.3",
|
||||
"sqlite": "3.0.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"unbzip2-stream": "^1.3.3",
|
||||
"vue": "^2.6.10",
|
||||
|
||||
@@ -7,6 +7,7 @@ const FileDownloader = require('./FileDownloader');
|
||||
const FileDecompressor = require('./FileDecompressor');
|
||||
const BookConverter = require('./BookConverter');
|
||||
const utils = require('./utils');
|
||||
const log = require('./getLogger').getLog();
|
||||
|
||||
let singleCleanExecute = false;
|
||||
|
||||
@@ -133,6 +134,7 @@ class ReaderWorker {
|
||||
|
||||
async periodicCleanDir(dir, maxSize, timeout) {
|
||||
try {
|
||||
log(`Start clean dir: ${dir}, maxSize=${maxSize}`);
|
||||
const list = await fs.readdir(dir);
|
||||
|
||||
let size = 0;
|
||||
@@ -144,16 +146,21 @@ class ReaderWorker {
|
||||
files.push({name, stat});
|
||||
}
|
||||
}
|
||||
log(`found ${files.length} files in dir ${dir}`);
|
||||
|
||||
files.sort((a, b) => a.stat.mtimeMs - b.stat.mtimeMs);
|
||||
|
||||
let i = 0;
|
||||
while (i < files.length && size > maxSize) {
|
||||
const file = files[i];
|
||||
log(`rm ${dir}/${file.name}`);
|
||||
await fs.remove(`${dir}/${file.name}`);
|
||||
size -= file.stat.size;
|
||||
i++;
|
||||
}
|
||||
log(`removed ${i} files`);
|
||||
} catch(e) {
|
||||
log(LM_ERR, e.message);
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
this.periodicCleanDir(dir, maxSize, timeout);
|
||||
|
||||
Reference in New Issue
Block a user