Skip to content

Commit

Permalink
Merge pull request #256 from Suwayomi/main
Browse files Browse the repository at this point in the history
library filter per category with default
  • Loading branch information
Robonau authored Dec 31, 2024
2 parents 25ab56e + 246f58b commit 94dab30
Show file tree
Hide file tree
Showing 10 changed files with 802 additions and 145 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"graphql": "^16.9.0",
"graphql-ws": "^5.16.0",
"p-queue": "^8.0.1",
"svelte-skeleton-three-state-switch": "0.0.7",
"svelte-skeleton-three-state-switch": "0.0.8",
"sveltekit-search-params": "^3.0.0"
}
}
3 changes: 3 additions & 0 deletions src/lib/components/switch.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
currentTarget: EventTarget & HTMLDivElement;
}
) => void;
title?: string;
[key: string]: unknown;
}
Expand All @@ -59,6 +60,7 @@
onchange = () => {},
onkeydown = () => {},
children,
title,
...rest
}: Props = $props();
Expand Down Expand Up @@ -129,6 +131,7 @@
aria-label={label}
aria-checked={checked}
tabindex="0"
{title}
>
<label class="slide-toggle-label {classesLabel}">
<!-- Hidden Input -->
Expand Down
14 changes: 14 additions & 0 deletions src/lib/gql/Mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -935,3 +935,17 @@ export const runUpdateLibraryManga = graphql(`
}
}
`);

export const setCategoryMeta = graphql(`
mutation MyMutation($id: Int!, $key: String!, $value: String!) {
setCategoryMeta(
input: { meta: { categoryId: $id, key: $key, value: $value } }
) {
meta {
key
value
categoryId
}
}
}
`);
5 changes: 5 additions & 0 deletions src/lib/gql/Queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export const getCategory = graphql(
...MangaTypeFragment
}
}
meta {
categoryId
key
value
}
}
}
`,
Expand Down
4 changes: 3 additions & 1 deletion src/lib/gql/graphqlClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ export const client = new Client({
ExtensionType: (e) =>
(e.pkgName as string) + (e.versionName as string) + e.repo,
TrackStatusType: () => null,
TrackerNodeList: () => null
TrackerNodeList: () => null,
CategoryMetaType: (e) =>
(e.categoryId as number).toString() + (e.key as string)
},
updates: {
Mutation: {
Expand Down
242 changes: 241 additions & 1 deletion src/lib/simpleStores.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ import type { ToastStore } from './components/Toast/types';
import {
deleteGlobalMeta,
deleteMangaMeta,
setCategoryMeta,
setGlobalMeta,
setMangaMeta
} from './gql/Mutations';
import { getManga, metas } from './gql/Queries';
import { getCategory, getManga, metas } from './gql/Queries';
import { client } from './gql/graphqlClient';
import type { presetConst } from './presets';
import { getObjectKeys, type TriState } from './util.svelte';
Expand Down Expand Up @@ -503,3 +504,242 @@ class MMState {
}

export const mmState = new MMState();

class categoryMetaStoreSingle<T> {
private key: string;
value = $state<T>() as T;
private id = -1;
private serializer: json<T> = JSON;
private cleanup = () => {};

constructor(key: string, value: T, serializer: json<T> = JSON) {
this.key = key;
this.value = value;
this.serializer = serializer;
this.setId(0);
}

public setId(id: number) {
if (this.id === id) return;
this.cleanup();
this.id = id;
const key = `VUI3_${this.id}_${this.key}`;
if (browser) {
const item = localStore(key, this.value, this.serializer);
this.value = $state.snapshot(item.value) as T;
let writeOver = true;
const data = queryStore({
client,
query: getCategory,
variables: { id }
});
let unSubscribe = () => {};
new Promise((resolve) => {
unSubscribe = data.subscribe((e) => {
if (e.data?.category) {
const val = e.data.category.meta.find(
(meta) => meta.key === key
)?.value;

if (
val &&
writeOver &&
val !== this.serialize(this.value) &&
id === this.id
) {
this.value = this.deserialize(val);
}
resolve(true);
}
});
setTimeout(() => {
resolve(true);
}, 10000);
}).then(() => {
unSubscribe();
});
this.cleanup = $effect.root(() => {
$effect(() => {
if (this.serialize(this.value) === this.serialize(item.value)) return;
writeOver = false;
item.value = $state.snapshot(this.value) as T;
client
.mutation(setCategoryMeta, {
id,
key,
value: this.serialize(this.value)
})
.toPromise();
});
});
}
}

private serialize(value: T): string {
return this.serializer.stringify(value);
}

private deserialize(item: string): T {
return this.serializer.parse(item);
}
}

function CategoryMetaStore<T>(
key: string,
value: T,
serializer: json<T> = JSON
) {
return new categoryMetaStoreSingle<T>(key, value, serializer);
}

const unread = CategoryMetaStore<'on' | 'intermediate' | 'off'>(
'Unread',
'intermediate'
);
const Downloaded = CategoryMetaStore<'on' | 'intermediate' | 'off'>(
'Downloaded',
'intermediate'
);
const Tracked = CategoryMetaStore<'on' | 'intermediate' | 'off'>(
'Tracked',
'intermediate'
);
const Ascending = CategoryMetaStore<boolean>('Ascending', false);
const sortOptions = CategoryMetaStore<keyof typeof sort>('Sort', 'ID');
const libraryCategoryTotalCounts = CategoryMetaStore<boolean>(
'TotalCounts',
true
);
const downloadsBadge = CategoryMetaStore<boolean>('DownloadsBadge', true);

const unreadBadge = CategoryMetaStore<boolean>('UnreadBadge', true);

const displayOptions = CategoryMetaStore<display>('Display', display.Compact);

const unreadUseDefault = CategoryMetaStore<boolean>('UnreadUseDefault', true);

const DownloadedUseDefault = CategoryMetaStore<boolean>(
'DownloadedUseDefault',
true
);

const TrackedUseDefault = CategoryMetaStore<boolean>('TrackedUseDefault', true);

const AscendingUseDefault = CategoryMetaStore<boolean>(
'AscendingUseDefault',
true
);

const sortOptionsUseDefault = CategoryMetaStore<boolean>(
'SortUseDefault',
true
);

const libraryCategoryTotalCountsUseDefault = CategoryMetaStore<boolean>(
'TotalCountsUseDefault',
true
);

const downloadsBadgeUseDefault = CategoryMetaStore<boolean>(
'DownloadsBadgeUseDefault',
true
);

const unreadBadgeUseDefault = CategoryMetaStore<boolean>(
'UnreadBadgeUseDefault',
true
);

const displayOptionsUseDefault = CategoryMetaStore<boolean>(
'DisplayUseDefault',
true
);
export function categoryFilterMetas(id: number) {
unread.setId(id);
Downloaded.setId(id);
Tracked.setId(id);
Ascending.setId(id);
sortOptions.setId(id);
libraryCategoryTotalCounts.setId(id);
downloadsBadge.setId(id);
unreadBadge.setId(id);
displayOptions.setId(id);
unreadUseDefault.setId(id);
DownloadedUseDefault.setId(id);
TrackedUseDefault.setId(id);
AscendingUseDefault.setId(id);
sortOptionsUseDefault.setId(id);
libraryCategoryTotalCountsUseDefault.setId(id);
downloadsBadgeUseDefault.setId(id);
unreadBadgeUseDefault.setId(id);
displayOptionsUseDefault.setId(id);
return {
unread,
Downloaded,
Tracked,
Ascending,
sortOptions,
libraryCategoryTotalCounts,
downloadsBadge,
unreadBadge,
displayOptions,
unreadUseDefault,
DownloadedUseDefault,
TrackedUseDefault,
AscendingUseDefault,
sortOptionsUseDefault,
libraryCategoryTotalCountsUseDefault,
downloadsBadgeUseDefault,
unreadBadgeUseDefault,
displayOptionsUseDefault
};
}

export function categoryFilterMetasReadOnly(id: number) {
const {
unread,
Downloaded,
Tracked,
Ascending,
sortOptions,
libraryCategoryTotalCounts,
downloadsBadge,
unreadBadge,
displayOptions,
unreadUseDefault,
DownloadedUseDefault,
TrackedUseDefault,
AscendingUseDefault,
sortOptionsUseDefault,
libraryCategoryTotalCountsUseDefault,
downloadsBadgeUseDefault,
unreadBadgeUseDefault,
displayOptionsUseDefault
} = untrack(() => categoryFilterMetas(id));

const value = $derived({
unread: unreadUseDefault.value ? gmState.value.Unread : unread.value,
Downloaded: DownloadedUseDefault.value
? gmState.value.Downloaded
: Downloaded.value,
Tracked: TrackedUseDefault.value ? gmState.value.Tracked : Tracked.value,
Ascending: AscendingUseDefault.value ? gmState.value.Asc : Ascending.value,
sortOptions: sortOptionsUseDefault.value
? gmState.value.Sort
: sortOptions.value,
libraryCategoryTotalCounts: libraryCategoryTotalCountsUseDefault.value
? gmState.value.libraryCategoryTotalCounts
: libraryCategoryTotalCounts.value,
downloadsBadge: downloadsBadgeUseDefault.value
? gmState.value.downloadsBadge
: downloadsBadge.value,
unreadBadge: unreadBadgeUseDefault.value
? gmState.value.unreadBadge
: unreadBadge.value,
displayOptions: displayOptionsUseDefault.value
? gmState.value.Display
: displayOptions.value
} as const);

return { value };
}
Loading

0 comments on commit 94dab30

Please sign in to comment.