Files
safetwitch/src/components/VodChat.vue
T
2025-09-15 21:26:50 -04:00

144 lines
3.9 KiB
Vue

<script lang="ts">
import { ref, inject } from 'vue'
import BadgeVue from './ChatBadge.vue'
import { parseRawBadges } from '@/assets/messageParser'
import { getEndpoint } from '@/mixins'
import type { Badge } from '@/assets/types'
import type { VodComment, VodMessage } from '@/types'
export default {
props: {
channelName: {
type: String
}
},
async setup(props) {
const messages = ref<VodMessage[]>([])
const messageCache = ref<VodMessage[]>([])
const fetchingMessages = false;
let badges: Badge[] = []
await getEndpoint(`api/badges?channelName=${props.channelName}`).then((data) => {
console.log(data)
badges = data
})
return {
messages,
messageCache,
fetchingMessages,
badges,
}
},
async mounted() {
/*
await getEndpoint(`api/chat/${this.$props.channelName}/history`).then((data) => {
this.messages = parseChatHistory(data, this.badges)
})
*/
},
methods: {
getChat() {
return this.messages
},
scrollToBottom() {
const el = this.$refs.chatList as Element
el.scrollTop = el.scrollHeight
},
clearMessages() {
if (this.messages.length > 50) {
this.messages.splice(0, this.messages.length - 50)
}
},
async updateVodComments(time: number) {
time = Math.round(time)
this.clearMessages()
for (let i = 0; i < this.messageCache.length; i++) {
const msg = this.messageCache[i]
if (!msg) return;
if (time >= msg.offset) {
this.messages.push(msg)
this.messageCache.splice(i, 1)
this.scrollToBottom()
}
}
this.clearMessages()
// Only fetch new messages if they are newer than newest message in cache
const offset = this.messageCache[this.messageCache.length - 1]?.offset ?? 0
if ( this.messageCache.length > 5) return;
if (this.fetchingMessages) return;
this.fetchingMessages = true
try {
const data: VodMessage[] = await getEndpoint(`api/vods/comments/${this.$route.params.vodID}/${time}` )
for (let msg of data) {
const badgesString = msg.badges.map((data) => { return data.setId + "/" + data.version }).join(',')
msg.badges = parseRawBadges(badgesString, this.badges)
}
this.messageCache.push(...data)
} catch (error) {
throw Error("Error fetching new messages: " + error)
}
this.scrollToBottom()
this.fetchingMessages = false;
}
},
components: {
BadgeVue
},
unmounted() {
this.messages = []
this.badges = []
}
}
</script>
<template>
<div
class="p-3 bg-crust rounded-lg w-[99vw] md:max-w-[15.625rem] lg:max-w-[20rem] flex flex-col" @PlayerTimeUpdate="updateVodComments"
>
<!-- SYSTEM MESSAGES -->
<ul
class="overflow-y-scroll overflow-x-hidden space-y-1 whitespace-pre-wrap h-[46.875rem]"
ref="chatList"
>
<li>
<p ref="initConnectingStatus" class="text-gray-500 text-sm italic">
{{ $t('chat.connecting', { username: channelName }) }}
</p>
</li>
<li v-for="message in getChat()" :key="messages.indexOf(message)">
<div class="text-contrast inline-flex">
<!-- CHAT MESSAGE-->
<div class="text-sm items-center">
<ul v-if="message.badges.length > 0" class="inline-flex space-x-1 pr-1">
<li v-for="badge in message.badges" :key="badge.setId">
<badge-vue :badge-info="badge"></badge-vue>
</li>
</ul>
<p class="inline">
<strong :style="message.messager.colorHex? `color: ${message.messager.colorHex};` : ``" class="text-purple font-bold">
{{ message.messager.name }}</strong
>: {{ message.message }}
</p>
</div>
</div>
</li>
</ul>
</div>
</template>