Merge branch 'release/0.9.1'
This commit is contained in:
@@ -54,6 +54,34 @@
|
||||
<!---------------------------------------------->
|
||||
<div class="part-header">Другое</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-6">Обработка</div>
|
||||
<div class="col row">
|
||||
<q-checkbox v-model="enableSitesFilter" @input="needTextReload" size="xs" label="Включить html-фильтр для сайтов">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
Html-фильтр вырезает лишние элементы со<br>
|
||||
страницы для определенных сайтов, таких как:<br>
|
||||
samlib.ru<br>
|
||||
www.fanfiction.net<br>
|
||||
archiveofourown.org<br>
|
||||
и других
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-6">Обработка</div>
|
||||
<q-checkbox size="xs" v-model="lazyParseEnabled" label="Предварительная подготовка текста">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
Включение этой опции позволяет делать предварительную<br>
|
||||
подготовку всего текста в ленивом режиме сразу после<br>
|
||||
загрузки книги. Это может повысить отзывчивость читалки,<br>
|
||||
но нагружает процессор каждый раз при открытии книги.
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-6">Парам. в URL</div>
|
||||
<q-checkbox size="xs" v-model="allowUrlParamBookPos">
|
||||
@@ -68,18 +96,6 @@
|
||||
</q-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-6">Парсинг</div>
|
||||
<q-checkbox size="xs" v-model="lazyParseEnabled" label="Предварительная обработка текста">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
Включение этой опции позволяет делать предварительную<br>
|
||||
обработку текста в ленивом режиме сразу после загрузки<br>
|
||||
книги. Это может повысить отзывчивость читалки, но<br>
|
||||
нагружает процессор каждый раз при открытии книги.
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-6">Копирование</div>
|
||||
<q-checkbox size="xs" v-model="copyFullText" label="Загружать весь текст">
|
||||
|
||||
@@ -22,3 +22,15 @@
|
||||
<NumInput class="col-left" v-model="statusBarColorAlpha" :min="0" :max="1" :digits="2" :step="0.1" :disable="!showStatusBar"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-2"></div>
|
||||
<div class="col row">
|
||||
<q-checkbox v-model="statusBarClickOpen" size="xs" label="Открывать оригинал по клику">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
По клику на автора-название в строке статуса<br>
|
||||
открывать оригинал произведения в новой вкладке
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -108,22 +108,6 @@
|
||||
<NumInput class="col" v-model="addEmptyParagraphs" :min="0" :max="2"/>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-2"></div>
|
||||
<div class="col row">
|
||||
<q-checkbox v-model="enableSitesFilter" @input="needTextReload" size="xs" label="Включить html-фильтр для сайтов">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
Html-фильтр вырезает лишние элементы со<br>
|
||||
страницы для определенных сайтов, таких как:<br>
|
||||
samlib.ru<br>
|
||||
www.fanfiction.net<br>
|
||||
archiveofourown.org<br>
|
||||
и других
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item row">
|
||||
<div class="label-2">Изображения</div>
|
||||
<div class="col row">
|
||||
|
||||
@@ -21,11 +21,12 @@
|
||||
@wheel.prevent.stop="onMouseWheel"
|
||||
@touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove" @touchcancel.prevent.stop="onTouchCancel"
|
||||
oncontextmenu="return false;">
|
||||
<div v-show="showStatusBar" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
|
||||
<div v-show="showStatusBar && statusBarClickOpen" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
|
||||
@click.prevent.stop="onStatusBarClick"></div>
|
||||
</div>
|
||||
<div v-show="!clickControl && showStatusBar" class="layout" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
|
||||
@click.prevent.stop="onStatusBarClick"></div>
|
||||
<div v-show="!clickControl && showStatusBar && statusBarClickOpen" class="layout" v-html="statusBarClickable" @mousedown.prevent.stop @touchstart.stop
|
||||
@click.prevent.stop="onStatusBarClick">
|
||||
</div>
|
||||
<!-- невидимым делать нельзя, вовремя не подгружаютя шрифты -->
|
||||
<canvas ref="offscreenCanvas" class="layout" style="visibility: hidden"></canvas>
|
||||
<div ref="measureWidth" style="position: absolute; visibility: hidden"></div>
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
showUntil: '2020-03-02',
|
||||
header: '0.9.1 (2020-03-03)',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>улучшение работы серверной части</li>
|
||||
<li>незначительные изменения интерфейса</li>
|
||||
</ul>
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
showUntil: '2020-02-25',
|
||||
header: '0.9.0 (2020-02-26)',
|
||||
|
||||
@@ -80,7 +80,6 @@ Vue.use(Quasar, { config, components, directives, plugins });
|
||||
//import '@quasar/extras/material-icons-outlined/material-icons-outlined.css';
|
||||
//import '@quasar/extras/fontawesome-v5/fontawesome-v5.css';
|
||||
|
||||
//import '@quasar/extras/material-icons-outlined/material-icons-outlined.css';
|
||||
import '@quasar/extras/line-awesome/line-awesome.css';
|
||||
|
||||
//import fontawesomeV5 from 'quasar/icon-set/fontawesome-v5.js'
|
||||
|
||||
@@ -160,6 +160,7 @@ const settingDefaults = {
|
||||
statusBarTop: false,// top, bottom
|
||||
statusBarHeight: 19,// px
|
||||
statusBarColorAlpha: 0.4,
|
||||
statusBarClickOpen: true,
|
||||
|
||||
scrollingDelay: 3000,// замедление, ms
|
||||
scrollingType: 'ease-in-out', //linear, ease, ease-in, ease-out, ease-in-out
|
||||
|
||||
1552
package-lock.json
generated
1552
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Liberama",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
"repository": "bookpauk/liberama",
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
@@ -32,7 +32,6 @@
|
||||
"clean-webpack-plugin": "^1.0.1",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^1.0.0",
|
||||
"element-theme-chalk": "^2.12.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-html": "^5.0.5",
|
||||
"eslint-plugin-node": "^8.0.0",
|
||||
@@ -41,27 +40,26 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"pkg": "^4.4.2",
|
||||
"pkg": "^4.4.4",
|
||||
"terser-webpack-plugin": "^1.4.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue-class-component": "^6.3.2",
|
||||
"vue-loader": "^15.7.1",
|
||||
"vue-loader": "^15.9.0",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"webpack": "^4.39.3",
|
||||
"webpack-cli": "^3.3.7",
|
||||
"webpack-dev-middleware": "^3.7.1",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-middleware": "^3.7.2",
|
||||
"webpack-hot-middleware": "^2.25.0",
|
||||
"webpack-merge": "^4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/extras": "^1.5.0",
|
||||
"@quasar/extras": "^1.5.2",
|
||||
"appcache-webpack-plugin": "^1.4.0",
|
||||
"axios": "^0.18.1",
|
||||
"base-x": "^3.0.6",
|
||||
"base-x": "^3.0.8",
|
||||
"chardet": "^0.7.0",
|
||||
"compression": "^1.7.4",
|
||||
"element-ui": "^2.12.0",
|
||||
"express": "^4.17.1",
|
||||
"fg-loadcss": "^2.1.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
@@ -72,21 +70,21 @@
|
||||
"lodash": "^4.17.15",
|
||||
"minimist": "^1.2.0",
|
||||
"multer": "^1.4.2",
|
||||
"pako": "^1.0.10",
|
||||
"pako": "^1.0.11",
|
||||
"path-browserify": "^1.0.0",
|
||||
"quasar": "^1.8.5",
|
||||
"quasar": "^1.9.6",
|
||||
"safe-buffer": "^5.2.0",
|
||||
"sjcl": "^1.0.8",
|
||||
"sql-template-strings": "^2.2.2",
|
||||
"sqlite": "^3.0.3",
|
||||
"tar-fs": "^2.0.0",
|
||||
"unbzip2-stream": "^1.3.3",
|
||||
"vue": "github:paulkamer/vue#fix_palemoon_clickhandlers_dist",
|
||||
"vue-router": "^3.1.3",
|
||||
"vuex": "^3.1.1",
|
||||
"vuex-persistedstate": "^2.5.4",
|
||||
"webdav": "^2.10.1",
|
||||
"vue": "github:bookpauk/vue",
|
||||
"vue-router": "^3.1.6",
|
||||
"vuex": "^3.1.2",
|
||||
"vuex-persistedstate": "^2.7.1",
|
||||
"webdav": "^2.10.2",
|
||||
"ws": "^7.2.1",
|
||||
"zip-stream": "^2.1.2"
|
||||
"zip-stream": "^2.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,27 +241,29 @@ class FileDecompressor {
|
||||
});
|
||||
}
|
||||
|
||||
async gzipFileIfNotExists(filename, outDir) {
|
||||
async gzipFileIfNotExists(filename, outDir, isMaxCompression) {
|
||||
const hash = await utils.getFileHash(filename, 'sha256', 'hex');
|
||||
|
||||
const outFilename = `${outDir}/${hash}`;
|
||||
|
||||
if (!await fs.pathExists(outFilename)) {
|
||||
await this.gzipFile(filename, outFilename, 1);
|
||||
await this.gzipFile(filename, outFilename, (isMaxCompression ? 9 : 1));
|
||||
|
||||
// переупакуем через некоторое время на максималках
|
||||
const filenameCopy = `${filename}.copy`;
|
||||
await fs.copy(filename, filenameCopy);
|
||||
// переупакуем через некоторое время на максималках, если упаковали плохо
|
||||
if (!isMaxCompression) {
|
||||
const filenameCopy = `${filename}.copy`;
|
||||
await fs.copy(filename, filenameCopy);
|
||||
|
||||
(async() => {
|
||||
await utils.sleep(5000);
|
||||
const filenameGZ = `${filename}.gz`;
|
||||
await this.gzipFile(filenameCopy, filenameGZ, 9);
|
||||
(async() => {
|
||||
await utils.sleep(5000);
|
||||
const filenameGZ = `${filename}.gz`;
|
||||
await this.gzipFile(filenameCopy, filenameGZ, 9);
|
||||
|
||||
await fs.move(filenameGZ, outFilename, {overwrite: true});
|
||||
await fs.move(filenameGZ, outFilename, {overwrite: true});
|
||||
|
||||
await fs.remove(filenameCopy);
|
||||
})().catch((e) => { if (appLogger.inited) appLogger.log(LM_ERR, `FileDecompressor.gzipFileIfNotExists: ${e.message}`) });
|
||||
await fs.remove(filenameCopy);
|
||||
})().catch((e) => { if (appLogger.inited) appLogger.log(LM_ERR, `FileDecompressor.gzipFileIfNotExists: ${e.message}`) });
|
||||
}
|
||||
} else {
|
||||
await utils.touchFile(outFilename);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ class ReaderWorker {
|
||||
let decompDir = '';
|
||||
let downloadedFilename = '';
|
||||
let isUploaded = false;
|
||||
let isRestored = false;
|
||||
let convertFilename = '';
|
||||
|
||||
const overLoadMes = 'Слишком большая очередь загрузки. Пожалуйста, попробуйте позже.';
|
||||
@@ -88,9 +89,17 @@ class ReaderWorker {
|
||||
downloadedFilename = `${this.config.tempDownloadDir}/${tempFilename}`;
|
||||
await fs.writeFile(downloadedFilename, downdata);
|
||||
} else {//uploaded file
|
||||
downloadedFilename = `${this.config.uploadDir}/${url.substr(7)}`;
|
||||
if (!await fs.pathExists(downloadedFilename))
|
||||
throw new Error('Файл не найден на сервере (возможно был удален как устаревший). Пожалуйста, загрузите файл с диска на сервер заново.');
|
||||
const fileHash = url.substr(7);
|
||||
downloadedFilename = `${this.config.uploadDir}/${fileHash}`;
|
||||
if (!await fs.pathExists(downloadedFilename)) {
|
||||
//если удалено из upload, попробуем восстановить из удаленного хранилища
|
||||
try {
|
||||
downloadedFilename = await this.restoreRemoteFile(fileHash);
|
||||
isRestored = true;
|
||||
} catch(e) {
|
||||
throw new Error('Файл не найден на сервере (возможно был удален как устаревший). Пожалуйста, загрузите файл с диска на сервер заново.');
|
||||
}
|
||||
}
|
||||
await utils.touchFile(downloadedFilename);
|
||||
isUploaded = true;
|
||||
}
|
||||
@@ -146,6 +155,20 @@ class ReaderWorker {
|
||||
})();
|
||||
}
|
||||
|
||||
//лениво сохраним downloadedFilename в tmp и в удаленном хранилище в случае isUploaded
|
||||
if (this.remoteWebDavStorage && isUploaded && !isRestored) {
|
||||
(async() => {
|
||||
await utils.sleep(30*1000);
|
||||
try {
|
||||
//сжимаем файл в tmp, если там уже нет с тем же именем-sha256
|
||||
const compDownloadedFilename = await this.decomp.gzipFileIfNotExists(downloadedFilename, this.config.tempPublicDir, true);
|
||||
await this.remoteWebDavStorage.putFile(compDownloadedFilename);
|
||||
} catch (e) {
|
||||
log(LM_ERR, e.stack);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
log(LM_ERR, e.stack);
|
||||
if (e.message == 'abort')
|
||||
@@ -188,6 +211,24 @@ class ReaderWorker {
|
||||
return `file://${hash}`;
|
||||
}
|
||||
|
||||
async restoreRemoteFile(filename) {
|
||||
const basename = path.basename(filename);
|
||||
const targetName = `${this.config.tempPublicDir}/${basename}`;
|
||||
|
||||
if (!await fs.pathExists(targetName)) {
|
||||
let found = false;
|
||||
if (this.remoteWebDavStorage) {
|
||||
found = await this.remoteWebDavStorage.getFileSuccess(targetName);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new Error('404 Файл не найден');
|
||||
}
|
||||
}
|
||||
|
||||
return targetName;
|
||||
}
|
||||
|
||||
restoreCachedFile(filename) {
|
||||
const workerId = this.workerState.generateWorkerId();
|
||||
const wState = this.workerState.getControl(workerId);
|
||||
@@ -197,21 +238,10 @@ class ReaderWorker {
|
||||
try {
|
||||
wState.set({state: 'download', step: 1, totalSteps: 1, path: filename, progress: 0});
|
||||
|
||||
const basename = path.basename(filename);
|
||||
const targetName = `${this.config.tempPublicDir}/${basename}`;
|
||||
|
||||
if (!await fs.pathExists(targetName)) {
|
||||
let found = false;
|
||||
if (this.remoteWebDavStorage) {
|
||||
found = await this.remoteWebDavStorage.getFileSuccess(targetName);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new Error('404 Файл не найден');
|
||||
}
|
||||
}
|
||||
|
||||
const targetName = await this.restoreRemoteFile(filename);
|
||||
const stat = await fs.stat(targetName);
|
||||
|
||||
const basename = path.basename(filename);
|
||||
wState.finish({path: `/tmp/${basename}`, size: stat.size, progress: 100});
|
||||
} catch (e) {
|
||||
if (e.message.indexOf('404') < 0)
|
||||
|
||||
Reference in New Issue
Block a user