diff --git a/src/lib/catalog/index.ts b/src/lib/catalog/index.ts index 6b1edb5..51df8f2 100644 --- a/src/lib/catalog/index.ts +++ b/src/lib/catalog/index.ts @@ -1,4 +1,30 @@ -import { db } from '$lib/catalog/db'; +import { page } from '$app/stores'; +import { db, type Catalog } from '$lib/catalog/db'; +import type { Volume } from '$lib/types'; import { liveQuery } from 'dexie'; +import { derived, type Readable } from 'svelte/store'; export const catalog = liveQuery(() => db.catalog.toArray()); + +function sortManga(a: Volume, b: Volume) { + if (a.volumeName < b.volumeName) { + return -1; + } + if (a.volumeName > b.volumeName) { + return 1; + } + return 0; +} + + +export const manga = derived([page, catalog as unknown as Readable], ([$page, $catalog]) => { + if ($page && $catalog) { + return $catalog.find((item) => item.id === $page.params.manga)?.manga.sort(sortManga) + } +}); + +export const volume = derived(([page, manga]), ([$page, $manga]) => { + if ($page && $manga) { + return $manga.find((item) => item.mokuroData.volume_uuid === $page.params.volume) + } +}) \ No newline at end of file diff --git a/src/lib/components/Reader/Timer.svelte b/src/lib/components/Reader/Timer.svelte new file mode 100644 index 0000000..03b842c --- /dev/null +++ b/src/lib/components/Reader/Timer.svelte @@ -0,0 +1,12 @@ + + +
+

{active ? 'Timer active' : 'Timer idle'} | Minutes read: {$volumeStats?.timeReadInMinutes}

+
diff --git a/src/lib/components/Settings/Reader/ReaderToggles.svelte b/src/lib/components/Settings/Reader/ReaderToggles.svelte index 4fc5c76..a98b13c 100644 --- a/src/lib/components/Settings/Reader/ReaderToggles.svelte +++ b/src/lib/components/Settings/Reader/ReaderToggles.svelte @@ -9,7 +9,8 @@ { key: 'boldFont', text: 'Bold font', value: $settings.boldFont }, { key: 'pageNum', text: 'Show page number', value: $settings.pageNum }, { key: 'charCount', text: 'Show character count', value: $settings.charCount }, - { key: 'mobile', text: 'Mobile', value: $settings.mobile } + { key: 'mobile', text: 'Mobile', value: $settings.mobile }, + { key: 'showTimer', text: 'Show timer', value: $settings.showTimer } ] as { key: SettingsKey; text: string; value: any }[]; diff --git a/src/lib/components/Settings/Stats.svelte b/src/lib/components/Settings/Stats.svelte index e6cf4bb..e1bc851 100644 --- a/src/lib/components/Settings/Stats.svelte +++ b/src/lib/components/Settings/Stats.svelte @@ -1,44 +1,14 @@ Stats
-

Completed volumes: {completed}

-

Pages read: {pagesRead}

-

Characters read: {charsRead}

-

Minutes read: {minutesRead}

+

Completed volumes: {$totalStats?.completed || 0}

+

Pages read: {$totalStats?.pagesRead || 0}

+

Characters read: {$totalStats?.charsRead || 0}

+

Minutes read: {$totalStats?.minutesRead || 0}

diff --git a/src/lib/settings/settings.ts b/src/lib/settings/settings.ts index b735e1a..cc02435 100644 --- a/src/lib/settings/settings.ts +++ b/src/lib/settings/settings.ts @@ -49,6 +49,7 @@ export type Settings = { mobile: boolean; backgroundColor: string; swipeThreshold: number; + showTimer: boolean; fontSize: FontSize; zoomDefault: ZoomModes; volumeDefaults: VolumeDefaults; @@ -71,6 +72,7 @@ const defaultSettings: Settings = { mobile: false, backgroundColor: '#030712', swipeThreshold: 50, + showTimer: false, fontSize: 'auto', zoomDefault: 'zoomFitToScreen', volumeDefaults: { diff --git a/src/lib/settings/volume-data.ts b/src/lib/settings/volume-data.ts index 8c55792..237624b 100644 --- a/src/lib/settings/volume-data.ts +++ b/src/lib/settings/volume-data.ts @@ -2,6 +2,8 @@ import { browser } from '$app/environment'; import { derived, get, writable } from 'svelte/store'; import { settings } from './settings'; import { zoomDefault } from '$lib/panzoom'; +import { page } from '$app/stores'; +import { manga, volume } from '$lib/catalog'; export type VolumeSettings = { rightToLeft: boolean; @@ -21,6 +23,13 @@ type VolumeData = { settings: VolumeSettings; } +type TotalStats = { + completed: number; + pagesRead: number; + charsRead: number; + minutesRead: number; +} + type Volumes = Record; @@ -132,4 +141,51 @@ export function updateVolumeSetting(volume: string, key: VolumeSettingsKey, valu }; }); zoomDefault(); -} \ No newline at end of file +} + +export const totalStats = derived([volumes, page], ([$volumes, $page]) => { + if ($page && $volumes) { + return Object.values($volumes).reduce((stats, { chars, completed, timeReadInMinutes, progress }) => { + if (completed) { + stats.completed++; + } + + stats.pagesRead += progress; + stats.minutesRead += timeReadInMinutes; + stats.charsRead += chars + + return stats; + }, { + charsRead: 0, + completed: 0, + pagesRead: 0, + minutesRead: 0 + }) + } +}) + +export const mangaStats = derived([manga, volumes], ([$manga, $volumes]) => { + if ($manga && $volumes) { + return $manga.map((vol) => vol.mokuroData.volume_uuid).reduce( + (stats: any, volumeId) => { + const timeReadInMinutes = $volumes[volumeId]?.timeReadInMinutes || 0; + const chars = $volumes[volumeId]?.chars || 0; + const completed = $volumes[volumeId]?.completed || 0; + + stats.timeReadInMinutes = stats.timeReadInMinutes + timeReadInMinutes; + stats.chars = stats.chars + chars; + stats.completed = stats.completed + completed; + + return stats; + }, + { timeReadInMinutes: 0, chars: 0, completed: 0 } + ); + } +}); + +export const volumeStats = derived([volume, volumes], ([$volume, $volumes]) => { + if ($volume && $volumes) { + const { chars, completed, timeReadInMinutes, progress } = $volumes[$volume.mokuroData.volume_uuid] + return { chars, completed, timeReadInMinutes, progress } + } +}); \ No newline at end of file diff --git a/src/routes/[manga]/+page.svelte b/src/routes/[manga]/+page.svelte index ab9d0a1..0995ec4 100644 --- a/src/routes/[manga]/+page.svelte +++ b/src/routes/[manga]/+page.svelte @@ -7,7 +7,7 @@ import { promptConfirmation, zipManga } from '$lib/util'; import { page } from '$app/stores'; import type { Volume } from '$lib/types'; - import { deleteVolume, volumes } from '$lib/settings'; + import { deleteVolume, mangaStats, volumes } from '$lib/settings'; function sortManga(a: Volume, b: Volume) { if (a.volumeName < b.volumeName) { @@ -66,15 +66,15 @@ {manga?.[0].mokuroData.title || 'Manga'} -{#if manga} +{#if manga && $mangaStats}

{manga[0].mokuroData.title}

-

Volumes: {stats.completed} / {manga.length}

-

Characters read: {stats.chars}

-

Minutes read: {stats.timeReadInMinutes}

+

Volumes: {$mangaStats.completed} / {manga.length}

+

Characters read: {$mangaStats.chars}

+

Minutes read: {$mangaStats.timeReadInMinutes}

diff --git a/src/routes/[manga]/[volume]/+page.svelte b/src/routes/[manga]/[volume]/+page.svelte index ca6ac34..a5805e2 100644 --- a/src/routes/[manga]/[volume]/+page.svelte +++ b/src/routes/[manga]/[volume]/+page.svelte @@ -1,24 +1,73 @@ + + {#if $volumeSettings[volumeId]} + {#if $settings.showTimer} + + {/if} {/if}