Merge pull request #2484 from lbryio/comicbook-reader
Comic-book reader
This commit is contained in:
commit
d15a85eaaa
10 changed files with 96 additions and 4 deletions
|
@ -172,6 +172,7 @@
|
||||||
"three-full": "^17.1.0",
|
"three-full": "^17.1.0",
|
||||||
"tree-kill": "^1.1.0",
|
"tree-kill": "^1.1.0",
|
||||||
"video.js": "^7.2.2",
|
"video.js": "^7.2.2",
|
||||||
|
"villain": "btzr-io/Villain",
|
||||||
"wavesurfer.js": "^2.2.1",
|
"wavesurfer.js": "^2.2.1",
|
||||||
"webpack": "^4.28.4",
|
"webpack": "^4.28.4",
|
||||||
"webpack-bundle-analyzer": "^3.1.0",
|
"webpack-bundle-analyzer": "^3.1.0",
|
||||||
|
|
|
@ -30,6 +30,11 @@ const PdfViewer = React.lazy<*>(() =>
|
||||||
);
|
);
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
|
const ComicBookViewer = React.lazy<*>(() =>
|
||||||
|
import(/* webpackChunkName: "comicBookViewer" */
|
||||||
|
'component/viewers/comicBookViewer')
|
||||||
|
);
|
||||||
|
|
||||||
const ThreeViewer = React.lazy<*>(() =>
|
const ThreeViewer = React.lazy<*>(() =>
|
||||||
import(/* webpackChunkName: "threeViewer" */
|
import(/* webpackChunkName: "threeViewer" */
|
||||||
'component/viewers/threeViewer')
|
'component/viewers/threeViewer')
|
||||||
|
@ -128,6 +133,7 @@ class FileRender extends React.PureComponent<Props> {
|
||||||
const mediaTypes = {
|
const mediaTypes = {
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
'3D-file': <ThreeViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
|
'3D-file': <ThreeViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
|
||||||
|
'comic-book': <ComicBookViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
application: !source.url ? null : (
|
application: !source.url ? null : (
|
||||||
|
|
|
@ -351,7 +351,6 @@ class MediaPlayer extends React.PureComponent<Props, State> {
|
||||||
render() {
|
render() {
|
||||||
const { mediaType, claim } = this.props;
|
const { mediaType, claim } = this.props;
|
||||||
const { fileSource } = this.state;
|
const { fileSource } = this.state;
|
||||||
|
|
||||||
const isFileType = this.isSupportedFile();
|
const isFileType = this.isSupportedFile();
|
||||||
|
|
||||||
const isFileReady = fileSource && isFileType;
|
const isFileReady = fileSource && isFileType;
|
||||||
|
|
28
src/ui/component/viewers/comicBookViewer.jsx
Normal file
28
src/ui/component/viewers/comicBookViewer.jsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// @flow
|
||||||
|
import * as React from 'react';
|
||||||
|
import Villain from 'villain';
|
||||||
|
import 'villain/dist/style.css';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
source: {
|
||||||
|
fileType: string,
|
||||||
|
downloadPath: string,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const opts = {
|
||||||
|
workerPath: '/webworkers/worker-bundle.js',
|
||||||
|
allowFullScreen: false,
|
||||||
|
autoHideControls: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ComicBookViewer extends React.PureComponent<Props> {
|
||||||
|
render() {
|
||||||
|
const { downloadPath } = this.props.source || {};
|
||||||
|
const file = `file://${downloadPath}`;
|
||||||
|
|
||||||
|
return <Villain file={file} width={'100%'} height={'100%'} options={opts} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ComicBookViewer;
|
|
@ -56,6 +56,7 @@ class FilePage extends React.Component<Props> {
|
||||||
'script',
|
'script',
|
||||||
'document',
|
'document',
|
||||||
'3D-file',
|
'3D-file',
|
||||||
|
'comic-book',
|
||||||
// Bypass unplayable files
|
// Bypass unplayable files
|
||||||
// TODO: Find a better way to detect supported types
|
// TODO: Find a better way to detect supported types
|
||||||
'application',
|
'application',
|
||||||
|
|
|
@ -7,6 +7,7 @@ const formats = [
|
||||||
[/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
|
[/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
|
||||||
[/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'],
|
[/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'],
|
||||||
[/\.(stl|obj|fbx|gcode)$/i, '3D-file'],
|
[/\.(stl|obj|fbx|gcode)$/i, '3D-file'],
|
||||||
|
[/\.(cbr|cbt|cbz)$/i, 'comic-book'],
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function getMediaType(contentType, fileName) {
|
export default function getMediaType(contentType, fileName) {
|
||||||
|
|
4
static/webworkers/wasm-gen/libarchive.js
Normal file
4
static/webworkers/wasm-gen/libarchive.js
Normal file
File diff suppressed because one or more lines are too long
BIN
static/webworkers/wasm-gen/libarchive.wasm
Normal file
BIN
static/webworkers/wasm-gen/libarchive.wasm
Normal file
Binary file not shown.
10
static/webworkers/worker-bundle.js
Normal file
10
static/webworkers/worker-bundle.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
This webworker bundle is part of the libarchive.js module,
|
||||||
|
so we need to make sure that it is available in the public (static) directory,
|
||||||
|
since it will not get bundled if you're using a bundler tool such as webpack
|
||||||
|
(it's all bundled up already) and specify the correct path in Archive.init() method.
|
||||||
|
|
||||||
|
https://github.com/nika-begiashvili/libarchivejs#how-to-use
|
||||||
|
*/
|
||||||
|
|
||||||
|
!function(){"use strict";const e={32768:"FILE",16384:"DIR",40960:"SYMBOLIC_LINK",49152:"SOCKET",8192:"CHARACTER_DEVICE",24576:"BLOCK_DEVICE",4096:"NAMED_PIPE"};class t{constructor(e){this._wasmModule=e,this._runCode=e.runCode,this._file=null}open(e){null!==this._file&&(console.warn("Closing previous file"),this.close());const{promise:t,resolve:r,reject:s}=this._promiseHandles();this._file=e;const i=new FileReader;return i.onload=(()=>this._loadFile(i.result,r,s)),i.readAsArrayBuffer(e),t}close(){this._runCode.closeArchive(this._archive),this._wasmModule._free(this._filePtr),this._file=null,this._filePtr=null,this._archive=null}*entries(t=!1,r=null){let s;for(this._archive=this._runCode.openArchive(this._filePtr,this._fileLength);0!==(s=this._runCode.getNextEntry(this._archive));){const i={size:this._runCode.getEntrySize(s),path:this._runCode.getEntryName(s),type:e[this._runCode.getEntryType(s)],ref:s};if("FILE"===i.type){let e=i.path.split("/");i.fileName=e[e.length-1]}if(t&&r!==i.path)this._runCode.skipEntry(this._archive);else{const e=this._runCode.getFileData(this._archive,i.size);if(e<0)throw new Error(this._runCode.getError(this._archive));i.fileData=this._wasmModule.HEAP8.slice(e,e+i.size),this._wasmModule._free(e)}yield i}}_loadFile(e,t,r){try{const s=new Uint8Array(e);this._fileLength=s.length,this._filePtr=this._runCode.malloc(this._fileLength),this._wasmModule.HEAP8.set(s,this._filePtr),t()}catch(e){r(e)}}_promiseHandles(){let e=null,t=null;return{promise:new Promise((r,s)=>{e=r,t=s}),resolve:e,reject:t}}}self.Module=new class{constructor(){this.preRun=[],this.postRun=[],this.totalDependencies=0}onRuntimeInitialized(){this.runCode={getVersion:Module.cwrap("get_version","string",[]),openArchive:Module.cwrap("archive_open","number",["number","number"]),getNextEntry:Module.cwrap("get_next_entry","number",["number"]),getFileData:Module.cwrap("get_filedata","number",["number","number"]),skipEntry:Module.cwrap("archive_read_data_skip","number",["number"]),closeArchive:Module.cwrap("archive_close",null,["number"]),getEntrySize:Module.cwrap("archive_entry_size","number",["number"]),getEntryName:Module.cwrap("archive_entry_pathname","string",["number"]),getEntryType:Module.cwrap("archive_entry_filetype","number",["number"]),getError:Module.cwrap("archive_error_string","string",["number"]),malloc:Module.cwrap("malloc","number",["number"]),free:Module.cwrap("free",null,["number"])},this.ready&&this.ready()}print(...e){console.log(e)}printErr(...e){console.error(e)}monitorRunDependencies(e){}locateFile(e,t=""){return`wasm-gen/${t}${e}`}},importScripts("wasm-gen/libarchive.js");let r=null,s=!1;self.Module.ready=(()=>{r=new t(self.Module),s=!1,self.postMessage({type:"READY"})}),self.onmessage=(async({data:e})=>{if(s)return void self.postMessage({type:"BUSY"});let t=!1;s=!0;try{switch(e.type){case"HELLO":break;case"OPEN":await r.open(e.file),self.postMessage({type:"OPENED"});break;case"LIST_FILES":t=!0;case"EXTRACT_FILES":for(const e of r.entries(t))self.postMessage({type:"ENTRY",entry:e});self.postMessage({type:"END"});break;case"EXTRACT_SINGLE_FILE":for(const t of r.entries(!0,e.target))t.fileData&&self.postMessage({type:"FILE",entry:t});break;default:throw new Error("Invalid Command")}}catch(e){self.postMessage({type:"ERROR",error:{message:e.message,name:e.name,stack:e.stack}})}finally{s=!1}})}();
|
48
yarn.lock
48
yarn.lock
|
@ -762,7 +762,7 @@
|
||||||
pirates "^4.0.0"
|
pirates "^4.0.0"
|
||||||
source-map-support "^0.5.9"
|
source-map-support "^0.5.9"
|
||||||
|
|
||||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1":
|
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.3":
|
||||||
version "7.4.5"
|
version "7.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
|
||||||
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
|
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
|
||||||
|
@ -2484,6 +2484,11 @@ clone@^1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||||
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
||||||
|
|
||||||
|
clsx@^1.0.4:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec"
|
||||||
|
integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg==
|
||||||
|
|
||||||
coa@^2.0.2:
|
coa@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
|
resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
|
||||||
|
@ -3226,6 +3231,11 @@ cyclist@~0.2.2:
|
||||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
|
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
|
||||||
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
|
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
|
||||||
|
|
||||||
|
d3-array@^1.2.4:
|
||||||
|
version "1.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
|
||||||
|
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
|
||||||
|
|
||||||
damerau-levenshtein@^1.0.4:
|
damerau-levenshtein@^1.0.4:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz#780cf7144eb2e8dbd1c3bb83ae31100ccc31a414"
|
resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz#780cf7144eb2e8dbd1c3bb83ae31100ccc31a414"
|
||||||
|
@ -6598,6 +6608,11 @@ levn@^0.3.0, levn@~0.3.0:
|
||||||
prelude-ls "~1.1.2"
|
prelude-ls "~1.1.2"
|
||||||
type-check "~0.3.2"
|
type-check "~0.3.2"
|
||||||
|
|
||||||
|
libarchive.js@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/libarchive.js/-/libarchive.js-1.1.0.tgz#8cc21a5a8ee59e5a02ce6eb966e140a7a44622bc"
|
||||||
|
integrity sha512-vh0dHBPK00ggbmTupqFWfws46a5QO/S5ZQ36Ymdyo4R93crXewXKJpYDpC/HROgOofvO8ogDdOLmU5MX8xGfmQ==
|
||||||
|
|
||||||
lie@3.1.1:
|
lie@3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
|
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
|
||||||
|
@ -7893,6 +7908,11 @@ opener@^1.5.1:
|
||||||
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
|
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
|
||||||
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
|
integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
|
||||||
|
|
||||||
|
openseadragon@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/openseadragon/-/openseadragon-2.4.0.tgz#d0b28b37a953602c82432a0dbd8a3779dadf756f"
|
||||||
|
integrity sha512-e2fsoEiCDkmwc3vyrv396lkYu4c9CGlpbSX4kYE07eW0ZlEF5DnLbeY2PhqPTskkC1jlsPu2TGZwaZ9VhaAn/w==
|
||||||
|
|
||||||
opn@^5.5.0:
|
opn@^5.5.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
|
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"
|
||||||
|
@ -9340,7 +9360,17 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.1, rc@^1.2.7:
|
||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
strip-json-comments "~2.0.1"
|
strip-json-comments "~2.0.1"
|
||||||
|
|
||||||
react-dom@^16.8.2:
|
react-compound-slider@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-compound-slider/-/react-compound-slider-1.2.2.tgz#1cc6809bb2d0282ad90a06040e2b10635edfbea3"
|
||||||
|
integrity sha512-G2wD5CTjAOTjCnslpfjopB5qU6Kg0//3ChPifezSGtMali/1M/CRDCJAh6SQOgyDaQlNi/QV1Noo8Tvnjy2gcg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.4.3"
|
||||||
|
d3-array "^1.2.4"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
warning "^3.0.0"
|
||||||
|
|
||||||
|
react-dom@^16.8.2, react-dom@^16.8.6:
|
||||||
version "16.8.6"
|
version "16.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
|
||||||
integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
|
integrity sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==
|
||||||
|
@ -9468,7 +9498,7 @@ react-toggle@^4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.5"
|
||||||
|
|
||||||
react@^16.8.2:
|
react@^16.8.2, react@^16.8.6:
|
||||||
version "16.8.6"
|
version "16.8.6"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
|
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
|
||||||
integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
|
integrity sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==
|
||||||
|
@ -11774,6 +11804,18 @@ videostream@^2.5.1:
|
||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
range-slice-stream "^2.0.0"
|
range-slice-stream "^2.0.0"
|
||||||
|
|
||||||
|
villain@btzr-io/Villain:
|
||||||
|
version "0.0.7"
|
||||||
|
resolved "https://codeload.github.com/btzr-io/Villain/tar.gz/1f39a679cd78b08f8acc0b36615550eb91f6ee03"
|
||||||
|
dependencies:
|
||||||
|
clsx "^1.0.4"
|
||||||
|
libarchive.js "^1.1.0"
|
||||||
|
openseadragon "^2.4.0"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
react "^16.8.6"
|
||||||
|
react-compound-slider "^1.2.2"
|
||||||
|
react-dom "^16.8.6"
|
||||||
|
|
||||||
vm-browserify@0.0.4:
|
vm-browserify@0.0.4:
|
||||||
version "0.0.4"
|
version "0.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
|
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
|
||||||
|
|
Loading…
Reference in a new issue