aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-10-09 01:27:40 -0700
committerFuwn <[email protected]>2024-10-09 01:27:40 -0700
commite0e5ea6f25315a8ae4e39324131c7d90646943ce (patch)
tree4acdff309b007a021310745f009cc7c1443dcc36 /src
parentchore(prettier): use spaces instead of tabs (diff)
downloaddue.moe-e0e5ea6f25315a8ae4e39324131c7d90646943ce.tar.xz
due.moe-e0e5ea6f25315a8ae4e39324131c7d90646943ce.zip
feat(schedule): filter media list entries toggle
Diffstat (limited to 'src')
-rw-r--r--src/lib/Schedule/Days.svelte203
-rw-r--r--src/lib/Settings/Categories/Display.svelte4
-rw-r--r--src/routes/schedule/+page.svelte4
-rw-r--r--src/stores/settings.ts22
4 files changed, 142 insertions, 91 deletions
diff --git a/src/lib/Schedule/Days.svelte b/src/lib/Schedule/Days.svelte
index f4075313..f7a49029 100644
--- a/src/lib/Schedule/Days.svelte
+++ b/src/lib/Schedule/Days.svelte
@@ -1,6 +1,6 @@
<script lang="ts">
import { browser } from '$app/environment';
- import type { Media } from '$lib/Data/AniList/media';
+ import { mediaListCollection, Type, type Media } from '$lib/Data/AniList/media';
import { findClosestMedia } from '$lib/Media/Anime/Airing/Subtitled/match';
import type { SubsPlease, SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
import { outboundLink } from '$lib/Media/links';
@@ -10,14 +10,39 @@
import '$lib/List/covers.css';
import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte';
+ import { onMount } from 'svelte';
+ import identity from '$stores/identity';
+ import anime from '$stores/anime';
+ import lastPruneTimes from '$stores/lastPruneTimes';
+ import Message from '$lib/Loading/Message.svelte';
+ import Skeleton from '$lib/Loading/Skeleton.svelte';
+ import Error from '$lib/Error/RateLimited.svelte';
export let subsPlease: SubsPlease;
export let scheduledMedia: Partial<Media[]>;
export let forceListMode = false;
+ export let user;
const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
let day: string | null = parseOrDefault(urlParameters, 'day', null);
+ let mediaListPromise: Promise<Media[]>;
+
+ onMount(async () => {
+ if (user === undefined || $identity.id === -2) mediaListPromise = Promise.resolve([]);
+ else
+ mediaListPromise = mediaListCollection(
+ user,
+ $identity,
+ Type.Anime,
+ $anime,
+ $lastPruneTimes.anime,
+ {
+ all: true
+ }
+ );
+ });
+
const shiftSubsPleaseSchedule = (schedule: SubsPlease['schedule']) => {
const shiftedSchedule: { [key: string]: SubsPleaseEpisode[] } = {};
@@ -52,8 +77,14 @@
return shiftedSchedule;
};
- const associateMedia = (media: (Media | undefined)[], title: string) =>
- findClosestMedia(media as Media[], title);
+ const associateMedia = (media: (Media | undefined)[], title: string, mediaList: Media[]) => {
+ const closestMedia = findClosestMedia(media as Media[], title);
+
+ if ($settings.displayScheduleFilterList && closestMedia && mediaList)
+ return mediaList.find((m) => m.id === closestMedia?.id) || null;
+
+ return closestMedia;
+ };
const episode = (media: Media, weekday: string) => {
if (media.nextAiringEpisode?.episode === 1) return 1;
@@ -70,55 +101,86 @@
};
</script>
-{#each Object.entries(shiftSubsPleaseSchedule(subsPlease.schedule)) as [day, scheduleEntry], dayIndex}
- <details
- open
- class="list"
- class:today={day === new Date().toLocaleString('en-us', { weekday: 'long' })}
- >
- <summary>{day}</summary>
-
- {#if !$settings.displayScheduleListMode && !forceListMode}
- <div
- class="covers"
- style={`grid-template-columns: repeat(auto-fill, minmax(${$settings.displayCoverWidth}px, 1fr))`}
- >
- {#each Object.values(scheduleEntry) as entry, entryIndex}
- {@const media = associateMedia(scheduledMedia, entry.title)}
-
- <div class="cover-card" id={`cover-${dayIndex}-${entryIndex}`}>
- <LinkedTooltip
- content={media ? media.title.english || media.title.romaji : entry.title}
- pin={`cover-${dayIndex}-${entryIndex}`}
- >
- <a
- href={outboundLink(
- media ? media : null,
- 'anime',
- $settings.displayOutboundLinksTo,
- media === null,
- entry.title
- )}
- target="_blank"
- >
- <div class="cover-card-image">
- <ParallaxImage
- source={media
- ? $settings.displayDataSaver
- ? media.coverImage.medium
- : media.coverImage.extraLarge
- : `https://subsplease.org${entry.image_url}`}
- limit={12.5}
- alternativeText="Cover"
- />
- </div>
- </a>
-
- <div class="cover-title">
- <div class="cover-title-element">
- <CoverBypass {media} {entry} cover={false} showTooltip={false} />
- </div>
-
+{#await mediaListPromise}
+ <Message message="Loading media lists ..." />
+
+ <Skeleton grid={true} count={7} height="15em" width="49.5%" />
+{:then mediaList}
+ {#each Object.entries(shiftSubsPleaseSchedule(subsPlease.schedule)) as [day, scheduleEntry], dayIndex}
+ <details
+ open
+ class="list"
+ class:today={day === new Date().toLocaleString('en-us', { weekday: 'long' })}
+ >
+ <summary>{day}</summary>
+
+ {#if !$settings.displayScheduleListMode && !forceListMode}
+ <div
+ class="covers"
+ style={`grid-template-columns: repeat(auto-fill, minmax(${$settings.displayCoverWidth}px, 1fr))`}
+ >
+ {#each Object.values(scheduleEntry) as entry, entryIndex}
+ {@const media = associateMedia(scheduledMedia, entry.title, mediaList)}
+
+ {#if ($settings.displayScheduleFilterList && media) || !$settings.displayScheduleFilterList}
+ <div class="cover-card" id={`cover-${dayIndex}-${entryIndex}`}>
+ <LinkedTooltip
+ content={media ? media.title.english || media.title.romaji : entry.title}
+ pin={`cover-${dayIndex}-${entryIndex}`}
+ >
+ <a
+ href={outboundLink(
+ media ? media : null,
+ 'anime',
+ $settings.displayOutboundLinksTo,
+ media === null,
+ entry.title
+ )}
+ target="_blank"
+ >
+ <div class="cover-card-image">
+ <ParallaxImage
+ source={media
+ ? $settings.displayDataSaver
+ ? media.coverImage.medium
+ : media.coverImage.extraLarge
+ : `https://subsplease.org${entry.image_url}`}
+ limit={12.5}
+ alternativeText="Cover"
+ />
+ </div>
+ </a>
+
+ <div class="cover-title">
+ <div class="cover-title-element">
+ <CoverBypass {media} {entry} cover={false} showTooltip={false} />
+ </div>
+
+ <span class:countdown={$settings.displayCountdownRightAligned}>
+ {#if media && media.nextAiringEpisode}
+ <span class="opaque">
+ {episode(media, day)}{media.episodes ? `/${media.episodes}` : ''} at
+ </span>
+ {/if}
+ {entry.time}
+ </span>
+ </div>
+ </LinkedTooltip>
+ </div>
+ {/if}
+ {/each}
+ </div>
+ {:else}
+ <ol>
+ {#each Object.values(scheduleEntry) as entry}
+ {@const media = associateMedia(scheduledMedia, entry.title, mediaList)}
+
+ {#if ($settings.displayScheduleFilterList && media) || !$settings.displayScheduleFilterList}
+ <li class="entry">
+ <CoverBypass {media} {entry} />
+ {#if !$settings.displayCountdownRightAligned}
+ <span class="opaque">|</span>
+ {/if}
<span class:countdown={$settings.displayCountdownRightAligned}>
{#if media && media.nextAiringEpisode}
<span class="opaque">
@@ -127,35 +189,16 @@
{/if}
{entry.time}
</span>
- </div>
- </LinkedTooltip>
- </div>
- {/each}
- </div>
- {:else}
- <ol>
- {#each Object.values(scheduleEntry) as entry}
- {@const media = associateMedia(scheduledMedia, entry.title)}
-
- <li class="entry">
- <CoverBypass {media} {entry} />
- {#if !$settings.displayCountdownRightAligned}
- <span class="opaque">|</span>
+ </li>
{/if}
- <span class:countdown={$settings.displayCountdownRightAligned}>
- {#if media && media.nextAiringEpisode}
- <span class="opaque">
- {episode(media, day)}{media.episodes ? `/${media.episodes}` : ''} at
- </span>
- {/if}
- {entry.time}
- </span>
- </li>
- {/each}
- </ol>
- {/if}
- </details>
-{/each}
+ {/each}
+ </ol>
+ {/if}
+ </details>
+ {/each}
+{:catch}
+ <Error type="Media lists" loginSessionError={false} card list={false} />
+{/await}
<style>
.countdown {
diff --git a/src/lib/Settings/Categories/Display.svelte b/src/lib/Settings/Categories/Display.svelte
index 9f72f1e1..e1f96025 100644
--- a/src/lib/Settings/Categories/Display.svelte
+++ b/src/lib/Settings/Categories/Display.svelte
@@ -330,6 +330,10 @@
setting="displayTotalDueEpisodes"
text="Display total number of due episodes instead of due media count"
/>
+<SettingCheckboxToggle
+ setting="displayScheduleFilterList"
+ text="Only display media on your media lists in Subtitle Schedule"
+/>
<select bind:value={$settings.displayTitleFormat}>
<option value="english">
{$locale().settings.display.categories.media.fields.mediaTitleFormat.options.english}
diff --git a/src/routes/schedule/+page.svelte b/src/routes/schedule/+page.svelte
index 78744347..70b1e1e4 100644
--- a/src/routes/schedule/+page.svelte
+++ b/src/routes/schedule/+page.svelte
@@ -14,6 +14,8 @@
import Message from '$lib/Loading/Message.svelte';
import subsPlease from '$stores/subsPlease';
+ export let data;
+
let scheduledMediaPromise: Promise<Partial<Media[]>>;
const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
// let crunchyrollExpanded = false;
@@ -64,7 +66,7 @@
{:then scheduledMedia}
{#if scheduledMedia}
<div class="schedule-container" id="schedule">
- <Days subsPlease={$subsPlease} {scheduledMedia} {forceListMode} />
+ <Days subsPlease={$subsPlease} {scheduledMedia} {forceListMode} user={data.user} />
</div>
{:else}
<Message message="Loading schedule ..." />
diff --git a/src/stores/settings.ts b/src/stores/settings.ts
index 0d96d419..e55eeb0d 100644
--- a/src/stores/settings.ts
+++ b/src/stores/settings.ts
@@ -30,16 +30,16 @@ export interface Settings {
displayPlannedAnime: boolean;
displayFurigana: boolean;
displayAoButa:
- | 'kaede'
- | 'mai'
- | 'mai_2'
- | 'nodoka'
- | 'rio'
- | 'sakuta'
- | 'shouko'
- | 'tomoe'
- | 'random'
- | 'none';
+ | 'kaede'
+ | 'mai'
+ | 'mai_2'
+ | 'nodoka'
+ | 'rio'
+ | 'sakuta'
+ | 'shouko'
+ | 'tomoe'
+ | 'random'
+ | 'none';
disableManga: boolean;
disableAnime: boolean;
disableUpcomingAnime: boolean;
@@ -65,6 +65,7 @@ export interface Settings {
displayFiltersIncludeCompleted: boolean;
displayDataSaver: boolean;
debugDummyLists: boolean;
+ displayScheduleFilterList: boolean;
}
const defaultSettings: Settings = {
@@ -106,6 +107,7 @@ const defaultSettings: Settings = {
displayAniListNotifications: false,
displayFiltersIncludeCompleted: false,
displayDataSaver: false,
+ displayScheduleFilterList: false,
// Debug
debugDummyLists: false,