This commit is contained in:
dragongoose
2025-09-15 21:30:21 -04:00
parent 55ca6f35fe
commit a3c4c18cc0
14 changed files with 96 additions and 90 deletions
+2 -2
View File
@@ -94,7 +94,7 @@ export function parseRawMessage(rawMessage: string, allBadges: Badge[]): Message
}
}
return message;
return message
}
default:
@@ -123,4 +123,4 @@ export function parseRawBadges(rb: string, allBadges: Badge[]): Badge[] {
}
return foundBadges
}
}
+3 -1
View File
@@ -31,7 +31,9 @@ export default {
<div class="p-2">
<div>
<p class="font-bold text-contrast text-xl sm:text-base md:text-xl whitespace-nowrap overflow-hidden text-ellipsis">
<p
class="font-bold text-contrast text-xl sm:text-base md:text-xl whitespace-nowrap overflow-hidden text-ellipsis"
>
{{ category.displayName }}
</p>
<p class="text-sm text-contrast">{{ abbreviate(category.viewers) }} viewers</p>
+4 -4
View File
@@ -34,7 +34,7 @@ export default {
* @returns true if streamer was followed, false if streamer was already followed.
*/
followStreamer(username: string): boolean {
let follows = getFollows()
const follows = getFollows()
if (follows.includes(username)) return false
follows.push(username)
@@ -48,7 +48,7 @@ export default {
* @returns true if unfollowed, false if not followed.
*/
unfollowStreamer(username: string): boolean {
let follows = getFollows()
const follows = getFollows()
const index = follows.indexOf(username)
if (index === -1) return false
@@ -59,10 +59,10 @@ export default {
}
},
mounted() {
let followerData = localStorage.getItem('following')
const followerData = localStorage.getItem('following')
if (!followerData) return
let following: string[] = JSON.parse(followerData)
const following: string[] = JSON.parse(followerData)
const isFollower = following.includes(this.$props.username)
if (isFollower) {
+19 -17
View File
@@ -7,7 +7,6 @@ import { getEndpoint } from '@/mixins'
import type { Badge, Message } from '@/assets/types'
export default {
props: {
channelName: {
@@ -32,20 +31,20 @@ export default {
}
},
async mounted() {
const chatStatusMessage = this.$refs.initConnectingStatus as Element
this.ws!.onmessage = (message) => {
if (message.data == 'OK') {
chatStatusMessage.textContent = this.$t('chat.connected', { username: this.channelName })
} else {
this.messages.push(parseRawMessage(message.data, this.badges))
this.clearMessages()
this.scrollToBottom()
}
const chatStatusMessage = this.$refs.initConnectingStatus as Element
this.ws!.onmessage = (message) => {
if (message.data == 'OK') {
chatStatusMessage.textContent = this.$t('chat.connected', { username: this.channelName })
} else {
this.messages.push(parseRawMessage(message.data, this.badges))
this.clearMessages()
this.scrollToBottom()
}
}
this.ws!.onopen = () => {
this.ws!.send('JOIN ' + this.$props.channelName?.toLowerCase())
}
this.ws!.onopen = () => {
this.ws!.send('JOIN ' + this.$props.channelName?.toLowerCase())
}
/*
await getEndpoint(`api/chat/${this.$props.channelName}/history`).then((data) => {
@@ -80,9 +79,7 @@ export default {
}
</script>
<template>
<div
class="p-3 bg-crust rounded-lg w-[99vw] md:max-w-[15.625rem] lg:max-w-[20rem] flex flex-col"
>
<div class="p-3 bg-crust rounded-lg w-[99vw] md:max-w-[15.625rem] lg:max-w-[20rem] flex flex-col">
<!-- SYSTEM MESSAGES -->
<ul
class="overflow-y-scroll overflow-x-hidden space-y-1 whitespace-pre-wrap h-[46.875rem]"
@@ -128,7 +125,12 @@ export default {
class="text-contrast inline-flex bg-pink bg-opacity-50 p-1 rounded-md"
>
<p>
{{ $t('chat.resub', { username: message.username, duration: message.tags['msg-param-months'] }) }}
{{
$t('chat.resub', {
username: message.username,
duration: message.tags['msg-param-months']
})
}}
</p>
</div>
+34 -28
View File
@@ -8,7 +8,6 @@ import { getEndpoint } from '@/mixins'
import type { Badge } from '@/assets/types'
import type { VodComment, VodMessage } from '@/types'
export default {
props: {
channelName: {
@@ -18,7 +17,7 @@ export default {
async setup(props) {
const messages = ref<VodMessage[]>([])
const messageCache = ref<VodMessage[]>([])
const fetchingMessages = false;
const fetchingMessages = false
let badges: Badge[] = []
await getEndpoint(`api/badges?channelName=${props.channelName}`).then((data) => {
@@ -30,12 +29,10 @@ export default {
messages,
messageCache,
fetchingMessages,
badges,
badges
}
},
async mounted() {
/*
await getEndpoint(`api/chat/${this.$props.channelName}/history`).then((data) => {
this.messages = parseChatHistory(data, this.badges)
@@ -59,43 +56,48 @@ export default {
time = Math.round(time)
this.clearMessages()
for (let i = 0; i < this.messageCache.length; i++) {
const msg = this.messageCache[i]
if (!msg) return;
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()
}
if (time >= msg.offset) {
this.messages.push(msg)
this.messageCache.splice(i, 1)
this.scrollToBottom()
}
}
this.clearMessages()
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;
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(',')
const data: VodMessage[] = await getEndpoint(
`api/vods/comments/${this.$route.params.vodID}/${time}`
)
for (const 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)
throw Error('Error fetching new messages: ' + error)
}
this.scrollToBottom()
this.fetchingMessages = false;
}
this.scrollToBottom()
this.fetchingMessages = false
}
},
components: {
BadgeVue
@@ -108,7 +110,8 @@ export default {
</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"
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
@@ -131,7 +134,10 @@ export default {
</ul>
<p class="inline">
<strong :style="message.messager.colorHex? `color: ${message.messager.colorHex};` : ``" class="text-purple font-bold">
<strong
:style="message.messager.colorHex ? `color: ${message.messager.colorHex};` : ``"
class="text-purple font-bold"
>
{{ message.messager.name }}</strong
>: {{ message.message }}
</p>
+1 -1
View File
@@ -6,7 +6,7 @@ export default {
setup() {
const route = useRoute()
const instanceUrl = location.protocol + '//' + location.host
let currentUrl = ref(instanceUrl)
const currentUrl = ref(instanceUrl)
return {
// remove any query from the path
-2
View File
@@ -1,5 +1,3 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Badge } from "@/assets/types"
import type { Badge } from '@/assets/types'
export interface TwitchChatOptions {
login: {
+6 -6
View File
@@ -11,8 +11,8 @@ import { getEndpoint, abbreviate } from '@/mixins'
export default {
inject: ['protocol'],
async setup() {
let data = ref<CategoryData>()
let status = ref<'ok' | 'error'>()
const data = ref<CategoryData>()
const status = ref<'ok' | 'error'>()
return {
data,
@@ -35,7 +35,7 @@ export default {
},
methods: {
async getMoreStreams() {
let bottomOfWindow =
const bottomOfWindow =
document.documentElement.scrollTop + window.innerHeight ===
document.documentElement.offsetHeight
const streams = this.data!.streams
@@ -52,13 +52,13 @@ export default {
throw err
})
let lastStreamCursor = this.data!.streams[this.data!.streams.length - 1].cursor
let newLastStreamCursor = resData.streams[resData.streams.length - 1].cursor
const lastStreamCursor = this.data!.streams[this.data!.streams.length - 1].cursor
const newLastStreamCursor = resData.streams[resData.streams.length - 1].cursor
if (lastStreamCursor === newLastStreamCursor) {
// Add "no more streams!" screen later
console.log('no more streams!')
} else {
for (let stream of resData.streams) {
for (const stream of resData.streams) {
this.data!.streams.push(stream)
}
}
+6 -6
View File
@@ -13,8 +13,8 @@ import type { FollowingStreamer } from '@/types'
export default {
inject: ['rootBackendUrl'],
setup() {
let data = ref<FollowingStreamer[]>([])
let status = ref<'ok' | 'error'>()
const data = ref<FollowingStreamer[]>([])
const status = ref<'ok' | 'error'>()
return {
data,
@@ -25,7 +25,7 @@ export default {
methods: {
abbreviate,
async getNextFollowingStage() {
let bottomOfWindow =
const bottomOfWindow =
document.documentElement.scrollTop + window.innerHeight ===
document.documentElement.offsetHeight
@@ -39,11 +39,11 @@ export default {
return
}
let cursor = this.data.length / 35
let maxCursor = follows.length / 35
const cursor = this.data.length / 35
const maxCursor = follows.length / 35
if (cursor > maxCursor) return
let chunk = await getParsedFollowing(follows, cursor)
const chunk = await getParsedFollowing(follows, cursor)
this.data = [...this.data, ...chunk]
}
},
+16 -17
View File
@@ -13,10 +13,10 @@ import VueTitle from '@/components/VueTitle.vue'
export default {
async setup() {
let data = ref<CategoryPreviewInterface[]>()
let status = ref<'ok' | 'error'>()
let followingStreaming = ref<string[]>([])
let following = ref<string[]>([])
const data = ref<CategoryPreviewInterface[]>()
const status = ref<'ok' | 'error'>()
const followingStreaming = ref<string[]>([])
const following = ref<string[]>([])
return {
data,
@@ -32,15 +32,15 @@ export default {
const wantedTags = toFilter
.toLowerCase()
.split(',')
.map(tag => tag.trim())
.filter(tag => tag);
.map((tag) => tag.trim())
.filter((tag) => tag)
for (let category of categories as HTMLElement[]) {
let tagElements = category.getElementsByTagName('span')
const categoryTags = Array.from(tagElements, el => el.innerText.toLowerCase())
for (const category of categories as HTMLElement[]) {
const tagElements = category.getElementsByTagName('span')
const categoryTags = Array.from(tagElements, (el) => el.innerText.toLowerCase())
console.log(categoryTags)
if (!categoryTags.some(r=>wantedTags.includes(r))) {
if (!categoryTags.some((r) => wantedTags.includes(r))) {
category.style.display = 'none'
} else {
category.style.display = 'block'
@@ -48,32 +48,31 @@ export default {
}
},
async getNextCategory() {
let bottomOfWindow =
const bottomOfWindow =
document.documentElement.scrollTop + window.innerHeight ===
document.documentElement.offsetHeight
if (bottomOfWindow && this.data) {
const cursor = this.data[this.data.length - 1]?.cursor ?? null
if (!cursor) return
const res = await getEndpoint('api/discover?cursor=' + cursor)
for (let category of res) {
for (const category of res) {
this.data.push(category)
}
}
},
handleFollowingScroll(event: Event) {
let el = event.target as HTMLUListElement
let fullyScrolled = el.scrollLeft === el.scrollWidth - el.clientWidth
const el = event.target as HTMLUListElement
const fullyScrolled = el.scrollLeft === el.scrollWidth - el.clientWidth
if (!fullyScrolled) return
if (!this.following) return
let offset = Math.floor(this.following.length / 35)
const offset = Math.floor(this.following.length / 35)
console.log(offset)
followersStreaming(this.following, offset).then((newFollowers) => {
this.followingStreaming = [...this.following, ...newFollowers]
})
}
},
async mounted() {
+1 -1
View File
@@ -13,7 +13,7 @@ import type { SearchResult, StreamerData } from '@/types'
export default {
inject: ['protocol'],
setup() {
let data = ref<SearchResult>()
const data = ref<SearchResult>()
const status = ref<'ok' | 'error'>()
return {
data,
+3 -3
View File
@@ -14,7 +14,7 @@ import VueTitle from '@/components/VueTitle.vue'
export default {
setup() {
let settings: Settings
let storedSettings = localStorage.getItem('settings')
const storedSettings = localStorage.getItem('settings')
if (storedSettings === null) {
settings = getDefaultSettings()
} else {
@@ -26,7 +26,7 @@ export default {
settings = syncResp.settings
}
let selectedTheme = getTheme()
const selectedTheme = getTheme()
return {
settings,
@@ -55,7 +55,7 @@ export default {
return 'border-none'
},
download() {
var hiddenElement = document.createElement('a')
const hiddenElement = document.createElement('a')
this.settings.followers = getFollows()
-1
View File
@@ -16,7 +16,6 @@ import type { Video } from '@/types'
import { truncate, abbreviate, getEndpoint } from '@/mixins'
import { getSetting } from '@/settingsManager'
interface ChatComponent {
updateVodComments: (time: number) => void
}