From b354842a5d5e4fbd3d3dab205fddb03b3351a508 Mon Sep 17 00:00:00 2001 From: w3cj Date: Fri, 29 Mar 2024 09:29:58 -0600 Subject: [PATCH] feat: show video duration --- prisma/schema.prisma | 1 + src/lib/videos/PlaylistVideo.svelte | 29 +++++++++++++++--- src/lib/videos/parseDuration.ts | 16 ++++++++++ .../(site)/videos/[p_slug]/+page.svelte | 13 ++------ src/server/video/youtube_api.ts | 30 +++++++++---------- 5 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 src/lib/videos/parseDuration.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2bc2e0552..fd856ea00 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -234,6 +234,7 @@ model Video { url String published_at DateTime thumbnail String + duration String @default("00:00") slug String @unique playlists PlaylistOnVideo[] shows ShowVideo[] diff --git a/src/lib/videos/PlaylistVideo.svelte b/src/lib/videos/PlaylistVideo.svelte index 88b31a504..5edb0e54b 100644 --- a/src/lib/videos/PlaylistVideo.svelte +++ b/src/lib/videos/PlaylistVideo.svelte @@ -7,7 +7,12 @@
- {video.title} +
+ {video.title} + {#if video.duration} + {video.duration} + {/if} +

{video.title}

@@ -23,9 +28,25 @@ margin-top: 0; } - .thumbnail { - overflow: hidden; - border-radius: var(--brad); + + .thumbnail-wrapper { + position: relative; + + .thumbnail { + overflow: hidden; + border-radius: var(--brad); + } + .duration { + position: absolute; + display: inline-block; + background: var(--yellow); + color: var(--black); + border-radius: 1rem; + padding: 0.25rem; + right: 1rem; + top: 1rem; + font-weight: 600; + } } img { diff --git a/src/lib/videos/parseDuration.ts b/src/lib/videos/parseDuration.ts new file mode 100644 index 000000000..f5aef9c68 --- /dev/null +++ b/src/lib/videos/parseDuration.ts @@ -0,0 +1,16 @@ +// Match one part of the duration string at a time and pad with 0 +// Avoids a complex / hard to understand regex for matching all parts at once +function parseTime(duration: string, part: 'H' | 'M' | 'S') { + const match = duration.match(new RegExp(`(\\d+)${part}`)); + return match ? match[1].padStart(1, '0') : '00'; +} + +// Parses duration from YouTube duration format (ISO 8601) e.g. PT1H14M28S to 01:14:28 +export default function parseDuration(duration: string) { + const hours = parseTime(duration, 'H'); + const minutes = parseTime(duration, 'M'); + const seconds = parseTime(duration, 'S'); + + const result = `${minutes}:${seconds}`; + return hours !== '00' ? `${hours}:${duration}` : result; +} diff --git a/src/routes/(site)/videos/[p_slug]/+page.svelte b/src/routes/(site)/videos/[p_slug]/+page.svelte index 7aad1f098..591fd4e9f 100644 --- a/src/routes/(site)/videos/[p_slug]/+page.svelte +++ b/src/routes/(site)/videos/[p_slug]/+page.svelte @@ -1,4 +1,6 @@ @@ -7,21 +9,12 @@

{playlist.title}

{#each playlist.videos as { video }} - - {video.title} -

{video.title}

-
+ {/each}
{/if}