feat: Added epub preview. Resolves #3375 (#3376)

pull/3343/merge
Dmitriy 2024-08-17 20:07:55 +03:00 committed by GitHub
parent a53aac1c30
commit 99a6382b32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 424 additions and 19 deletions

View File

@ -32,6 +32,7 @@
"vue-final-modal": "^4.5.4",
"vue-i18n": "^9.10.2",
"vue-lazyload": "^3.0.0",
"vue-reader": "^1.2.14",
"vue-router": "^4.3.0",
"vue-toastification": "^2.0.0-rc.5"
},
@ -2762,6 +2763,16 @@
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/localforage": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/localforage/-/localforage-0.0.34.tgz",
"integrity": "sha512-tJxahnjm9dEI1X+hQSC5f2BSd/coZaqbIl1m3TCl0q9SVuC52XcXfV0XmoCU1+PmjyucuVITwoTnN8OlTbEXXA==",
"deprecated": "This is a stub types definition for localforage (https://github.com/localForage/localForage). localforage provides its own type definitions, so you don't need @types/localforage installed!",
"license": "MIT",
"dependencies": {
"localforage": "*"
}
},
"node_modules/@types/lodash": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz",
@ -4097,8 +4108,7 @@
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"dev": true
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cross-spawn": {
"version": "7.0.3",
@ -4148,6 +4158,19 @@
"resolved": "https://registry.npmjs.org/custom-error-instance/-/custom-error-instance-2.1.1.tgz",
"integrity": "sha512-p6JFxJc3M4OTD2li2qaHkDCw9SfMw82Ldr6OC9Je1aXiGfhx2W8p3GaoeaGrPJTUN9NirTM/KTxHWMUdR1rsUg=="
},
"node_modules/d": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
"integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
"license": "ISC",
"dependencies": {
"es5-ext": "^0.10.64",
"type": "^2.7.2"
},
"engines": {
"node": ">=0.12"
}
},
"node_modules/data-urls": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
@ -4299,6 +4322,72 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/epubjs": {
"version": "0.3.93",
"resolved": "https://registry.npmjs.org/epubjs/-/epubjs-0.3.93.tgz",
"integrity": "sha512-c06pNSdBxcXv3dZSbXAVLE1/pmleRhOT6mXNZo6INKmvuKpYB65MwU/lO7830czCtjIiK9i+KR+3S+p0wtljrw==",
"license": "BSD-2-Clause",
"dependencies": {
"@types/localforage": "0.0.34",
"@xmldom/xmldom": "^0.7.5",
"core-js": "^3.18.3",
"event-emitter": "^0.3.5",
"jszip": "^3.7.1",
"localforage": "^1.10.0",
"lodash": "^4.17.21",
"marks-pane": "^1.0.9",
"path-webpack": "0.0.3"
}
},
"node_modules/epubjs/node_modules/@xmldom/xmldom": {
"version": "0.7.13",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.13.tgz",
"integrity": "sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/es5-ext": {
"version": "0.10.64",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
"integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"esniff": "^2.0.1",
"next-tick": "^1.1.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
"license": "MIT",
"dependencies": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"node_modules/es6-symbol": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
"integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
"license": "ISC",
"dependencies": {
"d": "^1.0.2",
"ext": "^1.7.0"
},
"engines": {
"node": ">=0.12"
}
},
"node_modules/esbuild": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
@ -4657,6 +4746,21 @@
"node": ">=8"
}
},
"node_modules/esniff": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
"integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
"license": "ISC",
"dependencies": {
"d": "^1.0.1",
"es5-ext": "^0.10.62",
"event-emitter": "^0.3.5",
"type": "^2.7.2"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/espree": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
@ -4734,6 +4838,25 @@
"node": ">=0.10.0"
}
},
"node_modules/event-emitter": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
"integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
"license": "MIT",
"dependencies": {
"d": "1",
"es5-ext": "~0.10.14"
}
},
"node_modules/ext": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
"integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
"license": "ISC",
"dependencies": {
"type": "^2.7.2"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -5160,6 +5283,12 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
"license": "MIT"
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -5203,8 +5332,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@ -5318,8 +5446,7 @@
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"dev": true
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
@ -5465,6 +5592,18 @@
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
"dev": true
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"license": "(MIT OR GPL-3.0-or-later)",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
@ -5500,6 +5639,33 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"license": "MIT",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/localforage": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
"license": "Apache-2.0",
"dependencies": {
"lie": "3.1.1"
}
},
"node_modules/localforage/node_modules/lie": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
"license": "MIT",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -5518,8 +5684,7 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
@ -5636,6 +5801,12 @@
"node": ">=12"
}
},
"node_modules/marks-pane": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz",
"integrity": "sha512-Ahs4oeG90tbdPWwAJkAAoHg2lRR8lAs9mZXETNPO9hYg3AkjUJBKi1NQ4aaIQZVGrig7c/3NUV1jANl8rFTeMg==",
"license": "MIT"
},
"node_modules/material-icons": {
"version": "1.13.12",
"resolved": "https://registry.npmjs.org/material-icons/-/material-icons-1.13.12.tgz",
@ -5796,6 +5967,12 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
"license": "ISC"
},
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
@ -5976,6 +6153,12 @@
"node": ">=8"
}
},
"node_modules/path-webpack": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/path-webpack/-/path-webpack-0.0.3.tgz",
"integrity": "sha512-AmeDxedoo5svf7aB3FYqSAKqMxys014lVKBzy1o/5vv9CtU7U4wgGWL1dA2o6MOzcD53ScN4Jmiq6VbtLz1vIQ==",
"license": "MIT"
},
"node_modules/pathe": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
@ -6216,8 +6399,7 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/proper-lockfile": {
"version": "4.1.2",
@ -6308,7 +6490,6 @@
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dev": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@ -6557,8 +6738,7 @@
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/safe-json-parse": {
"version": "4.0.0",
@ -6619,6 +6799,12 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -6719,7 +6905,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@ -6956,6 +7141,12 @@
"node": ">=18"
}
},
"node_modules/type": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
"integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
"license": "ISC"
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@ -7134,8 +7325,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"dev": true
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/video.js": {
"version": "8.10.0",
@ -7374,6 +7564,55 @@
"resolved": "https://registry.npmjs.org/vue-lazyload/-/vue-lazyload-3.0.0.tgz",
"integrity": "sha512-h2keL/Rj550dLgesgOtXJS9qOiSMmuJNeVlfNAYV1/IYwOQYaWk5mFJlwRxmZDK9YC5gECcFLYYj7z1lKSf9ug=="
},
"node_modules/vue-reader": {
"version": "1.2.14",
"resolved": "https://registry.npmjs.org/vue-reader/-/vue-reader-1.2.14.tgz",
"integrity": "sha512-aGtJsmEdYcWLZmMqOrAzcb8/SYUcaz8zj9GtYFP+1cHs53IBG45/uZkywn/7RjWwFtiixSkLO7w/7qiqcyjwGQ==",
"license": "ISC",
"workspaces": [
"test/vue2",
"test/vue2.7"
],
"dependencies": {
"epubjs": "^0.3.93",
"vue-demi": "latest"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^2.0.0 || >=3.0.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-reader/node_modules/vue-demi": {
"version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true,
"license": "MIT",
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/vue-router": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz",

View File

@ -42,6 +42,7 @@
"vue-final-modal": "^4.5.4",
"vue-i18n": "^9.10.2",
"vue-lazyload": "^3.0.0",
"vue-reader": "^1.2.14",
"vue-router": "^4.3.0",
"vue-toastification": "^2.0.0-rc.5"
},

View File

@ -0,0 +1,78 @@
.epub-reader {
display: flex;
align-items: flex-end;
height: 100%;
}
.epub-reader .container {
width: 100%;
max-width: 100%;
height: calc(100% - 64px);
margin: 0;
}
.epub-reader .arrow.pre {
left: 0;
}
.epub-reader .readerArea {
background-color: var(--background) !important;
}
.epub-reader .titleArea {
color: var(--text);
}
.epub-reader .tocButtonBar {
background: var(--divider);
}
.epub-reader .tocButton {
color: var(--text);
}
.epub-reader .tocButton.tocButtonExpanded {
background-color: var(--background);
}
.epub-reader .tocAreaButton.active {
color: var(--blue);
border-color: var(--dark-blue);
}
.epub-reader .tocArea {
background-color: var(--background);
}
.epub-reader .readerArea .arrow {
color: var(--text);
}
.epub-reader .readerArea .arrow:hover {
color: var(--hover);
}
.epub-reader .size {
display: flex;
gap: 5px;
align-items: center;
z-index: 111;
right: 25px;
outline: none;
position: absolute;
top: 78px;
}
.epub-reader .size span {
color: var(--textSecondary);
}
.epub-reader .size button {
background: none;
outline: none;
border: none;
width: 25px;
height: 25px;
color: var(--textPrimary);
padding: 0;
}

View File

@ -15,6 +15,7 @@
@import "./dashboard.css";
@import "./login.css";
@import "./mobile.css";
@import "./epubReader.css";
/* For testing only
:focus {

View File

@ -6,7 +6,7 @@
@mousemove="toggleNavigation"
@touchstart="toggleNavigation"
>
<header-bar v-if="isPdf || showNav">
<header-bar v-if="isPdf || isEpub || showNav">
<action icon="close" :label="$t('buttons.close')" @action="close()" />
<title>{{ name }}</title>
<action
@ -57,7 +57,37 @@
</div>
<template v-else>
<div class="preview">
<ExtendedImage v-if="fileStore.req?.type == 'image'" :src="raw" />
<div v-if="isEpub" class="epub-reader">
<vue-reader
:location="location"
:url="raw"
:get-rendition="getRendition"
:epubInitOptions="{
requestCredentials: true,
}"
:epubOptions="{
allowPopups: true,
allowScriptedContent: true,
}"
@update:location="locationChange"
/>
<div class="size">
<button
@click="changeSize(Math.max(100, size - 10))"
class="reader-button"
>
<i class="material-icons">remove</i>
</button>
<button
@click="changeSize(Math.min(150, size + 10))"
class="reader-button"
>
<i class="material-icons">add</i>
</button>
<span>{{ size }}%</span>
</div>
</div>
<ExtendedImage v-else-if="fileStore.req?.type == 'image'" :src="raw" />
<audio
v-else-if="fileStore.req?.type == 'audio'"
ref="player"
@ -129,20 +159,69 @@
</template>
<script setup lang="ts">
import { useStorage } from "@vueuse/core";
import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { files as api } from "@/api";
import { createURL } from "@/api/utils";
import { resizePreview } from "@/utils/constants";
import url from "@/utils/url";
import throttle from "lodash/throttle";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue";
import ExtendedImage from "@/components/files/ExtendedImage.vue";
import VideoPlayer from "@/components/files/VideoPlayer.vue";
import { VueReader } from "vue-reader";
import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import VideoPlayer from "@/components/files/VideoPlayer.vue";
import type { Rendition } from "epubjs";
import { getTheme } from "@/utils/theme";
const location = useStorage("book-progress", 0, undefined, {
serializer: {
read: (v) => JSON.parse(v),
write: (v) => JSON.stringify(v),
},
});
const size = useStorage("book-size", 120, undefined, {
serializer: {
read: (v) => JSON.parse(v),
write: (v) => JSON.stringify(v),
},
});
const locationChange = (epubcifi: number) => {
location.value = epubcifi;
};
let rendition: Rendition | null = null;
const changeSize = (val: number) => {
size.value = val;
rendition?.themes.fontSize(`${val}%`);
};
const getRendition = (_rendition: Rendition) => {
rendition = _rendition;
switch (getTheme()) {
case "dark": {
rendition.themes.override("color", "rgba(255, 255, 255, 0.6)");
break;
}
case "light": {
rendition.themes.override("color", "rgb(111, 111, 111)");
break;
}
}
rendition.themes.registerRules("h2Transparent", {
"h1,h2,h3,h4": {
"background-color": "transparent !important",
},
});
rendition?.themes.fontSize(`${size.value}%`);
rendition.themes.select("h2Transparent");
rendition.themes.override("background-color", "transparent", true);
};
const mediaTypes: ResourceType[] = ["image", "video", "audio", "blob"];
@ -182,10 +261,17 @@ const raw = computed(() => {
return api.getPreviewURL(fileStore.req, "big");
}
if (isEpub.value) {
return createURL("api/raw" + fileStore.req?.path, {}, false);
}
return downloadUrl.value;
});
const isPdf = computed(() => fileStore.req?.extension.toLowerCase() == ".pdf");
const isEpub = computed(
() => fileStore.req?.extension.toLowerCase() == ".epub"
);
const isResizeEnabled = computed(() => resizePreview);