aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Tools/Wrapped
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-26 08:54:46 -0800
committerFuwn <[email protected]>2026-01-26 08:54:46 -0800
commite978d534b6b97962c9a6393da62d95e049dc3c1f (patch)
tree4bdb461f348853703a46015a359e2396ecffc357 /src/lib/Tools/Wrapped
parentrefactor:(lib): Migrate another 25 components to Svelte 5 syntax (diff)
downloaddue.moe-e978d534b6b97962c9a6393da62d95e049dc3c1f.tar.xz
due.moe-e978d534b6b97962c9a6393da62d95e049dc3c1f.zip
refactor: Complete Svelte 4 to Svelte 5 syntax migration
Diffstat (limited to 'src/lib/Tools/Wrapped')
-rw-r--r--src/lib/Tools/Wrapped/Media.svelte31
-rw-r--r--src/lib/Tools/Wrapped/Tool.svelte229
-rw-r--r--src/lib/Tools/Wrapped/Top/Activity.svelte13
3 files changed, 137 insertions, 136 deletions
diff --git a/src/lib/Tools/Wrapped/Media.svelte b/src/lib/Tools/Wrapped/Media.svelte
index 90e0cde3..d6b9baec 100644
--- a/src/lib/Tools/Wrapped/Media.svelte
+++ b/src/lib/Tools/Wrapped/Media.svelte
@@ -4,14 +4,25 @@
import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
import proxy from '$lib/Utility/proxy';
- export let animeList: Media[] | undefined;
- export let mangaList: Media[] | undefined;
- export let wrapped: Wrapped;
- export let updateWidth: () => void;
- export let highestRatedMediaPercentage: boolean;
- export let highestRatedCount: number;
- export let animeMostTitle: string;
- export let mangaMostTitle: string;
+ let {
+ animeList,
+ mangaList,
+ wrapped,
+ updateWidth,
+ highestRatedMediaPercentage,
+ highestRatedCount,
+ animeMostTitle,
+ mangaMostTitle
+ }: {
+ animeList: Media[] | undefined;
+ mangaList: Media[] | undefined;
+ wrapped: Wrapped;
+ updateWidth: () => void;
+ highestRatedMediaPercentage: boolean;
+ highestRatedCount: number;
+ animeMostTitle: string;
+ mangaMostTitle: string;
+ } = $props();
</script>
{#if animeList !== undefined || mangaList !== undefined}
@@ -35,7 +46,7 @@
<b>{animeMostTitle} Anime</b>
<ol>
{#if animeList !== undefined && animeList.length !== 0}
- {#each animeList?.slice(0, highestRatedCount) as anime}
+ {#each animeList?.slice(0, highestRatedCount) as anime (anime.id)}
<li>
<a href={`https://anilist.co/anime/${anime.id}`} target="_blank">
<MediaTitleDisplay title={anime.title} />
@@ -74,7 +85,7 @@
<b>{mangaMostTitle} Manga</b>
<ol>
{#if mangaList !== undefined && mangaList.length !== 0}
- {#each mangaList?.slice(0, highestRatedCount) as manga}
+ {#each mangaList?.slice(0, highestRatedCount) as manga (manga.id)}
<li>
<a href={`https://anilist.co/manga/${manga.id}`} target="_blank">
<MediaTitleDisplay title={manga.title} />
diff --git a/src/lib/Tools/Wrapped/Tool.svelte b/src/lib/Tools/Wrapped/Tool.svelte
index 3676cbdd..a1c9dfb2 100644
--- a/src/lib/Tools/Wrapped/Tool.svelte
+++ b/src/lib/Tools/Wrapped/Tool.svelte
@@ -11,6 +11,7 @@
SortOptions,
type Wrapped
} from '$lib/Data/AniList/wrapped';
+ import { untrack } from 'svelte';
import {
fullActivityHistory,
activityHistory as getActivityHistory,
@@ -40,61 +41,64 @@
import tooltip from '$lib/Tooltip/tooltip';
import LogInRestricted from '$lib/Error/LogInRestricted.svelte';
- export let user: AniListAuthorisation;
+ interface Props {
+ user: AniListAuthorisation;
+ }
+ let { user }: Props = $props();
const currentYear = new Date(Date.now()).getFullYear();
- let selectedYear = new Date(Date.now()).getFullYear();
- let episodes = 0;
- let chapters = 0;
- let minutesWatched = 0;
- let animeList: Media[] | undefined = undefined;
- let mangaList: Media[] | undefined = undefined;
- let calculatedAnimeList: Media[] | undefined = undefined;
- let calculatedMangaList: Media[] | undefined = undefined;
- let originalAnimeList: Media[] | undefined = undefined;
- let originalMangaList: Media[] | undefined = undefined;
- let transparency = false;
- let lightTheme = true;
- let watermark = false;
- let includeMusic = false;
- let includeSpecials = true;
- let includeRepeats = false;
- let width = 1920;
- let lightMode = false;
- let highestRatedCount = 5;
- let genreTagCount = 5;
- let mounted = false;
- let generated = false;
- let disableActivityHistory = true;
- let excludedKeywordsInput = '';
- let excludedKeywords: string[] = [];
- let useFullActivityHistory = false;
- let disableLoopingActivityCounter = false;
- let topGenresTags = true;
- let topMedia: TopMedia;
- let highestRatedMediaPercentage = true;
- let highestRatedGenreTagPercentage = true;
- let genreTagsSort = SortOptions.SCORE;
- let mediaSort = SortOptions.SCORE;
- let includeMovies = true;
- let includeOVAs = true;
- let activityHistoryPosition: 'TOP' | 'BELOW_TOP' | 'ORIGINAL' = 'ORIGINAL';
- let includeOngoingMediaFromPreviousYears = false;
- let excludeUnratedUnwatched = true;
- let startDateFilter: Date | null = null;
- let endDateFilter: Date | null = null;
- let dateTicked = false;
- let shouldFetchData = false;
- let needsRefetch = false;
- let dataFetched = false;
- let fetchKey = 0;
- let lastSelectedYear = selectedYear;
- let lastUseFullActivityHistory = useFullActivityHistory;
- let lastDisableLoopingActivityCounter = disableLoopingActivityCounter;
- let lastStartDateFilter: Date | null = startDateFilter;
- let lastEndDateFilter: Date | null = endDateFilter;
-
- $: {
+ let selectedYear = $state(new Date(Date.now()).getFullYear());
+ let episodes = $state(0);
+ let chapters = $state(0);
+ let minutesWatched = $state(0);
+ let animeList: Media[] | undefined = $state(undefined);
+ let mangaList: Media[] | undefined = $state(undefined);
+ let calculatedAnimeList: Media[] | undefined = $state(undefined);
+ let calculatedMangaList: Media[] | undefined = $state(undefined);
+ let originalAnimeList: Media[] | undefined = $state(undefined);
+ let originalMangaList: Media[] | undefined = $state(undefined);
+ let transparency = $state(false);
+ let lightTheme = $state(true);
+ let watermark = $state(false);
+ let includeMusic = $state(false);
+ let includeSpecials = $state(true);
+ let includeRepeats = $state(false);
+ let width = $state(1920);
+ let lightMode = $state(false);
+ let highestRatedCount = $state(5);
+ let genreTagCount = $state(5);
+ let mounted = $state(false);
+ let generated = $state(false);
+ let disableActivityHistory = $state(true);
+ let excludedKeywordsInput = $state('');
+ let excludedKeywords: string[] = $state([]);
+ let useFullActivityHistory = $state(false);
+ let disableLoopingActivityCounter = $state(false);
+ let topGenresTags = $state(true);
+ let topMedia: TopMedia = $state(undefined as unknown as TopMedia);
+ let highestRatedMediaPercentage = $state(true);
+ let highestRatedGenreTagPercentage = $state(true);
+ let genreTagsSort: SortOptions = $state(SortOptions.SCORE);
+ let mediaSort: SortOptions = $state(SortOptions.SCORE);
+ let includeMovies = $state(true);
+ let includeOVAs = $state(true);
+ let activityHistoryPosition: 'TOP' | 'BELOW_TOP' | 'ORIGINAL' = $state('ORIGINAL');
+ let includeOngoingMediaFromPreviousYears = $state(false);
+ let excludeUnratedUnwatched = $state(true);
+ let startDateFilter: Date | null = $state(null);
+ let endDateFilter: Date | null = $state(null);
+ let dateTicked = $state(false);
+ let shouldFetchData = $state(false);
+ let needsRefetch = $state(false);
+ let dataFetched = $state(false);
+ let fetchKey = $state(0);
+ let lastSelectedYear = $state(untrack(() => selectedYear));
+ let lastUseFullActivityHistory = $state(untrack(() => useFullActivityHistory));
+ let lastDisableLoopingActivityCounter = $state(untrack(() => disableLoopingActivityCounter));
+ let lastStartDateFilter: Date | null = $state(untrack(() => startDateFilter));
+ let lastEndDateFilter: Date | null = $state(untrack(() => endDateFilter));
+
+ $effect(() => {
if (browser && mounted) {
$page.url.searchParams.set('transparency', transparency.toString());
$page.url.searchParams.set('lightTheme', lightTheme.toString());
@@ -126,9 +130,9 @@
history.replaceState(null, '', `?${$page.url.searchParams.toString()}`);
}
- }
+ });
- $: {
+ $effect(() => {
if (dataFetched) {
const yearChanged = selectedYear !== lastSelectedYear;
const fullActivityChanged = useFullActivityHistory !== lastUseFullActivityHistory;
@@ -145,35 +149,36 @@
)
needsRefetch = true;
}
- }
+ });
- $: {
- includeMusic = includeMusic;
- includeSpecials = includeSpecials;
- includeRepeats = includeRepeats;
- disableActivityHistory = disableActivityHistory;
- highestRatedMediaPercentage = highestRatedMediaPercentage;
- highestRatedGenreTagPercentage = highestRatedGenreTagPercentage;
- topGenresTags = topGenresTags;
- genreTagsSort = genreTagsSort;
- mediaSort = mediaSort;
- includeMovies = includeMovies;
- includeOVAs = includeOVAs;
- selectedYear = selectedYear;
- includeOngoingMediaFromPreviousYears = includeOngoingMediaFromPreviousYears;
- excludeUnratedUnwatched = excludeUnratedUnwatched;
-
- if (shouldFetchData) update().then(updateWidth).catch(updateWidth);
- }
- $: {
- animeList = animeList;
- mangaList = mangaList;
- highestRatedCount = highestRatedCount;
+ $effect(() => {
+ includeMusic;
+ includeSpecials;
+ includeRepeats;
+ disableActivityHistory;
+ highestRatedMediaPercentage;
+ highestRatedGenreTagPercentage;
+ topGenresTags;
+ genreTagsSort;
+ mediaSort;
+ includeMovies;
+ includeOVAs;
+ includeOngoingMediaFromPreviousYears;
+ excludeUnratedUnwatched;
+
+ if (dataFetched) needsRefetch = true;
+ });
+
+ $effect(() => {
+ animeList;
+ mangaList;
+ highestRatedCount;
new Promise((resolve) => setTimeout(resolve, 1)).then(updateWidth);
- }
- $: {
- genreTagCount = genreTagCount;
+ });
+
+ $effect(() => {
+ genreTagCount;
if (animeList && mangaList)
topMedia = tops(
@@ -184,49 +189,31 @@
);
new Promise((resolve) => setTimeout(resolve, 1)).then(updateWidth);
- }
- $: {
- excludedKeywords = excludedKeywords;
+ });
+
+ $effect(() => {
+ excludedKeywords;
if (excludedKeywords.length > 0 && animeList !== undefined && mangaList !== undefined) {
animeList = originalAnimeList;
mangaList = originalMangaList;
- animeList = excludeKeywords(animeList as Media[]);
- mangaList = excludeKeywords(mangaList as Media[]);
+ animeList = excludeKeywordsFromMedia(animeList as Media[]);
+ mangaList = excludeKeywordsFromMedia(mangaList as Media[]);
}
updateWidth();
- }
- $: genreTagTitle = (() => {
- switch (genreTagsSort) {
- case SortOptions.SCORE:
- return 'Highest Rated';
- case SortOptions.MINUTES_WATCHED:
- return 'Most Watched';
- case SortOptions.COUNT:
- return 'Most Common';
- }
- })();
- $: animeMostTitle = (() => {
- switch (mediaSort) {
- case SortOptions.SCORE:
- return 'Highest Rated';
- case SortOptions.MINUTES_WATCHED:
- return 'Most Watched';
- case SortOptions.COUNT:
- return 'Most Common';
- }
- })();
- $: mangaMostTitle = (() => {
- switch (mediaSort) {
- case SortOptions.SCORE:
- return 'Highest Rated';
- case SortOptions.MINUTES_WATCHED:
- return 'Most Read';
- case SortOptions.COUNT:
- return 'Most Common';
- }
- })();
+ });
+
+ const getSortTitle = (sort: SortOptions, readVariant: boolean = false): string => {
+ if (sort === SortOptions.SCORE) return 'Highest Rated';
+ if (sort === SortOptions.MINUTES_WATCHED) return readVariant ? 'Most Read' : 'Most Watched';
+
+ return 'Most Common';
+ };
+
+ let genreTagTitle = $derived(getSortTitle(genreTagsSort));
+ let animeMostTitle = $derived(getSortTitle(mediaSort));
+ let mangaMostTitle = $derived(getSortTitle(mediaSort, true));
const updateWidth = () => {
if (!browser) return;
@@ -702,7 +689,7 @@
.filter((k) => k.length > 0);
};
- const excludeKeywords = (media: Media[]) => {
+ const excludeKeywordsFromMedia = (media: Media[]) => {
if (excludedKeywords.length <= 0) return media;
return media.filter((m) => {
@@ -955,13 +942,13 @@
</select>
Activity history position<br />
<select bind:value={highestRatedCount}>
- {#each [3, 4, 5, 6, 7, 8, 9, 10] as count}
+ {#each [3, 4, 5, 6, 7, 8, 9, 10] as count (count)}
<option value={count}>{count}</option>
{/each}
</select>
Highest rated media count<br />
<select bind:value={genreTagCount}>
- {#each [3, 4, 5, 6, 7, 8, 9, 10] as count}
+ {#each [3, 4, 5, 6, 7, 8, 9, 10] as count (count)}
<option value={count}>{count}</option>
{/each}
</select>
@@ -981,7 +968,7 @@
>
<br />
<select bind:value={selectedYear} disabled={needsRefetch}>
- {#each Array.from({ length: currentYear - 2012 }) as _, i}
+ {#each Array.from({ length: currentYear - 2012 }) as _, i (currentYear - i)}
<option value={currentYear - i}>
{currentYear - i}
</option>
diff --git a/src/lib/Tools/Wrapped/Top/Activity.svelte b/src/lib/Tools/Wrapped/Top/Activity.svelte
index ea6ba592..f5da509a 100644
--- a/src/lib/Tools/Wrapped/Top/Activity.svelte
+++ b/src/lib/Tools/Wrapped/Top/Activity.svelte
@@ -4,12 +4,15 @@
import type { Wrapped } from '$lib/Data/AniList/wrapped';
import proxy from '$lib/Utility/proxy';
- export let wrapped: Wrapped;
- export let year: number;
- export let activities: ActivityHistoryEntry[];
- export let useFullActivityHistory: boolean;
- export let updateWidth: () => void;
+ interface Props {
+ wrapped: Wrapped;
+ year: number;
+ activities: ActivityHistoryEntry[];
+ useFullActivityHistory: boolean;
+ updateWidth: () => void;
+ }
+ let { wrapped, year, activities, useFullActivityHistory, updateWidth }: Props = $props();
const currentYear = new Date(Date.now()).getFullYear();
</script>