Files
mokuro-reader/src/lib/components/UploadModal.svelte
2024-02-04 05:53:25 +02:00

179 lines
5.8 KiB
Svelte

<script lang="ts">
import { Button, Dropzone, Modal, Spinner, Accordion, AccordionItem } from 'flowbite-svelte';
import FileUpload from './FileUpload.svelte';
import { processFiles } from '$lib/upload';
import { onMount } from 'svelte';
import { scanFiles } from '$lib/upload';
import { formatBytes } from '$lib/util/upload';
import { toClipboard } from '$lib/util';
export let open = false;
let promise: Promise<void>;
let files: FileList | undefined = undefined;
async function onUpload() {
if (files) {
promise = processFiles([...files]).then(() => {
open = false;
});
} else if (draggedFiles) {
promise = processFiles(draggedFiles).then(() => {
open = false;
});
}
}
function reset() {
files = undefined;
draggedFiles = undefined;
}
let storageSpace = '';
onMount(() => {
navigator?.storage?.estimate().then(({ usage, quota }) => {
if (usage && quota) {
storageSpace = `Storage: ${formatBytes(usage)} / ${formatBytes(quota)}`;
}
});
});
let filePromises: Promise<File>[];
let draggedFiles: File[] | undefined;
let loading = false;
$: disabled = loading || (!draggedFiles && !files);
const dropHandle = async (event: DragEvent) => {
loading = true;
draggedFiles = [];
filePromises = [];
event.preventDefault();
activeStyle = defaultStyle;
if (event?.dataTransfer?.items) {
for (const item of [...event.dataTransfer.items]) {
const entry = item.webkitGetAsEntry();
if (item.kind === 'file' && entry) {
if (entry.isDirectory) {
await scanFiles(entry, filePromises);
} else {
const file = item.getAsFile();
if (file) {
draggedFiles.push(file);
draggedFiles = draggedFiles;
}
}
}
}
if (filePromises && filePromises.length > 0) {
const files = await Promise.all(filePromises);
if (files) {
draggedFiles = [...draggedFiles, ...files];
}
}
}
loading = false;
};
let defaultStyle =
'flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer dark:hover:bg-bray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600';
let highlightStyle =
'flex flex-col justify-center items-center w-full h-64 bg-gray-50 rounded-lg border-2 border-gray-300 border-dashed cursor-pointer dark:bg-bray-800 dark:bg-gray-700 bg-gray-100 dark:border-gray-600 dark:border-gray-500 dark:bg-gray-600';
let activeStyle = defaultStyle;
</script>
<Modal title="Upload" bind:open outsideclose on:close={reset}>
{#await promise}
<h2 class="justify-center flex">Loading...</h2>
<div class="text-center"><Spinner /></div>
{:then}
<Accordion flush>
<AccordionItem>
<span slot="header">What to upload?</span>
<div class="flex flex-col gap-5">
<div>
<p>
Firstly, ensure that you process your manga with the <b>0.2.0-beta.6</b> of mokuro, you
can install it by running the following command:
</p>
<div role="none" on:click={toClipboard}>
<code class="text-primary-600 bg-slate-900"
>pip3 install git+https://github.com/kha-white/mokuro.git@web-reader</code
>
</div>
</div>
<p>
This will generate a <code>.mokuro</code> file for each volume processed, upload your
manga along with the <code>.mokuro</code> files.
</p>
<p>
On mobile, uploading via directory is not supported so you will need to zip your manga
first and then upload it via
<code class="text-primary-600 bg-slate-900">choose files</code>.
</p>
</div>
</AccordionItem>
</Accordion>
<Dropzone
id="dropzone"
on:drop={dropHandle}
on:dragover={(event) => {
event.preventDefault();
activeStyle = highlightStyle;
}}
on:dragleave={(event) => {
event.preventDefault();
activeStyle = defaultStyle;
}}
on:click={(event) => {
event.preventDefault();
}}
defaultClass={activeStyle}
>
<svg
aria-hidden="true"
class="mb-3 w-10 h-10 text-gray-400"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
/></svg
>
{#if files}
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
Upload {files.length}
{files.length > 1 ? 'files' : 'file'}?
</p>
{:else if draggedFiles && draggedFiles.length > 0}
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
Upload {draggedFiles.length} hih
{draggedFiles.length > 1 ? 'files' : 'file'}?
</p>
{:else if loading}
<Spinner />
{:else}
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400">
Drag and drop / <FileUpload bind:files accept=".mokuro,.zip,.cbz" multiple
>choose files</FileUpload
> /
<FileUpload bind:files webkitdirectory>choose directory</FileUpload>
</p>
{/if}
</Dropzone>
<p class=" text-sm text-gray-500 dark:text-gray-400 text-center">{storageSpace}</p>
<div class="flex flex-1 flex-col gap-2">
<Button outline on:click={reset} {disabled} color="dark">Reset</Button>
<Button outline on:click={onUpload} {disabled}>Upload</Button>
</div>
{/await}
</Modal>