mirror of
https://codeberg.org/SafeTwitch/safetwitch.git
synced 2024-12-22 13:22:58 -05:00
Clip support #25
This commit is contained in:
parent
1b96f001f9
commit
99899258d4
3 changed files with 173 additions and 2 deletions
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<div v-if="videoData.type === 'vod'" class="min-w-[300px]">
|
||||
<div class="min-w-[300px]">
|
||||
<div class="relative">
|
||||
<RouterLink :to="'/videos/' + videoData.id">
|
||||
<RouterLink v-if="videoData.type === 'vod'" :to="'/videos/' + videoData.id">
|
||||
<img :src="videoData.preview" class="rounded-md" width="300" />
|
||||
</RouterLink>
|
||||
<RouterLink v-else :to="`${$route.params.username}/clip/${videoData.id}`">
|
||||
<img :src="videoData.preview" class="rounded-md" width="300" />
|
||||
</RouterLink>
|
||||
<p
|
||||
|
|
|
@ -7,6 +7,7 @@ const CategoryView = () => import('../views/CategoryView.vue')
|
|||
const SearchPageView = () => import('../views/SearchPageView.vue')
|
||||
const VodView = () => import('../views/VodView.vue')
|
||||
const SettingsView = () => import('../views/SettingsView.vue')
|
||||
const ClipView = () => import('../views/ClipView.vue')
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
|
@ -44,6 +45,10 @@ const router = createRouter({
|
|||
path: '/videos/:vodID',
|
||||
component: VodView
|
||||
},
|
||||
{
|
||||
path: '/:streamer/clip/:slug',
|
||||
component: ClipView
|
||||
},
|
||||
{ path: '/:pathMatch(.*)*', component: PageNotFound }
|
||||
]
|
||||
})
|
||||
|
|
163
src/views/ClipView.vue
Normal file
163
src/views/ClipView.vue
Normal file
|
@ -0,0 +1,163 @@
|
|||
<script lang="ts">
|
||||
import { ref, inject } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import VideoPlayer from '@/components/VideoPlayer.vue'
|
||||
import TwitchChat from '@/components/TwitchChat.vue'
|
||||
import ErrorMessage from '@/components/ErrorMessage.vue'
|
||||
import FollowButton from '@/components/FollowButton.vue'
|
||||
import LoadingScreen from '@/components/LoadingScreen.vue'
|
||||
|
||||
import type { Video } from '@/types'
|
||||
import { truncate, abbreviate, getEndpoint } from '@/mixins'
|
||||
import { chatVisible } from '@/settingsManager'
|
||||
|
||||
interface ChatComponent {
|
||||
updateVodComments: (time: number) => void
|
||||
}
|
||||
|
||||
export default {
|
||||
inject: ['rootBackendUrl'],
|
||||
async setup() {
|
||||
const route = useRoute()
|
||||
const clipSlug = route.params.slug
|
||||
const data = ref<Video>()
|
||||
const status = ref<'ok' | 'error'>()
|
||||
const rootBackendUrl = inject('rootBackendUrl')
|
||||
|
||||
let srcUrl
|
||||
await getEndpoint(`api/clips/getlink/${clipSlug}`)
|
||||
.then((data) => {
|
||||
srcUrl = data
|
||||
})
|
||||
.catch(() => {
|
||||
status.value = 'error'
|
||||
})
|
||||
|
||||
console.log(srcUrl)
|
||||
|
||||
const videoOptions = {
|
||||
autoplay: true,
|
||||
controls: true,
|
||||
sources: [
|
||||
{
|
||||
src: srcUrl,
|
||||
type: 'video/mp4'
|
||||
}
|
||||
],
|
||||
fluid: true
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
status,
|
||||
videoOptions
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
const clipSlug = this.$route.params.slug
|
||||
const streamerName = this.$route.params.streamer
|
||||
|
||||
await getEndpoint(`api/clips/${streamerName}/${clipSlug}`)
|
||||
.then((data) => {
|
||||
this.data = data
|
||||
})
|
||||
.catch(() => {
|
||||
this.status = 'error'
|
||||
})
|
||||
},
|
||||
components: {
|
||||
VideoPlayer,
|
||||
TwitchChat,
|
||||
ErrorMessage,
|
||||
FollowButton,
|
||||
LoadingScreen
|
||||
},
|
||||
methods: {
|
||||
truncate,
|
||||
abbreviate,
|
||||
handlePlayerTimeUpdate(time: number) {
|
||||
if (!chatVisible()) return
|
||||
const chat = this.$refs.chat as ChatComponent
|
||||
chat.updateVodComments(time)
|
||||
},
|
||||
chatVisible
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<loading-screen v-if="!data && status != 'error'"></loading-screen>
|
||||
<error-message v-else-if="status == 'error'"></error-message>
|
||||
|
||||
<div
|
||||
v-else-if="data"
|
||||
class="w-full justify-center md:inline-flex space-y-4 md:space-y-0 md:space-x-4 md:p-4"
|
||||
>
|
||||
<div
|
||||
class="flex bg-ctp-crust flex-col p-6 rounded-lg w-[99vw] md:max-w-prose md:min-w-[65ch] lg:max-w-[70rem] text-white"
|
||||
>
|
||||
<div class="w-full mx-auto rounded-lg mb-5">
|
||||
<video-player :options="videoOptions" @PlayerTimeUpdate="handlePlayerTimeUpdate">
|
||||
</video-player>
|
||||
</div>
|
||||
|
||||
<div class="w-full flex-wrap md:p-3">
|
||||
<div class="inline-flex md:w-full">
|
||||
<router-link :to="'/' + data.streamer.login">
|
||||
<img
|
||||
:src="data.streamer.pfp"
|
||||
class="rounded-full border-4 p-0.5 w-auto h-20"
|
||||
:style="`border-color: ${data.streamer.colorHex};`"
|
||||
/>
|
||||
</router-link>
|
||||
|
||||
<div class="ml-3 content-between">
|
||||
<router-link :to="'/' + data.streamer.login">
|
||||
<h1 class="text-2xl md:text-4xl font-bold">{{ data.streamer.username }}</h1>
|
||||
</router-link>
|
||||
<p class="text-sm font-bold text-gray-200 self-end">
|
||||
{{ truncate(data.title, 130) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-2 inline-flex">
|
||||
<follow-button :username="data.streamer.username"></follow-button>
|
||||
<p class="align-baseline font-bold ml-3">
|
||||
{{ abbreviate(data.streamer.followers) }} {{ $t('main.followers') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ABOUT TAB -->
|
||||
<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">{{ $t('streamer.about') }}</span>
|
||||
</div>
|
||||
|
||||
<p class="mb-5">{{ data.streamer.about }}</p>
|
||||
|
||||
<hr class="my-auto w-full bg-gray-200 rounded-full opacity-40" />
|
||||
|
||||
<ul class="flex font-semibold text-md justify-start flex-wrap flex-row">
|
||||
<li v-for="link in data.streamer.socials" :key="link.link">
|
||||
<a :href="link.link" class="text-white hover:text-gray-400 mr-4">
|
||||
<v-icon :name="`bi-${link.type}`" class="w-6 h-6 mr-1"></v-icon>
|
||||
<span>{{ link.name }}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<twitch-chat
|
||||
v-if="chatVisible()"
|
||||
:isVod="true"
|
||||
:channelName="data.streamer.login"
|
||||
ref="chat"
|
||||
></twitch-chat>
|
||||
-->
|
||||
</div>
|
||||
</template>
|
Loading…
Reference in a new issue