diff --git a/src/App.svelte b/src/App.svelte
index 6c505d6..05b9fde 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -4,7 +4,7 @@
import { listen } from "@tauri-apps/api/event";
import { gql } from "./lib/client";
import { GET_DOWNLOAD_STATUS } from "./lib/queries";
- import { activeChapter, settingsOpen, settings, activeDownloads, addToast } from "./store";
+ import { store, addToast, setActiveDownloads } from "./store/state.svelte";
import type { DownloadStatus, DownloadQueueItem } from "./lib/types";
import Layout from "./components/layout/Layout.svelte";
import Reader from "./components/reader/Reader.svelte";
@@ -16,8 +16,8 @@
const MAX_ATTEMPTS = 30;
- let serverProbeOk = $state(!settings.autoStartServer);
- let appReady = $state(!settings.autoStartServer);
+ let serverProbeOk = $state(!store.settings.autoStartServer);
+ let appReady = $state(!store.settings.autoStartServer);
let failed = $state(false);
let idle = $state(false);
let devSplash = $state(false);
@@ -42,15 +42,15 @@
function applyQueue(next: DownloadQueueItem[]) {
detectCompletions(prevQueue, next);
prevQueue = next;
- activeDownloads = next.map(item => ({
+ setActiveDownloads(next.map(item => ({
chapterId: item.chapter.id, mangaId: item.chapter.mangaId, progress: item.progress,
- }));
+ })));
}
function resetIdle() {
if (idle) return;
if (idleTimer) clearTimeout(idleTimer);
- const ms = (settings.idleTimeoutMin ?? 5) * 60 * 1000;
+ const ms = (store.settings.idleTimeoutMin ?? 5) * 60 * 1000;
if (ms === 0) return;
idleTimer = setTimeout(() => idle = true, ms);
}
@@ -65,11 +65,15 @@
});
$effect(() => {
- document.documentElement.style.zoom = `${settings.uiScale * 1.5}%`;
+ const scale = store.settings.uiScale * 1.5;
+ document.documentElement.style.zoom = `${scale}%`;
+ document.documentElement.style.setProperty("--ui-scale", String(scale));
+ // --visual-vh gives true viewport height independent of zoom
+ document.documentElement.style.setProperty("--visual-vh", `${window.innerHeight / (scale / 100)}px`);
});
$effect(() => {
- document.documentElement.setAttribute("data-theme", settings.theme ?? "dark");
+ document.documentElement.setAttribute("data-theme", store.settings.theme ?? "dark");
});
$effect(() => {
@@ -85,8 +89,8 @@
document.addEventListener("contextmenu", e => e.preventDefault());
(window as any).__mokuShowSplash = () => devSplash = true;
- if (settings.autoStartServer) {
- invoke("spawn_server", { binary: settings.serverBinary }).catch(err =>
+ if (store.settings.autoStartServer) {
+ invoke("spawn_server", { binary: store.settings.serverBinary }).catch(err =>
console.warn("Could not start server:", err));
}
@@ -96,7 +100,7 @@
if (cancelled) return;
tries++;
try {
- const res = await fetch(`${settings.serverUrl}/api/graphql`, {
+ const res = await fetch(`${store.settings.serverUrl}/api/graphql`, {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: "{ __typename }" }),
signal: AbortSignal.timeout(2000),
@@ -110,10 +114,10 @@
}
type P = { chapterId: number; mangaId: number; progress: number }[];
- unlistenDownload = await listen
("download-progress", e => { activeDownloads = e.payload; });
+ unlistenDownload = await listen
("download-progress", e => { setActiveDownloads(e.payload); });
return () => {
- if (settings.autoStartServer) invoke("kill_server").catch(() => {});
+ if (store.settings.autoStartServer) invoke("kill_server").catch(() => {});
if (idleTimer) clearTimeout(idleTimer);
if (pollInterval) clearInterval(pollInterval);
unlistenDownload?.();
@@ -125,24 +129,24 @@
{#if devSplash}
- setTimeout(() => devSplash = false, 340)} />
{:else if !appReady}
appReady = true}
onRetry={handleRetry} />
{:else}
- {#if idle && !activeChapter}
-
setTimeout(() => idle = false, 340)} />
{/if}
- {#if !activeChapter}{/if}
+ {#if !store.activeChapter}{/if}
- {#if activeChapter}{:else}{/if}
+ {#if store.activeChapter}{:else}{/if}
- {#if settingsOpen}{/if}
+ {#if store.settingsOpen}{/if}
diff --git a/src/components/layout/Layout.svelte b/src/components/layout/Layout.svelte
index b699b2c..4c7a585 100644
--- a/src/components/layout/Layout.svelte
+++ b/src/components/layout/Layout.svelte
@@ -1,34 +1,37 @@
- {#if activeManga}
+ {#if store.activeManga}
- {:else if navPage === "home"}
+ {:else if store.navPage === "home"}
- {:else if navPage === "library"}
+ {:else if store.navPage === "library"}
- {:else if navPage === "search"}
+ {:else if store.navPage === "search"}
- {:else if navPage === "history"}
+ {:else if store.navPage === "history"}
- {:else if navPage === "explore" || navPage === "sources"}
+ {:else if (store.navPage === "explore" || store.navPage === "sources") && store.genreFilter}
+
+ {:else if store.navPage === "explore" || store.navPage === "sources"}
- {:else if navPage === "downloads"}
+ {:else if store.navPage === "downloads"}
- {:else if navPage === "extensions"}
+ {:else if store.navPage === "extensions"}
{:else}
diff --git a/src/components/layout/RecentActivity.svelte b/src/components/layout/RecentActivity.svelte
index 1b0b1b6..f0c3881 100644
--- a/src/components/layout/RecentActivity.svelte
+++ b/src/components/layout/RecentActivity.svelte
@@ -1,13 +1,12 @@
@@ -35,14 +35,14 @@
-
diff --git a/src/components/layout/SplashScreen.svelte b/src/components/layout/SplashScreen.svelte
index 1f85b3a..d5570de 100644
--- a/src/components/layout/SplashScreen.svelte
+++ b/src/components/layout/SplashScreen.svelte
@@ -24,7 +24,7 @@
let exiting = $state(false);
let exitLock = false;
- let fpsEl: HTMLSpanElement;
+ let fpsEl = $state(undefined);
function triggerExit(cb?: () => void) {
if (exitLock) return;
diff --git a/src/components/layout/TitleBar.svelte b/src/components/layout/TitleBar.svelte
index 863dafa..4b7478f 100644
--- a/src/components/layout/TitleBar.svelte
+++ b/src/components/layout/TitleBar.svelte
@@ -6,17 +6,17 @@
Moku
-
win.minimize()} title="Minimize" aria-label="Minimize">
+ win.minimize()} title="Minimize" aria-label="Minimize">
- win.toggleMaximize()} title="Maximize" aria-label="Maximize">
+ win.toggleMaximize()} title="Maximize" aria-label="Maximize">
- win.close()} title="Close" aria-label="Close">
+ win.close()} title="Close" aria-label="Close">