aboutsummaryrefslogtreecommitdiff
path: root/src/routes/schedule
diff options
context:
space:
mode:
authorFuwn <[email protected]>2023-12-20 02:20:37 -0800
committerFuwn <[email protected]>2023-12-20 02:20:37 -0800
commita87fee111ccb501121b5aa3c1e48601f4869198a (patch)
treec1c55fc24a03bc7be848ee753ff76a76f397b4e2 /src/routes/schedule
parentfeat(attributions): add more anilist details (diff)
downloaddue.moe-a87fee111ccb501121b5aa3c1e48601f4869198a.tar.xz
due.moe-a87fee111ccb501121b5aa3c1e48601f4869198a.zip
feat(schedule): match media to anilist
Diffstat (limited to 'src/routes/schedule')
-rw-r--r--src/routes/schedule/+page.svelte153
1 files changed, 95 insertions, 58 deletions
diff --git a/src/routes/schedule/+page.svelte b/src/routes/schedule/+page.svelte
index c629f820..2a975c46 100644
--- a/src/routes/schedule/+page.svelte
+++ b/src/routes/schedule/+page.svelte
@@ -5,8 +5,14 @@
import settings from '../../stores/settings';
import { parseOrDefault } from '$lib/Tools/tool';
import { browser } from '$app/environment';
+ import type { Media } from '$lib/AniList/media';
+ import { scheduleMediaListCollection } from '$lib/AniList/schedule';
+ import { season } from '$lib/Media/Anime/season';
+ import { findClosestMedia } from '$lib/Media/Anime/airing';
+ import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
let subsPleasePromise: Promise<SubsPlease>;
+ let scheduledMediaPromise: Promise<Partial<Media[]>>;
const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
let timeZone = parseOrDefault(
urlParameters,
@@ -14,11 +20,13 @@
Intl.DateTimeFormat().resolvedOptions().timeZone
);
- onMount(
- async () => (subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json()))
- );
+ onMount(async () => {
+ subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json());
+ scheduledMediaPromise = scheduleMediaListCollection(new Date().getFullYear(), season());
+ });
let hoveredItem: SubsPleaseEpisode | null = null;
+ let hoveredMedia: Media | null = null;
let imageStyle = '';
let imageHeight = 0;
@@ -58,67 +66,94 @@
return shiftedSchedule;
};
+
+ const associateMedia = (media: (Media | undefined)[], title: string) =>
+ findClosestMedia(media as Media[], title);
</script>
{#await subsPleasePromise}
Loading ...
{:then subsPlease}
{#if subsPlease}
- <blockquote>
- {timeZone.split('/').reverse().join(', ').replace(/_/g, ' ')}
- </blockquote>
-
- <p>
- <select
- bind:value={timeZone}
- on:change={() =>
- (subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json()))}
- >
- {#each Intl.supportedValuesOf('timeZone') as zone}
- <option value={zone}>
- {zone.split('/').reverse().join(', ').replace(/_/g, ' ')}
- </option>
- {/each}
- </select>
- </p>
-
- <div id="list-container">
- {#each Object.entries(shiftSubsPleaseSchedule(subsPlease.schedule)) as [day, scheduleEntry]}
- <details
- open
- class="list"
- class:today={day === new Date().toLocaleString('en-us', { weekday: 'long' })}
- >
- <summary>{day}</summary>
-
- <ul>
- {#each Object.values(scheduleEntry) as entry}
- <li
- class="entry"
- on:mouseenter={() => (hoveredItem = entry)}
- on:mouseleave={() => (hoveredItem = null)}
- on:mousemove={onMouseMove}
- >
- <a
- href={`https://anilist.co/search?search=${encodeURIComponent(entry.title)}`}
- target="_blank"
- >
- {entry.title}
- </a>
- {#if !$settings.displayCountdownRightAligned}
- <span style="opacity: 50%;">|</span>
- {/if}
- <span class:countdown={$settings.displayCountdownRightAligned}>
- {entry.time}
- </span>
- </li>
+ {#await scheduledMediaPromise}
+ Loading ...
+ {:then scheduledMedia}
+ {#if scheduledMedia}
+ <blockquote>
+ {timeZone.split('/').reverse().join(', ').replace(/_/g, ' ')}
+ </blockquote>
+
+ <p>
+ <select
+ bind:value={timeZone}
+ on:change={() =>
+ (subsPleasePromise = fetch(`/api/subsplease?tz=${timeZone}`).then((r) => r.json()))}
+ >
+ {#each Intl.supportedValuesOf('timeZone') as zone}
+ <option value={zone}>
+ {zone.split('/').reverse().join(', ').replace(/_/g, ' ')}
+ </option>
{/each}
- </ul>
-
- <p />
- </details>
- {/each}
- </div>
+ </select>
+ </p>
+
+ <div id="list-container">
+ {#each Object.entries(shiftSubsPleaseSchedule(subsPlease.schedule)) as [day, scheduleEntry]}
+ <details
+ open
+ class="list"
+ class:today={day === new Date().toLocaleString('en-us', { weekday: 'long' })}
+ >
+ <summary>{day}</summary>
+
+ <ul>
+ {#each Object.values(scheduleEntry) as entry}
+ {@const media = associateMedia(scheduledMedia, entry.title)}
+
+ <li
+ class="entry"
+ on:mouseenter={() => {
+ hoveredItem = entry;
+ hoveredMedia = media;
+ }}
+ on:mouseleave={() => {
+ hoveredItem = null;
+ hoveredMedia = null;
+ }}
+ on:mousemove={onMouseMove}
+ >
+ <a
+ href={media
+ ? `https://anilist.co/anime/${media.id}`
+ : `https://anilist.co/search?search=${encodeURIComponent(entry.title)}`}
+ target="_blank"
+ >
+ {#if media}
+ <MediaTitleDisplay title={media.title} />
+ {:else}
+ {entry.title}
+ {/if}
+ </a>
+ {#if !$settings.displayCountdownRightAligned}
+ <span style="opacity: 50%;">|</span>
+ {/if}
+ <span class:countdown={$settings.displayCountdownRightAligned}>
+ {entry.time}
+ </span>
+ </li>
+ {/each}
+ </ul>
+
+ <p />
+ </details>
+ {/each}
+ </div>
+ {:else}
+ Loading ...
+ {/if}
+ {:catch}
+ <Error type="Media" loginSessionError={false} />
+ {/await}
{:else}
Loading ...
{/if}
@@ -129,7 +164,9 @@
{#if hoveredItem}
<img
class="hover-image show"
- src={`https://subsplease.org${hoveredItem.image_url}`}
+ src={hoveredMedia
+ ? hoveredMedia.coverImage.extraLarge
+ : `https://subsplease.org${hoveredItem.image_url}`}
alt="Media Cover"
style={imageStyle}
/>