diff --git a/package.json b/package.json index 41cc316..5b18513 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "react-monaco-editor": "^0.36.0", "react-pdf": "^4.1.0", "react-photo-view": "^0.4.0", + "react-reader": "^0.21.1", "react-redux": "^7.1.3", "react-router": "^5.1.2", "react-router-dom": "^5.1.2", diff --git a/src/App.js b/src/App.js index 1fcbfc9..279304d 100644 --- a/src/App.js +++ b/src/App.js @@ -31,6 +31,7 @@ import Reset from "./component/Login/Reset"; import PageLoading from "./component/Placeholder/PageLoading"; import CodeViewer from "./component/Viewer/Code"; import MusicPlayer from "./component/FileManager/MusicPlayer"; +import EpubViewer from "./component/Viewer/Epub"; const PDFViewer = React.lazy(() => import(/* webpackChunkName: "pdf" */ "./component/Viewer/PDF") @@ -127,6 +128,10 @@ export default function App() { + + + + @@ -204,6 +209,10 @@ export default function App() { + + + + diff --git a/src/component/FileManager/TypeIcon.js b/src/component/FileManager/TypeIcon.js index ce85d7d..fb75c84 100644 --- a/src/component/FileManager/TypeIcon.js +++ b/src/component/FileManager/TypeIcon.js @@ -24,6 +24,7 @@ import FileShowIcon from "@material-ui/icons/InsertDriveFile"; import { lighten } from "@material-ui/core/styles"; import useTheme from "@material-ui/core/styles/useTheme"; import { Avatar } from "@material-ui/core"; +import { MenuBook } from "@material-ui/icons"; const icons = { audio: { @@ -102,6 +103,10 @@ const icons = { color: "#f4d003", icon: LanguageJavascript, }, + epub: { + color: "#81b315", + icon: MenuBook, + }, }; const getColor = (theme, color) => diff --git a/src/component/Share/SharedFile.js b/src/component/Share/SharedFile.js index 37e8b2e..5fc215b 100644 --- a/src/component/Share/SharedFile.js +++ b/src/component/Share/SharedFile.js @@ -201,6 +201,13 @@ class SharedFileCompoment extends Component { encodeURIComponent(this.props.share.source.name) ); return; + case "epub": + this.props.history.push( + this.props.share.key + + "/epub?name=" + + encodeURIComponent(this.props.share.source.name) + ); + return; default: this.props.toggleSnackbar( "top", diff --git a/src/component/Viewer/Epub.js b/src/component/Viewer/Epub.js new file mode 100644 index 0000000..bf849d0 --- /dev/null +++ b/src/component/Viewer/Epub.js @@ -0,0 +1,78 @@ +import React, { Suspense, useCallback, useMemo, useState } from "react"; +import { makeStyles } from "@material-ui/core/styles"; +import { useLocation, useParams, useRouteMatch } from "react-router"; +import { useDispatch } from "react-redux"; +import { toggleSnackbar } from "../../redux/explorer"; +import UseFileSubTitle from "../../hooks/fileSubtitle"; +import { getPreviewURL } from "../../middleware/Api"; +import pathHelper from "../../utils/page"; +import TextLoading from "../Placeholder/TextLoading"; + +const ReactReader = React.lazy(() => + import(/* webpackChunkName: "ReactReader" */ "react-reader").then((m) => ({ + default: m.ReactReader, + })) +); + +const useStyles = makeStyles((theme) => ({ + layout: { + height: "calc(100vh - 64px)", + }, + paper: { + marginBottom: theme.spacing(3), + }, +})); + +function useQuery() { + return new URLSearchParams(useLocation().search); +} + +export default function EpubViewer() { + const math = useRouteMatch(); + const location = useLocation(); + const query = useQuery(); + const { id } = useParams(); + const { path } = UseFileSubTitle(query, math, location); + const isShare = pathHelper.isSharePage(location.pathname); + + const [currentLocation, setLocation] = useState(null); + const locationChanged = (epubcifi) => { + setLocation(epubcifi); + }; + + const dispatch = useDispatch(); + const ToggleSnackbar = useCallback( + (vertical, horizontal, msg, color) => + dispatch(toggleSnackbar(vertical, horizontal, msg, color)), + [dispatch] + ); + + const fileUrl = useMemo( + () => + getPreviewURL( + isShare, + id, + query.get("id"), + query.get("share_path") + ), + [id, location, path] + ); + + const classes = useStyles(); + return ( +
+ }> + + +
+ ); +} diff --git a/src/config.ts b/src/config.ts index a2474bc..32ed92d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -21,6 +21,7 @@ export const audioPreviewSuffix = ["mp3", "ogg", "flac", "m4a"]; export const videoPreviewSuffix = ["mp4", "mkv", "webm", "avi", "m3u8", "mov"]; export const pdfPreviewSuffix = ["pdf"]; export const editSuffix = ["md", "txt"]; +export const epubSuffix = ["epub"]; export const codePreviewSuffix = { json: "json", php: "php", @@ -64,6 +65,7 @@ export const mediaType = { cpp: ["cpp"], c: ["c"], js: ["js", "jsx"], + epub: epubSuffix, }; export const policyTypeMap = { local: "本机", @@ -91,6 +93,8 @@ export const isPreviewable = (name: any) => { return "pdf"; } else if (Object.keys(codePreviewSuffix).indexOf(suffix) !== -1) { return "code"; + } else if (epubSuffix.indexOf(suffix) !== -1) { + return "epub"; } return false; }; diff --git a/src/redux/explorer/action.ts b/src/redux/explorer/action.ts index 001bdee..ff97c1c 100644 --- a/src/redux/explorer/action.ts +++ b/src/redux/explorer/action.ts @@ -473,6 +473,9 @@ export const openPreview = (share: any) => { case "code": dispatch(openViewer("code", selected[0], isShare)); return; + case "epub": + dispatch(openViewer("epub", selected[0], isShare)); + return; default: dispatch(startDownload(share, selected[0])); return; diff --git a/yarn.lock b/yarn.lock index fec28d6..d96a0c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,6 +1773,13 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/localforage@0.0.34": + version "0.0.34" + resolved "https://registry.yarnpkg.com/@types/localforage/-/localforage-0.0.34.tgz#5e31c32dd8791ec4b9ff3ef47c9cb55b2d0d9438" + integrity sha1-XjHDLdh5HsS5/z70fJy1Wy0NlDg= + dependencies: + localforage "*" + "@types/minimatch@*": version "3.0.5" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" @@ -2081,6 +2088,11 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" +"@xmldom/xmldom@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" + integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3504,6 +3516,11 @@ core-js@^2.4.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== +core-js@^3.18.3: + version "3.22.2" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.2.tgz#3ea0a245b0895fa39d1faa15fe75d91ade504a01" + integrity sha512-Z5I2vzDnEIqO2YhELVMFcL1An2CIsFe9Q7byZhs8c/QxummxZlAHw33TUHbIte987LkisOgL0LwQ1P9D6VISnA== + core-js@^3.5.0: version "3.21.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" @@ -4374,6 +4391,21 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +epubjs@^0.3.93: + version "0.3.93" + resolved "https://registry.yarnpkg.com/epubjs/-/epubjs-0.3.93.tgz#100c4597db152fc07d5246be38acca928b6b0b22" + integrity sha512-c06pNSdBxcXv3dZSbXAVLE1/pmleRhOT6mXNZo6INKmvuKpYB65MwU/lO7830czCtjIiK9i+KR+3S+p0wtljrw== + 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" + errno@^0.1.3, errno@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -4432,7 +4464,16 @@ es5-ext@^0.10.35, es5-ext@^0.10.50: es6-symbol "~3.1.3" next-tick "~1.0.0" -es6-iterator@2.0.3, es6-iterator@~2.0.3: +es5-ext@~0.10.14: + version "0.10.61" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.61.tgz#311de37949ef86b6b0dcea894d1ffedb909d3269" + integrity sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@2.0.3, es6-iterator@^2.0.3, es6-iterator@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= @@ -4441,7 +4482,7 @@ es6-iterator@2.0.3, es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-symbol@^3.1.1, es6-symbol@~3.1.3: +es6-symbol@^3.1.1, es6-symbol@^3.1.3, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== @@ -4705,6 +4746,14 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + eventemitter3@^4.0.0, eventemitter3@^4.0.1: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -5769,6 +5818,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" @@ -7006,6 +7060,16 @@ jsx-ast-utils@^2.2.1: array-includes "^3.1.3" object.assign "^4.1.2" +jszip@^3.7.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.9.1.tgz#784e87f328450d1e8151003a9c67733e2b901051" + integrity sha512-H9A60xPqJ1CuC4Ka6qxzXZeU8aNmgOeP5IFqwJbQQwtu2EUYxota3LdsiZWplF7Wgd9tkAd0mdu36nceSaPuYw== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + set-immediate-shim "~1.0.1" + killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -7090,6 +7154,20 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + dependencies: + immediate "~3.0.5" + +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -7155,6 +7233,13 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" +localforage@*, localforage@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" + integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== + dependencies: + lie "3.1.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7326,6 +7411,11 @@ marked@^0.6.2: resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.3.tgz#79babad78af638ba4d522a9e715cdfdd2429e946" integrity sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ== +marks-pane@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/marks-pane/-/marks-pane-1.0.9.tgz#c0b5ab813384d8cd81faaeb3bbf3397dc809c1b3" + integrity sha512-Ahs4oeG90tbdPWwAJkAAoHg2lRR8lAs9mZXETNPO9hYg3AkjUJBKi1NQ4aaIQZVGrig7c/3NUV1jANl8rFTeMg== + material-colors@^1.2.1: version "1.2.6" resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46" @@ -7679,6 +7769,11 @@ neo-async@^2.5.0, neo-async@^2.6.1: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + next-tick@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" @@ -8131,7 +8226,7 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pako@~1.0.5: +pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -8293,6 +8388,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +path-webpack@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/path-webpack/-/path-webpack-0.0.3.tgz#ff6dec749eec5a94605c04d5f63fc55607a03a16" + integrity sha1-/23sdJ7sWpRgXATV9j/FVgegOhY= + pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -9502,6 +9602,15 @@ react-photo-view@^0.4.0: lodash.debounce "^4.0.8" lodash.uniqueid "^4.0.1" +react-reader@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/react-reader/-/react-reader-0.21.1.tgz#2baa5d884d98cb3fb42c68b4cbbd748a61a97156" + integrity sha512-6ocGxzgsHLk6WnJO1BsLymWh4rcP+wzuGOj3Xiq02W9cmt8OdvVeus6JtqwvEmgze8iNNdTAcXxDyjl8CkWiuQ== + dependencies: + epubjs "^0.3.93" + prop-types "^15.8.1" + react-swipeable "^6.2.1" + react-redux@^7.1.3: version "7.2.6" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.6.tgz#49633a24fe552b5f9caf58feb8a138936ddfe9aa" @@ -9561,6 +9670,11 @@ react-smooth@^2.0.0: raf "^3.4.0" react-transition-group "2.9.0" +react-swipeable@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/react-swipeable/-/react-swipeable-6.2.1.tgz#7359fadda9917ee8b214e946447b56d3c7b0d314" + integrity sha512-JpTj+tjJTDcIWtoMkab6zfwWD1T1tBzUyEfXsXnohnNkwA2dTuNS0gtN7HoxU1Qa+e3GDnfNYk2z7vwzfO4SoQ== + react-transition-group@2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" @@ -10296,6 +10410,11 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-immediate-shim@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"