Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c9fd7678d | ||
|
|
01313d66b2 | ||
|
|
eaeacbfb1b | ||
|
|
5328998c21 | ||
|
|
ee066c7c4b | ||
|
|
130aebb514 | ||
|
|
dbec1e630e | ||
|
|
583b966616 | ||
|
|
9e509ac845 | ||
|
|
4ea2d8918e | ||
|
|
6667688193 | ||
|
|
30a1629f23 | ||
|
|
ba50faeebb | ||
|
|
3c0d784e3d | ||
|
|
3e75310e1f | ||
|
|
2b01d6d8d7 | ||
|
|
be6d60d7a9 | ||
|
|
3c0815d55b | ||
|
|
abd8584cb8 | ||
|
|
5a910f80b3 | ||
|
|
67bdfd853e | ||
|
|
fc8e986acb | ||
|
|
64539785c2 | ||
|
|
f530455146 | ||
|
|
70dc66e1ae | ||
|
|
3e5894d9e0 | ||
|
|
d7ac9d1bfc | ||
|
|
5160c5fb75 | ||
|
|
d9c7964410 | ||
|
|
110952b4c4 | ||
|
|
ece17dc0dd | ||
|
|
35e1087531 |
@@ -1,11 +1,15 @@
|
||||
import wsc from './webSocketConnection';
|
||||
|
||||
class Misc {
|
||||
async loadConfig() {
|
||||
async loadConfig(_configHash) {
|
||||
|
||||
const query = {params: [
|
||||
'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink',
|
||||
]};
|
||||
const query = {
|
||||
params: [
|
||||
'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter',
|
||||
'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink', 'restricted'
|
||||
],
|
||||
_configHash,
|
||||
};
|
||||
|
||||
const config = await wsc.message(await wsc.send(Object.assign({action: 'get-config'}, query)));
|
||||
if (config.error)
|
||||
|
||||
@@ -154,8 +154,11 @@ class App {
|
||||
(async() => {
|
||||
//загрузим конфиг сервера
|
||||
try {
|
||||
const config = await miscApi.loadConfig();
|
||||
this.commit('config/setConfig', config);
|
||||
const config = await miscApi.loadConfig(this.config._configHash);
|
||||
|
||||
if (!config._useCached)
|
||||
this.commit('config/setConfig', config);
|
||||
|
||||
this.showPage = true;
|
||||
} catch(e) {
|
||||
//проверим, не получен ли конфиг ранее
|
||||
|
||||
@@ -52,18 +52,21 @@ class CopyTextPage {
|
||||
from = (from < 0 ? 0 : from);
|
||||
to = paraIndex + 100;
|
||||
to = (to > parsed.para.length ? parsed.para.length : to);
|
||||
cut = '<p>..... Текст вырезан. Если хотите скопировать больше, поставьте в настройках галочку "Загружать весь текст"';
|
||||
cut = '<dd>..... Текст вырезан. Если хотите скопировать больше, поставьте в настройках галочку "Загружать весь текст"';
|
||||
}
|
||||
|
||||
if (from > 0)
|
||||
text += cut;
|
||||
for (let i = from; i < to; i++) {
|
||||
const p = parsed.para[i];
|
||||
if (p.addIndex > 0)
|
||||
continue;
|
||||
|
||||
const parts = parsed.splitToStyle(p.text);
|
||||
if (this.stopInit)
|
||||
return;
|
||||
|
||||
text += `<p id="p${i}" class="copyPara">`;
|
||||
text += `<dd id="p${i}" class="copyPara"> `;
|
||||
for (const part of parts)
|
||||
text += part.text;
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ const tabs = [
|
||||
['MouseHelpPage', 'Мышь/тачскрин'],
|
||||
['HotkeysHelpPage', 'Клавиатура'],
|
||||
['VersionHistoryPage', 'История версий'],
|
||||
['DonateHelpPage', 'Помочь проекту'],
|
||||
//['DonateHelpPage', 'Помочь проекту'],
|
||||
];
|
||||
|
||||
const componentOptions = {
|
||||
|
||||
@@ -770,6 +770,10 @@ class Reader {
|
||||
return this.$store.state.config.bucEnabled && this.bucEnabled;
|
||||
}
|
||||
|
||||
get restricted() {
|
||||
return this.$store.state.config.restricted;
|
||||
}
|
||||
|
||||
get routeParamUrl() {
|
||||
let result = '';
|
||||
const path = this.$route.fullPath;
|
||||
@@ -1263,6 +1267,19 @@ class Reader {
|
||||
return result;
|
||||
}
|
||||
|
||||
isUrlAllowed(url) {
|
||||
const restrictedSites = this.restricted?.sites;
|
||||
if (restrictedSites) {
|
||||
url = url.toLowerCase();
|
||||
for (const site of restrictedSites) {
|
||||
if (url.indexOf(site) === 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async _loadBook(opts) {
|
||||
if (!opts || !opts.url) {
|
||||
this.mostRecentBook();
|
||||
@@ -1273,6 +1290,11 @@ class Reader {
|
||||
|
||||
let url = encodeURI(decodeURI(opts.url));
|
||||
|
||||
if (!this.isUrlAllowed(url)) {
|
||||
this.$root.stdDialog.alert('Книга не загружена, причина: нарушение авторских прав.<br>Приносим извинения за неудобство.', '', {color: 'negative'});
|
||||
return;
|
||||
}
|
||||
|
||||
if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) &&
|
||||
(url.indexOf('disk://') != 0))
|
||||
url = 'http://' + url;
|
||||
|
||||
@@ -131,7 +131,7 @@ class ReaderDialogs {
|
||||
|
||||
async init() {
|
||||
await this.showWhatsNew();
|
||||
await this.showDonation();
|
||||
//await this.showDonation();
|
||||
}
|
||||
|
||||
loadSettings() {
|
||||
|
||||
@@ -594,7 +594,7 @@ class RecentBooksPage {
|
||||
}
|
||||
|
||||
async handleDel(item) {
|
||||
if (item.group) {
|
||||
if (item.group?.length) {
|
||||
const keys = [{key: item.key}];
|
||||
for (const book of item.group)
|
||||
keys.push({key: book.key});
|
||||
@@ -615,14 +615,14 @@ class RecentBooksPage {
|
||||
} else {
|
||||
if (await this.$root.stdDialog.confirm('Подтвердите удаление книги из архива:', ' ')) {
|
||||
await bookManager.delRecentBooks([{key: item.key}], 2);
|
||||
this.$root.notify.info('Книга удалено безвозвратно');
|
||||
this.$root.notify.info('Книга удалена безвозвратно');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleRestore(item) {
|
||||
if (item.group) {
|
||||
if (item.group?.length) {
|
||||
const keys = [{key: item.key}];
|
||||
for (const book of item.group)
|
||||
keys.push({key: book.key});
|
||||
@@ -637,7 +637,7 @@ class RecentBooksPage {
|
||||
|
||||
async loadBook(item, force = false) {
|
||||
if (item.deleted)
|
||||
await this.handleRestore(item.key);
|
||||
await this.handleRestore(item);
|
||||
|
||||
this.$emit('load-book', {url: item.url, path: item.path, force});
|
||||
this.close();
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</q-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="sets-item row">
|
||||
<!--div class="sets-item row">
|
||||
<div class="sets-label label">
|
||||
Уведомление
|
||||
</div>
|
||||
@@ -63,7 +63,7 @@
|
||||
Показывать диалог для сбора пожертвований
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<!---------------------------------------------->
|
||||
<div class="sets-part-header">
|
||||
|
||||
@@ -14,6 +14,11 @@ export default class DrawHelper {
|
||||
return this.context.measureText(text).width;
|
||||
}
|
||||
|
||||
measureTextMetrics(text, style) {// eslint-disable-line no-unused-vars
|
||||
this.context.font = this.fontByStyle(style);
|
||||
return this.context.measureText(text);
|
||||
}
|
||||
|
||||
measureTextFont(text, font) {// eslint-disable-line no-unused-vars
|
||||
this.context.font = font;
|
||||
return this.context.measureText(text).width;
|
||||
@@ -39,7 +44,6 @@ export default class DrawHelper {
|
||||
let center = false;
|
||||
let space = 0;
|
||||
let j = 0;
|
||||
const pad = this.fontSize/2;
|
||||
//формируем строку
|
||||
for (const part of line.parts) {
|
||||
let tOpen = '';
|
||||
@@ -47,10 +51,20 @@ export default class DrawHelper {
|
||||
tOpen += (part.style.italic ? '<i>' : '');
|
||||
tOpen += (part.style.sup ? '<span style="vertical-align: baseline; position: relative; line-height: 0; top: -0.3em">' : '');
|
||||
tOpen += (part.style.sub ? '<span style="vertical-align: baseline; position: relative; line-height: 0; top: 0.3em">' : '');
|
||||
tOpen += (part.style.note ? `<span style="position: relative;">` +
|
||||
`<span style="position: absolute; background-color: ${this.textColor}; opacity: 0.1; cursor: pointer; pointer-events: auto; ` +
|
||||
`height: ${this.fontSize + pad*2}px; padding: ${pad}px; left: -${pad}px; top: -${pad*0.9}px; border-radius: ${this.fontSize}px;" ` +
|
||||
`onclick="onNoteClickLiberama('${part.style.note.id}', ${part.style.note.orig ? 1 : 0})"><span style="visibility: hidden;">__TEXT</span></span>` : '');
|
||||
if (part.style.note) {
|
||||
const t = part.text;
|
||||
const m = this.measureTextMetrics(t, part.style);
|
||||
const d = this.fontSize - 1.1*m.fontBoundingBoxAscent;
|
||||
const w = m.width;
|
||||
const size = (this.fontSize > 18 ? this.fontSize : 18);
|
||||
const pad = size/2;
|
||||
const btnW = (w >= size ? w : size) + pad*2;
|
||||
|
||||
tOpen += `<span style="position: relative;">` +
|
||||
`<span style="position: absolute; background-color: ${this.textColor}; opacity: 0.1; cursor: pointer; pointer-events: auto; ` +
|
||||
`height: ${this.fontSize + pad*2}px; padding: ${pad}px; left: -${(btnW - w)/2 - pad*0.05}px; top: -${pad + d}px; width: ${btnW}px; border-radius: ${size}px;" ` +
|
||||
`onclick="onNoteClickLiberama('${part.style.note.id}', ${part.style.note.orig ? 1 : 0})"><span style="visibility: hidden;" class="dborder">${t}</span></span>`;
|
||||
}
|
||||
let tClose = '';
|
||||
tClose += (part.style.note ? '</span>' : '');
|
||||
tClose += (part.style.sub ? '</span>' : '');
|
||||
@@ -70,9 +84,6 @@ export default class DrawHelper {
|
||||
if (text && text.trim() == '')
|
||||
text = `<span style="white-space: pre">${text}</span>`;
|
||||
|
||||
if (part.style.note)
|
||||
tOpen = tOpen.replace('__TEXT', text);
|
||||
|
||||
lineText += `${tOpen}${text}${tClose}`;
|
||||
|
||||
center = center || part.style.center;
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
<div @copy.prevent="copyText" v-html="page2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="showStatusBar" ref="statusBar" class="layout">
|
||||
<div v-show="showStatusBar" ref="statusBar" class="layout" :class="{'no-events': clickControl}">
|
||||
<div v-html="statusBar"></div>
|
||||
</div>
|
||||
<div
|
||||
v-show="clickControl" ref="layoutEvents" class="layout events"
|
||||
oncontextmenu="return false;"
|
||||
@mousedown.prevent.stop="onMouseDown" @mouseup.prevent.stop="onMouseUp"
|
||||
@mouseover.prevent.stop="onMouseEvent" @mouseout.prevent.stop="onMouseEvent" @mousemove.prevent.stop="onMouseEvent"
|
||||
@wheel.prevent.stop="onMouseWheel"
|
||||
@touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove" @touchcancel.prevent.stop="onTouchCancel"
|
||||
>
|
||||
@@ -38,9 +39,9 @@
|
||||
|
||||
<!-- Примечание -->
|
||||
<Dialog ref="dialog1" v-model="noteDialogVisible">
|
||||
<!--template #header>
|
||||
Примечание
|
||||
</template-->
|
||||
<template #header>
|
||||
{{ noteTitle }}
|
||||
</template>
|
||||
|
||||
<div class="column col" style="line-height: 20px; max-width: 400px; max-height: 200px; overflow-x: hidden; overflow-y: auto">
|
||||
<div v-html="noteHtml"></div>
|
||||
@@ -49,7 +50,7 @@
|
||||
<template #footer>
|
||||
<div class="row col">
|
||||
<q-btn class="q-px-md q-mr-md" color="btn2" text-color="app" dense no-caps @click="goToNotes">
|
||||
В примечаниях
|
||||
В примечания
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
@@ -148,6 +149,7 @@ class TextPage {
|
||||
|
||||
noteDialogVisible = false;
|
||||
noteId = '';
|
||||
noteTitle = '';
|
||||
noteHtml = '';
|
||||
|
||||
created() {
|
||||
@@ -1072,6 +1074,7 @@ class TextPage {
|
||||
if (this.startTouch) {
|
||||
event.preventDefault();
|
||||
}
|
||||
this.endClickRepeat();
|
||||
}
|
||||
|
||||
onTouchEnd(event) {
|
||||
@@ -1156,6 +1159,9 @@ class TextPage {
|
||||
onMouseWheel(event) {
|
||||
if (this.$root.isMobileDevice)
|
||||
return;
|
||||
|
||||
this.endClickRepeat();
|
||||
|
||||
if (event.deltaY > 0) {
|
||||
this.doDown();
|
||||
} else if (event.deltaY < 0) {
|
||||
@@ -1163,6 +1169,12 @@ class TextPage {
|
||||
}
|
||||
}
|
||||
|
||||
onMouseEvent() {
|
||||
if (this.$root.isMobileDevice)
|
||||
return;
|
||||
this.endClickRepeat();
|
||||
}
|
||||
|
||||
onStatusBarClick() {
|
||||
const url = this.meta.url;
|
||||
if (url && url.indexOf('disk://') != 0) {
|
||||
@@ -1271,6 +1283,7 @@ class TextPage {
|
||||
if (note) {
|
||||
if (orig) {//show dialog
|
||||
this.noteId = noteId;
|
||||
this.noteTitle = `[${note.title?.trim()}]`;
|
||||
this.noteHtml = note.xml
|
||||
.replace(/<p>/g, '<p class="note-para">')
|
||||
.replace(/<stanza>/g, '<br>').replace(/<\/stanza>/g, '')
|
||||
@@ -1340,6 +1353,9 @@ export default vueComponent(TextPage);
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
.no-events {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.note-para {
|
||||
|
||||
@@ -402,17 +402,6 @@ export default class BookParser {
|
||||
bodyIndex++;
|
||||
}
|
||||
|
||||
if (tag == 'title') {
|
||||
newParagraph();
|
||||
isFirstTitlePara = true;
|
||||
bold = true;
|
||||
center = true;
|
||||
|
||||
inTitle = true;
|
||||
curTitle = {paraIndex, title: '', inset: sectionLevel, bodyIndex, subtitles: []};
|
||||
this.contents.push(curTitle);
|
||||
}
|
||||
|
||||
if (tag == 'section') {
|
||||
if (!isFirstSection)
|
||||
newParagraph();
|
||||
@@ -431,12 +420,24 @@ export default class BookParser {
|
||||
|
||||
note.noteParaIndex = paraIndex;
|
||||
note.xml = '';
|
||||
note.title = '';
|
||||
noteId = id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (tag == 'title') {
|
||||
newParagraph();
|
||||
isFirstTitlePara = true;
|
||||
bold = true;
|
||||
center = true;
|
||||
|
||||
inTitle = true;
|
||||
curTitle = {paraIndex, title: '', inset: sectionLevel, bodyIndex, subtitles: []};
|
||||
this.contents.push(curTitle);
|
||||
}
|
||||
|
||||
if (tag == 'emphasis' || tag == 'strong' || tag == 'sup' || tag == 'sub') {
|
||||
growParagraph(`<${tag}>`, 0);
|
||||
}
|
||||
@@ -642,8 +643,12 @@ export default class BookParser {
|
||||
else
|
||||
growParagraph(' ', 1);
|
||||
|
||||
if (!inTitle && inNotesBody && noteId) {
|
||||
this.notes[noteId].xml += text;
|
||||
if (inNotesBody && noteId) {
|
||||
if (inTitle) {
|
||||
this.notes[noteId].title += text;
|
||||
} else {
|
||||
this.notes[noteId].xml += text;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,74 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
version: '1.2.8',
|
||||
releaseDate: '2025-06-04',
|
||||
showUntil: '2025-06-03',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправление багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.2.7',
|
||||
releaseDate: '2025-02-22',
|
||||
showUntil: '2025-02-21',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>отключена форма для сбора донатов</li>
|
||||
<li>мелкие оптимизации</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.2.6',
|
||||
releaseDate: '2024-10-03',
|
||||
showUntil: '2024-10-02',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправления из-за нарушения авторских прав</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.2.4',
|
||||
releaseDate: '2024-08-27',
|
||||
showUntil: '2024-08-26',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправление багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.2.3',
|
||||
releaseDate: '2024-08-02',
|
||||
showUntil: '2024-08-01',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправление багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '1.2.2',
|
||||
releaseDate: '2024-07-28',
|
||||
showUntil: '2024-08-04',
|
||||
showUntil: '2024-07-27',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import miscApi from '../../api/misc';
|
||||
// initial state
|
||||
const state = {
|
||||
name: null,
|
||||
|
||||
16
package-lock.json
generated
16
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "liberama",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.6",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "liberama",
|
||||
"version": "1.2.0",
|
||||
"version": "1.2.6",
|
||||
"hasInstallScript": true,
|
||||
"license": "CC0-1.0",
|
||||
"dependencies": {
|
||||
@@ -3364,9 +3364,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001643",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
|
||||
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==",
|
||||
"version": "1.0.30001700",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
|
||||
"integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -13709,9 +13709,9 @@
|
||||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001643",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz",
|
||||
"integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==",
|
||||
"version": "1.0.30001700",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
|
||||
"integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "liberama",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.8",
|
||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
"repository": "bookpauk/liberama",
|
||||
|
||||
@@ -18,7 +18,8 @@ module.exports = {
|
||||
|
||||
useExternalBookConverter: false,
|
||||
acceptFileExt: '.fb2, .fb3, .html, .txt, .zip, .bz2, .gz, .rar, .epub, .mobi, .rtf, .doc, .docx, .pdf, .djvu, .jpg, .jpeg, .png',
|
||||
webConfigParams: ['name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink'],
|
||||
restricted: {},
|
||||
webConfigParams: ['name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'acceptFileExt', 'bucEnabled', 'branch', 'networkLibraryLink', 'restricted'],
|
||||
|
||||
jembaDb: [
|
||||
{
|
||||
|
||||
@@ -56,6 +56,7 @@ class ConfigManager {
|
||||
|
||||
await fs.ensureDir(config.dataDir);
|
||||
this._userConfigFile = `${config.dataDir}/config.json`;
|
||||
this._restrictedFile = `${config.dataDir}/restricted.json`;
|
||||
this._config = config;
|
||||
|
||||
this.inited = true;
|
||||
@@ -75,6 +76,10 @@ class ConfigManager {
|
||||
return this._userConfigFile;
|
||||
}
|
||||
|
||||
get restrictedFile() {
|
||||
return this._restrictedFile;
|
||||
}
|
||||
|
||||
set userConfigFile(value) {
|
||||
if (value)
|
||||
this._userConfigFile = value;
|
||||
@@ -100,6 +105,12 @@ class ConfigManager {
|
||||
} else {
|
||||
await this.save();
|
||||
}
|
||||
|
||||
if (await fs.pathExists(this.restrictedFile)) {
|
||||
const data = JSON.parse(await fs.readFile(this.restrictedFile, 'utf8'));
|
||||
|
||||
this.config = {restricted: data};
|
||||
}
|
||||
} catch(e) {
|
||||
throw new Error(`Error while loading "${this.userConfigFile}": ${e.message}`);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ class WebSocketController {
|
||||
this.readerWorker = new ReaderWorker(config);
|
||||
this.workerState = new WorkerState();
|
||||
|
||||
this.configHash = '';
|
||||
|
||||
if (config.bucEnabled) {
|
||||
this.bucClient = new BUCClient(config);
|
||||
}
|
||||
@@ -119,8 +121,22 @@ class WebSocketController {
|
||||
async getConfig(req, ws) {
|
||||
if (Array.isArray(req.params)) {
|
||||
const paramsSet = new Set(req.params);
|
||||
const _configHash = req._configHash;
|
||||
|
||||
this.send(_.pick(this.config, this.config.webConfigParams.filter(x => paramsSet.has(x))), req, ws);
|
||||
let response = {_useCached: true};
|
||||
|
||||
//оптимизация, чтобы не отдавал большой конфиг каждый раз при обновлении страницы
|
||||
if (!_configHash || _configHash !== this.configHash) {
|
||||
if (!this.configHash) {
|
||||
const webConfig = _.pick(this.config, this.config.webConfigParams);
|
||||
this.configHash = await utils.getBufHash(Buffer.from(JSON.stringify(webConfig)), 'sha256', 'hex');
|
||||
}
|
||||
|
||||
response = _.pick(this.config, this.config.webConfigParams.filter(x => paramsSet.has(x)));
|
||||
response._configHash = this.configHash;
|
||||
}
|
||||
|
||||
this.send(response, req, ws);
|
||||
} else {
|
||||
throw new Error('params is not an array');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user