safetwitch/src/components/TwitchChat.vue

124 lines
3.5 KiB
Vue
Raw Normal View History

2023-03-17 22:57:54 -04:00
<script lang="ts">
2023-03-18 13:49:02 -04:00
import { ref, type Ref } from 'vue'
2023-03-31 07:50:46 -04:00
import BadgeVue from './ChatBadge.vue'
import { getBadges } from '@/assets/badges'
2023-04-06 10:20:22 -04:00
import { parseMessage } from '@/assets/messageParser'
import type { Badge, ParsedMessage } from '@/assets/types'
2023-03-18 13:49:02 -04:00
export default {
props: {
isLive: {
type: Boolean,
default() {
return false
}
},
channelName: {
type: String
2023-03-17 22:57:54 -04:00
}
2023-03-18 13:49:02 -04:00
},
2023-03-30 10:30:21 -04:00
async setup(props) {
2023-04-06 10:20:22 -04:00
let messages: Ref<ParsedMessage[]> = ref([])
2023-03-30 10:30:21 -04:00
const badgesFetch = await fetch(`${import.meta.env.VITE_BACKEND_URL}/api/badges?channelName=${props.channelName}`)
let badges: Badge[] = await badgesFetch.json()
2023-03-18 13:49:02 -04:00
return {
2023-04-06 10:20:22 -04:00
ws: new WebSocket(`ws://localhost:7001`),
2023-03-18 13:49:02 -04:00
messages,
2023-03-30 10:30:21 -04:00
badges,
props,
2023-03-18 13:49:02 -04:00
}
},
mounted() {
const chatList = this.$refs.chatList as Element
2023-03-19 19:51:14 -04:00
const chatStatusMessage = this.$refs.initConnectingStatus as Element
2023-03-18 13:49:02 -04:00
this.ws.onmessage = (message) => {
2023-03-19 19:51:14 -04:00
if (message.data == 'OK') {
chatStatusMessage.textContent = `Connected to ${this.channelName}`
} else {
2023-04-06 10:20:22 -04:00
this.messages.push(parseMessage(message.data, this.badges))
2023-03-27 16:40:48 -04:00
this.clearMessages()
2023-03-18 13:49:02 -04:00
this.scrollToBottom(chatList)
}
}
2023-03-31 07:50:46 -04:00
this.ws.onopen = () => {
2023-03-19 19:51:14 -04:00
this.ws.send('JOIN ' + this.props.channelName?.toLowerCase())
2023-03-18 13:49:02 -04:00
}
},
methods: {
getChat() {
return this.messages
},
scrollToBottom(el: Element) {
el.scrollTop = el.scrollHeight
2023-03-27 16:40:48 -04:00
},
clearMessages() {
if (this.messages.length > 50) {
this.messages.shift
}
2023-03-30 10:30:21 -04:00
},
2023-04-06 10:20:22 -04:00
getBadges(message: ParsedMessage) {
let badgesString = message.data.tags.badges;
if (!badgesString) return;
let badges = badgesString.split(',');
2023-04-06 10:20:22 -04:00
let formatedBadges = badges.map((badgeWithVersion: string) => {
const [setId, version] = badgeWithVersion.split('/');
return { setId, version };
});
2023-03-30 10:30:21 -04:00
return getBadges(this.badges, formatedBadges);
2023-03-18 13:49:02 -04:00
}
2023-03-30 10:30:21 -04:00
},
components: {
BadgeVue
2023-03-18 13:49:02 -04:00
}
}
2023-03-17 22:57:54 -04:00
</script>
<template>
2023-03-19 19:51:14 -04:00
<div v-if="isLive" class="p-3 bg-ctp-crust rounded-lg w-full max-w-[15.625rem] flex flex-col">
2023-03-30 12:24:52 -04:00
<!-- SYSTEM MESSAGES -->
2023-03-29 10:26:55 -04:00
<ul
class="overflow-y-scroll overflow-x-hidden space-y-1 whitespace-pre-wrap h-[46.875rem]"
2023-03-29 10:26:55 -04:00
ref="chatList"
>
2023-03-19 19:51:14 -04:00
<li>
<p ref="initConnectingStatus" class="text-gray-500 text-sm italic">
Connecting to {{ channelName }}.
</p>
2023-03-19 19:51:14 -04:00
</li>
2023-03-18 13:49:02 -04:00
<li v-for="message in getChat()" :key="messages.indexOf(message)">
2023-04-06 10:20:22 -04:00
<div v-if="message.type === 'PRIVMSG'" class="text-white inline-flex">
2023-03-30 12:24:52 -04:00
<!-- CHAT MESSAGE-->
2023-03-30 10:30:21 -04:00
<p class="text-sm items-center">
<ul class="inline-flex space-x-1 pr-1">
2023-03-31 07:50:46 -04:00
<li v-for="badge in getBadges(message)" :key="badge.id">
2023-03-30 10:30:21 -04:00
<badge-vue :badge-info="badge"></badge-vue>
</li>
</ul>
2023-03-29 10:26:55 -04:00
<strong
2023-04-06 10:20:22 -04:00
:style="message.data.tags.color ? `color: ${message.data.tags.color};` : ``"
2023-03-30 10:30:21 -04:00
class="text-ctp-pink font-bold">
2023-04-06 10:20:22 -04:00
{{ message.data.username }}</strong>: {{ message.data.message }}
2023-03-18 13:49:02 -04:00
</p>
</div>
2023-04-06 10:20:22 -04:00
<div v-else-if="message.type === 'CLEARMSG'" class="text-white inline-flex">
<p class="text-sm text-gray-500 italic"> Message by {{ message.data.username }} removed </p>
</div>
<div v-else class="text-white">
{{ message }}
</div>
2023-03-18 13:49:02 -04:00
</li>
</ul>
</div>
</template>