mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 08:22:24 +01:00
chore (plugin): polish the new plugin interface
This commit is contained in:
parent
daf96fdcff
commit
1510e0bcda
8 changed files with 64 additions and 63 deletions
|
|
@ -57,6 +57,8 @@
|
|||
"gltf": "model/gltf+json",
|
||||
"glb": "model/gltf-binary",
|
||||
"gpx": "application/gpx+xml",
|
||||
"gp4": "application/x-guitar-pro",
|
||||
"gp5": "application/x-guitar-pro",
|
||||
"gz": "application/x-gzip",
|
||||
"heic": "image/heic",
|
||||
"heif": "image/heic",
|
||||
|
|
@ -92,6 +94,7 @@
|
|||
"mef": "image/x-mamiya-mef",
|
||||
"mid": "audio/midi",
|
||||
"midi": "application/x-midi",
|
||||
"mjs": "application/javascript",
|
||||
"mkv": "video/x-matroska",
|
||||
"mml": "text/mathml",
|
||||
"mng": "video/x-mng",
|
||||
|
|
@ -118,6 +121,7 @@
|
|||
"ogv": "application/ogg",
|
||||
"orf": "image/x-olympus-orf",
|
||||
"org": "text/org",
|
||||
"otf": "font/otf",
|
||||
"pdb": "application/x-pilot",
|
||||
"pdf": "application/pdf",
|
||||
"pef": "image/x-pentax-pef",
|
||||
|
|
@ -169,6 +173,7 @@
|
|||
"tiff": "image/tiff",
|
||||
"tk": "application/x-tcl",
|
||||
"ts": "text/plain",
|
||||
"ttf": "application/x-font-ttf",
|
||||
"txt": "text/plain",
|
||||
"url": "application/x-url",
|
||||
"vcf": "text/vcard",
|
||||
|
|
@ -185,7 +190,8 @@
|
|||
"wmlc": "application/vnd.wap.wmlc",
|
||||
"wms": "application/vnd.ogc.wms_xml",
|
||||
"wmv": "video/x-ms-wmv",
|
||||
"woff": "application/font-woff",
|
||||
"woff": "font/woff",
|
||||
"woff2": "font/woff2",
|
||||
"wrl": "x-world/x-vrml",
|
||||
"x3d": "model/x3d+xml",
|
||||
"x3dv": "model/x3d-vrml",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
const DEBUG = false;
|
||||
const log = (msg) => DEBUG && console.log(msg);
|
||||
|
||||
export default async function(baseURL, path, opts = {}) {
|
||||
const wasi = new Wasi();
|
||||
const wasm = await WebAssembly.instantiateStreaming(
|
||||
|
|
@ -43,11 +46,18 @@ export function readFS(fd) {
|
|||
return file.buffer.subarray(0, end);
|
||||
}
|
||||
|
||||
export function clearFS() {
|
||||
Object.keys(FS).forEach((key) => {
|
||||
if (key > 2) delete FS[key];
|
||||
});
|
||||
nextFd = 3;
|
||||
}
|
||||
|
||||
function getFile(path) {
|
||||
const allFds = Object.keys(FS);
|
||||
for (let i=allFds.length - 1; i>0; i--) {
|
||||
if (FS[allFds[i]].path === path) {
|
||||
console.log(`fileopen fd=${i} path=${path}`);
|
||||
log(` fileopen fd=${i} path=${path}`);
|
||||
return FS[allFds[i]];
|
||||
}
|
||||
}
|
||||
|
|
@ -182,7 +192,14 @@ export class Wasi {
|
|||
if (fd === 1 || fd === 2) {
|
||||
let msg = fd === 1? "stdout: " : "stderr: ";
|
||||
msg += new TextDecoder().decode(readFS(fd));
|
||||
FS[fd] = { buffer: new Uint8Array(0), position: 0, path: "" };
|
||||
console.log(msg);
|
||||
FS[fd] = {
|
||||
buffer: new Uint8Array(0),
|
||||
position: 0,
|
||||
path: FS[fd].path || "",
|
||||
};
|
||||
} else {
|
||||
log(`wasi::fd_write fd=${fd}`);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -204,7 +221,7 @@ export class Wasi {
|
|||
length,
|
||||
file.buffer.length - file.position,
|
||||
);
|
||||
if (bytesToRead <= 0) {
|
||||
if (bytesToRead < 0) {
|
||||
break;
|
||||
}
|
||||
memory.set(
|
||||
|
|
@ -214,6 +231,7 @@ export class Wasi {
|
|||
file.position += bytesToRead;
|
||||
totalBytesRead += bytesToRead;
|
||||
}
|
||||
log(`wasi::fd_read fd=${fd} iovs_len=${iovs_len} totalBytesRead=${totalBytesRead}`);
|
||||
new DataView(this.#instance.exports.memory.buffer).setUint32(
|
||||
nread,
|
||||
totalBytesRead,
|
||||
|
|
@ -222,7 +240,8 @@ export class Wasi {
|
|||
return 0;
|
||||
}
|
||||
|
||||
fd_seek(fd, offsetBigInt, whence) {
|
||||
fd_seek(fd, offsetBigInt, _, whence) {
|
||||
log(`wasi::fd_seek fd=${fd} offset=${offsetBigInt} whence=${whence}`);
|
||||
const offset = Number(offsetBigInt);
|
||||
const file = FS[fd];
|
||||
if (!file) {
|
||||
|
|
@ -283,7 +302,6 @@ export class Wasi {
|
|||
}
|
||||
|
||||
__syscall_openat(dirFd, pathPtr, flags, mode) {
|
||||
console.debug(`openat called with dirFd=${dirFd}, pathPtr=${pathPtr}, flags=${flags}, mode=${mode}`);
|
||||
const memory = new Uint8Array(this.#instance.exports.memory.buffer);
|
||||
let path = "";
|
||||
for (let i = pathPtr; memory[i] !== 0; i++) {
|
||||
|
|
@ -292,15 +310,15 @@ export class Wasi {
|
|||
const allFds = Object.keys(FS);
|
||||
for (let i=allFds.length - 1; i>0; i--) {
|
||||
if (FS[allFds[i]].path === path) {
|
||||
console.log(`fileopen fd=${i} path=${path}`);
|
||||
log(` syscall::openat::result fd=${i} path=${path}`);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
throw new Error("Unknown file for __syscall_openat");
|
||||
}
|
||||
|
||||
__syscall_stat64(pathPtr, buf) {
|
||||
console.log(`stat64`);
|
||||
log(` syscall::stat64 pathPtr=${pathPtr}, bufPtr=${buf}`);
|
||||
const memory = new Uint8Array(this.#instance.exports.memory.buffer);
|
||||
let path = "";
|
||||
for (let i = pathPtr; memory[i] !== 0; i++) {
|
||||
|
|
@ -309,11 +327,6 @@ export class Wasi {
|
|||
const file = getFile(path);
|
||||
const HEAP32 = new Int32Array(this.#instance.exports.memory.buffer);
|
||||
const HEAPU32 = new Uint32Array(this.#instance.exports.memory.buffer);
|
||||
|
||||
const tempI64 = [0, 0];
|
||||
const tempDouble = 0;
|
||||
|
||||
// Dummy stat data
|
||||
const stat = {
|
||||
dev: 1,
|
||||
ino: 42,
|
||||
|
|
@ -329,47 +342,32 @@ export class Wasi {
|
|||
mtime: new Date(),
|
||||
ctime: new Date(),
|
||||
};
|
||||
// Fill the buffer
|
||||
HEAP32[(buf >> 2)] = stat.dev;
|
||||
HEAP32[((buf + 4) >> 2)] = stat.mode;
|
||||
HEAPU32[((buf + 8) >> 2)] = stat.nlink;
|
||||
HEAP32[((buf + 12) >> 2)] = stat.uid;
|
||||
HEAP32[((buf + 16) >> 2)] = stat.gid;
|
||||
HEAP32[((buf + 20) >> 2)] = stat.rdev;
|
||||
HEAP32[((buf + 24) >> 2)] = stat.size & 0xFFFFFFFF; // Lower 32 bits
|
||||
HEAP32[((buf + 28) >> 2)] = Math.floor(stat.size / 4294967296); // Upper 32 bits
|
||||
HEAP32[((buf + 24) >> 2)] = stat.size & 0xFFFFFFFF;
|
||||
HEAP32[((buf + 28) >> 2)] = Math.floor(stat.size / 4294967296);
|
||||
HEAP32[((buf + 32) >> 2)] = stat.blksize;
|
||||
HEAP32[((buf + 36) >> 2)] = stat.blocks;
|
||||
|
||||
// Write timestamps
|
||||
const atimeSeconds = Math.floor(stat.atime.getTime() / 1000);
|
||||
const atimeNanos = (stat.atime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 40) >> 2)] = atimeSeconds;
|
||||
HEAP32[((buf + 44) >> 2)] = 0; // Upper 32 bits of atime
|
||||
HEAP32[((buf + 48) >> 2)] = atimeNanos;
|
||||
|
||||
const mtimeSeconds = Math.floor(stat.mtime.getTime() / 1000);
|
||||
const mtimeNanos = (stat.mtime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 56) >> 2)] = mtimeSeconds;
|
||||
HEAP32[((buf + 60) >> 2)] = 0; // Upper 32 bits of mtime
|
||||
HEAP32[((buf + 64) >> 2)] = mtimeNanos;
|
||||
|
||||
const ctimeSeconds = Math.floor(stat.ctime.getTime() / 1000);
|
||||
const ctimeNanos = (stat.ctime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 72) >> 2)] = ctimeSeconds;
|
||||
HEAP32[((buf + 76) >> 2)] = 0; // Upper 32 bits of ctime
|
||||
HEAP32[((buf + 80) >> 2)] = ctimeNanos;
|
||||
|
||||
// Dummy inode
|
||||
HEAP32[((buf + 88) >> 2)] = stat.ino & 0xFFFFFFFF; // Lower 32 bits
|
||||
HEAP32[((buf + 92) >> 2)] = Math.floor(stat.ino / 4294967296); // Upper 32 bits
|
||||
|
||||
console.debug(`Stubbed __syscall_stat64 called with pathPtr=${pathPtr}, bufPtr=${buf}`);
|
||||
HEAP32[((buf + 40) >> 2)] = Math.floor(stat.atime.getTime() / 1000);
|
||||
HEAP32[((buf + 44) >> 2)] = 0;
|
||||
HEAP32[((buf + 48) >> 2)] = (stat.atime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 56) >> 2)] = Math.floor(stat.mtime.getTime() / 1000);
|
||||
HEAP32[((buf + 60) >> 2)] = 0;
|
||||
HEAP32[((buf + 64) >> 2)] = (stat.mtime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 72) >> 2)] = Math.floor(stat.ctime.getTime() / 1000);
|
||||
HEAP32[((buf + 76) >> 2)] = 0;
|
||||
HEAP32[((buf + 80) >> 2)] = (stat.ctime.getTime() % 1000) * 1e6;
|
||||
HEAP32[((buf + 88) >> 2)] = stat.ino & 0xFFFFFFFF;
|
||||
HEAP32[((buf + 92) >> 2)] = Math.floor(stat.ino / 4294967296);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__cxa_throw(ptr, type, destructor) {
|
||||
console.error(`Exception thrown at ptr=${ptr}, type=${type}, destructor=${destructor}`);
|
||||
console.error(` syscall::cxa_throw ptr=${ptr}, type=${type}, destructor=${destructor}`);
|
||||
throw new Error("WebAssembly exception");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export function get(mime) {
|
|||
export async function load(mime) {
|
||||
const specs = plugins[mime];
|
||||
if (!specs) return null;
|
||||
const [_, url] = specs;
|
||||
const [, url] = specs;
|
||||
const module = await import(url);
|
||||
return module.default;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ 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 t from "../../locales/index.js";
|
||||
import ctrlError from "../ctrl_error.js";
|
||||
|
||||
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
||||
|
|
@ -18,7 +17,6 @@ import withCube from "./application_3d/scene_cube.js";
|
|||
import ctrlToolbar from "./application_3d/toolbar.js";
|
||||
|
||||
class I3DLoader {
|
||||
constructor() {}
|
||||
load() { throw new Error("NOT_IMPLEMENTED"); }
|
||||
transform() { throw new Error("NOT_IMPLEMENTED"); }
|
||||
is2D() { return false; }
|
||||
|
|
@ -45,7 +43,7 @@ export default async function(render, { mime, acl$, getDownloadUrl = nop, getFil
|
|||
|
||||
const removeLoader = createLoader($draw);
|
||||
await effect(rxjs.from(loadPlugin(mime)).pipe(
|
||||
rxjs.mergeMap(async (loader) => {
|
||||
rxjs.mergeMap(async(loader) => {
|
||||
if (!loader) {
|
||||
componentDownloader(render, { mime, acl$, getFilename, getDownloadUrl });
|
||||
return rxjs.EMPTY;
|
||||
|
|
@ -59,11 +57,7 @@ export default async function(render, { mime, acl$, getDownloadUrl = nop, getFil
|
|||
(err) => observer.error(err),
|
||||
)).pipe(
|
||||
removeLoader,
|
||||
rxjs.mergeMap((mesh) => create3DScene({
|
||||
mesh,
|
||||
$draw, $toolbar, $menubar,
|
||||
hasCube, mime, is2D: loader.is2D,
|
||||
})),
|
||||
rxjs.mergeMap((mesh) => create3DScene({ mime, mesh, is2D: loader.is2D, $draw, $toolbar, $menubar, hasCube })),
|
||||
)),
|
||||
rxjs.catchError((err) => {
|
||||
let _err = err;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ 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";
|
||||
|
||||
export default function(render, { mime, getFilename, getDownloadUrl, acl$ }) {
|
||||
const $page = createElement(`
|
||||
|
|
@ -35,5 +36,6 @@ export default function(render, { mime, getFilename, getDownloadUrl, acl$ }) {
|
|||
export function init() {
|
||||
return Promise.all([
|
||||
loadCSS(import.meta.url, "./application_skeleton.css"),
|
||||
initDownloader(),
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default async function(render, { mime, getDownloadUrl = nop, getFilename
|
|||
rxjs.mergeMap(async({ response }) => {
|
||||
const loader = getPlugin(mime);
|
||||
if (!loader) throw new TypeError(`unsupported mimetype "${mime}"`);
|
||||
const [_, url] = loader;
|
||||
const [, url] = loader;
|
||||
const module = await import(url);
|
||||
const table = new (await module.default(ITable))(response, { $menubar });
|
||||
STATE.header = table.getHeader();
|
||||
|
|
@ -98,7 +98,7 @@ export default async function(render, { mime, getDownloadUrl = nop, getFilename
|
|||
|
||||
// feature: infinite scroll
|
||||
effect(rxjs.fromEvent($dom.tbody, "scroll").pipe(
|
||||
rxjs.mergeMap(async (e) => {
|
||||
rxjs.mergeMap(async(e) => {
|
||||
const scrollBottom = e.target.scrollHeight - (e.target.scrollTop + e.target.clientHeight);
|
||||
if (scrollBottom > 0) return;
|
||||
else if (STATE.rows.length <= MAX_ROWS) return;
|
||||
|
|
@ -115,7 +115,7 @@ export default async function(render, { mime, getDownloadUrl = nop, getFilename
|
|||
init$,
|
||||
init$.pipe(
|
||||
rxjs.mergeMap(() => rxjs.fromEvent(window, "resize")),
|
||||
rxjs.debounce((e) => e.debounce === false ? rxjs.of(null) : rxjs.timer(100)),
|
||||
rxjs.debounce((e) => e["debounce"] === false ? rxjs.of(null) : rxjs.timer(100)),
|
||||
),
|
||||
).pipe(
|
||||
rxjs.tap(() => resizeLastColumnIfNeeded({
|
||||
|
|
@ -159,7 +159,7 @@ async function buildRows(rows, legends, $tbody, padding, isInit, withClear) {
|
|||
`));
|
||||
if (!isInit) {
|
||||
const e = new Event("resize");
|
||||
e.debounce = false;
|
||||
e["debounce"] = false;
|
||||
window.dispatchEvent(e);
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ function sortBy(rows, ascending, key) {
|
|||
const o = ascending ? 1 : -1;
|
||||
return rows.sort((a, b) => {
|
||||
if (a[key] === b[key]) return 0;
|
||||
else if (a[key] < b[key]) return -o
|
||||
else if (a[key] < b[key]) return -o;
|
||||
return o;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,20 +81,21 @@ export function buttonDownload(name, link) {
|
|||
}
|
||||
|
||||
export function buttonFullscreen($screen, fullscreen = null) {
|
||||
let fullscreenHandler = null;
|
||||
if (fullscreen === null) {
|
||||
if ("webkitRequestFullscreen" in document.body) {
|
||||
fullscreen = () => $screen.webkitRequestFullscreen();
|
||||
fullscreenHandler = () => $screen.webkitRequestFullscreen();
|
||||
} else if ("mozRequestFullScreen" in document.body) {
|
||||
fullscreen = () => $screen.mozRequestFullScreen();
|
||||
fullscreenHandler = () => $screen.mozRequestFullScreen();
|
||||
}
|
||||
}
|
||||
if (!fullscreen) return;
|
||||
if (!fullscreenHandler) return;
|
||||
const $el = createElement(`
|
||||
<span>
|
||||
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MzguNTQzIDQzOC41NDMiPgogIDxnIHRyYW5zZm9ybT0ibWF0cml4KDAuNzI5LDAsMCwwLjcyOSw1OS40MjI1NzYsNTkuNDIyNDQxKSI+CiAgICA8cGF0aCBzdHlsZT0iZmlsbDojZjJmMmYyO2ZpbGwtb3BhY2l0eToxIiBkPSJtIDQwNy40MiwxNTkuMDI5IGMgMy42MiwzLjYxNiA3Ljg5OCw1LjQyOCAxMi44NDcsNS40MjggMi4yODIsMCA0LjY2OCwtMC40NzYgNy4xMzksLTEuNDI5IDcuNDI2LC0zLjIzNSAxMS4xMzYsLTguODUzIDExLjEzNiwtMTYuODQ2IFYgMTguMjc2IGMgMCwtNC45NDkgLTEuODA3LC05LjIzMSAtNS40MjgsLTEyLjg0NyAtMy42MSwtMy42MTcgLTcuODk4LC01LjQyNCAtMTIuODQ3LC01LjQyNCBIIDI5Mi4zNiBjIC03Ljk5MSwwIC0xMy42MDcsMy44MDUgLTE2Ljg0OCwxMS40MTkgLTMuMjMsNy40MjMgLTEuOTAyLDEzLjk5IDQsMTkuNjk4IEwgMzIwLjYyMyw3Mi4yMzQgMjE5LjI3MSwxNzMuNTg5IDExNy45MTcsNzIuMjMxIDE1OS4wMjksMzEuMTE5IGMgNS45MDEsLTUuNzA4IDcuMjMyLC0xMi4yNzUgMy45OTksLTE5LjY5OCBDIDE1OS43ODksMy44MDcgMTU0LjE3NSwwIDE0Ni4xODIsMCBIIDE4LjI3NiBDIDEzLjMyNCwwIDkuMDQxLDEuODA5IDUuNDI1LDUuNDI2IDEuODA4LDkuMDQyIDAuMDAxLDEzLjMyNCAwLjAwMSwxOC4yNzMgViAxNDYuMTggYyAwLDcuOTk2IDMuODA5LDEzLjYxIDExLjQxOSwxNi44NDYgMi4yODUsMC45NDggNC41NywxLjQyOSA2Ljg1NSwxLjQyOSA0Ljk0OCwwIDkuMjI5LC0xLjgxMiAxMi44NDcsLTUuNDI3IEwgNzIuMjM0LDExNy45MTkgMTczLjU4OCwyMTkuMjczIDcyLjIzNCwzMjAuNjIyIDMxLjEyMiwyNzkuNTA5IGMgLTUuNzExLC01LjkwMyAtMTIuMjc1LC03LjIzMSAtMTkuNzAyLC00LjAwMSAtNy42MTQsMy4yNDEgLTExLjQxOSw4Ljg1NiAtMTEuNDE5LDE2Ljg1NCB2IDEyNy45MDYgYyAwLDQuOTQ4IDEuODA3LDkuMjI5IDUuNDI0LDEyLjg0NyAzLjYxOSwzLjYxNCA3LjkwMiw1LjQyMSAxMi44NTEsNS40MjEgaCAxMjcuOTA2IGMgNy45OTYsMCAxMy42MSwtMy44MDYgMTYuODQ2LC0xMS40MTYgMy4yMzQsLTcuNDI3IDEuOTAzLC0xMy45OSAtMy45OTksLTE5LjcwNSBMIDExNy45MTcsMzY2LjMwOSAyMTkuMjcxLDI2NC45NSAzMjAuNjI0LDM2Ni4zMTEgMjc5LjUxLDQwNy40MjEgYyAtNS44OTksNS43MDggLTcuMjI4LDEyLjI3OSAtMy45OTcsMTkuNjk4IDMuMjM3LDcuNjE3IDguODU2LDExLjQyMyAxNi44NTEsMTEuNDIzIGggMTI3LjkwNyBjIDQuOTQ4LDAgOS4yMzIsLTEuODEzIDEyLjg0NywtNS40MjggMy42MTMsLTMuNjEzIDUuNDIsLTcuODk4IDUuNDIsLTEyLjg0NyBWIDI5Mi4zNjIgYyAwLC03Ljk5NCAtMy43MDksLTEzLjYxMyAtMTEuMTM2LC0xNi44NTEgLTcuODAyLC0zLjIzIC0xNC40NjIsLTEuOTAzIC0xOS45ODUsNC4wMDQgTCAzNjYuMzExLDMyMC42MjEgMjY0Ljk1MiwyMTkuMjcxIDM2Ni4zMSwxMTcuOTE3IFoiIC8+CiAgPC9nPgo8L3N2Zz4K" alt="fullscreen">
|
||||
</span>
|
||||
`);
|
||||
$el.onclick = fullscreen;
|
||||
$el.onclick = fullscreenHandler;
|
||||
return $el;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ func init() {
|
|||
BUILD_REF = "%s"
|
||||
BUILD_DATE = "%s"
|
||||
}
|
||||
`, b.String(), time.Now().Format("20060102"))))
|
||||
`, strings.TrimSpace(b.String()), time.Now().Format("20060102"))))
|
||||
f.Close()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue