Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions app/composables/useBunnyChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ async function init(tvUrl: string, tvToken: string) {
const items: ChatMessage[] = (message as any).data ?? [];

for (const item of items) {
messages.value.push(item);
if (!messages.value.some((m) => m.id === item.id)) {
messages.value.push(item);
}
}
}
})();
Expand Down Expand Up @@ -147,12 +149,14 @@ async function send(text: string, url: string) {
});
}

export { destroy };

export function useBunnyChat() {
const {
public: { tvUrl, tvToken },
} = useRuntimeConfig();

onMounted(() => init(tvUrl as string, tvToken as string));

return { messages, handle, visitorId, isConnected, send, destroy };
return { messages, handle, visitorId, isConnected, send };
}
108 changes: 16 additions & 92 deletions app/pages/tv/bunny/[video].vue
Original file line number Diff line number Diff line change
@@ -1,97 +1,12 @@
<script setup lang="ts">
import { allVideos } from '~/utils/bunnyShows';

definePageMeta({
layout: 'tv',
});

const route = useRoute();

const shows = [
{
title: 'Bunnies Being Bunnies',
videos: [
{
slug: 'bunny-stream-1',
youtubeId: 'WtM4OW2qVjY',
title: 'The Great Hop',
description: 'A bunny does what bunnies do best.',
},
{
slug: 'bunny-stream-12',
youtubeId: 'aWYcjCt4cqc',
title: 'Live and Unfiltered',
description: 'No script. No plan. Pure bunny.',
},
{
slug: 'bunny-stream-4',
youtubeId: 'pguISUUXWHc',
title: 'Zoomies: Unlocked',
description: 'No warning. Full speed. No regrets.',
},
{
slug: 'bunny-stream-6',
youtubeId: 'HLL5uGs_mSg',
title: 'The Nose Twitch Chronicles',
description: 'Sniffing everything. Trusting nothing.',
},
],
},
{
title: 'Flop Era',
videos: [
{
slug: 'bunny-stream-2',
youtubeId: 'f_b_MtB2tws',
title: 'Flop Era',
description: 'Maximum flop. Minimum effort.',
},
{
slug: 'bunny-stream-3',
youtubeId: 'VjqBt9lbOT0',
title: 'Lettuce Dreams',
description: 'A meditation on greens.',
},
{
slug: 'bunny-stream-5',
youtubeId: 'urANZiTyBD4',
title: 'Binky Season',
description: 'Pure joy, no explanation needed.',
},
{
slug: 'bunny-stream-8',
youtubeId: 'EY89M2qRNlc',
title: 'Disapproving Stare',
description: 'You have been judged.',
},
],
},
{
title: 'Bad Bunny',
videos: [
{
slug: 'bunny-stream-7',
youtubeId: 'ouuPSxE1hK4',
title: 'Cardboard Palace',
description: 'One box. Infinite possibilities.',
},
{
slug: 'bunny-stream-9',
youtubeId: 'vmbyVU9w47Y',
title: 'Pelo Suave',
description: 'Softest fur in the game.',
},

{
slug: 'bunny-stream-11',
youtubeId: 'H7-7TXXnw8I',
title: 'Conejito Malcriado',
description: 'Raised in the wild. Answers to no one.',
},
],
},
];

const allVideos = shows.flatMap((s) => s.videos);

const currentIndex = allVideos.findIndex((v) => v.slug === route.params.video);

if (currentIndex === -1) {
Expand Down Expand Up @@ -175,7 +90,11 @@ const isChatOpen = ref(true);
</div>
<NuxtLink v-if="nextVideo" :to="`/tv/bunny/${nextVideo.slug}`" class="next-video">
<div class="next-thumbnail">
<img :src="`https://img.youtube.com/vi/${nextVideo.youtubeId}/maxresdefault.jpg`" :alt="nextVideo.title" />
<img
:src="`https://img.youtube.com/vi/${nextVideo.youtubeId}/maxresdefault.jpg`"
:alt="nextVideo.title"
loading="lazy"
/>
<div class="play-overlay">
<BaseIcon name="play_circle" size="large" />
</div>
Expand Down Expand Up @@ -240,17 +159,22 @@ const isChatOpen = ref(true);

@media (width > 60rem) {
flex-direction: row;
align-items: stretch;
height: min(75vh, calc((100vw - 340px) * 9 / 16));

.stream {
flex: 1 1 0;
min-width: 0;
min-height: 0;
height: 100%;
aspect-ratio: unset;
}

.chat {
flex-basis: 340px;
flex-shrink: 0;
height: auto;
flex: 0 0 340px;
height: 100%;
max-height: none;
min-height: 450px;
min-height: unset;
}

.chat-toggle-enter-from,
Expand Down
100 changes: 7 additions & 93 deletions app/pages/tv/bunny/index.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { shows } from '~/utils/bunnyShows';

definePageMeta({
layout: 'tv',
});
Expand All @@ -10,91 +12,6 @@ useSeoMeta({
ogDescription: 'Going down the rabbit hole... literally.',
twitterCard: 'summary_large_image',
});

const shows = [
{
title: 'Bunnies Being Bunnies',
videos: [
{
slug: 'bunny-stream-1',
youtubeId: 'WtM4OW2qVjY',
title: 'The Great Hop',
description: 'A bunny does what bunnies do best.',
},
{
slug: 'bunny-stream-12',
youtubeId: 'aWYcjCt4cqc',
title: 'Live and Unfiltered',
description: 'No script. No plan. Pure bunny.',
},
{
slug: 'bunny-stream-4',
youtubeId: 'pguISUUXWHc',
title: 'Zoomies: Unlocked',
description: 'No warning. Full speed. No regrets.',
},
{
slug: 'bunny-stream-6',
youtubeId: 'HLL5uGs_mSg',
title: 'The Nose Twitch Chronicles',
description: 'Sniffing everything. Trusting nothing.',
},
],
},
{
title: 'Flop Era',
videos: [
{
slug: 'bunny-stream-2',
youtubeId: 'f_b_MtB2tws',
title: 'Flop Era',
description: 'Maximum flop. Minimum effort.',
},
{
slug: 'bunny-stream-3',
youtubeId: 'VjqBt9lbOT0',
title: 'Lettuce Dreams',
description: 'A meditation on greens.',
},
{
slug: 'bunny-stream-5',
youtubeId: 'urANZiTyBD4',
title: 'Binky Season',
description: 'Pure joy, no explanation needed.',
},
{
slug: 'bunny-stream-8',
youtubeId: 'EY89M2qRNlc',
title: 'Disapproving Stare',
description: 'You have been judged.',
},
],
},
{
title: 'Bad Bunny',
videos: [
{
slug: 'bunny-stream-7',
youtubeId: 'ouuPSxE1hK4',
title: 'Cardboard Palace',
description: 'One box. Infinite possibilities.',
},
{
slug: 'bunny-stream-9',
youtubeId: 'vmbyVU9w47Y',
title: 'Pelo Suave',
description: 'Softest fur in the game.',
},

{
slug: 'bunny-stream-11',
youtubeId: 'H7-7TXXnw8I',
title: 'Conejito Malcriado',
description: 'Raised in the wild. Answers to no one.',
},
],
},
];
</script>

<template>
Expand Down Expand Up @@ -127,7 +44,11 @@ const shows = [
<li v-for="video in show.videos" :key="video.slug">
<NuxtLink :to="`/tv/bunny/${video.slug}`" class="video-card">
<div class="thumbnail">
<img :src="`https://img.youtube.com/vi/${video.youtubeId}/maxresdefault.jpg`" :alt="video.title" />
<img
:src="`https://img.youtube.com/vi/${video.youtubeId}/maxresdefault.jpg`"
:alt="video.title"
loading="lazy"
/>
</div>
<h3>{{ video.title }}</h3>
<p>{{ video.description }}</p>
Expand Down Expand Up @@ -247,13 +168,6 @@ const shows = [
}
}

.disclaimer {
margin-top: 3rem;
text-align: center;
color: rgba(255, 255, 255, 0.4);
font-style: italic;
}

@media (width > 60rem) {
.featured {
margin: 7rem 0 10em;
Expand Down
8 changes: 8 additions & 0 deletions app/plugins/tv.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { authentication, createDirectus, rest } from '@directus/sdk';
import Queue from 'p-queue';

import { destroy as destroyBunnyChat } from '~/composables/useBunnyChat';

import type { Schema } from '~~/types/schema';

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
Expand Down Expand Up @@ -35,6 +37,12 @@ export default defineNuxtPlugin((nuxtApp) => {
});
}

if (import.meta.client) {
nuxtApp.hook('app:unmount', () => {
destroyBunnyChat();
});
}

return { provide: { directusTv } };
});

Expand Down
Loading
Loading