mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 08:22:24 +01:00
114 lines
3.9 KiB
JavaScript
114 lines
3.9 KiB
JavaScript
import { createElement, createRender, nop } from "../../lib/skeleton/index.js";
|
|
import rxjs, { effect } from "../../lib/rx.js";
|
|
import { qs } from "../../lib/dom.js";
|
|
import { AjaxError } from "../../lib/error.js";
|
|
import { load as loadPlugin } from "../../model/plugin.js";
|
|
import { loadCSS } from "../../helpers/loader.js";
|
|
import { createLoader } from "../../components/loader.js";
|
|
import ctrlError from "../ctrl_error.js";
|
|
|
|
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
|
import { renderMenubar, buttonDownload } from "./component_menubar.js";
|
|
|
|
import * as THREE from "../../../lib/vendor/three/three.module.js";
|
|
import setup3D from "./application_3d/init.js";
|
|
import withLight from "./application_3d/scene_light.js";
|
|
import withCube from "./application_3d/scene_cube.js";
|
|
import ctrlToolbar from "./application_3d/toolbar.js";
|
|
|
|
class I3DLoader {
|
|
load() { throw new Error("NOT_IMPLEMENTED"); }
|
|
transform() { throw new Error("NOT_IMPLEMENTED"); }
|
|
is2D() { return false; }
|
|
}
|
|
|
|
export default async function(render, { mime, acl$, getDownloadUrl = nop, getFilename = nop, hasCube = true, hasMenubar = true }) {
|
|
const $page = createElement(`
|
|
<div class="component_3dviewer">
|
|
<component-menubar filename="${getFilename() || ""}" class="${!hasMenubar && "hidden"}"></component-menubar>
|
|
<div class="threeviewer_container">
|
|
<div class="drawarea"></div>
|
|
<div class="toolbar scroll-y"></div>
|
|
</div>
|
|
</div>
|
|
`);
|
|
render($page);
|
|
|
|
const $menubar = renderMenubar(
|
|
qs($page, "component-menubar"),
|
|
buttonDownload(getFilename(), getDownloadUrl()),
|
|
);
|
|
const $draw = qs($page, ".drawarea");
|
|
const $toolbar = qs($page, ".toolbar");
|
|
|
|
const removeLoader = createLoader($draw);
|
|
await effect(rxjs.from(loadPlugin(mime)).pipe(
|
|
rxjs.mergeMap(async(loader) => {
|
|
if (!loader) {
|
|
componentDownloader(render, { mime, acl$, getFilename, getDownloadUrl });
|
|
return rxjs.EMPTY;
|
|
}
|
|
return new (await loader(I3DLoader, { THREE }))();
|
|
}),
|
|
rxjs.mergeMap((loader) => new rxjs.Observable((observer) => loader.load(
|
|
getDownloadUrl(),
|
|
(object) => observer.next(loader.transform(object)),
|
|
null,
|
|
(err) => observer.error(err),
|
|
)).pipe(
|
|
removeLoader,
|
|
rxjs.mergeMap((mesh) => create3DScene({ mime, mesh, is2D: loader.is2D, $draw, $toolbar, $menubar, hasCube })),
|
|
)),
|
|
rxjs.catchError((err) => {
|
|
let _err = err;
|
|
if (err.response.status === 401) {
|
|
_err = new Error(err.message);
|
|
_err.status = err.response.status;
|
|
_err = new AjaxError(err.message, _err, "Not Authorised");
|
|
}
|
|
return ctrlError()(_err);
|
|
}),
|
|
));
|
|
}
|
|
|
|
function create3DScene({ mesh, $draw, $toolbar, $menubar, hasCube, is2D }) {
|
|
const refresh = [];
|
|
const { renderer, camera, scene, controls, box } = setup3D({
|
|
THREE,
|
|
$page: $draw,
|
|
mesh,
|
|
refresh,
|
|
$menubar,
|
|
is2D,
|
|
});
|
|
|
|
withLight({ scene, box });
|
|
if (hasCube && !is2D()) withCube({ camera, renderer, refresh, controls });
|
|
ctrlToolbar(createRender($toolbar), {
|
|
mesh,
|
|
controls,
|
|
camera,
|
|
refresh,
|
|
$menubar,
|
|
$toolbar,
|
|
is2D,
|
|
});
|
|
|
|
return rxjs.animationFrames().pipe(rxjs.tap(() => {
|
|
refresh.forEach((fn) => fn());
|
|
}));
|
|
}
|
|
|
|
export function init($root) {
|
|
const priors = ($root && [
|
|
$root.classList.add("component_page_viewerpage"),
|
|
loadCSS(import.meta.url, "./component_menubar.css"),
|
|
loadCSS(import.meta.url, "../ctrl_viewerpage.css"),
|
|
]);
|
|
|
|
return Promise.all([
|
|
loadCSS(import.meta.url, "./application_3d.css"),
|
|
initDownloader(),
|
|
...priors,
|
|
]);
|
|
}
|