Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e72ca0de7e | ||
|
|
c44c27d3d2 | ||
|
|
df4e201ccd | ||
|
|
c8c0e9ec1a | ||
|
|
9a4a84a367 | ||
|
|
1dc3424411 | ||
|
|
c13745e913 | ||
|
|
25c12309f2 | ||
|
|
4b632da5af | ||
|
|
87c364b8ee | ||
|
|
efa48fbc8a | ||
|
|
21df6c1d21 | ||
|
|
39d2ceb94b | ||
|
|
1dad013d60 | ||
|
|
add7a03f88 | ||
|
|
0cefaa6d48 | ||
|
|
f08e73f359 |
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Window ref="window" @close="close">
|
<Window ref="window" @close="close" margin="2px">
|
||||||
<template slot="header">
|
<template slot="header">
|
||||||
{{ header }}
|
{{ header }}
|
||||||
</template>
|
</template>
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
<div v-show="ready" class="col column" style="min-width: 600px">
|
<div v-show="ready" class="col column" style="min-width: 600px">
|
||||||
<div class="row items-center q-px-sm" style="height: 50px">
|
<div class="row items-center q-px-sm" style="height: 50px">
|
||||||
<q-select class="q-mr-sm" v-model="rootLink" :options="rootLinkOptions"
|
<q-select class="q-mr-sm" ref="rootLink" v-model="rootLink" :options="rootLinkOptions" @input="rootLinkInput"
|
||||||
|
@popup-show="onSelectPopupShow" @popup-hide="onSelectPopupHide"
|
||||||
style="width: 230px"
|
style="width: 230px"
|
||||||
dropdown-icon="la la-angle-down la-sm"
|
dropdown-icon="la la-angle-down la-sm"
|
||||||
rounded outlined dense emit-value map-options display-value-sanitize options-sanitize
|
rounded outlined dense emit-value map-options display-value-sanitize options-sanitize
|
||||||
@@ -30,13 +31,18 @@
|
|||||||
<div style="overflow: hidden; white-space: nowrap;">{{ removeProtocol(rootLink) }}</div>
|
<div style="overflow: hidden; white-space: nowrap;">{{ removeProtocol(rootLink) }}</div>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
<q-select class="q-mr-sm" v-model="selectedLink" :options="selectedLinkOptions" style="width: 50px"
|
|
||||||
|
<q-select class="q-mr-sm" ref="selectedLink" v-model="selectedLink" :options="selectedLinkOptions" @input="selectedLinkInput" style="width: 50px"
|
||||||
|
@popup-show="onSelectPopupShow" @popup-hide="onSelectPopupHide"
|
||||||
dropdown-icon="la la-angle-down la-sm"
|
dropdown-icon="la la-angle-down la-sm"
|
||||||
rounded outlined dense emit-value map-options hide-selected display-value-sanitize options-sanitize
|
rounded outlined dense emit-value map-options hide-selected display-value-sanitize options-sanitize
|
||||||
>
|
>
|
||||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Закладки</q-tooltip>
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Закладки</q-tooltip>
|
||||||
</q-select>
|
</q-select>
|
||||||
<q-input class="col q-mr-sm" ref="input" rounded outlined dense bg-color="white" v-model="bookUrl" placeholder="Скопируйте сюда URL книги" @focus="onInputFocus">
|
|
||||||
|
<q-input class="col q-mr-sm" ref="input" rounded outlined dense bg-color="white" v-model="bookUrl" placeholder="Скопируйте сюда URL книги"
|
||||||
|
@focus="selectAllOnFocus" @keydown="bookUrlKeyDown"
|
||||||
|
>
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<q-btn class="q-mr-xs" round dense color="blue" icon="la la-home" @click="goToLink(libs.startLink)" size="12px">
|
<q-btn class="q-mr-xs" round dense color="blue" icon="la la-home" @click="goToLink(libs.startLink)" size="12px">
|
||||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Вернуться на стартовую страницу</q-tooltip>
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Вернуться на стартовую страницу</q-tooltip>
|
||||||
@@ -46,13 +52,17 @@
|
|||||||
</q-btn>
|
</q-btn>
|
||||||
</template>
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<q-btn rounded color="green-7" no-caps size="14px" @click="submitUrl">Открыть
|
<q-btn rounded color="green-7" no-caps size="14px" @click="submitUrl">Открыть
|
||||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Открыть в читалке</q-tooltip>
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">Открыть в читалке</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
|
|
||||||
<iframe v-if="frameVisible" class="col fit" ref="frame" :src="frameSrc" frameborder="0"></iframe>
|
<div class="col fit" style="position: relative;">
|
||||||
|
<iframe v-if="frameVisible" class="fit" ref="frame" :src="frameSrc" frameborder="0"></iframe>
|
||||||
|
<div v-show="transparentLayoutVisible" ref="transparentLayout" class="fit transparent-layout" @click="transparentLayoutClick"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Dialog ref="dialogAddBookmark" v-model="addBookmarkVisible">
|
<Dialog ref="dialogAddBookmark" v-model="addBookmarkVisible">
|
||||||
<template slot="header">
|
<template slot="header">
|
||||||
@@ -63,11 +73,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="q-mx-md row">
|
<div class="q-mx-md row">
|
||||||
<q-input ref="bookmarkLink" class="col q-mr-sm" outlined dense bg-color="white" v-model="bookmarkLink"
|
<q-input ref="bookmarkLink" class="col q-mr-sm" outlined dense bg-color="white" v-model="bookmarkLink" @keydown="bookmarkLinkKeyDown"
|
||||||
placeholder="Ссылка для закладки" maxlength="2000" @focus="onInputFocus">
|
placeholder="Ссылка для закладки" maxlength="2000" @focus="selectAllOnFocus">
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<q-select class="q-mr-sm" v-model="defaultRootLink" :options="defaultRootLinkOptions" style="width: 50px"
|
<q-select class="q-mr-sm" ref="defaultRootLink" v-model="defaultRootLink" :options="defaultRootLinkOptions" @input="defaultRootLinkInput" style="width: 50px"
|
||||||
dropdown-icon="la la-angle-down la-sm"
|
dropdown-icon="la la-angle-down la-sm"
|
||||||
outlined dense emit-value map-options hide-selected display-value-sanitize options-sanitize
|
outlined dense emit-value map-options hide-selected display-value-sanitize options-sanitize
|
||||||
>
|
>
|
||||||
@@ -76,8 +86,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="q-mx-md q-mt-md">
|
<div class="q-mx-md q-mt-md">
|
||||||
<q-input class="col q-mr-sm" outlined dense bg-color="white" v-model="bookmarkDesc"
|
<q-input class="col q-mr-sm" ref="bookmarkDesc" outlined dense bg-color="white" v-model="bookmarkDesc" @keydown="bookmarkDescKeyDown"
|
||||||
placeholder="Описание" style="width: 400px" maxlength="100" @focus="onInputFocus">
|
placeholder="Описание" style="width: 400px" maxlength="100" @focus="selectAllOnFocus">
|
||||||
</q-input>
|
</q-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -137,6 +147,7 @@ class ExternalLibs extends Vue {
|
|||||||
libs = {};
|
libs = {};
|
||||||
fullScreenActive = false;
|
fullScreenActive = false;
|
||||||
addBookmarkVisible = false;
|
addBookmarkVisible = false;
|
||||||
|
transparentLayoutVisible = false;
|
||||||
|
|
||||||
bookmarkLink = '';
|
bookmarkLink = '';
|
||||||
bookmarkDesc = '';
|
bookmarkDesc = '';
|
||||||
@@ -145,11 +156,38 @@ class ExternalLibs extends Vue {
|
|||||||
created() {
|
created() {
|
||||||
this.$root.addKeyHook(this.keyHook);
|
this.$root.addKeyHook(this.keyHook);
|
||||||
|
|
||||||
|
document.addEventListener('fullscreenchange', () => {
|
||||||
|
this.fullScreenActive = (document.fullscreenElement !== null);
|
||||||
|
});
|
||||||
|
|
||||||
//this.commit = this.$store.commit;
|
//this.commit = this.$store.commit;
|
||||||
//this.commit('reader/setLibs', rstore.libsDefaults);
|
//this.commit('reader/setLibs', rstore.libsDefaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
//Поправка метода toggleOption компонента select фреймворка quasar, необходимо другое поведение
|
||||||
|
//$emit('input'.. вызывается всегда
|
||||||
|
this.toggleOption = function(opt, keepOpen) {
|
||||||
|
if (this.editable !== true || opt === void 0 || this.isOptionDisabled(opt) === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const optValue = this.getOptionValue(opt);
|
||||||
|
|
||||||
|
if (this.multiple !== true) {
|
||||||
|
if (keepOpen !== true) {
|
||||||
|
this.updateInputValue(this.fillInput === true ? this.getOptionLabel(opt) : '', true, true);
|
||||||
|
this.hidePopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$refs.target !== void 0 && this.$refs.target.focus();
|
||||||
|
this.$emit('input', this.emitValue === true ? optValue : opt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$refs.rootLink.toggleOption = this.toggleOption;
|
||||||
|
this.$refs.selectedLink.toggleOption = this.toggleOption;
|
||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
//подождем this.mode
|
//подождем this.mode
|
||||||
let i = 0;
|
let i = 0;
|
||||||
@@ -320,8 +358,9 @@ class ExternalLibs extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openBookUrlInFrame() {
|
openBookUrlInFrame() {
|
||||||
if (this.bookUrl)
|
if (this.bookUrl) {
|
||||||
this.goToLink(this.addProtocol(this.bookUrl));
|
this.goToLink(this.addProtocol(this.bookUrl));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goToLink(link) {
|
goToLink(link) {
|
||||||
@@ -332,6 +371,9 @@ class ExternalLibs extends Vue {
|
|||||||
this.frameVisible = false;
|
this.frameVisible = false;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.frameVisible = true;
|
this.frameVisible = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.frame.contentWindow.focus();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,11 +434,20 @@ class ExternalLibs extends Vue {
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
onInputFocus(event) {
|
selectAllOnFocus(event) {
|
||||||
if (event.target.select)
|
if (event.target.select)
|
||||||
event.target.select();
|
event.target.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootLinkInput() {
|
||||||
|
this.updateSelectedLink();
|
||||||
|
this.updateStartLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedLinkInput() {
|
||||||
|
this.updateStartLink();
|
||||||
|
}
|
||||||
|
|
||||||
submitUrl() {
|
submitUrl() {
|
||||||
if (this.bookUrl) {
|
if (this.bookUrl) {
|
||||||
this.sendMessage({type: 'submitUrl', data: {
|
this.sendMessage({type: 'submitUrl', data: {
|
||||||
@@ -415,6 +466,7 @@ class ExternalLibs extends Vue {
|
|||||||
this.addBookmarkVisible = true;
|
this.addBookmarkVisible = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.bookmarkLink.focus();
|
this.$refs.bookmarkLink.focus();
|
||||||
|
this.$refs.defaultRootLink.toggleOption = this.toggleOption;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,7 +481,28 @@ class ExternalLibs extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultRootLinkInput() {
|
||||||
|
this.updateBookmarkLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
bookmarkLinkKeyDown(event) {
|
||||||
|
if (event.key == 'Enter') {
|
||||||
|
this.$refs.bookmarkDesc.focus();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bookmarkDescKeyDown(event) {
|
||||||
|
if (event.key == 'Enter') {
|
||||||
|
this.okAddBookmark();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async okAddBookmark() {
|
async okAddBookmark() {
|
||||||
|
if (!this.bookmarkLink)
|
||||||
|
return;
|
||||||
|
|
||||||
const link = this.addProtocol(this.bookmarkLink);
|
const link = this.addProtocol(this.bookmarkLink);
|
||||||
let index = -1;
|
let index = -1;
|
||||||
try {
|
try {
|
||||||
@@ -488,23 +561,43 @@ class ExternalLibs extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transparentLayoutClick() {
|
||||||
|
this.transparentLayoutVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectPopupShow() {
|
||||||
|
this.transparentLayoutVisible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectPopupHide() {
|
||||||
|
this.transparentLayoutVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.sendMessage({type: 'close'});
|
this.sendMessage({type: 'close'});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bookUrlKeyDown(event) {
|
||||||
|
if (event.key == 'Enter') {
|
||||||
|
this.submitUrl();
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
keyHook() {
|
keyHook() {
|
||||||
if (this.$root.rootRoute() == '/external-libs') {
|
if (this.$root.rootRoute() == '/external-libs') {
|
||||||
if (this.$refs.dialogAddBookmark.active)
|
if (this.$refs.dialogAddBookmark.active)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//недостатки сторонних ui
|
if (event.type == 'keydown' && event.key == 'F4') {
|
||||||
const input = this.$refs.input.$refs.input;
|
this.addBookmark()
|
||||||
if (document.activeElement === input && event.type == 'keydown' && event.key == 'Enter') {
|
return;
|
||||||
this.submitUrl();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.type == 'keydown' && event.key == 'Escape') {
|
if (event.type == 'keydown' && event.key == 'Escape' &&
|
||||||
|
(document.activeElement != this.$refs.rootLink.$refs.target || !this.$refs.rootLink.menu) &&
|
||||||
|
(document.activeElement != this.$refs.selectedLink.$refs.target || !this.$refs.selectedLink.menu)
|
||||||
|
) {
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -532,4 +625,9 @@ class ExternalLibs extends Vue {
|
|||||||
background-color: #69C05F;
|
background-color: #69C05F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transparent-layout {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="main" class="column no-wrap" style="min-height: 500px">
|
<div ref="main" class="column no-wrap" style="min-height: 500px">
|
||||||
<div class="relative-position">
|
<div v-if="mode != 'liberama.top'" class="relative-position">
|
||||||
<GithubCorner url="https://github.com/bookpauk/liberama" cornerColor="#1B695F" gitColor="#EBE2C9"></GithubCorner>
|
<GithubCorner url="https://github.com/bookpauk/liberama" cornerColor="#1B695F" gitColor="#EBE2C9"></GithubCorner>
|
||||||
</div>
|
</div>
|
||||||
<div class="col column justify-center items-center no-wrap overflow-hidden" style="min-height: 230px">
|
<div class="col column justify-center items-center no-wrap overflow-hidden" style="min-height: 230px">
|
||||||
|
|||||||
@@ -39,6 +39,10 @@
|
|||||||
<q-icon name="la la-copy" size="32px"/>
|
<q-icon name="la la-copy" size="32px"/>
|
||||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['copyText'] }}</q-tooltip>
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['copyText'] }}</q-tooltip>
|
||||||
</button>
|
</button>
|
||||||
|
<button ref="splitToPara" v-show="showToolButton['splitToPara']" class="tool-button" :class="buttonActiveClass('splitToPara')" @click="buttonClick('splitToPara')" v-ripple>
|
||||||
|
<q-icon name="la la-retweet" size="32px"/>
|
||||||
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['splitToPara'] }}</q-tooltip>
|
||||||
|
</button>
|
||||||
<button ref="refresh" v-show="showToolButton['refresh']" class="tool-button" :class="buttonActiveClass('refresh')" @click="buttonClick('refresh')" v-ripple>
|
<button ref="refresh" v-show="showToolButton['refresh']" class="tool-button" :class="buttonActiveClass('refresh')" @click="buttonClick('refresh')" v-ripple>
|
||||||
<q-icon name="la la-sync" size="32px" :class="{clear: !showRefreshIcon}"/>
|
<q-icon name="la la-sync" size="32px" :class="{clear: !showRefreshIcon}"/>
|
||||||
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['refresh'] }}</q-tooltip>
|
<q-tooltip :delay="1500" anchor="bottom middle" content-style="font-size: 80%">{{ rstore.readerActions['refresh'] }}</q-tooltip>
|
||||||
@@ -699,6 +703,12 @@ class Reader extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshBookSplitToPara() {
|
||||||
|
if (this.mostRecentBook()) {
|
||||||
|
this.loadBook({url: this.mostRecentBook().url, skipCheck: true, isText: true, force: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
recentBooksClose() {
|
recentBooksClose() {
|
||||||
this.recentBooksActive = false;
|
this.recentBooksActive = false;
|
||||||
}
|
}
|
||||||
@@ -816,6 +826,7 @@ class Reader extends Vue {
|
|||||||
case 'scrolling':
|
case 'scrolling':
|
||||||
case 'search':
|
case 'search':
|
||||||
case 'copyText':
|
case 'copyText':
|
||||||
|
case 'splitToPara':
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
case 'libs':
|
case 'libs':
|
||||||
case 'recentBooks':
|
case 'recentBooks':
|
||||||
@@ -847,8 +858,9 @@ class Reader extends Vue {
|
|||||||
case 'copyText':
|
case 'copyText':
|
||||||
classResult = classDisabled;
|
classResult = classDisabled;
|
||||||
break;
|
break;
|
||||||
case 'recentBooks':
|
case 'splitToPara':
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
|
case 'recentBooks':
|
||||||
if (!this.mostRecentBookReactive)
|
if (!this.mostRecentBookReactive)
|
||||||
classResult = classDisabled;
|
classResult = classDisabled;
|
||||||
break;
|
break;
|
||||||
@@ -1001,9 +1013,16 @@ class Reader extends Vue {
|
|||||||
// не удалось, скачиваем книгу полностью с конвертацией
|
// не удалось, скачиваем книгу полностью с конвертацией
|
||||||
let loadCached = true;
|
let loadCached = true;
|
||||||
if (!book) {
|
if (!book) {
|
||||||
book = await readerApi.loadBook({url, enableSitesFilter: this.enableSitesFilter}, (state) => {
|
book = await readerApi.loadBook({
|
||||||
progress.setState(state);
|
url,
|
||||||
});
|
skipCheck: (opts.skipCheck ? true : false),
|
||||||
|
isText: (opts.isText ? true : false),
|
||||||
|
enableSitesFilter: this.enableSitesFilter
|
||||||
|
},
|
||||||
|
(state) => {
|
||||||
|
progress.setState(state);
|
||||||
|
}
|
||||||
|
);
|
||||||
loadCached = false;
|
loadCached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1122,6 +1141,9 @@ class Reader extends Vue {
|
|||||||
case 'copyText':
|
case 'copyText':
|
||||||
this.copyTextToggle();
|
this.copyTextToggle();
|
||||||
break;
|
break;
|
||||||
|
case 'splitToPara':
|
||||||
|
this.refreshBookSplitToPara();
|
||||||
|
break;
|
||||||
case 'refresh':
|
case 'refresh':
|
||||||
this.refreshBook();
|
this.refreshBook();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -69,15 +69,15 @@ class ServerStorage extends Vue {
|
|||||||
try {
|
try {
|
||||||
this.cachedRecent = await ssCacheStore.getItem('recent');
|
this.cachedRecent = await ssCacheStore.getItem('recent');
|
||||||
if (!this.cachedRecent)
|
if (!this.cachedRecent)
|
||||||
await this.setCachedRecent({rev: 0, data: {}});
|
await this.cleanCachedRecent('cachedRecent');
|
||||||
|
|
||||||
this.cachedRecentPatch = await ssCacheStore.getItem('recent-patch');
|
this.cachedRecentPatch = await ssCacheStore.getItem('recent-patch');
|
||||||
if (!this.cachedRecentPatch)
|
if (!this.cachedRecentPatch)
|
||||||
await this.setCachedRecentPatch({rev: 0, data: {}});
|
await this.cleanCachedRecent('cachedRecentPatch');
|
||||||
|
|
||||||
this.cachedRecentMod = await ssCacheStore.getItem('recent-mod');
|
this.cachedRecentMod = await ssCacheStore.getItem('recent-mod');
|
||||||
if (!this.cachedRecentMod)
|
if (!this.cachedRecentMod)
|
||||||
await this.setCachedRecentMod({rev: 0, data: {}});
|
await this.cleanCachedRecent('cachedRecentMod');
|
||||||
|
|
||||||
if (!this.serverStorageKey) {
|
if (!this.serverStorageKey) {
|
||||||
//генерируем новый ключ
|
//генерируем новый ключ
|
||||||
@@ -105,6 +105,15 @@ class ServerStorage extends Vue {
|
|||||||
this.cachedRecentMod = value;
|
this.cachedRecentMod = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async cleanCachedRecent(whatToClean) {
|
||||||
|
if (whatToClean == 'cachedRecent' || whatToClean == 'all')
|
||||||
|
await this.setCachedRecent({rev: 0, data: {}});
|
||||||
|
if (whatToClean == 'cachedRecentPatch' || whatToClean == 'all')
|
||||||
|
await this.setCachedRecentPatch({rev: 0, data: {}});
|
||||||
|
if (whatToClean == 'cachedRecentMod' || whatToClean == 'all')
|
||||||
|
await this.setCachedRecentMod({rev: 0, data: {}});
|
||||||
|
}
|
||||||
|
|
||||||
async generateNewServerStorageKey() {
|
async generateNewServerStorageKey() {
|
||||||
const key = utils.toBase58(utils.randomArray(32));
|
const key = utils.toBase58(utils.randomArray(32));
|
||||||
this.commit('reader/setServerStorageKey', key);
|
this.commit('reader/setServerStorageKey', key);
|
||||||
@@ -134,9 +143,12 @@ class ServerStorage extends Vue {
|
|||||||
await this.currentProfileChanged(force);
|
await this.currentProfileChanged(force);
|
||||||
await this.loadLibs(force);
|
await this.loadLibs(force);
|
||||||
|
|
||||||
|
if (force)
|
||||||
|
await this.cleanCachedRecent('all');
|
||||||
const loadSuccess = await this.loadRecent();
|
const loadSuccess = await this.loadRecent();
|
||||||
if (loadSuccess && force)
|
if (loadSuccess && force) {
|
||||||
await this.saveRecent();
|
await this.saveRecent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
export const versionHistory = [
|
export const versionHistory = [
|
||||||
|
{
|
||||||
|
showUntil: '2020-10-31',
|
||||||
|
header: '0.9.5 (2020-11-01)',
|
||||||
|
content:
|
||||||
|
`
|
||||||
|
<ul>
|
||||||
|
<li>на панель инструментов добавлена новая кнопка "Обновить с разбиением на параграфы"</li>
|
||||||
|
<li>исправления багов</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
showUntil: '2020-10-28',
|
showUntil: '2020-10-28',
|
||||||
header: '0.9.4 (2020-10-29)',
|
header: '0.9.4 (2020-10-29)',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="main" class="main xyfit absolute" @click="close" @mouseup="onMouseUp" @mousemove="onMouseMove">
|
<div ref="main" class="main xyfit absolute" @click="close" @mouseup="onMouseUp" @mousemove="onMouseMove">
|
||||||
<div ref="windowBox" class="xyfit absolute flex no-wrap" @click.stop>
|
<div ref="windowBox" class="xyfit absolute flex no-wrap" @click.stop>
|
||||||
<div class="window flexfit column no-wrap">
|
<div ref="window" class="window flexfit column no-wrap">
|
||||||
<div ref="header" class="header row justify-end" @mousedown.prevent.stop="onMouseDown"
|
<div ref="header" class="header row justify-end" @mousedown.prevent.stop="onMouseDown"
|
||||||
@touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove">
|
@touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove">
|
||||||
<span class="header-text col"><slot name="header"></slot></span>
|
<span class="header-text col"><slot name="header"></slot></span>
|
||||||
@@ -26,6 +26,7 @@ export default @Component({
|
|||||||
width: { type: String, default: '100%' },
|
width: { type: String, default: '100%' },
|
||||||
maxWidth: { type: String, default: '' },
|
maxWidth: { type: String, default: '' },
|
||||||
topShift: { type: Number, default: 0 },
|
topShift: { type: Number, default: 0 },
|
||||||
|
margin: '',
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
class Window extends Vue {
|
class Window extends Vue {
|
||||||
@@ -40,6 +41,9 @@ class Window extends Vue {
|
|||||||
const top = (this.$refs.main.offsetHeight - this.$refs.windowBox.offsetHeight)/2 + this.topShift;
|
const top = (this.$refs.main.offsetHeight - this.$refs.windowBox.offsetHeight)/2 + this.topShift;
|
||||||
this.$refs.windowBox.style.left = (left > 0 ? left : 0) + 'px';
|
this.$refs.windowBox.style.left = (left > 0 ? left : 0) + 'px';
|
||||||
this.$refs.windowBox.style.top = (top > 0 ? top : 0) + 'px';
|
this.$refs.windowBox.style.top = (top > 0 ? top : 0) + 'px';
|
||||||
|
|
||||||
|
if (this.margin)
|
||||||
|
this.$refs.window.style.margin = this.margin;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const readerActions = {
|
|||||||
'setPosition': 'Установить позицию',
|
'setPosition': 'Установить позицию',
|
||||||
'search': 'Найти в тексте',
|
'search': 'Найти в тексте',
|
||||||
'copyText': 'Скопировать текст со страницы',
|
'copyText': 'Скопировать текст со страницы',
|
||||||
|
'splitToPara': 'Обновить с разбиением на параграфы',
|
||||||
'refresh': 'Принудительно обновить книгу',
|
'refresh': 'Принудительно обновить книгу',
|
||||||
'offlineMode': 'Автономный режим (без интернета)',
|
'offlineMode': 'Автономный режим (без интернета)',
|
||||||
'libs': 'Библиотека',
|
'libs': 'Библиотека',
|
||||||
@@ -37,6 +38,7 @@ const toolButtons = [
|
|||||||
{name: 'setPosition', show: true},
|
{name: 'setPosition', show: true},
|
||||||
{name: 'search', show: true},
|
{name: 'search', show: true},
|
||||||
{name: 'copyText', show: false},
|
{name: 'copyText', show: false},
|
||||||
|
{name: 'splitToPara', show: false},
|
||||||
{name: 'refresh', show: true},
|
{name: 'refresh', show: true},
|
||||||
{name: 'libs', show: true},
|
{name: 'libs', show: true},
|
||||||
{name: 'recentBooks', show: true},
|
{name: 'recentBooks', show: true},
|
||||||
@@ -55,6 +57,7 @@ const hotKeys = [
|
|||||||
{name: 'setPosition', codes: ['P']},
|
{name: 'setPosition', codes: ['P']},
|
||||||
{name: 'search', codes: ['Ctrl+F']},
|
{name: 'search', codes: ['Ctrl+F']},
|
||||||
{name: 'copyText', codes: ['Ctrl+C']},
|
{name: 'copyText', codes: ['Ctrl+C']},
|
||||||
|
{name: 'splitToPara', codes: ['Shift+R']},
|
||||||
{name: 'refresh', codes: ['R']},
|
{name: 'refresh', codes: ['R']},
|
||||||
{name: 'offlineMode', codes: ['O']},
|
{name: 'offlineMode', codes: ['O']},
|
||||||
{name: 'libs', codes: ['L']},
|
{name: 'libs', codes: ['L']},
|
||||||
|
|||||||
85
docs/beta/beta.liberama
Normal file
85
docs/beta/beta.liberama
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
server {
|
||||||
|
listen 443 ssl; # managed by Certbot
|
||||||
|
ssl_certificate /etc/letsencrypt/live/beta.liberama.top/fullchain.pem; # managed by Certbot
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/beta.liberama.top/privkey.pem; # managed by Certbot
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
||||||
|
|
||||||
|
server_name beta.liberama.top;
|
||||||
|
|
||||||
|
client_max_body_size 50m;
|
||||||
|
proxy_read_timeout 1h;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types *;
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
proxy_pass http://127.0.0.1:34082;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ws {
|
||||||
|
proxy_pass http://127.0.0.1:34082;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /home/beta.liberama/public;
|
||||||
|
|
||||||
|
location /tmp {
|
||||||
|
types { } default_type "application/xml; charset=utf-8";
|
||||||
|
add_header Content-Encoding gzip;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(?:manifest|appcache|html)$ {
|
||||||
|
expires -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name beta.liberama.top;
|
||||||
|
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name b.beta.liberama.top;
|
||||||
|
|
||||||
|
client_max_body_size 50m;
|
||||||
|
proxy_read_timeout 1h;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types *;
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
proxy_pass http://127.0.0.1:34082;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /ws {
|
||||||
|
proxy_pass http://127.0.0.1:34082;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /home/beta.liberama/public;
|
||||||
|
|
||||||
|
location /tmp {
|
||||||
|
types { } default_type "application/xml; charset=utf-8";
|
||||||
|
add_header Content-Encoding gzip;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(?:manifest|appcache|html)$ {
|
||||||
|
expires -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,7 +64,7 @@ sudo -u www-data cp -r docs/omnireader.ru/old/* /home/oldreader
|
|||||||
|
|
||||||
## Запуск по крону
|
## Запуск по крону
|
||||||
```
|
```
|
||||||
* * * * * /root/liberama/docs/omnireader/cron_server.sh
|
* * * * * /root/liberama/docs/omnireader.ru/cron_server.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## Деплой и запуск
|
## Деплой и запуск
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Liberama",
|
"name": "Liberama",
|
||||||
"version": "0.9.4",
|
"version": "0.9.5",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Liberama",
|
"name": "Liberama",
|
||||||
"version": "0.9.4",
|
"version": "0.9.5",
|
||||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||||
"license": "CC0-1.0",
|
"license": "CC0-1.0",
|
||||||
"repository": "bookpauk/liberama",
|
"repository": "bookpauk/liberama",
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ class ReaderController extends BaseController {
|
|||||||
throw new Error(`key 'url' is empty`);
|
throw new Error(`key 'url' is empty`);
|
||||||
const workerId = this.readerWorker.loadBookUrl({
|
const workerId = this.readerWorker.loadBookUrl({
|
||||||
url: request.url,
|
url: request.url,
|
||||||
enableSitesFilter: (request.hasOwnProperty('enableSitesFilter') ? request.enableSitesFilter : true)
|
enableSitesFilter: (request.hasOwnProperty('enableSitesFilter') ? request.enableSitesFilter : true),
|
||||||
|
skipCheck: (request.hasOwnProperty('skipCheck') ? request.skipCheck : false),
|
||||||
|
isText: (request.hasOwnProperty('isText') ? request.isText : false),
|
||||||
});
|
});
|
||||||
const state = this.workerState.getState(workerId);
|
const state = this.workerState.getState(workerId);
|
||||||
return (state ? state : {});
|
return (state ? state : {});
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ class ConvertHtml extends ConvertBase {
|
|||||||
|
|
||||||
titleInfo['book-title'] = title;
|
titleInfo['book-title'] = title;
|
||||||
//подозрение на чистый текст, надо разбить на параграфы
|
//подозрение на чистый текст, надо разбить на параграфы
|
||||||
if (isText || pars.length < buf.length/2000) {
|
if (isText || (buf.length > 30*1024 && pars.length < buf.length/2000)) {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
let count = 1;
|
let count = 1;
|
||||||
for (let i = 0; i < spaceCounter.length; i++) {
|
for (let i = 0; i < spaceCounter.length; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user