mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 09:19:56 -05:00
Feat: Reworked ENTIRE Project for Readability
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||
import { gql } from "@api/client";
|
||||
import { GET_DOWNLOAD_STATUS } from "@api/queries/downloads";
|
||||
import { addToast, setActiveDownloads } from "@store/state.svelte";
|
||||
import type { DownloadStatus, DownloadQueueItem } from "@types/index";
|
||||
|
||||
let prevQueue: DownloadQueueItem[] = [];
|
||||
|
||||
function detectCompletions(prev: DownloadQueueItem[], next: DownloadQueueItem[]) {
|
||||
for (const item of prev) {
|
||||
if (item.state !== "DOWNLOADING") continue;
|
||||
if (!next.some(q => q.chapter.id === item.chapter.id)) {
|
||||
const manga = item.chapter.manga;
|
||||
addToast({
|
||||
kind: "success",
|
||||
title: "Chapter downloaded",
|
||||
body: manga ? `${manga.title} — ${item.chapter.name}` : item.chapter.name,
|
||||
duration: 4000,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyQueue(next: DownloadQueueItem[]) {
|
||||
detectCompletions(prevQueue, next);
|
||||
prevQueue = next;
|
||||
setActiveDownloads(next.map(item => ({
|
||||
chapterId: item.chapter.id,
|
||||
mangaId: item.chapter.mangaId,
|
||||
progress: item.progress,
|
||||
})));
|
||||
}
|
||||
|
||||
export async function mountDownloadPoller(): Promise<() => void> {
|
||||
const win = getCurrentWindow();
|
||||
let paused = false;
|
||||
let interval: ReturnType<typeof setInterval>;
|
||||
|
||||
const poll = () => {
|
||||
if (paused) return;
|
||||
gql<{ downloadStatus: DownloadStatus }>(GET_DOWNLOAD_STATUS)
|
||||
.then(d => applyQueue(d.downloadStatus.queue))
|
||||
.catch(console.error);
|
||||
};
|
||||
|
||||
poll();
|
||||
interval = setInterval(poll, 2000);
|
||||
|
||||
const onVisibility = () => { paused = document.hidden; };
|
||||
document.addEventListener("visibilitychange", onVisibility);
|
||||
|
||||
const unlistenFocus = await win.onFocusChanged(({ payload: focused }) => {
|
||||
paused = !focused;
|
||||
});
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
document.removeEventListener("visibilitychange", onVisibility);
|
||||
unlistenFocus();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { DownloadQueueItem, ActiveDownload } from "@types/index";
|
||||
|
||||
export function toActiveDownloads(queue: DownloadQueueItem[]): ActiveDownload[] {
|
||||
return queue.map((item) => ({
|
||||
chapterId: item.chapter.id,
|
||||
mangaId: item.chapter.mangaId,
|
||||
progress: item.progress,
|
||||
}));
|
||||
}
|
||||
|
||||
export function optimisticRemove(queue: DownloadQueueItem[], chapterId: number): DownloadQueueItem[] {
|
||||
return queue.filter((i) => i.chapter.id !== chapterId);
|
||||
}
|
||||
|
||||
export function optimisticToggle(state: string, wasRunning: boolean): string {
|
||||
return wasRunning ? "STOPPED" : "STARTED";
|
||||
}
|
||||
|
||||
export function isRunning(state: string | undefined): boolean {
|
||||
return state === "STARTED";
|
||||
}
|
||||
|
||||
export function pageProgress(progress: number, pageCount: number): { done: number; total: number } {
|
||||
return { done: Math.round(progress * pageCount), total: pageCount };
|
||||
}
|
||||
Reference in New Issue
Block a user