Compare commits
34 Commits
0.12.0-2
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9809e6661 | ||
|
|
083151460a | ||
|
|
c8f97ef386 | ||
|
|
c9a22a5eaf | ||
|
|
f926732070 | ||
|
|
3fbe6e9d9b | ||
|
|
225230381f | ||
|
|
b58d3a1b8b | ||
|
|
ffedce4351 | ||
|
|
a4fdb67913 | ||
|
|
6ba46421b9 | ||
|
|
d201961046 | ||
|
|
614a7f9da7 | ||
|
|
113ab3e596 | ||
|
|
c95870bfe5 | ||
|
|
e69e9335f9 | ||
|
|
fd21cd77dd | ||
|
|
d1880acaf9 | ||
|
|
428b507257 | ||
|
|
043dab0731 | ||
|
|
a7b4d9c0d8 | ||
|
|
6f9c95e351 | ||
|
|
7a53063ea8 | ||
|
|
ec4d5cac4f | ||
|
|
f8557cba88 | ||
|
|
5dead039f5 | ||
|
|
ea38392df4 | ||
|
|
0cc9d90a94 | ||
|
|
8c7b86c458 | ||
|
|
0e29546fc5 | ||
|
|
c9fa90d07c | ||
|
|
7d8e0525b1 | ||
|
|
ddf69876a6 | ||
|
|
1d78e75e38 |
86
README.md
86
README.md
@@ -1,43 +1,43 @@
|
||||
# Liberama
|
||||
|
||||
Браузерная онлайн-читалка книг и децентрализованная библиотека.
|
||||
|
||||
Читалка <img src="https://omnireader.ru/favicon.ico" width="14px"/>[OmniReader](https://omnireader.ru) является частью данного проекта, размещенной на VPS:
|
||||
|
||||

|
||||

|
||||
|
||||
## VPS
|
||||
Для разворачивания читалки на чистом VPS с нуля смотрите [docs/omnireader.ru](docs/omnireader.ru/README.md)
|
||||
|
||||
## Сборка проекта
|
||||
Необходима версия node.js не ниже 14.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/bookpauk/liberama
|
||||
$ cd liberama
|
||||
$ npm i
|
||||
```
|
||||
|
||||
### Windows
|
||||
```
|
||||
$ npm run build:win
|
||||
```
|
||||
|
||||
### Linux
|
||||
```
|
||||
$ npm run build:linux
|
||||
```
|
||||
|
||||
Результат сборки будет доступен в каталоге `dist/linux|win` в виде исполнимого (standalone) файла
|
||||
|
||||
### Разработка
|
||||
```
|
||||
$ npm run dev
|
||||
```
|
||||
|
||||
## Помочь проекту
|
||||
|
||||
* bitcoin: 3EbgZ7MK1UVaN38Gty5DCBtS4PknM4Ut85
|
||||
* litecoin: MP39Riec4oSNB3XMjiquKoLWxbufRYNXxZ
|
||||
* monero: 8BQPnvHcPSHM5gMQsmuypDgx9NNsYqwXKfDDuswEyF2Q2ewQSfd2pkK6ydH2wmMyq2JViZvy9DQ35hLMx7g72mFWNJTPtnz
|
||||
# Liberama
|
||||
|
||||
Браузерная онлайн-читалка книг и децентрализованная библиотека.
|
||||
|
||||
Читалка <img src="https://omnireader.ru/favicon.ico" width="14px"/>[OmniReader](https://omnireader.ru) является частью данного проекта, размещенной на VPS:
|
||||
|
||||

|
||||

|
||||
|
||||
## VPS
|
||||
Для разворачивания читалки на чистом VPS с нуля смотрите [docs/omnireader.ru](docs/omnireader.ru/README.md)
|
||||
|
||||
## Сборка проекта
|
||||
Необходима версия node.js не ниже 14.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/bookpauk/liberama
|
||||
$ cd liberama
|
||||
$ npm i
|
||||
```
|
||||
|
||||
### Windows
|
||||
```
|
||||
$ npm run build:win
|
||||
```
|
||||
|
||||
### Linux
|
||||
```
|
||||
$ npm run build:linux
|
||||
```
|
||||
|
||||
Результат сборки будет доступен в каталоге `dist/linux|win` в виде исполнимого (standalone) файла
|
||||
|
||||
### Разработка
|
||||
```
|
||||
$ npm run dev
|
||||
```
|
||||
|
||||
## Помочь проекту
|
||||
|
||||
* bitcoin: bc1q3tyumaj648pp2e69jalsez2lnt462ttc33nup9
|
||||
* litecoin: MP39Riec4oSNB3XMjiquKoLWxbufRYNXxZ
|
||||
* monero: 8BQPnvHcPSHM5gMQsmuypDgx9NNsYqwXKfDDuswEyF2Q2ewQSfd2pkK6ydH2wmMyq2JViZvy9DQ35hLMx7g72mFWNJTPtnz
|
||||
|
||||
@@ -14,6 +14,7 @@ module.exports = {
|
||||
entry: [`${clientDir}/main.js`],
|
||||
output: {
|
||||
publicPath: '/app/',
|
||||
clean: true
|
||||
},
|
||||
|
||||
module: {
|
||||
|
||||
@@ -16,7 +16,8 @@ module.exports = merge(baseWpConfig, {
|
||||
devtool: 'inline-source-map',
|
||||
output: {
|
||||
path: `${publicDir}/app`,
|
||||
filename: 'bundle.js'
|
||||
filename: 'bundle.js',
|
||||
clean: true
|
||||
},
|
||||
|
||||
module: {
|
||||
@@ -38,6 +39,6 @@ module.exports = merge(baseWpConfig, {
|
||||
template: `${clientDir}/index.html.template`,
|
||||
filename: `${publicDir}/index.html`
|
||||
}),
|
||||
new CopyWebpackPlugin({patterns: [{from: `${clientDir}/assets/*`, to: `${publicDir}/`}]})
|
||||
new CopyWebpackPlugin({patterns: [{context: `${clientDir}/assets`, from: `${clientDir}/assets/*`, to: `${publicDir}/`}]})
|
||||
]
|
||||
});
|
||||
|
||||
@@ -18,7 +18,8 @@ module.exports = merge(baseWpConfig, {
|
||||
mode: 'production',
|
||||
output: {
|
||||
path: `${publicDir}/app_new`,
|
||||
filename: 'bundle.[contenthash].js'
|
||||
filename: 'bundle.[contenthash].js',
|
||||
clean: true
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
@@ -54,7 +55,7 @@ module.exports = merge(baseWpConfig, {
|
||||
filename: `${publicDir}/index.html`
|
||||
}),
|
||||
new CopyWebpackPlugin({patterns:
|
||||
[{from: `${clientDir}/assets/*`, to: `${publicDir}/`, context: `${clientDir}/assets` }]
|
||||
[{context: `${clientDir}/assets`, from: `${clientDir}/assets/*`, to: `${publicDir}/` }]
|
||||
}),
|
||||
new GenerateSW({
|
||||
cacheId: 'liberama',
|
||||
|
||||
@@ -238,7 +238,7 @@ class App {
|
||||
const url = s[1] || '';
|
||||
const q = utils.parseQuery(s[0] || '');
|
||||
if (url) {
|
||||
q.url = decodeURIComponent(url);
|
||||
q.url = url;
|
||||
}
|
||||
|
||||
window.history.replaceState({}, '', '/');
|
||||
@@ -271,6 +271,10 @@ body, html, #app {
|
||||
font: normal 12pt ReaderDefault;
|
||||
}
|
||||
|
||||
.notify-margin {
|
||||
margin-top: 55px;
|
||||
}
|
||||
|
||||
.dborder {
|
||||
border: 2px solid magenta !important;
|
||||
}
|
||||
|
||||
@@ -1,70 +1,17 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="box">
|
||||
<div class="column items-center" style="width: 500px">
|
||||
<p class="p">
|
||||
Вы можете пожертвовать на развитие проекта любую сумму:
|
||||
Здесь вы можете пожертвовать на развитие проекта:
|
||||
</p>
|
||||
<div class="address">
|
||||
<img class="logo" src="./assets/yoomoney.png">
|
||||
<q-btn class="q-ml-sm q-px-sm" dense no-caps @click="donateYooMoney">
|
||||
Пожертвовать
|
||||
</q-btn><br>
|
||||
<div class="para">
|
||||
{{ yooAddress }}
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyAddress(yooAddress, 'Кошелёк ЮMoney')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--div class="address">
|
||||
<img class="logo" src="./assets/paypal.png">
|
||||
<div class="para">
|
||||
{{ paypalAddress }}
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyAddress(paypalAddress, 'Paypal-адрес')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
</div-->
|
||||
<q-btn no-caps class="q-my-lg" color="green-8" size="14px" style="width: 200px" @click="makeDonation">
|
||||
<q-icon class="q-mr-xs" name="la la-donate" size="24px" />
|
||||
Поддержать проект
|
||||
</q-btn>
|
||||
|
||||
<div class="address">
|
||||
<img class="logo" src="./assets/bitcoin.png">
|
||||
<div class="para">
|
||||
{{ bitcoinAddress }}
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyAddress(bitcoinAddress, 'Bitcoin-адрес')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="address">
|
||||
<img class="logo" src="./assets/litecoin.png">
|
||||
<div class="para">
|
||||
{{ litecoinAddress }}
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyAddress(litecoinAddress, 'Litecoin-адрес')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="address">
|
||||
<img class="logo" src="./assets/monero.png">
|
||||
<div class="para">
|
||||
{{ moneroAddress }}
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyAddress(moneroAddress, 'Monero-адрес')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
</div>
|
||||
<div style="font-size: 60%">
|
||||
* Ваш донат является подарком автору проекта
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,28 +21,14 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
import vueComponent from '../../../vueComponent.js';
|
||||
|
||||
import {copyTextToClipboard} from '../../../../share/utils';
|
||||
import * as utils from '../../../../share/utils';
|
||||
|
||||
class DonateHelpPage {
|
||||
yooAddress = '410018702323056';
|
||||
paypalAddress = 'bookpauk@gmail.com';
|
||||
bitcoinAddress = '3EbgZ7MK1UVaN38Gty5DCBtS4PknM4Ut85';
|
||||
litecoinAddress = 'MP39Riec4oSNB3XMjiquKoLWxbufRYNXxZ';
|
||||
moneroAddress = '8BQPnvHcPSHM5gMQsmuypDgx9NNsYqwXKfDDuswEyF2Q2ewQSfd2pkK6ydH2wmMyq2JViZvy9DQ35hLMx7g72mFWNJTPtnz';
|
||||
|
||||
created() {
|
||||
}
|
||||
|
||||
donateYooMoney() {
|
||||
window.open(`https://yoomoney.ru/to/${this.yooAddress}`, '_blank');
|
||||
}
|
||||
|
||||
async copyAddress(address, prefix) {
|
||||
const result = await copyTextToClipboard(address);
|
||||
if (result)
|
||||
this.$root.notify.success(`${prefix} ${address} успешно скопирован в буфер обмена`);
|
||||
else
|
||||
this.$root.notify.error('Копирование не удалось');
|
||||
makeDonation() {
|
||||
utils.makeDonation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,31 +49,4 @@ export default vueComponent(DonateHelpPage);
|
||||
padding: 0;
|
||||
text-indent: 20px;
|
||||
}
|
||||
|
||||
.box {
|
||||
max-width: 550px;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.address {
|
||||
padding-top: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.para {
|
||||
margin: 10px 10px 10px 40px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 130px;
|
||||
position: relative;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
font-size: 120%;
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.8 KiB |
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Window @close="close">
|
||||
<Window @close="close" style="z-index: 200">
|
||||
<template #header>
|
||||
Справка
|
||||
</template>
|
||||
@@ -36,14 +36,14 @@ import CommonHelpPage from './CommonHelpPage/CommonHelpPage.vue';
|
||||
import HotkeysHelpPage from './HotkeysHelpPage/HotkeysHelpPage.vue';
|
||||
import MouseHelpPage from './MouseHelpPage/MouseHelpPage.vue';
|
||||
import VersionHistoryPage from './VersionHistoryPage/VersionHistoryPage.vue';
|
||||
//import DonateHelpPage from './DonateHelpPage/DonateHelpPage.vue';
|
||||
import DonateHelpPage from './DonateHelpPage/DonateHelpPage.vue';
|
||||
|
||||
const pages = {
|
||||
'CommonHelpPage': CommonHelpPage,
|
||||
'HotkeysHelpPage': HotkeysHelpPage,
|
||||
'MouseHelpPage': MouseHelpPage,
|
||||
'VersionHistoryPage': VersionHistoryPage,
|
||||
//'DonateHelpPage': DonateHelpPage,
|
||||
'DonateHelpPage': DonateHelpPage,
|
||||
};
|
||||
|
||||
const tabs = [
|
||||
@@ -51,7 +51,7 @@ const tabs = [
|
||||
['MouseHelpPage', 'Мышь/тачскрин'],
|
||||
['HotkeysHelpPage', 'Клавиатура'],
|
||||
['VersionHistoryPage', 'История версий'],
|
||||
//['DonateHelpPage', 'Помочь проекту'],
|
||||
['DonateHelpPage', 'Помочь проекту'],
|
||||
];
|
||||
|
||||
const componentOptions = {
|
||||
@@ -80,7 +80,7 @@ class HelpPage {
|
||||
}
|
||||
|
||||
activateDonateHelpPage() {
|
||||
//this.selectedTab = 'DonateHelpPage';
|
||||
this.selectedTab = 'DonateHelpPage';
|
||||
}
|
||||
|
||||
activateVersionHistoryHelpPage() {
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="col column justify-end items-center no-wrap overflow-hidden">
|
||||
<span v-if="mode == 'omnireader'" class="bottom-span clickable" @click="findBook">Найти книгу</span>
|
||||
<span class="bottom-span clickable" @click="openHelp">Справка</span>
|
||||
<!--span class="bottom-span clickable" @click="openDonate">Помочь проекту</span-->
|
||||
<span class="bottom-span clickable" @click="openDonate">Помочь проекту</span>
|
||||
|
||||
<span v-if="version == clientVersion" class="bottom-span">v{{ version }}</span>
|
||||
<span v-else class="bottom-span">Версия сервера {{ version }}, версия клиента {{ clientVersion }}, необходимо обновить страницу</span>
|
||||
|
||||
@@ -292,7 +292,6 @@ class Reader {
|
||||
libsActive = false;
|
||||
recentBooksActive = false;
|
||||
clickControlActive = false;
|
||||
offlineModeActive = false;
|
||||
settingsActive = false;
|
||||
|
||||
clickMapActive = false;
|
||||
@@ -721,7 +720,7 @@ class Reader {
|
||||
return;
|
||||
const recent = this.mostRecentBook();
|
||||
const pos = (recent && recent.bookPos && this.allowUrlParamBookPos ? `__p=${recent.bookPos}&` : '');
|
||||
const url = (recent ? `url=${recent.url}` : '');
|
||||
const url = (recent ? `url=${encodeURIComponent(recent.url)}` : '');
|
||||
if (isNewRoute)
|
||||
this.$router.push(`/reader?${pos}${url}`).catch(() => {});
|
||||
else
|
||||
@@ -807,6 +806,10 @@ class Reader {
|
||||
return this.reader.toolBarActive;
|
||||
}
|
||||
|
||||
get offlineModeActive() {
|
||||
return this.reader.offlineModeActive;
|
||||
}
|
||||
|
||||
mostRecentBook() {
|
||||
const result = bookManager.mostRecentBook();
|
||||
this.mostRecentBookReactive = result;
|
||||
@@ -1019,7 +1022,7 @@ class Reader {
|
||||
}
|
||||
|
||||
offlineModeToggle() {
|
||||
this.offlineModeActive = !this.offlineModeActive;
|
||||
this.commit('reader/setOfflineModeActive', !this.offlineModeActive);
|
||||
this.$refs.serverStorage.offlineModeActive = this.offlineModeActive;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,56 +18,51 @@
|
||||
</template>
|
||||
</Dialog>
|
||||
|
||||
<Dialog ref="dialog2" v-model="donationVisible">
|
||||
<template #header>
|
||||
Здравствуйте, уважаемые читатели!
|
||||
</template>
|
||||
<q-dialog ref="dialog2" v-model="donationVisible" style="z-index: 100" no-route-dismiss no-esc-dismiss no-backdrop-dismiss>
|
||||
<div class="column bg-white no-wrap q-pa-md">
|
||||
<div class="row justify-center q-mb-md" style="font-size: 110%">
|
||||
Здравствуйте, дорогие читатели!
|
||||
</div>
|
||||
|
||||
<div style="word-break: normal">
|
||||
Стартовала ежегодная акция "Оплатим хостинг вместе".<br><br>
|
||||
<div class="q-mx-md column" style="word-break: normal">
|
||||
<div>
|
||||
Вот уже много лет мы все вместе пользуемся нашей любимой читалкой.<br><br>
|
||||
|
||||
Для оплаты годового хостинга читалки, необходимо собрать около 2000 рублей.
|
||||
В настоящий момент у автора эта сумма есть в наличии. Однако будет справедливо, если каждый
|
||||
сможет проголосовать рублем за то, чтобы читалка так и оставалась:
|
||||
Напоминаем вам, что проект является некоммерческим и обладает такими
|
||||
достоинствами, как:
|
||||
|
||||
<ul>
|
||||
<li>непрерывно улучшаемой</li>
|
||||
<li>без рекламы</li>
|
||||
<li>без регистрации</li>
|
||||
<li>Open Source</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>все функции читалки открыты и доступны совершенно бесплатно</li>
|
||||
<li>в проекте отсутствует какая-либо реклама или баннеры</li>
|
||||
<li>нет никакой регистрации и монетизации</li>
|
||||
<li>нет сбора персональных данных</li>
|
||||
<li>открытый исходный код</li>
|
||||
<li>проект постепенно улучшается, по мере возможности</li>
|
||||
</ul>
|
||||
|
||||
Автор также обращается с просьбой о помощи в распространении
|
||||
<a href="https://omnireader.ru" target="_blank">ссылки</a>
|
||||
<q-icon class="copy-icon" name="la la-copy" @click="copyLink('https://omnireader.ru')">
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="center middle" content-style="font-size: 80%">
|
||||
Скопировать
|
||||
</q-tooltip>
|
||||
</q-icon>
|
||||
на читалку через тематические форумы, соцсети, мессенджеры и пр.
|
||||
Чем нас больше, тем легче оставаться на плаву и тем больше мотивации у разработчика, чтобы продолжать работать над проектом.
|
||||
Однако на оплату хостинга читалки и сервера обновлений автор тратит свои
|
||||
собственные средства, а также тратит свое время и силы на улучшение проекта.
|
||||
<br><br>
|
||||
Поддержим же материально наш ресурс, чтобы и дальше спокойно существовать и развиваться:
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
Если соберется бóльшая сумма, то разработка децентрализованной библиотеки для свободного обмена книгами будет по возможности ускорена.
|
||||
<br><br>
|
||||
P.S. При необходимости можно воспользоваться подходящим обменником на <a href="https://www.bestchange.ru" target="_blank">bestchange.ru</a>
|
||||
<q-btn style="margin: 10px 50px 10px 50px" color="green-8" size="14px" no-caps @click="makeDonation">
|
||||
<q-icon class="q-mr-xs" name="la la-donate" size="24px" />
|
||||
Поддержать проект
|
||||
</q-btn>
|
||||
|
||||
<br><br>
|
||||
<div class="row justify-center">
|
||||
<!--q-btn class="q-px-sm" color="primary" dense no-caps @click="openDonate">
|
||||
Помочь проекту
|
||||
</q-btn-->
|
||||
<q-btn style="margin: 0 50px 20px 50px" size="14px" no-caps @click="donationDialogRemind">
|
||||
Напомнить в следующем месяце
|
||||
</q-btn>
|
||||
|
||||
<div class="row justify-center">
|
||||
<div class="q-px-sm clickable" style="font-size: 80%" @click="openDonate">
|
||||
Помочь проекту можно в любое время
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="clickable row justify-end" style="font-size: 60%; color: grey" @click="donationDialogDisable">Больше не показывать</span>
|
||||
<br>
|
||||
<q-btn class="q-px-sm" dense no-caps @click="donationDialogRemind">
|
||||
Напомнить позже
|
||||
</q-btn>
|
||||
</template>
|
||||
</Dialog>
|
||||
</q-dialog>
|
||||
|
||||
<Dialog ref="dialog3" v-model="urlHelpVisible">
|
||||
<template #header>
|
||||
@@ -134,7 +129,7 @@ class ReaderDialogs {
|
||||
loadSettings() {
|
||||
const settings = this.settings;
|
||||
this.showWhatsNewDialog = settings.showWhatsNewDialog;
|
||||
this.showDonationDialog2020 = settings.showDonationDialog2020;
|
||||
this.showDonationDialog = settings.showDonationDialog;
|
||||
}
|
||||
|
||||
async showWhatsNew() {
|
||||
@@ -149,9 +144,9 @@ class ReaderDialogs {
|
||||
}
|
||||
|
||||
async showDonation() {
|
||||
const today = utils.formatDate(new Date(), 'coDate');
|
||||
const today = utils.formatDate(new Date(), 'coMonth');
|
||||
|
||||
if ((this.mode == 'omnireader' || this.mode == 'liberama.top') && today < '2020-03-01' && this.showDonationDialog2020 && this.donationRemindDate != today) {
|
||||
if ((this.mode == 'omnireader' || this.mode == 'liberama.top') && this.showDonationDialog && this.donationRemindDate != today) {
|
||||
await utils.sleep(3000);
|
||||
this.donationVisible = true;
|
||||
}
|
||||
@@ -166,20 +161,17 @@ class ReaderDialogs {
|
||||
this.urlHelpVisible = false;
|
||||
}
|
||||
|
||||
donationDialogDisable() {
|
||||
this.donationVisible = false;
|
||||
if (this.showDonationDialog2020) {
|
||||
this.commit('reader/setSettings', { showDonationDialog2020: false });
|
||||
}
|
||||
}
|
||||
|
||||
donationDialogRemind() {
|
||||
this.donationVisible = false;
|
||||
this.commit('reader/setDonationRemindDate', utils.formatDate(new Date(), 'coDate'));
|
||||
this.commit('reader/setDonationRemindDate', utils.formatDate(new Date(), 'coMonth'));
|
||||
}
|
||||
|
||||
makeDonation() {
|
||||
utils.makeDonation();
|
||||
this.donationDialogRemind();
|
||||
}
|
||||
|
||||
openDonate() {
|
||||
this.donationVisible = false;
|
||||
this.$emit('donate-toggle');
|
||||
}
|
||||
|
||||
|
||||
@@ -813,6 +813,12 @@ class RecentBooksPage {
|
||||
const book = await bookManager.getRecentBook(item);
|
||||
if (book) {
|
||||
await bookManager.setCheckBuc(book, item.checkBuc);
|
||||
|
||||
this.$root.notify.info(item.checkBuc
|
||||
? 'Проверка обновлений книги включена'
|
||||
: 'Проверка обновлений книги отключена'
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,15 +41,15 @@
|
||||
</q-checkbox>
|
||||
</div>
|
||||
|
||||
<!--div class="item row">
|
||||
<div class="item row">
|
||||
<div class="label-6">Уведомление</div>
|
||||
<q-checkbox size="xs" v-model="showDonationDialog2020">
|
||||
Показывать "Оплатим хостинг вместе"
|
||||
<q-checkbox size="xs" v-model="showDonationDialog">
|
||||
Показывать форму доната
|
||||
<q-tooltip :delay="1000" anchor="top middle" self="bottom middle" content-style="font-size: 80%">
|
||||
Показывать уведомление "Оплатим хостинг вместе"
|
||||
Показывать диалог для сбора пожертвований
|
||||
</q-tooltip>
|
||||
</q-checkbox>
|
||||
</div-->
|
||||
</div>
|
||||
|
||||
<!---------------------------------------------->
|
||||
<div class="part-header">Другое</div>
|
||||
|
||||
@@ -1,4 +1,32 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
version: '0.12.2',
|
||||
releaseDate: '2022-09-04',
|
||||
showUntil: '2022-09-11',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>исправлен баг с формой для доната, показывалась каждый день, а не каждый месяц</li>
|
||||
<li>автор приносит извинения за доставленные неудобства</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '0.12.1',
|
||||
releaseDate: '2022-09-01',
|
||||
showUntil: '2022-08-30',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>добавлена форма для доната</li>
|
||||
<li>исправления багов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '0.12.0',
|
||||
releaseDate: '2022-07-27',
|
||||
|
||||
@@ -27,9 +27,10 @@ class Notify {
|
||||
icon,
|
||||
actions: [{icon: 'la la-times notify-button-icon', color: 'black'}],
|
||||
html: true,
|
||||
classes: 'notify-margin',
|
||||
|
||||
message:
|
||||
`<div style="max-width: 350px;">
|
||||
`<div style="max-width: 350px">
|
||||
${caption}
|
||||
<div style="color: ${messageColor}; overflow-wrap: break-word; word-wrap: break-word;">${message}</div>
|
||||
</div>`
|
||||
|
||||
@@ -45,6 +45,8 @@ export function formatDate(d, format) {
|
||||
`${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
|
||||
case 'coDate':
|
||||
return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, '0')}-${d.getDate().toString().padStart(2, '0')}`;
|
||||
case 'coMonth':
|
||||
return `${(d.getMonth() + 1).toString().padStart(2, '0')}`;
|
||||
case 'noDate':
|
||||
return `${d.getDate().toString().padStart(2, '0')}.${(d.getMonth() + 1).toString().padStart(2, '0')}.${d.getFullYear()}`;
|
||||
}
|
||||
@@ -409,4 +411,8 @@ export function resizeImage(dataUrl, toWidth, toHeight, quality = 0.9) {
|
||||
if (!resolved)
|
||||
reject('Не удалось изменить размер');
|
||||
})().catch(reject); });
|
||||
}
|
||||
}
|
||||
|
||||
export function makeDonation() {
|
||||
window.open('https://donatty.com/liberama', '_blank');
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ const settingDefaults = {
|
||||
|
||||
showServerStorageMessages: true,
|
||||
showWhatsNewDialog: true,
|
||||
showDonationDialog2020: true,
|
||||
showDonationDialog: true,
|
||||
showNeedUpdateNotify: true,
|
||||
|
||||
fontShifts: {},
|
||||
@@ -255,6 +255,7 @@ const libsDefaults = {
|
||||
// initial state
|
||||
const state = {
|
||||
toolBarActive: true,
|
||||
offlineModeActive: false,
|
||||
serverSyncEnabled: false,
|
||||
serverStorageKey: '',
|
||||
profiles: {},
|
||||
@@ -280,6 +281,9 @@ const mutations = {
|
||||
setToolBarActive(state, value) {
|
||||
state.toolBarActive = value;
|
||||
},
|
||||
setOfflineModeActive(state, value) {
|
||||
state.offlineModeActive = value;
|
||||
},
|
||||
setServerSyncEnabled(state, value) {
|
||||
state.serverSyncEnabled = value;
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ git clone https://github.com/bookpauk/liberama
|
||||
### node.js
|
||||
```
|
||||
sudo apt install -y curl
|
||||
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
|
||||
curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
|
||||
sudo apt install -y nodejs
|
||||
```
|
||||
|
||||
|
||||
1721
package-lock.json
generated
1721
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "Liberama",
|
||||
"version": "0.12.0",
|
||||
"version": "0.12.2",
|
||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
"repository": "bookpauk/liberama",
|
||||
"engines": {
|
||||
"node": ">=14.4.0"
|
||||
"node": ">=16.16.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nodemon --inspect --ignore server/public --ignore server/data --ignore client --exec 'node server'",
|
||||
"build:client": "webpack --config build/webpack.prod.config.js",
|
||||
"build:linux": "npm run build:client && node build/linux && pkg -t node14-linux-x64 -C GZip -o dist/linux/liberama .",
|
||||
"build:win": "npm run build:client && node build/win && pkg -t node14-win-x64 -C GZip -o dist/win/liberama .",
|
||||
"build:linux": "npm run build:client && node build/linux && pkg -t node16-linux-x64 -C GZip -o dist/linux/liberama .",
|
||||
"build:win": "npm run build:client && node build/win && pkg -t node16-win-x64 -C GZip -o dist/win/liberama .",
|
||||
"lint": "eslint --ext=.js,.vue client server",
|
||||
"build:client-dev": "webpack --config build/webpack.dev.config.js",
|
||||
"postinstall": "npm run build:client-dev && node build/linux"
|
||||
@@ -21,35 +21,35 @@
|
||||
"scripts": "server/config/*.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.18.9",
|
||||
"@babel/core": "^7.18.13",
|
||||
"@babel/eslint-parser": "^7.18.9",
|
||||
"@babel/eslint-plugin": "^7.17.7",
|
||||
"@babel/plugin-proposal-decorators": "^7.18.9",
|
||||
"@babel/preset-env": "^7.18.9",
|
||||
"@babel/eslint-plugin": "^7.18.10",
|
||||
"@babel/plugin-proposal-decorators": "^7.18.10",
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"@vue/compiler-sfc": "^3.2.22",
|
||||
"babel-loader": "^8.2.5",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"css-minimizer-webpack-plugin": "^4.0.0",
|
||||
"eslint": "^8.20.0",
|
||||
"eslint-plugin-vue": "^9.3.0",
|
||||
"eslint": "^8.23.0",
|
||||
"eslint-plugin-vue": "^9.4.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"mini-css-extract-plugin": "^2.6.1",
|
||||
"pkg": "^5.8.0",
|
||||
"terser-webpack-plugin": "^5.3.3",
|
||||
"terser-webpack-plugin": "^5.3.6",
|
||||
"vue-eslint-parser": "^9.0.3",
|
||||
"vue-loader": "^17.0.0",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-dev-middleware": "^5.3.3",
|
||||
"webpack-hot-middleware": "^2.25.1",
|
||||
"webpack-hot-middleware": "^2.25.2",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"workbox-webpack-plugin": "^6.5.3"
|
||||
"workbox-webpack-plugin": "^6.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/extras": "^1.15.0",
|
||||
"@vue/compat": "^3.2.37",
|
||||
"@quasar/extras": "^1.15.2",
|
||||
"@vue/compat": "^3.2.38",
|
||||
"axios": "^0.27.2",
|
||||
"base-x": "^4.0.0",
|
||||
"chardet": "^1.4.0",
|
||||
@@ -59,7 +59,7 @@
|
||||
"fs-extra": "^10.1.0",
|
||||
"he": "^1.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jembadb": "^3.0.9",
|
||||
"jembadb": "^4.2.0",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "^1.2.6",
|
||||
@@ -67,17 +67,17 @@
|
||||
"pako": "^2.0.4",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pidusage": "^3.0.0",
|
||||
"quasar": "^2.7.5",
|
||||
"quasar": "^2.7.7",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"sanitize-html": "^2.7.1",
|
||||
"sjcl": "^1.0.8",
|
||||
"tar-fs": "^2.1.1",
|
||||
"unbzip2-stream": "^1.4.3",
|
||||
"vue": "^3.2.37",
|
||||
"vue-router": "^4.1.2",
|
||||
"vue-router": "^4.1.5",
|
||||
"vuex": "^4.0.2",
|
||||
"vuex-persist": "^3.1.3",
|
||||
"webdav": "^4.10.0",
|
||||
"webdav": "^4.11.0",
|
||||
"ws": "^8.8.1",
|
||||
"zip-stream": "^4.1.0"
|
||||
}
|
||||
|
||||
@@ -177,8 +177,10 @@ class BUCClient {
|
||||
|
||||
const ids = new Set();
|
||||
let id = iter.next();
|
||||
while (!id.done && ids.size < 1000) {
|
||||
while (!id.done) {
|
||||
ids.add(id.value);
|
||||
if (ids.size >= 1000)
|
||||
break;
|
||||
id = iter.next();
|
||||
}
|
||||
|
||||
|
||||
@@ -78,8 +78,10 @@ class BUCServer {
|
||||
|
||||
const ids = new Set();
|
||||
let id = iter.next();
|
||||
while (!id.done && ids.size < 100) {
|
||||
while (!id.done) {
|
||||
ids.add(id.value);
|
||||
if (ids.size >= 100)
|
||||
break;
|
||||
id = iter.next();
|
||||
}
|
||||
|
||||
@@ -222,8 +224,10 @@ class BUCServer {
|
||||
});
|
||||
|
||||
//пушим в очередь, после этого их обработает periodicCheck
|
||||
for (const row of rowsToPush)
|
||||
for (const row of rowsToPush) {
|
||||
this.checkQueue.push(row);
|
||||
log(LM_INFO, ` add ${row.id}`);
|
||||
}
|
||||
|
||||
log(LM_WARN, `checkQueue: added ${ids.length} recs, total ${this.checkQueue.length}`);
|
||||
}
|
||||
@@ -271,6 +275,7 @@ class BUCServer {
|
||||
&& (!modTime || !row.modTime || (modTime !== row.modTime))
|
||||
&& (!size || !row.size || (size !== row.size))
|
||||
) {
|
||||
|
||||
const downdata = await this.down.load(row.id);
|
||||
|
||||
size = downdata.length;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const https = require('https');
|
||||
const axios = require('axios');
|
||||
const utils = require('./utils');
|
||||
|
||||
const userAgent = 'Mozilla/5.0 (X11; HasCodingOs 1.0; Linux x64) AppleWebKit/637.36 (KHTML, like Gecko) Chrome/70.0.3112.101 Safari/637.36 HasBrowser/5.0';
|
||||
|
||||
@@ -12,8 +14,12 @@ class FileDownloader {
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'user-agent': userAgent
|
||||
'user-agent': userAgent,
|
||||
timeout: 300*1000,
|
||||
},
|
||||
httpsAgent: new https.Agent({
|
||||
rejectUnauthorized: false // решение проблемы 'unable to verify the first certificate' для некоторых сайтов с валидным сертификатом
|
||||
}),
|
||||
responseType: 'stream',
|
||||
};
|
||||
|
||||
@@ -67,7 +73,8 @@ class FileDownloader {
|
||||
async head(url) {
|
||||
const options = {
|
||||
headers: {
|
||||
'user-agent': userAgent
|
||||
'user-agent': userAgent,
|
||||
timeout: 10*1000,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -75,25 +82,42 @@ class FileDownloader {
|
||||
return res.headers;
|
||||
}
|
||||
|
||||
streamToBuffer(stream, progress) {
|
||||
streamToBuffer(stream, progress, timeout = 30*1000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (!progress)
|
||||
progress = () => {};
|
||||
|
||||
const _buf = [];
|
||||
let resolved = false;
|
||||
let timer = 0;
|
||||
|
||||
stream.on('data', (chunk) => {
|
||||
timer = 0;
|
||||
_buf.push(chunk);
|
||||
progress(chunk);
|
||||
});
|
||||
stream.on('end', () => resolve(Buffer.concat(_buf)));
|
||||
stream.on('end', () => {
|
||||
resolved = true;
|
||||
timer = timeout;
|
||||
resolve(Buffer.concat(_buf));
|
||||
});
|
||||
stream.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
stream.on('aborted', () => {
|
||||
reject(new Error('aborted'));
|
||||
});
|
||||
|
||||
//бодяга с timer и timeout, чтобы гарантировать отсутствие зависания по каким-либо причинам
|
||||
(async() => {
|
||||
while (timer < timeout) {
|
||||
await utils.sleep(1000);
|
||||
timer += 1000;
|
||||
}
|
||||
if (!resolved)
|
||||
reject(new Error('FileDownloader: timed out'))
|
||||
})();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ class ReaderWorker {
|
||||
let convertFilename = '';
|
||||
|
||||
const overLoadMes = 'Слишком большая очередь загрузки. Пожалуйста, попробуйте позже.';
|
||||
const fileNotFoundMes = 'Файл не найден';
|
||||
const overLoadErr = new Error(overLoadMes);
|
||||
|
||||
let q = null;
|
||||
@@ -184,26 +185,33 @@ class ReaderWorker {
|
||||
})();
|
||||
|
||||
} catch (e) {
|
||||
log(LM_ERR, `url: ${url}, downloadedFilename: ${downloadedFilename}`);
|
||||
log(LM_ERR, e.stack);
|
||||
let mes = e.message.split('|FORLOG|');
|
||||
if (mes[1])
|
||||
log(LM_ERR, mes[0] + mes[1]);
|
||||
log(LM_ERR, `downloadedFilename: ${downloadedFilename}`);
|
||||
|
||||
mes = mes[0];
|
||||
if (mes == 'abort')
|
||||
mes = overLoadMes;
|
||||
if (mes.indexOf('ENOTDIR') >= 0)
|
||||
mes = fileNotFoundMes;
|
||||
|
||||
wState.set({state: 'error', error: mes});
|
||||
} finally {
|
||||
//clean
|
||||
if (q)
|
||||
q.ret();
|
||||
if (decompDir)
|
||||
await fs.remove(decompDir);
|
||||
if (downloadedFilename && !isUploaded)
|
||||
await fs.remove(downloadedFilename);
|
||||
if (convertFilename)
|
||||
await fs.remove(convertFilename);
|
||||
try {
|
||||
if (q)
|
||||
q.ret();
|
||||
if (decompDir)
|
||||
await fs.remove(decompDir);
|
||||
if (downloadedFilename && !isUploaded)
|
||||
await fs.remove(downloadedFilename);
|
||||
if (convertFilename)
|
||||
await fs.remove(convertFilename);
|
||||
} catch (e) {
|
||||
log(LM_ERR, `Remove error: ${e.stack}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class WorkerState {
|
||||
return {
|
||||
set: state => this.setState(workerId, state),
|
||||
finish: state => this.finishState(workerId, state),
|
||||
get: workerId => this.getState(workerId),
|
||||
get: () => this.getState(workerId),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user