diff --git a/client/api/reader.js b/client/api/reader.js index 7bba118f..f93efc39 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -1,5 +1,6 @@ import axios from 'axios'; import * as utils from '../share/utils'; +import * as cryptoUtils from '../share/cryptoUtils'; import wsc from './webSocketConnection'; const api = axios.create({ @@ -225,8 +226,20 @@ class Reader { return response; } - async uploadFileBuf(buf) { - const response = await wsc.message(await wsc.send({action: 'upload-file-buf', buf})); + async uploadFileBuf(buf, urlCallback) { + const key = utils.toHex(cryptoUtils.sha256(buf)); + const url = `disk://${key}`; + + if (urlCallback) + urlCallback(url); + + let response; + try { + await axios.head(`/upload/${key}`, {headers: {'Cache-Control': 'no-cache'}}); + response = await wsc.message(await wsc.send({action: 'upload-file-touch', url})); + } catch (e) { + response = await wsc.message(await wsc.send({action: 'upload-file-buf', buf})); + } if (response.error) throw new Error(response.error); diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index af537445..c1c824b4 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -194,6 +194,7 @@ import ReaderDialogs from './ReaderDialogs/ReaderDialogs.vue'; import bookManager from './share/bookManager'; import wallpaperStorage from './share/wallpaperStorage'; +import coversStorage from './share/coversStorage'; import dynamicCss from '../../share/dynamicCss'; import rstore from '../../store/modules/reader'; @@ -366,6 +367,8 @@ class Reader { mounted() { (async() => { await wallpaperStorage.init(); + await coversStorage.init(); + await bookManager.init(this.settings); bookManager.addEventListener(this.bookManagerEvent); diff --git a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue index 98d86fc3..d70ab44c 100644 --- a/client/components/Reader/RecentBooksPage/RecentBooksPage.vue +++ b/client/components/Reader/RecentBooksPage/RecentBooksPage.vue @@ -106,7 +106,8 @@
- +
+
@@ -213,6 +214,7 @@ import LockQueue from '../../../share/LockQueue'; import Window from '../../share/Window.vue'; import bookManager from '../share/bookManager'; import readerApi from '../../../api/reader'; +import coversStorage from '../share/coversStorage'; const componentOptions = { components: { @@ -240,6 +242,8 @@ class RecentBooksPage { showSameBook = false; archive = false; + covers = {}; + created() { this.commit = this.$store.commit; @@ -337,6 +341,7 @@ class RecentBooksPage { active: (activeBook.key == book.key), activeParent: false, inGroup: false, + coverPageUrl: book.coverPageUrl, //для сортировки loadTimeRaw, @@ -654,6 +659,43 @@ class RecentBooksPage { } return true; } + + makeCoverHtml(data) { + return ``; + } + + isLoadedCover(coverPageUrl) { + if (!coverPageUrl) + return false; + + let loadedCover = this.covers[coverPageUrl]; + if (!loadedCover) { + (async() => { + //сначала заглянем в storage + let data = await coversStorage.getData(coverPageUrl); + if (data) { + this.covers[coverPageUrl] = this.makeCoverHtml(data); + } else {//иначе идем на сервер + try { + data = await readerApi.getUploadedFileBuf(coverPageUrl); + await coversStorage.setData(coverPageUrl, data); + this.covers[coverPageUrl] = this.makeCoverHtml(data); + } catch (e) { + console.error(e); + } + } + })(); + } + + return (loadedCover != undefined); + } + + getCoverHtml(coverPageUrl) { + if (coverPageUrl && this.covers[coverPageUrl]) + return this.covers[coverPageUrl]; + else + return ''; + } } export default vueComponent(RecentBooksPage); diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js index 2ff421fb..9f4a9211 100644 --- a/client/components/Reader/share/BookParser.js +++ b/client/components/Reader/share/BookParser.js @@ -85,6 +85,7 @@ export default class BookParser { let binaryId = ''; let binaryType = ''; let dimPromises = []; + this.coverPageId = ''; //оглавление this.contents = []; @@ -289,7 +290,7 @@ export default class BookParser { const href = attrs.href.value; const alt = (attrs.alt && attrs.alt.value ? attrs.alt.value : ''); const {id, local} = this.imageHrefToId(href); - if (href[0] == '#') {//local + if (local) {//local imageNum++; if (inPara && !this.sets.showInlineImagesInCenter && !center) @@ -301,6 +302,11 @@ export default class BookParser { if (inPara && this.sets.showInlineImagesInCenter) newParagraph(); + + //coverpage + if (path == '/fictionbook/description/title-info/coverpage/image') { + this.coverPageId = id; + } } else {//external imageNum++; diff --git a/client/components/Reader/share/bookManager.js b/client/components/Reader/share/bookManager.js index cc7d76f9..fee42a52 100644 --- a/client/components/Reader/share/bookManager.js +++ b/client/components/Reader/share/bookManager.js @@ -2,8 +2,9 @@ import localForage from 'localforage'; import path from 'path-browserify'; import _ from 'lodash'; -import * as utils from '../../../share/utils'; import BookParser from './BookParser'; +import readerApi from '../../../api/reader'; +import * as utils from '../../../share/utils'; const maxDataSize = 500*1024*1024;//compressed bytes const maxRecentLength = 5000; @@ -345,9 +346,27 @@ class BookManager { const parsed = new BookParser(this.settings); const parsedMeta = await parsed.parse(data, callback); + + //cover page + let coverPageUrl = ''; + if (parsed.coverPageId && parsed.binary[parsed.coverPageId]) { + const bin = parsed.binary[parsed.coverPageId]; + const dataUrl = await utils.resizeImage(`data:${bin.type};base64,${bin.data}`); + + //отправим dataUrl на сервер в /upload + try { + await readerApi.uploadFileBuf(dataUrl, (url) => { + coverPageUrl = url; + }); + } catch (e) { + console.error(e); + } + } + const result = Object.assign({}, meta, parsedMeta, { length: data.length, textLength: parsed.textLength, + coverPageUrl, parsed }); diff --git a/client/share/utils.js b/client/share/utils.js index 916d94a0..c0f20519 100644 --- a/client/share/utils.js +++ b/client/share/utils.js @@ -363,4 +363,8 @@ export function getBookTitle(fb2) { ]).join(' - '); return result; +} + +export async function resizeImage(dataUrl) { + return dataUrl; } \ No newline at end of file