Refactor catalog

This commit is contained in:
ZXY101
2023-09-27 11:06:03 +02:00
parent 53f5a48d3e
commit d6bb0b1ddc
11 changed files with 109 additions and 99 deletions

View File

@@ -10,7 +10,7 @@
/> />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover" class="bg-white dark:bg-gray-800 dark:text-white">
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@@ -1,7 +1,4 @@
import type { Volume } from '$lib/types';
import { writable } from 'svelte/store';
import { db } from '$lib/catalog/db'; import { db } from '$lib/catalog/db';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
export const currentManga = writable<Volume[] | undefined>(undefined);
export const currentVolume = writable<Volume | undefined>(undefined);
export const catalog = liveQuery(() => db.catalog.toArray()); export const catalog = liveQuery(() => db.catalog.toArray());

View File

@@ -1,24 +1,14 @@
<script lang="ts"> <script lang="ts">
import { catalog } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import { Button } from 'flowbite-svelte';
import CatalogItem from './CatalogItem.svelte'; import CatalogItem from './CatalogItem.svelte';
import { promptConfirmation } from '$lib/util';
import { db } from '$lib/catalog/db';
function onClear() {
promptConfirmation('Are you sure you want to clear your catalog?', () => db.catalog.clear());
}
</script> </script>
{#if $catalog} {#if $catalog}
{#if $catalog.length > 0} {#if $catalog.length > 0}
<div class="flex flex-col gap-5"> <div class="flex flex-col gap-5">
<div class="sm:block flex-col flex">
<Button outline color="red" class="float-right" on:click={onClear}>Clear catalog</Button>
</div>
<div class="flex sm:flex-row flex-col gap-5 flex-wrap justify-center sm:justify-start"> <div class="flex sm:flex-row flex-col gap-5 flex-wrap justify-center sm:justify-start">
{#each $catalog as { id, manga } (id)} {#each $catalog as { id } (id)}
<CatalogItem {manga} /> <CatalogItem {id} />
{/each} {/each}
</div> </div>
</div> </div>

View File

@@ -1,23 +1,22 @@
<script lang="ts"> <script lang="ts">
import { currentManga } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import type { Volume } from '$lib/types';
export let manga: Volume[];
const { volumeName, files, mokuroData } = manga[0];
function onClick() { export let id: string;
currentManga.set(manga);
} $: manga = $catalog?.find((item) => item.id === id)?.manga[0];
</script> </script>
<a href={volumeName} on:click={onClick}> {#if manga}
<div class="flex flex-col gap-[5px] text-center items-center"> <a href={id}>
{mokuroData.title} <div class="flex flex-col gap-[5px] text-center items-center">
{#if files} {manga.mokuroData.title}
<img {#if manga.files}
src={URL.createObjectURL(Object.values(files)[0])} <img
alt="img" src={URL.createObjectURL(Object.values(manga.files)[0])}
class="object-contain w-[250px] h-[350px] bg-black border-gray-900 border" alt="img"
/> class="object-contain w-[250px] h-[350px] bg-black border-gray-900 border"
{/if} />
</div> {/if}
</a> </div>
</a>
{/if}

View File

@@ -1,16 +1,19 @@
<script lang="ts"> <script lang="ts">
import type { Page } from '$lib/types'; import type { Page } from '$lib/types';
import { onMount } from 'svelte';
import TextBoxes from './TextBoxes.svelte'; import TextBoxes from './TextBoxes.svelte';
export let page: Page; export let page: Page;
export let src: File; export let src: File;
$: url = `url(${URL.createObjectURL(src)})`;
</script> </script>
<div <div
draggable="false" draggable="false"
style:width={`${page.img_width}px`} style:width={`${page.img_width}px`}
style:height={`${page.img_height}px`} style:height={`${page.img_height}px`}
style:background-image={`url(${URL.createObjectURL(src)})`} style:background-image={url}
class="relative" class="relative"
> >
<TextBoxes {page} {src} /> <TextBoxes {page} {src} />

View File

@@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import { currentVolume } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import { Panzoom, toggleFullScreen, zoomDefault } from '$lib/panzoom'; import { Panzoom, toggleFullScreen, zoomDefault } from '$lib/panzoom';
import { progress, settings, updateProgress } from '$lib/settings'; import { progress, settings, updateProgress } from '$lib/settings';
import { clamp } from '$lib/util'; import { clamp } from '$lib/util';
import { Input, Popover, Range } from 'flowbite-svelte'; import { Input, Popover, Range, Spinner } from 'flowbite-svelte';
import MangaPage from './MangaPage.svelte'; import MangaPage from './MangaPage.svelte';
import { import {
ChervonDoubleLeftSolid, ChervonDoubleLeftSolid,
@@ -13,9 +13,13 @@
} from 'flowbite-svelte-icons'; } from 'flowbite-svelte-icons';
import { afterUpdate, onMount } from 'svelte'; import { afterUpdate, onMount } from 'svelte';
import Cropper from './Cropper.svelte'; import Cropper from './Cropper.svelte';
import { page as pageStore } from '$app/stores';
const volume = $currentVolume; $: volume = $catalog
const pages = volume?.mokuroData.pages; ?.find((item) => item.id === $pageStore.params.manga)
?.manga.find((item) => item.mokuroData.volume_uuid === $pageStore.params.volume);
$: pages = volume?.mokuroData.pages;
$: page = $progress?.[volume?.mokuroData.volume_uuid || 0] || 1; $: page = $progress?.[volume?.mokuroData.volume_uuid || 0] || 1;
$: index = page - 1; $: index = page - 1;
@@ -102,7 +106,6 @@
}); });
onMount(() => { onMount(() => {
getMaxCharCount();
updateCharacterCount(page); updateCharacterCount(page);
}); });
@@ -143,7 +146,7 @@
function updateCharacterCount(currentPage: number) { function updateCharacterCount(currentPage: number) {
charCount = 0; charCount = 0;
if (pages && $settings.charCount) { if (pages && pages.length > 0 && $settings.charCount) {
for (let i = 0; i < currentPage; i++) { for (let i = 0; i < currentPage; i++) {
const blocks = pages[i].blocks; const blocks = pages[i].blocks;
blocks.forEach((block) => { blocks.forEach((block) => {
@@ -157,8 +160,10 @@
let maxCharCount = 0; let maxCharCount = 0;
$: pages?.length, getMaxCharCount();
function getMaxCharCount() { function getMaxCharCount() {
if (pages) { if (pages && pages.length > 0) {
for (let i = 0; i < pages.length; i++) { for (let i = 0; i < pages.length; i++) {
const blocks = pages[i].blocks; const blocks = pages[i].blocks;
blocks.forEach((block) => { blocks.forEach((block) => {
@@ -174,6 +179,9 @@
</script> </script>
<svelte:window on:resize={zoomDefault} on:keyup|preventDefault={handleShortcuts} /> <svelte:window on:resize={zoomDefault} on:keyup|preventDefault={handleShortcuts} />
<svelte:head>
<title>{volume?.mokuroData.volume || 'Volume'}</title>
</svelte:head>
{#if volume && pages} {#if volume && pages}
<Cropper /> <Cropper />
<Popover placement="bottom-end" trigger="click" triggeredBy="#page-num" class="z-20"> <Popover placement="bottom-end" trigger="click" triggeredBy="#page-num" class="z-20">
@@ -235,4 +243,8 @@
on:mouseup={right} on:mouseup={right}
class="right-0 top-0 absolute h-full w-10 hover:bg-slate-400 opacity-[0.01]" class="right-0 top-0 absolute h-full w-10 hover:bg-slate-400 opacity-[0.01]"
/> />
{:else}
<div class="fixed z-50 left-1/2 top-1/2">
<Spinner />
</div>
{/if} {/if}

View File

@@ -1,5 +1,7 @@
<script lang="ts"> <script lang="ts">
import { AccordionItem, Button, Label, Select } from 'flowbite-svelte'; import { db } from '$lib/catalog/db';
import { promptConfirmation } from '$lib/util';
import { AccordionItem, Button, Select } from 'flowbite-svelte';
let profiles = [ let profiles = [
{ value: 'default', name: 'Default' }, { value: 'default', name: 'Default' },
@@ -8,12 +10,19 @@
]; ];
let profile = 'default'; let profile = 'default';
function onClear() {
promptConfirmation('Are you sure you want to clear your catalog?', () => db.catalog.clear());
}
</script> </script>
<AccordionItem> <AccordionItem>
<span slot="header">Profile</span> <span slot="header">Profile</span>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-5">
<Select items={profiles} value={profile} /> <div class="flex flex-col gap-2">
<Button size="sm" outline color="dark">Manage profiles</Button> <Select items={profiles} value={profile} />
<Button size="sm" outline color="dark">Manage profiles</Button>
</div>
<Button on:click={onClear} outline color="red">Clear catalog</Button>
</div> </div>
</AccordionItem> </AccordionItem>

View File

@@ -1,25 +1,30 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { currentVolume } from '$lib/catalog'; import { progress } from '$lib/settings';
import type { Volume } from '$lib/types'; import type { Volume } from '$lib/types';
import { ListgroupItem } from 'flowbite-svelte';
import type { ListGroupItemType } from 'flowbite-svelte/dist/types';
export let volume: Volume; export let item: string | ListGroupItemType;
const { volumeName, files } = volume; const volume = item as Volume;
const { volumeName, mokuroData } = volume as Volume;
function onClick() { function onClick() {
currentVolume.set(volume); goto(`${$page.params.manga}/${mokuroData.volume_uuid}`);
} }
$: currentPage = $progress?.[volume?.mokuroData.volume_uuid || 0] || 1;
$: progressDisplay = `${currentPage} / ${volume.mokuroData.pages.length}`;
</script> </script>
<a href={`${$page.params.manga}/${volumeName}`} on:click={onClick}> <a href={`${$page.params.manga}/${mokuroData.volume_uuid}`} class="h-full w-full">
<div class="flex flex-col gap-[5px] text-center items-center"> <ListgroupItem>
{volumeName} <div>
{#if files} <h3 class="font-semibold">{volumeName}</h3>
<img <p>{progressDisplay}</p>
src={URL.createObjectURL(Object.values(files)[0])} </div>
alt="img" </ListgroupItem>
class="object-contain sm:w-[250px] h-[350px] bg-black border-gray-900 border"
/>
{/if}
</div>
</a> </a>

View File

@@ -2,6 +2,10 @@
import Catalog from '$lib/components/Catalog.svelte'; import Catalog from '$lib/components/Catalog.svelte';
</script> </script>
<div class="p-2"> <svelte:head>
<title>Mokuro</title>
</svelte:head>
<div class="p-5">
<Catalog /> <Catalog />
</div> </div>

View File

@@ -1,13 +1,15 @@
<script lang="ts"> <script lang="ts">
import { currentManga } from '$lib/catalog'; import { catalog } from '$lib/catalog';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { onMount } from 'svelte';
import VolumeItem from '$lib/components/VolumeItem.svelte'; import VolumeItem from '$lib/components/VolumeItem.svelte';
import { Button } from 'flowbite-svelte'; import { Button, Listgroup } from 'flowbite-svelte';
import { db } from '$lib/catalog/db'; import { db } from '$lib/catalog/db';
import { promptConfirmation } from '$lib/util'; import { promptConfirmation } from '$lib/util';
import { page } from '$app/stores';
import type { Volume } from '$lib/types';
import { onMount } from 'svelte';
const manga = $currentManga?.sort((a, b) => { function sortManga(a: Volume, b: Volume) {
if (a.volumeName < b.volumeName) { if (a.volumeName < b.volumeName) {
return -1; return -1;
} }
@@ -15,13 +17,9 @@
return 1; return 1;
} }
return 0; return 0;
}); }
onMount(() => { $: manga = $catalog?.find((item) => item.id === $page.params.manga)?.manga.sort(sortManga);
if (!manga) {
goto('/');
}
});
async function confirmDelete() { async function confirmDelete() {
const title = manga?.[0].mokuroData.title_uuid; const title = manga?.[0].mokuroData.title_uuid;
@@ -34,15 +32,22 @@
} }
</script> </script>
<div class="p-2 flex flex-col gap-5"> <svelte:head>
<div class="sm:block flex-col flex"> <title>{manga?.[0].mokuroData.title || 'Manga'}</title>
<Button outline color="red" class="float-right" on:click={onDelete}>Delete manga</Button> </svelte:head>
{#if manga}
<div class="p-5 flex flex-col gap-5">
<div class="flex flex-row justify-between">
<div class="flex flex-col">
<h3 class="font-bold">{manga[0].mokuroData.title}</h3>
<p>Volumes: {manga.length}</p>
</div>
<div><Button color="alternative" on:click={onDelete}>Remove manga</Button></div>
</div>
<Listgroup items={manga} let:item active class="flex-1 h-full w-full">
<VolumeItem {item} />
</Listgroup>
</div> </div>
<div class="flex sm:flex-row flex-col justify-center sm:justify-start gap-5 flex-wrap"> {:else}
{#if manga} <div class="flex justify-center p-16">Manga not found</div>
{#each manga as volume} {/if}
<VolumeItem {volume} />
{/each}
{/if}
</div>
</div>

View File

@@ -1,17 +1,3 @@
<script lang="ts">
import { currentVolume } from '$lib/catalog';
import { onMount } from 'svelte';
import { goto } from '$app/navigation';
const volume = $currentVolume;
onMount(() => {
if (!volume) {
goto('/');
}
});
</script>
<slot /> <slot />
<style> <style>