mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-10-31 18:16:00 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			204 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			204 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import React, { useReducer, useEffect } from "react";
 | |
| import { useHistory } from "react-router-dom";
 | |
| import Path from "path";
 | |
| 
 | |
| import "./viewerpage.scss";
 | |
| import "./error.scss";
 | |
| import { Files, Chromecast } from "../model/";
 | |
| import {
 | |
|     BreadCrumb, Bundle, NgIf, Loader, EventReceiver, LoggedInOnly, ErrorPage,
 | |
| } from "../components/";
 | |
| import { opener, notify, objectGet } from "../helpers/";
 | |
| import { FileDownloader, ImageViewer, PDFViewer, FormViewer } from "./viewerpage/";
 | |
| 
 | |
| const VideoPlayer = (props) => (
 | |
|     <Bundle
 | |
|         loader={import(/* webpackChunkName: "video" */"./viewerpage/videoplayer")}
 | |
|         symbol="VideoPlayer" overrides={["/overrides/video-transcoder.js"]}>
 | |
|         {(Comp) => <Comp {...props}/>}
 | |
|     </Bundle>
 | |
| );
 | |
| const IDE = (props) => (
 | |
|     <Bundle
 | |
|         loader={import(/* webpackChunkName: "ide" */"./viewerpage/ide")}
 | |
|         symbol="IDE">
 | |
|         {(Comp) => <Comp {...props}/>}
 | |
|     </Bundle>
 | |
| );
 | |
| const AudioPlayer = (props) => (
 | |
|     <Bundle
 | |
|         loader={import(/* webpackChunkName: "audioplayer" */"./viewerpage/audioplayer")}
 | |
|         symbol="AudioPlayer">
 | |
|         {(Comp) => <Comp {...props}/>}
 | |
|     </Bundle>
 | |
| );
 | |
| const Appframe = (props) => (
 | |
|     <Bundle
 | |
|         loader={import(/* webpackChunkName: "appframe" */"./viewerpage/appframe")}
 | |
|         symbol="AppFrame">
 | |
|         {(Comp) => <Comp {...props}/>}
 | |
|     </Bundle>
 | |
| );
 | |
| const EbookViewer = (props) => (
 | |
|     <Bundle
 | |
|         loader={import(/* webpackChunkName: "ebookviewer" */"./viewerpage/ebookviewer")}
 | |
|         symbol="EbookViewer">
 | |
|         {(Comp) => <Comp {...props}/>}
 | |
|     </Bundle>
 | |
| )
 | |
| 
 | |
| 
 | |
| export function ViewerPageComponent({ error, subscribe, unsubscribe, match, location }) {
 | |
|     const history = useHistory();
 | |
|     const currentUrl = history.location.pathname;
 | |
| 
 | |
|     const [state, setState] = useReducer((s, a) => {
 | |
|         return { ...s, ...a };
 | |
|     }, {
 | |
|         url: null,
 | |
|         opener: null,
 | |
|         content: null,
 | |
|         needSaving: false,
 | |
|         isSaving: false,
 | |
|         loading: false,
 | |
|         application_arguments: null,
 | |
|     });
 | |
|     const path = currentUrl.replace("/view", "").replace(/%23/g, "#") + (location.hash || "");
 | |
|     const filename = Path.basename(currentUrl.replace("/view", "")) || "untitled.dat";
 | |
| 
 | |
|     const save = (file) => {
 | |
|         setState({ isSaving: true, needSaving: false });
 | |
|         return (new Promise((done, err) => {
 | |
|             const reader = new FileReader();
 | |
|             reader.onload = () => done(reader.result);
 | |
|             reader.readAsText(file);
 | |
|         })).then((content) => {
 | |
|             let oldContent = state.content;
 | |
|             setState({ content: content });
 | |
|             return Files.save(path, file)
 | |
|                 .then(() => setState({ isSaving: false }))
 | |
|                 .catch((err) => {
 | |
|                     if (err && err.code === "CANCELLED") return;
 | |
|                     setState({ isSaving: false, needSaving: true, content: oldContent });
 | |
|                     notify.send(err, "error");
 | |
|                 });
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     const needSaving = (bool) => {
 | |
|         setState({ needSaving: bool });
 | |
|         return Promise.resolve();
 | |
|     };
 | |
| 
 | |
|     useEffect(() => {
 | |
|         const metadata = () => {
 | |
|             const [app_opener, app_args] = opener(path);
 | |
|             setState({ loading: true, needSaving: false, url: null, opener: null, application_arguments: null });
 | |
|             return Files.url(path).then((url) => {
 | |
|                 setState({
 | |
|                     url: url,
 | |
|                     opener: app_opener,
 | |
|                     application_arguments: app_args,
 | |
|                 });
 | |
|                 return app_opener;
 | |
|             }).catch((_err) => error(_err));
 | |
|         };
 | |
| 
 | |
|         const data_fetch = (app) => {
 | |
|             if (app !== "editor" && app !== "form") {
 | |
|                 setState({ loading: false });
 | |
|                 return null;
 | |
|             }
 | |
|             return Promise.all([
 | |
|                 Files.cat(path),
 | |
|                 Files.options(path),
 | |
|             ]).then((d) => {
 | |
|                 const [content, options] = d;
 | |
|                 setState({
 | |
|                     content: content,
 | |
|                     loading: false,
 | |
|                     acl: options["allow"],
 | |
|                 });
 | |
|             }).catch((err) => {
 | |
|                 if (err.code !== "BINARY_FILE") {
 | |
|                     error(err);
 | |
|                     return;
 | |
|                 }
 | |
|                 setState({
 | |
|                     loading: false,
 | |
|                     opener: "download",
 | |
|                 });
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         metadata().then(data_fetch);
 | |
|         return history.listen(() => {})
 | |
|     }, [path]);
 | |
| 
 | |
|     return (
 | |
|         <div className="component_page_viewerpage">
 | |
|             <BreadCrumb needSaving={state.needSaving} className="breadcrumb" path={path} />
 | |
|             <div className="page_container">
 | |
|                 <NgIf cond={state.loading === true}>
 | |
|                     <Loader/>
 | |
|                 </NgIf>
 | |
|                 <NgIf cond={state.loading === false}>
 | |
|                     <NgIf cond={state.opener === "editor"}>
 | |
|                         <IDE
 | |
|                             needSavingUpdate={needSaving}
 | |
|                             needSaving={state.needSaving}
 | |
|                             isSaving={state.isSaving}
 | |
|                             onSave={save}
 | |
|                             content={state.content || ""}
 | |
|                             url={state.url}
 | |
|                             path={path}
 | |
|                             acl={state.acl}
 | |
|                             filename={filename} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "image"}>
 | |
|                         <ImageViewer
 | |
|                             data={state.url}
 | |
|                             filename={filename}
 | |
|                             path={path} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "pdf"}>
 | |
|                         <PDFViewer
 | |
|                             data={state.url}
 | |
|                             filename={filename} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "video"}>
 | |
|                         <VideoPlayer
 | |
|                             data={state.url}
 | |
|                             filename={filename}
 | |
|                             path={path} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "form"}>
 | |
|                         <FormViewer
 | |
|                             needSavingUpdate={needSaving}
 | |
|                             needSaving={state.needSaving}
 | |
|                             isSaving={state.isSaving}
 | |
|                             onSave={save}
 | |
|                             content={state.content || ""}
 | |
|                             data={state.url}
 | |
|                             filename={filename} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "audio"}>
 | |
|                         <AudioPlayer data={state.url} filename={filename} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "download"}>
 | |
|                         <FileDownloader data={state.url} filename={filename} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "appframe"}>
 | |
|                         <Appframe data={path} filename={filename} args={state.application_arguments} />
 | |
|                     </NgIf>
 | |
|                     <NgIf cond={state.opener === "ebook"}>
 | |
|                         <EbookViewer filename={filename} data={state.url} />
 | |
|                     </NgIf>
 | |
|                 </NgIf>
 | |
|             </div>
 | |
|         </div>
 | |
|     );
 | |
| }
 | |
| 
 | |
| export const ViewerPage = ErrorPage(LoggedInOnly(EventReceiver(ViewerPageComponent)));
 | 
