mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 09:19:56 -05:00
Chore: Restructure Repository for SvelteKit
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
export interface DownloadQueueItem {
|
||||
progress: number;
|
||||
state: "QUEUED" | "DOWNLOADING" | "FINISHED" | "ERROR";
|
||||
tries: number;
|
||||
chapter: {
|
||||
id: number;
|
||||
name: string;
|
||||
mangaId: number;
|
||||
pageCount: number;
|
||||
manga: { id: number; title: string; thumbnailUrl: string } | null;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DownloadStatus {
|
||||
state: "STARTED" | "STOPPED";
|
||||
queue: DownloadQueueItem[];
|
||||
}
|
||||
|
||||
export interface Connection<T> {
|
||||
nodes: T[];
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
hasNextPage: boolean;
|
||||
}
|
||||
|
||||
export interface PaginatedConnection<T> extends Connection<T> {
|
||||
pageInfo: PageInfo;
|
||||
totalCount?: number;
|
||||
}
|
||||
|
||||
export interface MetaEntry {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface UpdaterJobsInfo {
|
||||
isRunning: boolean;
|
||||
finishedJobs: number;
|
||||
totalJobs: number;
|
||||
skippedMangasCount: number;
|
||||
skippedCategoriesCount: number;
|
||||
}
|
||||
|
||||
export interface UpdateStatus {
|
||||
jobsInfo: UpdaterJobsInfo;
|
||||
}
|
||||
|
||||
export interface AboutServer {
|
||||
name: string;
|
||||
version: string;
|
||||
buildType: string;
|
||||
buildTime: string;
|
||||
github: string;
|
||||
discord: string;
|
||||
}
|
||||
|
||||
export interface ServerUpdateEntry {
|
||||
channel: string;
|
||||
tag: string;
|
||||
url: string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export interface Chapter {
|
||||
id: number;
|
||||
name: string;
|
||||
chapterNumber: number;
|
||||
sourceOrder: number;
|
||||
isRead: boolean;
|
||||
isDownloaded: boolean;
|
||||
isBookmarked: boolean;
|
||||
pageCount: number;
|
||||
mangaId: number;
|
||||
fetchedAt?: string;
|
||||
uploadDate?: string | null;
|
||||
realUrl?: string | null;
|
||||
url?: string;
|
||||
lastPageRead?: number;
|
||||
lastReadAt?: string;
|
||||
scanlator?: string | null;
|
||||
manga?: { id: number; title: string; thumbnailUrl: string; inLibrary: boolean } | null;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export interface Source {
|
||||
id: string;
|
||||
name: string;
|
||||
lang: string;
|
||||
displayName: string;
|
||||
iconUrl: string;
|
||||
isNsfw: boolean;
|
||||
isConfigurable: boolean;
|
||||
supportsLatest: boolean;
|
||||
baseUrl?: string | null;
|
||||
}
|
||||
|
||||
export interface Extension {
|
||||
apkName: string;
|
||||
pkgName: string;
|
||||
name: string;
|
||||
lang: string;
|
||||
versionName: string;
|
||||
isInstalled: boolean;
|
||||
isObsolete: boolean;
|
||||
hasUpdate: boolean;
|
||||
iconUrl: string;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
export interface HistoryEntry {
|
||||
mangaId: number; mangaTitle: string; thumbnailUrl: string;
|
||||
chapterId: number; chapterName: string; readAt: number;
|
||||
}
|
||||
|
||||
export interface BookmarkEntry {
|
||||
mangaId: number; mangaTitle: string; thumbnailUrl: string;
|
||||
chapterId: number; chapterName: string; pageNumber: number;
|
||||
savedAt: number; label?: string;
|
||||
}
|
||||
|
||||
export type MarkerColor = "yellow" | "red" | "blue" | "green" | "purple";
|
||||
|
||||
export interface MarkerEntry {
|
||||
id: string; mangaId: number; mangaTitle: string; thumbnailUrl: string;
|
||||
chapterId: number; chapterName: string; pageNumber: number;
|
||||
note: string; color: MarkerColor; createdAt: number; updatedAt?: number;
|
||||
}
|
||||
|
||||
export interface ReadLogEntry { mangaId: number; chapterId: number; readAt: number; minutes: number; }
|
||||
|
||||
export interface ReadingStats {
|
||||
totalChaptersRead: number; totalMangaRead: number; totalMinutesRead: number;
|
||||
firstReadAt: number; lastReadAt: number;
|
||||
currentStreakDays: number; longestStreakDays: number; lastStreakDate: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_READING_STATS: ReadingStats = {
|
||||
totalChaptersRead: 0, totalMangaRead: 0, totalMinutesRead: 0,
|
||||
firstReadAt: 0, lastReadAt: 0, currentStreakDays: 0, longestStreakDays: 0, lastStreakDate: "",
|
||||
};
|
||||
|
||||
export interface LibraryUpdateEntry {
|
||||
mangaId: number; mangaTitle: string; thumbnailUrl: string; newChapters: number; checkedAt: number;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export * from "./manga";
|
||||
export * from "./chapter";
|
||||
export * from "./extension";
|
||||
export * from "./tracking";
|
||||
export * from "./api";
|
||||
export * from "./settings";
|
||||
export * from "./history";
|
||||
@@ -0,0 +1,59 @@
|
||||
export interface Category {
|
||||
id: number;
|
||||
name: string;
|
||||
order: number;
|
||||
default: boolean;
|
||||
includeInUpdate: string;
|
||||
includeInDownload: string;
|
||||
mangas?: { nodes: Manga[] };
|
||||
}
|
||||
|
||||
export interface ChapterRef {
|
||||
id: number;
|
||||
chapterNumber: number;
|
||||
uploadDate?: string;
|
||||
lastPageRead?: number;
|
||||
}
|
||||
|
||||
export interface Manga {
|
||||
id: number;
|
||||
title: string;
|
||||
thumbnailUrl: string;
|
||||
inLibrary: boolean;
|
||||
initialized?: boolean;
|
||||
downloadCount?: number;
|
||||
unreadCount?: number;
|
||||
bookmarkCount?: number;
|
||||
hasDuplicateChapters?: boolean;
|
||||
chapters?: { totalCount: number };
|
||||
description?: string | null;
|
||||
status?: string | null;
|
||||
author?: string | null;
|
||||
artist?: string | null;
|
||||
genre?: string[];
|
||||
realUrl?: string | null;
|
||||
url?: string;
|
||||
sourceId?: string;
|
||||
inLibraryAt?: string | null;
|
||||
lastFetchedAt?: string | null;
|
||||
chaptersLastFetchedAt?: string | null;
|
||||
thumbnailUrlLastFetched?: string | null;
|
||||
age?: string | null;
|
||||
chaptersAge?: string | null;
|
||||
updateStrategy?: "ALWAYS_UPDATE" | "ONLY_FETCH_ONCE";
|
||||
latestFetchedChapter?: ChapterRef | null;
|
||||
latestUploadedChapter?: ChapterRef | null;
|
||||
latestReadChapter?: ChapterRef | null;
|
||||
lastReadChapter?: ChapterRef | null;
|
||||
firstUnreadChapter?: ChapterRef | null;
|
||||
highestNumberedChapter?: ChapterRef | null;
|
||||
source?: { id: string; name: string; displayName: string } | null;
|
||||
}
|
||||
|
||||
export interface MangaDetail extends Manga {
|
||||
description: string | null;
|
||||
author: string | null;
|
||||
artist: string | null;
|
||||
status: string | null;
|
||||
genre: string[];
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
import { DEFAULT_KEYBINDS, type Keybinds } from "../core/keybinds/defaultBinds";
|
||||
|
||||
export type PageStyle = "single" | "double" | "longstrip";
|
||||
export type FitMode = "width" | "height" | "screen" | "original";
|
||||
export type LibraryFilter = "all" | "library" | "downloaded" | string;
|
||||
export type ReadingDirection = "ltr" | "rtl";
|
||||
export type ChapterSortDir = "desc" | "asc";
|
||||
export type ChapterSortMode = "source" | "chapterNumber" | "uploadDate";
|
||||
export type ContentLevel = "strict" | "moderate" | "unrestricted";
|
||||
|
||||
export type LibrarySortMode =
|
||||
| "az" | "unreadCount" | "totalChapters"
|
||||
| "recentlyAdded" | "recentlyRead" | "latestFetched" | "latestUploaded";
|
||||
|
||||
export type LibrarySortDir = "asc" | "desc";
|
||||
|
||||
export type LibraryStatusFilter = "ALL" | "ONGOING" | "COMPLETED" | "CANCELLED" | "HIATUS" | "UNKNOWN";
|
||||
export type LibraryContentFilter = "unread" | "started" | "downloaded" | "bookmarked" | "marked";
|
||||
|
||||
export type BuiltinTheme = "original" | "dark" | "light" | "light-contrast" | "midnight" | "warm";
|
||||
export type Theme = BuiltinTheme | string;
|
||||
|
||||
export interface ThemeTokens {
|
||||
"bg-void": string; "bg-base": string; "bg-surface": string;
|
||||
"bg-raised": string; "bg-overlay": string; "bg-subtle": string;
|
||||
"border-dim": string; "border-base": string; "border-strong": string; "border-focus": string;
|
||||
"text-primary": string; "text-secondary": string; "text-muted": string;
|
||||
"text-faint": string; "text-disabled": string;
|
||||
"accent": string; "accent-dim": string; "accent-muted": string;
|
||||
"accent-fg": string; "accent-bright": string;
|
||||
"color-error": string; "color-error-bg": string;
|
||||
"color-success": string; "color-info": string; "color-info-bg": string;
|
||||
}
|
||||
|
||||
export interface CustomTheme { id: string; name: string; tokens: ThemeTokens; }
|
||||
|
||||
export const DEFAULT_THEME_TOKENS: ThemeTokens = {
|
||||
"bg-void": "#080808", "bg-base": "#0c0c0c", "bg-surface": "#101010",
|
||||
"bg-raised": "#151515", "bg-overlay": "#1a1a1a", "bg-subtle": "#202020",
|
||||
"border-dim": "#1c1c1c", "border-base": "#242424", "border-strong": "#2e2e2e", "border-focus": "#4a5c4a",
|
||||
"text-primary": "#f0efec", "text-secondary": "#c8c6c0", "text-muted": "#8a8880",
|
||||
"text-faint": "#4e4d4a", "text-disabled": "#2a2a28",
|
||||
"accent": "#6b8f6b", "accent-dim": "#2a3d2a", "accent-muted": "#1a251a",
|
||||
"accent-fg": "#a8c4a8", "accent-bright": "#8fb88f",
|
||||
"color-error": "#c47a7a", "color-error-bg": "#1f1212",
|
||||
"color-success": "#7aab7a", "color-info": "#7a9ec4", "color-info-bg": "#121a1f",
|
||||
};
|
||||
|
||||
export interface MangaPrefs {
|
||||
autoDownload: boolean; downloadAhead: number; deleteOnRead: boolean;
|
||||
deleteDelayHours: number; maxKeepChapters: number; pauseUpdates: boolean;
|
||||
refreshInterval: "global" | "daily" | "weekly" | "manual";
|
||||
preferredScanlator: string; scanlatorFilter: string[];
|
||||
scanlatorBlacklist: string[]; scanlatorForce: boolean;
|
||||
autoDownloadScanlators: string[];
|
||||
coverUrl?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_MANGA_PREFS: MangaPrefs = {
|
||||
autoDownload: false, downloadAhead: 0, deleteOnRead: false,
|
||||
deleteDelayHours: 0, maxKeepChapters: 0, pauseUpdates: false,
|
||||
refreshInterval: "global", preferredScanlator: "", scanlatorFilter: [],
|
||||
scanlatorBlacklist: [], scanlatorForce: false,
|
||||
autoDownloadScanlators: [],
|
||||
};
|
||||
|
||||
export interface ReaderSettings {
|
||||
pageStyle: PageStyle;
|
||||
fitMode: FitMode;
|
||||
readingDirection: ReadingDirection;
|
||||
readerZoom: number;
|
||||
pageGap: boolean;
|
||||
optimizeContrast: boolean;
|
||||
offsetDoubleSpreads: boolean;
|
||||
barPosition?: "top" | "left" | "right";
|
||||
}
|
||||
|
||||
export interface ReaderPreset {
|
||||
id: string;
|
||||
name: string;
|
||||
settings: ReaderSettings;
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
pageStyle: PageStyle; readingDirection: ReadingDirection; fitMode: FitMode;
|
||||
readerZoom: number; pageGap: boolean; optimizeContrast: boolean;
|
||||
offsetDoubleSpreads: boolean; preloadPages: number;
|
||||
autoMarkRead: boolean; autoNextChapter: boolean;
|
||||
libraryCropCovers: boolean; libraryPageSize: number;
|
||||
contentLevel: ContentLevel; sourceOverridesEnabled: boolean;
|
||||
nsfwAllowedSourceIds: string[]; nsfwBlockedSourceIds: string[];
|
||||
discordRpc: boolean;
|
||||
chapterSortDir: ChapterSortDir; chapterSortMode: ChapterSortMode; chapterPageSize: number;
|
||||
uiZoom: number; compactSidebar: boolean; gpuAcceleration: boolean;
|
||||
serverUrl: string; serverBinary: string; serverBinaryArgs: string; autoStartServer: boolean; suwayomiWebUI: boolean;
|
||||
preferredExtensionLang: string; keybinds: Keybinds;
|
||||
idleTimeoutMin?: number; splashCards?: boolean;
|
||||
storageLimitGb: number | null; markReadOnNext: boolean; readerDebounceMs: number;
|
||||
autoBookmark: boolean; theme: Theme; libraryBranches: boolean; renderLimit: number;
|
||||
heroSlots: (number | null)[]; mangaLinks: Record<number, number[]>;
|
||||
mangaPrefs: Record<number, Partial<MangaPrefs>>;
|
||||
serverAuthUser: string; serverAuthPass: string;
|
||||
serverAuthMode: "NONE" | "BASIC_AUTH" | "SIMPLE_LOGIN" | "UI_LOGIN";
|
||||
socksProxyEnabled: boolean; socksProxyHost: string; socksProxyPort: string;
|
||||
socksProxyVersion: number; socksProxyUsername: string; socksProxyPassword: string;
|
||||
flareSolverrEnabled: boolean; flareSolverrUrl: string; flareSolverrTimeout: number;
|
||||
flareSolverrSessionName: string; flareSolverrSessionTtl: number; flareSolverrAsResponseFallback: boolean;
|
||||
appLockEnabled: boolean; appLockPin: string;
|
||||
customThemes: CustomTheme[]; hiddenCategoryIds: number[];
|
||||
defaultLibraryCategoryId: number | null; savedIsDefaultCategory: boolean;
|
||||
libraryTabSort: Record<string, { mode: LibrarySortMode; dir: LibrarySortDir }>;
|
||||
libraryTabStatus: Record<string, LibraryStatusFilter>;
|
||||
libraryTabFilters: Record<string, Partial<Record<LibraryContentFilter, boolean>>>;
|
||||
maxPageWidth?: number; uiScale?: number;
|
||||
extraScanDirs: string[]; serverDownloadsPath: string; serverLocalSourcePath: string;
|
||||
qolAnimations: boolean;
|
||||
libraryStatsAlways: boolean;
|
||||
pinnedSourceIds: string[];
|
||||
readerPresets: ReaderPreset[];
|
||||
mangaReaderSettings: Record<number, ReaderSettings>;
|
||||
barPosition?: "top" | "left" | "right";
|
||||
trackerSyncBack: boolean;
|
||||
trackerSyncBackThreshold: number | null;
|
||||
trackerRespectScanlatorFilter: boolean;
|
||||
pinchZoom?: boolean;
|
||||
autoLinkOnOpen: boolean;
|
||||
downloadToastsEnabled: boolean;
|
||||
downloadAutoRetry: boolean;
|
||||
hiddenLibraryTabs: string[];
|
||||
libraryPinnedTabOrder: string[];
|
||||
autoScroll?: boolean;
|
||||
autoScrollSpeed?: number;
|
||||
disableAutoComplete: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: Settings = {
|
||||
pageStyle: "longstrip", readingDirection: "ltr", fitMode: "width",
|
||||
readerZoom: 1.0, pageGap: true, optimizeContrast: false, offsetDoubleSpreads: false,
|
||||
preloadPages: 3, autoMarkRead: true, autoNextChapter: true,
|
||||
libraryCropCovers: true, libraryPageSize: 48,
|
||||
contentLevel: "strict", sourceOverridesEnabled: false,
|
||||
nsfwAllowedSourceIds: [], nsfwBlockedSourceIds: [],
|
||||
discordRpc: false,
|
||||
chapterSortDir: "desc", chapterSortMode: "source", chapterPageSize: 25,
|
||||
uiZoom: 1.0, compactSidebar: false, gpuAcceleration: true,
|
||||
serverUrl: "http://localhost:4567", serverBinary: "", serverBinaryArgs: "", autoStartServer: true, suwayomiWebUI: false,
|
||||
preferredExtensionLang: "en", keybinds: DEFAULT_KEYBINDS,
|
||||
idleTimeoutMin: 5, splashCards: true, storageLimitGb: null,
|
||||
markReadOnNext: true, readerDebounceMs: 120, autoBookmark: true,
|
||||
theme: "dark", libraryBranches: true, renderLimit: 48,
|
||||
heroSlots: [null, null, null, null], mangaLinks: {}, mangaPrefs: {},
|
||||
serverAuthUser: "", serverAuthPass: "", serverAuthMode: "NONE",
|
||||
socksProxyEnabled: false, socksProxyHost: "", socksProxyPort: "1080",
|
||||
socksProxyVersion: 5, socksProxyUsername: "", socksProxyPassword: "",
|
||||
flareSolverrEnabled: false, flareSolverrUrl: "http://localhost:8191",
|
||||
flareSolverrTimeout: 60, flareSolverrSessionName: "moku",
|
||||
flareSolverrSessionTtl: 15, flareSolverrAsResponseFallback: false,
|
||||
appLockEnabled: false, appLockPin: "",
|
||||
customThemes: [], hiddenCategoryIds: [], defaultLibraryCategoryId: null,
|
||||
savedIsDefaultCategory: false,
|
||||
libraryTabSort: {}, libraryTabStatus: {}, libraryTabFilters: {},
|
||||
extraScanDirs: [], serverDownloadsPath: "", serverLocalSourcePath: "",
|
||||
qolAnimations: true,
|
||||
libraryStatsAlways: false,
|
||||
pinnedSourceIds: [],
|
||||
readerPresets: [],
|
||||
mangaReaderSettings: {},
|
||||
trackerSyncBack: false,
|
||||
trackerSyncBackThreshold: 20,
|
||||
trackerRespectScanlatorFilter: true,
|
||||
pinchZoom: false,
|
||||
autoLinkOnOpen: false,
|
||||
downloadToastsEnabled: true,
|
||||
downloadAutoRetry: false,
|
||||
hiddenLibraryTabs: [],
|
||||
libraryPinnedTabOrder: [],
|
||||
autoScroll: false,
|
||||
autoScrollSpeed: 5,
|
||||
disableAutoComplete: false,
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
export interface TrackerStatus {
|
||||
value: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Tracker {
|
||||
id: number;
|
||||
name: string;
|
||||
icon: string;
|
||||
isLoggedIn: boolean;
|
||||
isTokenExpired: boolean;
|
||||
authUrl: string | null;
|
||||
supportsPrivateTracking: boolean;
|
||||
supportsReadingDates: boolean;
|
||||
supportsTrackDeletion: boolean;
|
||||
scores: string[];
|
||||
statuses: TrackerStatus[];
|
||||
}
|
||||
|
||||
export interface TrackRecord {
|
||||
id: number;
|
||||
trackerId: number;
|
||||
mangaId: number;
|
||||
remoteId: string;
|
||||
libraryId: string | null;
|
||||
title: string;
|
||||
status: number;
|
||||
score: number;
|
||||
displayScore: string;
|
||||
lastChapterRead: number;
|
||||
totalChapters: number;
|
||||
remoteUrl: string;
|
||||
startDate: string;
|
||||
finishDate: string;
|
||||
private: boolean;
|
||||
manga?: { id: number; title: string; thumbnailUrl: string; inLibrary?: boolean } | null;
|
||||
tracker?: Pick<Tracker, "id" | "name" | "icon" | "isLoggedIn" | "statuses"> | null;
|
||||
}
|
||||
|
||||
export interface TrackSearch {
|
||||
id: number;
|
||||
trackerId: number;
|
||||
remoteId: string;
|
||||
title: string;
|
||||
coverUrl: string | null;
|
||||
summary: string | null;
|
||||
publishingStatus: string | null;
|
||||
publishingType: string | null;
|
||||
startDate: string | null;
|
||||
totalChapters: number;
|
||||
trackingUrl: string | null;
|
||||
}
|
||||
Reference in New Issue
Block a user