156 lines
5.2 KiB
TypeScript
156 lines
5.2 KiB
TypeScript
import { useNavigate, type RouteSectionProps } from "@solidjs/router";
|
|
import { createSignal, type JSX, Show, type Component } from "solid-js";
|
|
|
|
import { Title } from "@solidjs/meta";
|
|
import { Portal } from "solid-js/web";
|
|
import { Flex } from "~/components/ui/flex";
|
|
|
|
import { Progress, ProgressLabel, ProgressValueLabel } from "~/components/ui/progress";
|
|
import { loadDb } from "~/db/db-queries";
|
|
import { decryptBackup } from "~/lib/decryptor";
|
|
import { createDropzone, createFileUploader } from "@solid-primitives/upload";
|
|
import { Button } from "~/components/ui/button";
|
|
import { TextField, TextFieldInput, TextFieldLabel } from "~/components/ui/text-field";
|
|
|
|
export const Home: Component<RouteSectionProps> = () => {
|
|
const navigate = useNavigate();
|
|
|
|
const fileUploader = createFileUploader({
|
|
accept: ".backup",
|
|
multiple: false,
|
|
});
|
|
|
|
const dropzone = createDropzone({
|
|
onDrop: (files) => {
|
|
const file = files.at(0);
|
|
|
|
if (file?.name.endsWith(".backup")) {
|
|
setBackupFile(file.file);
|
|
}
|
|
},
|
|
});
|
|
|
|
const [passphrase, setPassphrase] = createSignal("");
|
|
const [backupFile, setBackupFile] = createSignal<File>();
|
|
|
|
const [decryptionProgress, setDecryptionProgress] = createSignal<number>();
|
|
const [loadingProgress, setLoadingProgress] = createSignal<number>();
|
|
// const [isLoadingDatabase, setIsLoadingDatabase] = createSignal(false);
|
|
|
|
const onSubmit: JSX.EventHandler<HTMLFormElement, SubmitEvent> = (event) => {
|
|
event.preventDefault();
|
|
|
|
const currentBackupFile = backupFile();
|
|
const currentPassphrase = passphrase();
|
|
|
|
if (currentBackupFile && currentPassphrase) {
|
|
decryptBackup(currentBackupFile, currentPassphrase, setDecryptionProgress)
|
|
.then((result) => {
|
|
setDecryptionProgress(undefined);
|
|
// setIsLoadingDatabase(true);
|
|
setLoadingProgress(0);
|
|
|
|
setTimeout(() => {
|
|
loadDb(result.database_statements, (newValue) => (console.log(newValue), setLoadingProgress(newValue)));
|
|
|
|
// setIsLoadingDatabase(false);
|
|
setLoadingProgress(undefined);
|
|
|
|
navigate("/overview");
|
|
}, 0);
|
|
})
|
|
.catch((error) => {
|
|
console.error("Decryption failed:", error);
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Portal>
|
|
<Flex
|
|
flexDirection="col"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
class="fixed inset-0 gap-y-8 backdrop-blur-lg backdrop-filter"
|
|
classList={{
|
|
// hidden: decryptionProgress() === undefined && !isLoadingDatabase(),
|
|
hidden: decryptionProgress() === undefined && loadingProgress() === undefined,
|
|
}}
|
|
>
|
|
<Show when={decryptionProgress() !== undefined}>
|
|
<p class="font-bold text-2xl">Decrypting database</p>
|
|
<Progress
|
|
value={decryptionProgress()}
|
|
minValue={0}
|
|
maxValue={100}
|
|
getValueLabel={({ value }) => `${value}%`}
|
|
class="w-[300px] space-y-1"
|
|
>
|
|
<div class="flex justify-between">
|
|
<ProgressLabel>Processing...</ProgressLabel>
|
|
<ProgressValueLabel />
|
|
</div>
|
|
</Progress>
|
|
</Show>
|
|
<Show when={loadingProgress() !== undefined}>
|
|
{/* <p class="font-bold text-2xl">Loading database</p>
|
|
<p class="text-muted-foreground">This can take some time</p> */}
|
|
<p class="font-bold text-2xl">Loading database</p>
|
|
<Progress
|
|
value={loadingProgress()}
|
|
minValue={0}
|
|
maxValue={100}
|
|
getValueLabel={({ value }) => `${value}%`}
|
|
class="w-[300px] space-y-1"
|
|
>
|
|
<div class="flex justify-between">
|
|
<ProgressLabel>Loading...</ProgressLabel>
|
|
<ProgressValueLabel />
|
|
</div>
|
|
</Progress>
|
|
</Show>
|
|
</Flex>
|
|
</Portal>
|
|
<Title>Signal stats</Title>
|
|
<form class="flex flex-col gap-y-8 p-8" onSubmit={onSubmit}>
|
|
<TextField onChange={(value) => setPassphrase(value)}>
|
|
<TextFieldLabel>Passphrase</TextFieldLabel>
|
|
<TextFieldInput type="password" class="max-w-md" />
|
|
</TextField>
|
|
<Flex
|
|
ref={dropzone.setRef}
|
|
justifyContent="center"
|
|
alignItems="center"
|
|
class="relative min-h-32 min-w-96 max-w-xl rounded-lg border-4 border-border border-dashed"
|
|
classList={{
|
|
"border-ring": dropzone.isDragging(),
|
|
}}
|
|
>
|
|
<Button
|
|
onClick={() =>
|
|
fileUploader.selectFiles((files) => {
|
|
setBackupFile(files.at(0)?.file);
|
|
})
|
|
}
|
|
>
|
|
Select backup file
|
|
</Button>
|
|
<span
|
|
class="absolute bottom-2"
|
|
classList={{
|
|
"text-muted-foreground": !backupFile(),
|
|
}}
|
|
>
|
|
{backupFile() ? backupFile()?.name : "or drop the file here"}
|
|
</span>
|
|
</Flex>
|
|
<Button type="submit" class="max-w-72">
|
|
Decrypt and load backup
|
|
</Button>
|
|
</form>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default Home;
|