aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Hololive
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Hololive')
-rw-r--r--src/lib/Hololive/Lives.svelte130
-rw-r--r--src/lib/Hololive/Stream.svelte290
-rw-r--r--src/lib/Hololive/hololive.ts18
3 files changed, 219 insertions, 219 deletions
diff --git a/src/lib/Hololive/Lives.svelte b/src/lib/Hololive/Lives.svelte
index 7281b18f..9e762df9 100644
--- a/src/lib/Hololive/Lives.svelte
+++ b/src/lib/Hololive/Lives.svelte
@@ -1,93 +1,93 @@
<script lang="ts">
- import Message from '$lib/Loading/Message.svelte';
- import root from '$lib/Utility/root';
- import type { Live, ParseResult } from './hololive';
- import Stream from './Stream.svelte';
+ import Message from '$lib/Loading/Message.svelte';
+ import root from '$lib/Utility/root';
+ import type { Live, ParseResult } from './hololive';
+ import Stream from './Stream.svelte';
- export let schedule: ParseResult;
- export let pinnedStreams: string[];
- export let getPinnedStreams: () => void;
- export let filter: string | undefined;
+ export let schedule: ParseResult;
+ export let pinnedStreams: string[];
+ export let getPinnedStreams: () => void;
+ export let filter: string | undefined;
- const pinStream = (streamer: string) =>
- fetch(root(`/api/preferences/pin?stream=${encodeURIComponent(streamer)}`), {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json'
- }
- }).then(getPinnedStreams);
+ const pinStream = (streamer: string) =>
+ fetch(root(`/api/preferences/pin?stream=${encodeURIComponent(streamer)}`), {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json'
+ }
+ }).then(getPinnedStreams);
- $: categorisedStreams = schedule.lives
- .filter((live) => (filter ? live.streamer === filter : true))
- .sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime())
- .sort((a, b) => {
- const aPinned = pinnedStreams.includes(a.streamer);
- const bPinned = pinnedStreams.includes(b.streamer);
+ $: categorisedStreams = schedule.lives
+ .filter((live) => (filter ? live.streamer === filter : true))
+ .sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime())
+ .sort((a, b) => {
+ const aPinned = pinnedStreams.includes(a.streamer);
+ const bPinned = pinnedStreams.includes(b.streamer);
- if (aPinned && !bPinned) return -1;
- if (!aPinned && bPinned) return 1;
+ if (aPinned && !bPinned) return -1;
+ if (!aPinned && bPinned) return 1;
- return 0;
- })
- .reduce(
- (
- acc: {
- live: Live[];
- upcoming: Live[];
- ended: Live[];
- },
- live
- ) => {
- const now = Date.now();
- const time = new Date(live.time).getTime();
- const isLive = live.streaming;
- const isUpcoming = time > now && !isLive;
- const isEnded = time < now && !isLive;
+ return 0;
+ })
+ .reduce(
+ (
+ acc: {
+ live: Live[];
+ upcoming: Live[];
+ ended: Live[];
+ },
+ live
+ ) => {
+ const now = Date.now();
+ const time = new Date(live.time).getTime();
+ const isLive = live.streaming;
+ const isUpcoming = time > now && !isLive;
+ const isEnded = time < now && !isLive;
- if (isLive) {
- acc.live.push(live);
- } else if (isUpcoming) {
- acc.upcoming.push(live);
- } else if (isEnded) {
- acc.ended.push(live);
- }
+ if (isLive) {
+ acc.live.push(live);
+ } else if (isUpcoming) {
+ acc.upcoming.push(live);
+ } else if (isEnded) {
+ acc.ended.push(live);
+ }
- return acc;
- },
- { live: [], upcoming: [], ended: [] }
- );
+ return acc;
+ },
+ { live: [], upcoming: [], ended: [] }
+ );
</script>
{#if schedule.lives.length === 0}
- <Message message="No upcoming streams." loader="ripple" />
+ <Message message="No upcoming streams." loader="ripple" />
{/if}
<div class="container">
- {#each categorisedStreams.live as live}
- <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
- {/each}
+ {#each categorisedStreams.live as live}
+ <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
+ {/each}
</div>
<p />
<div class="container">
- {#each categorisedStreams.upcoming as live}
- <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
- {/each}
+ {#each categorisedStreams.upcoming as live}
+ <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
+ {/each}
</div>
<p />
<div class="container">
- {#each categorisedStreams.ended as live}
- <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
- {/each}
+ {#each categorisedStreams.ended as live}
+ <Stream {live} {pinStream} {pinnedStreams} icon={schedule.dict[live.streamer]} />
+ {/each}
</div>
<style lang="scss">
- .container {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(22em, 1fr));
- gap: 0.5em;
- }
+ .container {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(22em, 1fr));
+ gap: 0.5em;
+ }
</style>
diff --git a/src/lib/Hololive/Stream.svelte b/src/lib/Hololive/Stream.svelte
index cde3be68..12681acb 100644
--- a/src/lib/Hololive/Stream.svelte
+++ b/src/lib/Hololive/Stream.svelte
@@ -1,153 +1,153 @@
<script lang="ts">
- import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
- import root from '$lib/Utility/root';
- import identity from '$stores/identity';
- import locale from '$stores/locale';
- import Icon from '@iconify/svelte';
-
- export let live: any;
- export let pinStream: (streamer: string) => void;
- export let pinnedStreams: string[];
- export let icon: string;
+ import ParallaxImage from '$lib/Image/ParallaxImage.svelte';
+ import root from '$lib/Utility/root';
+ import identity from '$stores/identity';
+ import locale from '$stores/locale';
+ import Icon from '@iconify/svelte';
+
+ export let live: any;
+ export let pinStream: (streamer: string) => void;
+ export let pinnedStreams: string[];
+ export let icon: string;
</script>
<div class="stream card">
- {#if $identity.id !== -2}
- <div class="pin-icon">
- <a
- href={'#'}
- on:click={(e) => {
- e.preventDefault();
- pinStream(live.streamer);
- }}
- >
- <Icon
- icon={`pajamas:thumbtack${pinnedStreams.includes(live.streamer) ? '-solid' : ''}`}
- width="1em"
- />
- </a>
- </div>
- {/if}
-
- <p class="stream-heading">
- {#if live.streaming}
- <b class="live">{$locale().hololive.live}</b
- >{:else if new Date(live.time).getTime() < Date.now()}
- <span class="ended">{$locale().hololive.ended}</span>{:else}
- <span class="upcoming">{$locale().hololive.upcoming}</span>{/if}
- <span class="opaque">|</span>
- {#if icon}
- <a href={root(`/hololive/${encodeURIComponent(live.streamer)}`)}>
- <img src={icon} alt="Avatar" class="stream-icon" />
- </a>
- {/if}
- <a href={root(`/hololive/${encodeURIComponent(live.streamer)}`)} class="streamer-link">
- <b>{live.streamer}</b>
- </a>
- <br />
- {$locale().hololive.dateFormatter(new Date(live.time))}
- {#if live.guests.length > 0}
- {$locale().hololive.with}{live.guests
- .join($locale().hololive.comma)
- .replace(
- new RegExp(`${$locale().hololive.comma}([^${$locale().hololive.commaNoSpace}]+)$`, 'g'),
- `${$locale().hololive.comma}${$locale().hololive.ampersand}$1`
- )}
- {/if}
- </p>
-
- <a href={live.link} class="preview" target="_blank">
- <span class="preview-image">
- <ParallaxImage
- source={live.livePreviewImage}
- alternativeText="Stream Thumbnail"
- limit={12.5}
- duration={2750}
- />
- </span>
- </a>
+ {#if $identity.id !== -2}
+ <div class="pin-icon">
+ <a
+ href={'#'}
+ on:click={(e) => {
+ e.preventDefault();
+ pinStream(live.streamer);
+ }}
+ >
+ <Icon
+ icon={`pajamas:thumbtack${pinnedStreams.includes(live.streamer) ? '-solid' : ''}`}
+ width="1em"
+ />
+ </a>
+ </div>
+ {/if}
+
+ <p class="stream-heading">
+ {#if live.streaming}
+ <b class="live">{$locale().hololive.live}</b
+ >{:else if new Date(live.time).getTime() < Date.now()}
+ <span class="ended">{$locale().hololive.ended}</span>{:else}
+ <span class="upcoming">{$locale().hololive.upcoming}</span>{/if}
+ <span class="opaque">|</span>
+ {#if icon}
+ <a href={root(`/hololive/${encodeURIComponent(live.streamer)}`)}>
+ <img src={icon} alt="Avatar" class="stream-icon" />
+ </a>
+ {/if}
+ <a href={root(`/hololive/${encodeURIComponent(live.streamer)}`)} class="streamer-link">
+ <b>{live.streamer}</b>
+ </a>
+ <br />
+ {$locale().hololive.dateFormatter(new Date(live.time))}
+ {#if live.guests.length > 0}
+ {$locale().hololive.with}{live.guests
+ .join($locale().hololive.comma)
+ .replace(
+ new RegExp(`${$locale().hololive.comma}([^${$locale().hololive.commaNoSpace}]+)$`, 'g'),
+ `${$locale().hololive.comma}${$locale().hololive.ampersand}$1`
+ )}
+ {/if}
+ </p>
+
+ <a href={live.link} class="preview" target="_blank">
+ <span class="preview-image">
+ <ParallaxImage
+ source={live.livePreviewImage}
+ alternativeText="Stream Thumbnail"
+ limit={12.5}
+ duration={2750}
+ />
+ </span>
+ </a>
</div>
<style lang="scss">
- $transition: transform 0.3s ease;
-
- .preview {
- // margin: 0.15rem;
-
- :global(img) {
- border-radius: 8px;
- height: 20vh;
- object-fit: cover;
- }
-
- .preview-image {
- transition: $transition;
- }
-
- &:hover {
- .preview-image {
- position: relative;
- z-index: 2;
- transition: $transition;
- transform: scale(1.025) !important;
- }
- }
-
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .live {
- color: var(--base0F);
- }
-
- .upcoming {
- color: var(--base0C);
- }
-
- .ended {
- color: var(--base0D);
- }
-
- .pin-icon {
- position: absolute;
- right: 0;
- top: 0;
- padding: 0.75rem;
- }
-
- .stream {
- position: relative;
- }
-
- .stream-heading {
- padding-right: 2em;
- padding-left: 2.5em;
- }
-
- .stream-icon {
- $size: 2em;
-
- position: absolute;
- top: 0;
- left: 0;
- border-radius: 8px;
- width: $size;
- height: $size;
- margin: 0.75rem;
- object-fit: cover;
- transition: $transition;
-
- &:hover {
- z-index: 2;
- transition: $transition;
- transform: scale(1.1);
- }
- }
-
- .streamer-link {
- color: var(--fg);
- text-decoration: none;
- }
+ $transition: transform 0.3s ease;
+
+ .preview {
+ // margin: 0.15rem;
+
+ :global(img) {
+ border-radius: 8px;
+ height: 20vh;
+ object-fit: cover;
+ }
+
+ .preview-image {
+ transition: $transition;
+ }
+
+ &:hover {
+ .preview-image {
+ position: relative;
+ z-index: 2;
+ transition: $transition;
+ transform: scale(1.025) !important;
+ }
+ }
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .live {
+ color: var(--base0F);
+ }
+
+ .upcoming {
+ color: var(--base0C);
+ }
+
+ .ended {
+ color: var(--base0D);
+ }
+
+ .pin-icon {
+ position: absolute;
+ right: 0;
+ top: 0;
+ padding: 0.75rem;
+ }
+
+ .stream {
+ position: relative;
+ }
+
+ .stream-heading {
+ padding-right: 2em;
+ padding-left: 2.5em;
+ }
+
+ .stream-icon {
+ $size: 2em;
+
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: 8px;
+ width: $size;
+ height: $size;
+ margin: 0.75rem;
+ object-fit: cover;
+ transition: $transition;
+
+ &:hover {
+ z-index: 2;
+ transition: $transition;
+ transform: scale(1.1);
+ }
+ }
+
+ .streamer-link {
+ color: var(--fg);
+ text-decoration: none;
+ }
</style>
diff --git a/src/lib/Hololive/hololive.ts b/src/lib/Hololive/hololive.ts
index 4b9ed25e..f348567c 100644
--- a/src/lib/Hololive/hololive.ts
+++ b/src/lib/Hololive/hololive.ts
@@ -1,16 +1,16 @@
export interface Live {
- time: Date;
- link: string;
- videoId: string;
- streamer: string;
- livePreviewImage: string;
- guests: string[];
- streaming: boolean;
+ time: Date;
+ link: string;
+ videoId: string;
+ streamer: string;
+ livePreviewImage: string;
+ guests: string[];
+ streaming: boolean;
}
export interface ParseResult {
- lives: Live[];
- dict: Record<string, string>;
+ lives: Live[];
+ dict: Record<string, string>;
}
export const typeSchedule = (schedule: object) => schedule as ParseResult;