Files
filestash/client/pages/viewerpage.js
2023-04-18 00:01:32 +10:00

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)));