aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Schedule
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-10-09 00:41:20 -0700
committerFuwn <[email protected]>2024-10-09 00:41:43 -0700
commit998b63a35256ac985a5a2714dd1ca451af4dfd8a (patch)
tree50796121a9d5ab0330fdc5d7e098bda2860d9726 /src/lib/Schedule
parentfeat(graphql): add badgeCount field (diff)
downloaddue.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.tar.xz
due.moe-998b63a35256ac985a5a2714dd1ca451af4dfd8a.zip
chore(prettier): use spaces instead of tabs
Diffstat (limited to 'src/lib/Schedule')
-rw-r--r--src/lib/Schedule/CoverBypass.svelte90
-rw-r--r--src/lib/Schedule/Crunchyroll.svelte164
-rw-r--r--src/lib/Schedule/Days.svelte366
-rw-r--r--src/lib/Schedule/container.css2
4 files changed, 311 insertions, 311 deletions
diff --git a/src/lib/Schedule/CoverBypass.svelte b/src/lib/Schedule/CoverBypass.svelte
index 1b7cce17..e94ddd40 100644
--- a/src/lib/Schedule/CoverBypass.svelte
+++ b/src/lib/Schedule/CoverBypass.svelte
@@ -1,55 +1,55 @@
<script lang="ts" ts>
- import type { Media } from '$lib/Data/AniList/media';
- import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
- import type { SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
+ import type { Media } from '$lib/Data/AniList/media';
+ import MediaTitleDisplay from '$lib/List/MediaTitleDisplay.svelte';
+ import type { SubsPleaseEpisode } from '$lib/Media/Anime/Airing/Subtitled/subsPlease';
- import { outboundLink } from '$lib/Media/links';
- import tooltip from '$lib/Tooltip/tooltip';
- import { abbreviate } from '$lib/Utility/string';
- import settings from '$stores/settings';
+ import { outboundLink } from '$lib/Media/links';
+ import tooltip from '$lib/Tooltip/tooltip';
+ import { abbreviate } from '$lib/Utility/string';
+ import settings from '$stores/settings';
- export let media: Media | null;
- export let entry: SubsPleaseEpisode;
- export let cover = true;
- export let showTooltip = true;
+ export let media: Media | null;
+ export let entry: SubsPleaseEpisode;
+ export let cover = true;
+ export let showTooltip = true;
- const abbreviateTo = 40;
+ const abbreviateTo = 40;
- const titleSelect = (media: Media | null) =>
- media ? media.title.english || media.title.romaji || media.title.native : null;
+ const titleSelect = (media: Media | null) =>
+ media ? media.title.english || media.title.romaji || media.title.native : null;
</script>
<a
- href={media
- ? outboundLink(media, 'anime', $settings.displayOutboundLinksTo)
- : outboundLink(
- null,
- 'anime',
- $settings.displayOutboundLinksTo,
- true,
- titleSelect(media) || entry.title
- )}
- target="_blank"
- title={`<img src="${
- $settings.displayDataSaver ? media?.coverImage.medium : media?.coverImage.extraLarge
- }" style="width: 250px; object-fit: cover; border-radius: 8px;" />`}
- use:tooltip
- data-tooltip-disable={media && cover ? false : true}
+ href={media
+ ? outboundLink(media, 'anime', $settings.displayOutboundLinksTo)
+ : outboundLink(
+ null,
+ 'anime',
+ $settings.displayOutboundLinksTo,
+ true,
+ titleSelect(media) || entry.title
+ )}
+ target="_blank"
+ title={`<img src="${
+ $settings.displayDataSaver ? media?.coverImage.medium : media?.coverImage.extraLarge
+ }" style="width: 250px; object-fit: cover; border-radius: 8px;" />`}
+ use:tooltip
+ data-tooltip-disable={media && cover ? false : true}
>
- {#if media}
- <MediaTitleDisplay
- title={media.title}
- abbreviate
- {abbreviateTo}
- tooltip={showTooltip
- ? media.title.english?.length > abbreviateTo ||
- media.title.romaji?.length > abbreviateTo ||
- media.title.native?.length > abbreviateTo
- : false}
- />
- {:else}
- <span title={entry.title} use:tooltip>
- {abbreviate(entry.title, abbreviateTo)}
- </span>
- {/if}
+ {#if media}
+ <MediaTitleDisplay
+ title={media.title}
+ abbreviate
+ {abbreviateTo}
+ tooltip={showTooltip
+ ? media.title.english?.length > abbreviateTo ||
+ media.title.romaji?.length > abbreviateTo ||
+ media.title.native?.length > abbreviateTo
+ : false}
+ />
+ {:else}
+ <span title={entry.title} use:tooltip>
+ {abbreviate(entry.title, abbreviateTo)}
+ </span>
+ {/if}
</a>
diff --git a/src/lib/Schedule/Crunchyroll.svelte b/src/lib/Schedule/Crunchyroll.svelte
index 0cfd0811..d22cff42 100644
--- a/src/lib/Schedule/Crunchyroll.svelte
+++ b/src/lib/Schedule/Crunchyroll.svelte
@@ -1,100 +1,100 @@
<script lang="ts">
- import crunchyroll from '$lib/Data/Static/crunchyroll.json';
- import './container.css';
+ import crunchyroll from '$lib/Data/Static/crunchyroll.json';
+ import './container.css';
- interface CrunchyrollMedia<T = number | 'soon' | 'continuing'> {
- year: number;
- month: number;
- day: T;
- title: string;
- }
+ interface CrunchyrollMedia<T = number | 'soon' | 'continuing'> {
+ year: number;
+ month: number;
+ day: T;
+ title: string;
+ }
- type KnownMedia = { [key: string]: CrunchyrollMedia<number>[] };
+ type KnownMedia = { [key: string]: CrunchyrollMedia<number>[] };
- const days: KnownMedia = crunchyroll
- .filter((media) => media.day !== 'soon' && media.day !== 'continuing')
- .reduce((acc: KnownMedia, media) => {
- const date = new Date(media.year, media.month - 1, media.day as number).toLocaleDateString();
+ const days: KnownMedia = crunchyroll
+ .filter((media) => media.day !== 'soon' && media.day !== 'continuing')
+ .reduce((acc: KnownMedia, media) => {
+ const date = new Date(media.year, media.month - 1, media.day as number).toLocaleDateString();
- if (!acc[date]) acc[date] = [];
+ if (!acc[date]) acc[date] = [];
- acc[date].push(media as CrunchyrollMedia<number>);
+ acc[date].push(media as CrunchyrollMedia<number>);
- return acc;
- }, {});
- const continuing: CrunchyrollMedia<number | string>[] = crunchyroll.filter(
- (media) => media.day === 'continuing'
- );
- const soon: CrunchyrollMedia<number | string>[] = crunchyroll.filter(
- (media) => media.day === 'soon'
- );
+ return acc;
+ }, {});
+ const continuing: CrunchyrollMedia<number | string>[] = crunchyroll.filter(
+ (media) => media.day === 'continuing'
+ );
+ const soon: CrunchyrollMedia<number | string>[] = crunchyroll.filter(
+ (media) => media.day === 'soon'
+ );
- $: columnCount = Math.ceil(Object.keys(days).length / 2);
+ $: columnCount = Math.ceil(Object.keys(days).length / 2);
- const ordinalSuffix = (i: number) => {
- const j = i % 10;
- const k = i % 100;
+ const ordinalSuffix = (i: number) => {
+ const j = i % 10;
+ const k = i % 100;
- if (j === 1 && k !== 11) return i + 'st';
- if (j === 2 && k !== 12) return i + 'nd';
- if (j === 3 && k !== 13) return i + 'rd';
+ if (j === 1 && k !== 11) return i + 'st';
+ if (j === 2 && k !== 12) return i + 'nd';
+ if (j === 3 && k !== 13) return i + 'rd';
- return i + 'th';
- };
+ return i + 'th';
+ };
</script>
<div class="list-container" id="crunchyroll" style={`column-count: ${columnCount};`}>
- {#each Object.values(days) as day}
- {@const date = new Date(day[0].year, day[0].month - 1, day[0].day)}
-
- <div class="card day">
- <details open class="details-unstyled">
- <summary>
- {date.toLocaleString('default', { month: 'long' })}
- {ordinalSuffix(day[0].day)}, {day[0].year}
- </summary>
- <ol>
- {#each day as media}
- <li>{media.title}</li>
- {/each}
- </ol>
- </details>
- </div>
-
- <p />
- {/each}
-
- <div class="card day">
- <details open class="details-unstyled">
- <summary>Coming soon</summary>
-
- <ol>
- {#each soon as media}
- <li>{media.title}</li>
- {/each}
- </ol>
- </details>
- </div>
-
- <p />
-
- <div class="card day">
- <details open class="details-unstyled">
- <summary>Continuing from previous season</summary>
-
- <ol>
- {#each continuing as media}
- <li>{media.title}</li>
- {/each}
- </ol>
- </details>
- </div>
+ {#each Object.values(days) as day}
+ {@const date = new Date(day[0].year, day[0].month - 1, day[0].day)}
+
+ <div class="card day">
+ <details open class="details-unstyled">
+ <summary>
+ {date.toLocaleString('default', { month: 'long' })}
+ {ordinalSuffix(day[0].day)}, {day[0].year}
+ </summary>
+ <ol>
+ {#each day as media}
+ <li>{media.title}</li>
+ {/each}
+ </ol>
+ </details>
+ </div>
+
+ <p />
+ {/each}
+
+ <div class="card day">
+ <details open class="details-unstyled">
+ <summary>Coming soon</summary>
+
+ <ol>
+ {#each soon as media}
+ <li>{media.title}</li>
+ {/each}
+ </ol>
+ </details>
+ </div>
+
+ <p />
+
+ <div class="card day">
+ <details open class="details-unstyled">
+ <summary>Continuing from previous season</summary>
+
+ <ol>
+ {#each continuing as media}
+ <li>{media.title}</li>
+ {/each}
+ </ol>
+ </details>
+ </div>
</div>
<style>
- .day {
- overflow-y: auto;
- break-inside: avoid;
- page-break-inside: avoid;
- }
+ .day {
+ overflow-y: auto;
+ break-inside: avoid;
+ page-break-inside: avoid;
+ }
</style>
diff --git a/src/lib/Schedule/Days.svelte b/src/lib/Schedule/Days.svelte
index 59f64e4a..f4075313 100644
--- a/src/lib/Schedule/Days.svelte
+++ b/src/lib/Schedule/Days.svelte
@@ -1,191 +1,191 @@
<script lang="ts">
- import { browser } from '$app/environment';
- import 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';
- import { parseOrDefault } from '$lib/Utility/parameters';
- import settings from '$stores/settings';
- import CoverBypass from './CoverBypass.svelte';
- import '$lib/List/covers.css';
- import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
- import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte';
-
- export let subsPlease: SubsPlease;
- export let scheduledMedia: Partial<Media[]>;
- export let forceListMode = false;
-
- const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
- let day: string | null = parseOrDefault(urlParameters, 'day', null);
-
- const shiftSubsPleaseSchedule = (schedule: SubsPlease['schedule']) => {
- const shiftedSchedule: { [key: string]: SubsPleaseEpisode[] } = {};
-
- if (day && Object.keys(schedule).includes(day)) {
- shiftedSchedule[day] = schedule[
- day as keyof typeof schedule
- ] as unknown as SubsPleaseEpisode[];
-
- return shiftedSchedule;
- }
-
- const days = Object.keys(schedule);
- const currentDayIndex = days.indexOf(new Date().toLocaleString('en-us', { weekday: 'long' }));
-
- days
- .slice(currentDayIndex)
- .concat(days.slice(0, currentDayIndex))
- .forEach((day) => {
- const scheduleEntry = schedule[day as keyof typeof schedule];
-
- shiftedSchedule[day] = Array.isArray(scheduleEntry)
- ? scheduleEntry
- : ([scheduleEntry] as unknown as SubsPleaseEpisode[]);
- });
-
- Object.entries(shiftedSchedule).forEach(([day, scheduleEntry]) => {
- if (scheduleEntry.length === 0) {
- delete shiftedSchedule[day];
- }
- });
-
- return shiftedSchedule;
- };
-
- const associateMedia = (media: (Media | undefined)[], title: string) =>
- findClosestMedia(media as Media[], title);
-
- const episode = (media: Media, weekday: string) => {
- if (media.nextAiringEpisode?.episode === 1) return 1;
-
- if (
- media.nextAiringEpisode?.airingAt &&
- weekday === new Date().toLocaleString('en-us', { weekday: 'long' }) &&
- new Date(media.nextAiringEpisode.airingAt * 1000).getTime() - new Date().getTime() >
- 24 * 60 * 60 * 1000
- )
- return media.nextAiringEpisode?.episode - 1;
-
- return media.nextAiringEpisode?.episode || 1;
- };
+ import { browser } from '$app/environment';
+ import 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';
+ import { parseOrDefault } from '$lib/Utility/parameters';
+ import settings from '$stores/settings';
+ import CoverBypass from './CoverBypass.svelte';
+ import '$lib/List/covers.css';
+ import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
+ import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte';
+
+ export let subsPlease: SubsPlease;
+ export let scheduledMedia: Partial<Media[]>;
+ export let forceListMode = false;
+
+ const urlParameters = browser ? new URLSearchParams(window.location.search) : null;
+ let day: string | null = parseOrDefault(urlParameters, 'day', null);
+
+ const shiftSubsPleaseSchedule = (schedule: SubsPlease['schedule']) => {
+ const shiftedSchedule: { [key: string]: SubsPleaseEpisode[] } = {};
+
+ if (day && Object.keys(schedule).includes(day)) {
+ shiftedSchedule[day] = schedule[
+ day as keyof typeof schedule
+ ] as unknown as SubsPleaseEpisode[];
+
+ return shiftedSchedule;
+ }
+
+ const days = Object.keys(schedule);
+ const currentDayIndex = days.indexOf(new Date().toLocaleString('en-us', { weekday: 'long' }));
+
+ days
+ .slice(currentDayIndex)
+ .concat(days.slice(0, currentDayIndex))
+ .forEach((day) => {
+ const scheduleEntry = schedule[day as keyof typeof schedule];
+
+ shiftedSchedule[day] = Array.isArray(scheduleEntry)
+ ? scheduleEntry
+ : ([scheduleEntry] as unknown as SubsPleaseEpisode[]);
+ });
+
+ Object.entries(shiftedSchedule).forEach(([day, scheduleEntry]) => {
+ if (scheduleEntry.length === 0) {
+ delete shiftedSchedule[day];
+ }
+ });
+
+ return shiftedSchedule;
+ };
+
+ const associateMedia = (media: (Media | undefined)[], title: string) =>
+ findClosestMedia(media as Media[], title);
+
+ const episode = (media: Media, weekday: string) => {
+ if (media.nextAiringEpisode?.episode === 1) return 1;
+
+ if (
+ media.nextAiringEpisode?.airingAt &&
+ weekday === new Date().toLocaleString('en-us', { weekday: 'long' }) &&
+ new Date(media.nextAiringEpisode.airingAt * 1000).getTime() - new Date().getTime() >
+ 24 * 60 * 60 * 1000
+ )
+ return media.nextAiringEpisode?.episode - 1;
+
+ return media.nextAiringEpisode?.episode || 1;
+ };
</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>
-
- <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>
- {/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>
- {/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>
+ <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>
+
+ <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>
+ {/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>
+ {/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}
<style>
- .countdown {
- white-space: nowrap;
- float: right;
- }
-
- .today {
- box-shadow: 0 2.5px 10px var(--base01), 0 0 0 5px var(--base0E), 0 4px 30px var(--base01);
- }
-
- .list {
- overflow-y: auto;
- break-inside: avoid-column;
- page-break-inside: avoid;
- }
-
- @media (max-width: 800px) {
- .cover-title-element {
- display: none;
- }
-
- .cover-card-image {
- margin-bottom: 0em;
- }
- }
-
- @media (max-width: 1600px) {
- .cover-title-element {
- display: none;
- }
- }
+ .countdown {
+ white-space: nowrap;
+ float: right;
+ }
+
+ .today {
+ box-shadow: 0 2.5px 10px var(--base01), 0 0 0 5px var(--base0E), 0 4px 30px var(--base01);
+ }
+
+ .list {
+ overflow-y: auto;
+ break-inside: avoid-column;
+ page-break-inside: avoid;
+ }
+
+ @media (max-width: 800px) {
+ .cover-title-element {
+ display: none;
+ }
+
+ .cover-card-image {
+ margin-bottom: 0em;
+ }
+ }
+
+ @media (max-width: 1600px) {
+ .cover-title-element {
+ display: none;
+ }
+ }
</style>
diff --git a/src/lib/Schedule/container.css b/src/lib/Schedule/container.css
index 3a3beb1f..8690629d 100644
--- a/src/lib/Schedule/container.css
+++ b/src/lib/Schedule/container.css
@@ -1,3 +1,3 @@
.list-container {
- column-width: 250px;
+ column-width: 250px;
}