fformat/src/components/MagikaProcess.tsx
2024-02-26 21:51:11 -05:00

120 lines
4.2 KiB
TypeScript

"use client";
import { Button } from "@/components/ui/button";
import { Loader } from "@/components/ui/loader";
//@ts-ignore
import { Magika } from "magika";
import { listen } from "@tauri-apps/api/event";
import { useEffect, useState } from "react";
import { readFile } from "@tauri-apps/plugin-fs";
//@ts-ignore
import { open } from "@tauri-apps/plugin-dialog";
import { columns } from "@/components/DT/columns";
import { DataTable } from "@/components/DT/data-table";
const MagikaProcess = () => {
const [loading, setLoading] = useState(false);
const [predictions, setPredictions] = useState<any[]>([]);
useEffect(() => {
if (loading) return;
listen("tauri://file-drop", async ({ payload }: any) => {
setLoading(true);
const filepaths: string[] = payload.paths;
const filepredictions: any[] = [];
for await (const filepath of filepaths) {
const prediction = await getPrediction(filepath);
filepredictions.push(prediction);
}
setPredictions(filepredictions);
setLoading(false);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const getPrediction = async (filepath: string) => {
try {
const fileBytes = await readFile(filepath);
const magika = new Magika();
await magika.load({});
const prediction = await magika.identifyBytes(fileBytes);
prediction.path = filepath;
return prediction;
} catch (e) {
console.error(
`Error while getting prediction for ${filepath}: ${e}`
);
}
};
const handleClick = async () => {
// Open a selection dialog for files
const selected = await open({
multiple: true,
});
setLoading(true);
if (Array.isArray(selected)) {
// user selected multiple files
const filePredictions: any[] = [];
for await (const file of selected) {
const prediction = await getPrediction(file.path);
filePredictions.push(prediction);
}
setPredictions(filePredictions);
} else if (selected === null) {
console.log("User cancelled selection");
} else {
// user selected a single file
const { label, score }: { label: string; score: number } = selected;
setPredictions([{ label: label, score: score }]);
}
setLoading(false);
};
return (
<div
className={`flex h-full min-h-[100vh] w-full items-center justify-center text-center lg:m-8 ${
predictions.length > 0 && "m-16"
}`}
>
<div className="w-fit">
<div className="flex flex-col items-center justify-center pb-4">
<h2 className="scroll-m-20 text-3xl font-semibold tracking-tight first:mt-0">
fformat
</h2>
<p className="text-md w-fit border-b text-muted-foreground">
Identify potential file content types
</p>
</div>
<div className="mb-4">
<div className="mx-auto grid w-fit items-center gap-1.5">
<Button
disabled={loading}
onClick={async () => await handleClick()}
>
Choose file(s){" "}
{loading && (
<Loader className="ml-2 w-4 animate-spin" />
)}
</Button>
</div>
<p className="text-md text-muted-foreground">
or drag and drop
</p>
</div>
{predictions.length > 0 && (
<DataTable
columns={columns}
data={predictions}
setData={setPredictions}
/>
)}
</div>
</div>
);
};
export default MagikaProcess;