diff --git a/client/api/misc.js b/client/api/misc.js index dee0c134..94ebdab5 100644 --- a/client/api/misc.js +++ b/client/api/misc.js @@ -6,7 +6,7 @@ const api = axios.create({ class Misc { async loadConfig() { - const response = await api.post('/config', {params: ['name', 'version', 'mode']}); + const response = await api.post('/config', {params: ['name', 'version', 'mode', 'maxUploadFileSize']}); return response.data; } } diff --git a/client/api/reader.js b/client/api/reader.js index e6d73773..8031e10a 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -1,7 +1,6 @@ import axios from 'axios'; import {sleep} from '../share/utils'; -const maxFileUploadSize = 50*1024*1024; const api = axios.create({ baseURL: '/api/reader' }); @@ -75,9 +74,11 @@ class Reader { return await axios.get(url, options); } - async uploadFile(file, callback) { - if (file.size > maxFileUploadSize) - throw new Error(`Размер файла превышает ${maxFileUploadSize} байт`); + async uploadFile(file, maxUploadFileSize, callback) { + if (!maxUploadFileSize) + maxUploadFileSize = 10*1024*1024; + if (file.size > maxUploadFileSize) + throw new Error(`Размер файла превышает ${maxUploadFileSize} байт`); let formData = new FormData(); formData.append('file', file); diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 97b62e5e..d4fb7e8e 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -168,6 +168,7 @@ class Reader extends Vue { this.commit = this.$store.commit; this.dispatch = this.$store.dispatch; this.reader = this.$store.state.reader; + this.config = this.$store.state.config; this.$root.addKeyHook(this.keyHook); @@ -179,7 +180,7 @@ class Reader extends Vue { this.debouncedSetRecentBook = _.debounce(async(newValue) => { const recent = this.mostRecentBook(); - if (recent && recent.bookPos != newValue) { + if (recent && (recent.bookPos != newValue || recent.bookPosSeen !== this.bookPosSeen)) { await bookManager.setRecentBook(Object.assign({}, recent, {bookPos: newValue, bookPosSeen: this.bookPosSeen})); if (this.actionCur < 0 || (this.actionCur >= 0 && this.actionList[this.actionCur] != newValue)) @@ -713,7 +714,7 @@ class Reader extends Vue { progress.show(); progress.setState({state: 'upload'}); - const url = await readerApi.uploadFile(opts.file, (state) => { + const url = await readerApi.uploadFile(opts.file, this.config.maxUploadFileSize, (state) => { progress.setState(state); }); diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue index 8c071993..4f4c08c0 100644 --- a/client/components/Reader/TextPage/TextPage.vue +++ b/client/components/Reader/TextPage/TextPage.vue @@ -45,10 +45,13 @@ const minLayoutWidth = 100; export default @Component({ watch: { - bookPos: function(newValue) { - this.$emit('book-pos-changed', {bookPos: newValue, bookPosSeen: this.bookPosSeen}); + bookPos: function() { + this.$emit('book-pos-changed', {bookPos: this.bookPos, bookPosSeen: this.bookPosSeen}); this.draw(); }, + bookPosSeen: function() { + this.$emit('book-pos-changed', {bookPos: this.bookPos, bookPosSeen: this.bookPosSeen}); + }, settings: function() { this.debouncedLoadSettings(); }, @@ -69,6 +72,7 @@ class TextPage extends Vue { lastBook = null; bookPos = 0; + bookPosSeen = null; fontStyle = null; fontSize = null; diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js index 1d9ac436..d8dedb39 100644 --- a/client/components/Reader/share/BookParser.js +++ b/client/components/Reader/share/BookParser.js @@ -63,7 +63,8 @@ export default class BookParser { const growParagraph = (text, len) => { if (paraIndex < 0) { - newParagraph(text, len); + newParagraph(' ', 1); + growParagraph(text, len); return; } @@ -96,55 +97,63 @@ export default class BookParser { tag = elemName; path += '/' + elemName; - if ((tag == 'p' || tag == 'empty-line' || tag == 'v') && path.indexOf('/fictionbook/body/section') == 0) { - newParagraph(' ', 1); - } + if (path.indexOf('/fictionbook/body') == 0) { + if (tag == 'title') { + newParagraph(' ', 1); + bold = true; + center = true; + } - if (tag == 'emphasis' || tag == 'strong') { - growParagraph(`<${tag}>`, 0); - } + if (tag == 'emphasis' || tag == 'strong') { + growParagraph(`<${tag}>`, 0); + } - if (tag == 'title') { - newParagraph(' ', 1); - bold = true; - center = true; - } + if ((tag == 'p' || tag == 'empty-line' || tag == 'v')) { + newParagraph(' ', 1); + } - if (tag == 'subtitle') { - newParagraph(' ', 1); - bold = true; - } + if (tag == 'subtitle') { + newParagraph(' ', 1); + bold = true; + } - if (tag == 'epigraph') { - italic = true; - } + if (tag == 'epigraph') { + italic = true; + } - if (tag == 'stanza') { - newParagraph(' ', 1); + if (tag == 'poem') { + newParagraph(' ', 1); + } + + if (tag == 'text-author') { + newParagraph(' ', 4); + } } }; const onEndNode = (elemName) => {// eslint-disable-line no-unused-vars if (tag == elemName) { - if (tag == 'emphasis' || tag == 'strong') { - growParagraph(``, 0); - } + if (path.indexOf('/fictionbook/body') == 0) { + if (tag == 'title') { + bold = false; + center = false; + } - if (tag == 'title') { - bold = false; - center = false; - } + if (tag == 'emphasis' || tag == 'strong') { + growParagraph(``, 0); + } - if (tag == 'subtitle') { - bold = false; - } + if (tag == 'subtitle') { + bold = false; + } - if (tag == 'epigraph') { - italic = false; - } + if (tag == 'epigraph') { + italic = false; + } - if (tag == 'stanza') { - newParagraph(' ', 1); + if (tag == 'stanza') { + newParagraph(' ', 1); + } } path = path.substr(0, path.length - tag.length - 1); @@ -206,12 +215,12 @@ export default class BookParser { let tOpen = (center ? '
' : ''); tOpen += (bold ? '' : ''); tOpen += (italic ? '' : ''); - let tClose = (center ? '
' : ''); + let tClose = (italic ? '' : ''); tClose += (bold ? '' : ''); - tClose += (italic ? '' : ''); + tClose += (center ? '' : ''); if (path.indexOf('/fictionbook/body/title') == 0) { - newParagraph(`${tOpen}${text}${tClose}`, text.length, true); + growParagraph(`${tOpen}${text}${tClose}`, text.length, true); } if (path.indexOf('/fictionbook/body/section') == 0) { diff --git a/package-lock.json b/package-lock.json index 698fbd36..d04e1d2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Liberama", - "version": "0.1.0", + "version": "0.1.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -6501,9 +6501,9 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "minipass": { "version": "2.3.5", @@ -6567,6 +6567,13 @@ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } } }, "move-concurrently": { diff --git a/package.json b/package.json index c57049b6..671143ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Liberama", - "version": "0.1.3", + "version": "0.1.4", "engines": { "node": ">=10.0.0" }, @@ -70,6 +70,7 @@ "iconv-lite": "^0.4.24", "localforage": "^1.7.3", "lodash": "^4.17.11", + "minimist": "^1.2.0", "multer": "^1.4.1", "path-browserify": "^1.0.0", "sql-template-strings": "^2.2.2", diff --git a/server/config/base.js b/server/config/base.js index 0670e60b..0ec65f87 100644 --- a/server/config/base.js +++ b/server/config/base.js @@ -17,6 +17,10 @@ module.exports = { dbFileName: 'db.sqlite', loggingEnabled: true, + maxUploadFileSize: 50*1024*1024,//50Мб + maxTempPublicDirSize: 512*1024*1024,//512Мб + maxUploadPublicDirSize: 200*1024*1024,//100Мб + servers: [ { serverName: '1', @@ -24,12 +28,6 @@ module.exports = { ip: '0.0.0.0', port: '33080', }, - { - serverName: '2', - mode: 'omnireader', - ip: '0.0.0.0', - port: '33081', - }, ], }; diff --git a/server/config/configSaver.js b/server/config/configSaver.js new file mode 100644 index 00000000..f39b920f --- /dev/null +++ b/server/config/configSaver.js @@ -0,0 +1,36 @@ +const fs = require('fs-extra'); +const _ = require('lodash'); + +const propsToSave = [ + 'maxUploadFileSize', + 'maxTempPublicDirSize', + 'maxUploadPublicDirSize', + + 'servers', +]; + +async function load(config, configFilename) { + if (!configFilename) { + configFilename = `${config.dataDir}/config.json`; + + if (!await fs.pathExists(configFilename)) { + save(config); + return; + } + } + + const data = await fs.readFile(configFilename, 'utf8'); + Object.assign(config, JSON.parse(data)); +} + +async function save(config) { + const configFilename = `${config.dataDir}/config.json`; + const dataToSave = _.pick(config, propsToSave); + + await fs.writeFile(configFilename, JSON.stringify(dataToSave, null, 4)); +} + +module.exports = { + load, + save +}; \ No newline at end of file diff --git a/server/config/production.js b/server/config/production.js index 98c40e72..d98af428 100644 --- a/server/config/production.js +++ b/server/config/production.js @@ -19,12 +19,6 @@ module.exports = Object.assign({}, base, { ip: '0.0.0.0', port: '44080', }, - { - serverName: '2', - mode: 'omnireader', - ip: '0.0.0.0', - port: '44081', - }, ], } diff --git a/server/core/ReaderWorker.js b/server/core/ReaderWorker.js index 7c9d5783..a087da8c 100644 --- a/server/core/ReaderWorker.js +++ b/server/core/ReaderWorker.js @@ -8,8 +8,6 @@ const FileDecompressor = require('./FileDecompressor'); const BookConverter = require('./BookConverter'); const utils = require('./utils'); -const maxTempPublicDirSize = 512*1024*1024;//512Мб -const maxUploadDirSize = 200*1024*1024;//100Мб let singleCleanExecute = false; class ReaderWorker { @@ -27,8 +25,8 @@ class ReaderWorker { this.bookConverter = new BookConverter(); if (!singleCleanExecute) { - this.periodicCleanDir(this.config.tempPublicDir, maxTempPublicDirSize, 60*60*1000);//1 раз в час - this.periodicCleanDir(this.config.uploadDir, maxUploadDirSize, 60*60*1000);//1 раз в час + this.periodicCleanDir(this.config.tempPublicDir, this.config.maxTempPublicDirSize, 60*60*1000);//1 раз в час + this.periodicCleanDir(this.config.uploadDir, this.config.maxUploadPublicDirSize, 60*60*1000);//1 раз в час singleCleanExecute = true; } } diff --git a/server/index.js b/server/index.js index fcb697e1..1d8e79e9 100644 --- a/server/index.js +++ b/server/index.js @@ -1,9 +1,11 @@ const config = require('./config'); - const {initLogger, getLog} = require('./core/getLogger'); initLogger(config); const log = getLog(); +const configSaver = require('./config/configSaver'); +const argv = require('minimist')(process.argv.slice(2)); + const fs = require('fs-extra'); const path = require('path'); const express = require('express'); @@ -23,15 +25,17 @@ async function init() { await fs.remove(appDir); await fs.move(appNewDir, appDir); } + + //загружаем конфиг из файла + await configSaver.load(config, argv.config); } async function main() { - const connPool = new SqliteConnectionPool(20, config); - log('Initializing'); await init(); log('Opening database'); + const connPool = new SqliteConnectionPool(20, config); await connPool.init(); //servers @@ -42,7 +46,7 @@ async function main() { let devModule = undefined; if (serverConfig.branch == 'development') { - const devFileName = './dev.js'; //ignored by pkg -50Mb executable size + const devFileName = './dev.js'; //require ignored by pkg -50Mb executable size devModule = require(devFileName); devModule.webpackDevMiddleware(app); } @@ -80,4 +84,12 @@ async function main() { } } -main(); \ No newline at end of file + +(async() => { + try { + await main(); + } catch (e) { + console.error(e.message); + process.exit(1); + } +})(); \ No newline at end of file diff --git a/server/routes.js b/server/routes.js index aa6014c0..0b57da60 100644 --- a/server/routes.js +++ b/server/routes.js @@ -2,8 +2,6 @@ const c = require('./controllers'); const utils = require('./core/utils'); const multer = require('multer'); -const maxUploadSize = 50*1024*1024; - function initRoutes(app, connPool, config) { const misc = new c.MiscController(connPool, config); const reader = new c.ReaderController(connPool, config); @@ -22,7 +20,7 @@ function initRoutes(app, connPool, config) { cb(null, utils.randomHexString(30)); } }); - const upload = multer({ storage, limits: {fileSize: maxUploadSize} }); + const upload = multer({ storage, limits: {fileSize: config.maxUploadFileSize} }); //routes const routes = [