0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch.git synced 2024-12-22 21:33:01 -05:00

Add support for displaying VODS

This commit is contained in:
dragongoose 2023-07-04 20:53:02 -04:00
parent 2faba34838
commit fd054bd207
No known key found for this signature in database
GPG key ID: 50DB99B921579009
4 changed files with 138 additions and 1 deletions

View file

@ -0,0 +1,44 @@
<template>
<div class="min-w-[300px]">
<div class="relative">
<img :src="data.preview" class="rounded-md" width="300">
<p class="absolute bottom-2 right-2 bg-black p-1 py-0.5 rounded-md bg-opacity-70 text-xs font-bold"> {{ new Date(data.duration * 1000).toISOString().slice(11, 19) }}</p>
<p class="absolute bottom-2 left-2 bg-black p-1 py-0.5 rounded-md bg-opacity-70 text-xs font-bold"> {{ abbreviate(data.views) }} {{ $t("main.views") }}</p>
</div>
<div class="pt-2 space-x-2">
<div class="space-x-2 inline-flex">
<img :src="data.game.image">
<div class="w-full">
<p class="font-bold text-sm truncate h-6 max-w-[255px]">{{ data.title }}</p>
<div class="text-xs text-gray-400">
<p>{{ data.streamer.name }}</p>
<p>{{ data.game.displayName || data.game.name }}</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import type { Video } from '@/types/VOD';
import { abbreviate } from '@/mixins';
export default {
props: {
data: Object
},
setup(props) {
return {
data: props.data as Video
}
},
methods: {
abbreviate
}
}
</script>

View file

@ -0,0 +1,57 @@
<!--
This component is used for the video tab under a user
-->
<template>
<div class="bg-ctp-mantle mt-1 p-5 pt-3 rounded-lg w-full space-y-3">
<div class="inline-flex w-full">
<span class="pr-3 font-bold text-3xl">Videos</span>
</div>
<h1 v-if="!shelves && status === 'error'">Error getting videos</h1>
<div v-else-if="shelves" class="mb-5">
<div class="space-y-5">
<div v-for="shelve of shelves">
<h1 class="font-bold text-lg">{{ shelve.title }}</h1>
<div class="whitespace-nowrap overflow-x-auto overflow-y-hidden w-full inline-flex space-x-5">
<video-preview v-for="video of shelve.videos" :data="video"></video-preview>
</div>
</div>
<hr>
</div>
</div>
</div>
</template>
<script lang="ts">
import { ref } from 'vue'
import { getEndpoint } from '@/mixins'
import type { Shelve } from '@/types/VOD'
import VideoPreview from '@/components/user/VideoPreview.vue'
export default {
setup() {
return {
shelves: ref<Shelve[]>([]),
status: ""
}
},
async mounted() {
const username = this.$route.params.username
await getEndpoint("api/vods/shelve/" + username)
.then((data) => {
this.shelves = data
})
.catch(() => {
this.status = "error"
})
},
components: {
VideoPreview
}
}
</script>

30
src/types/VOD.ts Normal file
View file

@ -0,0 +1,30 @@
export interface MinifiedCategory {
image: string
id: string
name: string
displayName: string
}
export interface MinifiedStreamer {
name: string
login: string
pfp: string
colorHex: string
}
export interface Video {
preview: string
game: MinifiedCategory
duration: number
title: string
publishedAt: string
views: number
tag: string[]
streamer: MinifiedStreamer
}
export interface Shelve {
title: string
videos: Video[]
}

View file

@ -7,6 +7,7 @@ import TwitchChat from '@/components/TwitchChat.vue'
import ErrorMessage from '@/components/ErrorMessage.vue' import ErrorMessage from '@/components/ErrorMessage.vue'
import FollowButton from '@/components/FollowButton.vue' import FollowButton from '@/components/FollowButton.vue'
import LoadingScreen from '@/components/LoadingScreen.vue' import LoadingScreen from '@/components/LoadingScreen.vue'
import VideoTab from '@/components/user/VideoTab.vue'
import type { StreamerData, ApiResponse } from '@/types' import type { StreamerData, ApiResponse } from '@/types'
import { truncate, abbreviate, getEndpoint } from '@/mixins' import { truncate, abbreviate, getEndpoint } from '@/mixins'
@ -53,7 +54,8 @@ export default {
TwitchChat, TwitchChat,
ErrorMessage, ErrorMessage,
FollowButton, FollowButton,
LoadingScreen LoadingScreen,
VideoTab
}, },
methods: { methods: {
truncate, abbreviate truncate, abbreviate
@ -134,6 +136,10 @@ export default {
</div> </div>
</div> </div>
<!-- VIDEOS TAB -->
<video-tab class="mb-4"></video-tab>
<!-- ABOUT TAB -->
<div class="bg-ctp-mantle mt-1 p-5 pt-3 rounded-lg w-full space-y-3"> <div class="bg-ctp-mantle mt-1 p-5 pt-3 rounded-lg w-full space-y-3">
<div class="inline-flex w-full"> <div class="inline-flex w-full">
<span class="pr-3 font-bold text-3xl">{{ $t("streamer.about") }}</span> <span class="pr-3 font-bold text-3xl">{{ $t("streamer.about") }}</span>