Add manga extracting

This commit is contained in:
ZXY101
2024-01-06 17:32:37 +02:00
parent dffc3cbed0
commit 801ecf929e
4 changed files with 71 additions and 3 deletions

View File

@@ -1,6 +1,5 @@
<script lang="ts"> <script lang="ts">
import { catalog } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import { P } from 'flowbite-svelte';
export let id: string; export let id: string;

View File

@@ -2,3 +2,4 @@ export * from './snackbar';
export * from './upload'; export * from './upload';
export * from './misc'; export * from './misc';
export * from './modals'; export * from './modals';
export * from './zip'

56
src/lib/util/zip.ts Normal file
View File

@@ -0,0 +1,56 @@
import type { Volume } from "$lib/types";
import {
BlobReader,
BlobWriter,
TextReader,
ZipWriter,
} from "@zip.js/zip.js";
async function zipVolumes(manga: Volume[]) {
const volumeZips = []
for (const volume of manga) {
const files = Object.values(volume.files);
const zipWriter = new ZipWriter(new BlobWriter("application/zip"));
const promises = files.map((file) => {
return zipWriter.add(file.name, new BlobReader(file))
})
await Promise.all(promises);
volumeZips.push({
zipName: volume.volumeName,
zipBlob: await zipWriter.close(),
mokuroData: JSON.stringify(volume.mokuroData)
});
}
return volumeZips;
}
export async function zipManga(manga: Volume[]) {
const volumeZips = await zipVolumes(manga)
const zipWriter = new ZipWriter(new BlobWriter("application/zip"));
const promises = volumeZips.map((volumeZip) => {
return [
zipWriter.add(`${volumeZip.zipName}.mokuro`, new TextReader(volumeZip.mokuroData)),
zipWriter.add(`${volumeZip.zipName}.zip`, new BlobReader(volumeZip.zipBlob))
]
})
await Promise.all(promises);
const zipFileBlob = await zipWriter.close();
const link = document.createElement('a');
link.href = URL.createObjectURL(zipFileBlob);
link.download = `${manga[0].mokuroData.title}.zip`;
link.click();
return false
}

View File

@@ -2,9 +2,9 @@
import { catalog } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import VolumeItem from '$lib/components/VolumeItem.svelte'; import VolumeItem from '$lib/components/VolumeItem.svelte';
import { Button, Listgroup } from 'flowbite-svelte'; import { Button, Listgroup, Progressbar, Spinner } from 'flowbite-svelte';
import { db } from '$lib/catalog/db'; import { db } from '$lib/catalog/db';
import { promptConfirmation } from '$lib/util'; import { promptConfirmation, zipManga } from '$lib/util';
import { page } from '$app/stores'; import { page } from '$app/stores';
import type { Volume } from '$lib/types'; import type { Volume } from '$lib/types';
import { deleteVolume, volumes } from '$lib/settings'; import { deleteVolume, volumes } from '$lib/settings';
@@ -38,6 +38,8 @@
{ timeReadInMinutes: 0, chars: 0, completed: 0 } { timeReadInMinutes: 0, chars: 0, completed: 0 }
); );
$: loading = false;
async function confirmDelete() { async function confirmDelete() {
const title = manga?.[0].mokuroData.title_uuid; const title = manga?.[0].mokuroData.title_uuid;
manga?.forEach((vol) => { manga?.forEach((vol) => {
@@ -52,6 +54,13 @@
function onDelete() { function onDelete() {
promptConfirmation('Are you sure you want to delete this manga?', confirmDelete); promptConfirmation('Are you sure you want to delete this manga?', confirmDelete);
} }
async function onExtract() {
if (manga) {
loading = true;
loading = await zipManga(manga);
}
}
</script> </script>
<svelte:head> <svelte:head>
@@ -70,6 +79,9 @@
</div> </div>
<div> <div>
<Button color="alternative" on:click={onDelete}>Remove manga</Button> <Button color="alternative" on:click={onDelete}>Remove manga</Button>
<Button color="light" on:click={onExtract} disabled={loading}>
{loading ? 'Extracting...' : 'Extract manga'}
</Button>
</div> </div>
</div> </div>
<Listgroup items={manga} let:item active class="flex-1 h-full w-full"> <Listgroup items={manga} let:item active class="flex-1 h-full w-full">