0
Fork 0
mirror of https://codeberg.org/SafeTwitch/safetwitch.git synced 2025-04-12 21:31:19 -05:00

fix following page & add suspended account handle

This commit is contained in:
wowie 2024-10-13 09:30:42 -05:00
parent f274ba527d
commit ad0f79b889
2 changed files with 49 additions and 20 deletions

View file

@ -126,18 +126,16 @@ export async function followersStreaming(streamers: string[], cursor: number): P
* @param cursor which 35 streamer chunk to fetch
* @returns the streamers in that list that are online
*/
export async function getParsedFollowing(
streamers: string[],
cursor: number
): Promise<FollowingStreamer[]> {
export async function getParsedFollowing(streamers: string[], cursor: number): Promise<FollowingStreamer[]> {
// do not make request if no followers
if (streamers.length == 0) {
return []
}
let res: FollowingStreamer[] = []
const payloadData = streamers.slice(cursor, cursor + 35)
const start = cursor * 35
const end = (cursor + 1) * 35
const payloadData = streamers.slice(start, end)
const payload = {
streamers: payloadData

View file

@ -1,13 +1,11 @@
<script lang="ts">
import { ref, inject } from 'vue'
import FollowButton from '@/components/FollowButton.vue'
import LoadingScreen from '@/components/LoadingScreen.vue'
import ErrorMessage from '@/components/ErrorMessage.vue'
import VueTitle from '@/components/VueTitle.vue'
import { getFollows } from '@/settingsManager'
import { postEndpoint, abbreviate, getParsedFollowing } from '@/mixins'
import { abbreviate, getParsedFollowing } from '@/mixins'
import type { FollowingStreamer } from '@/types'
export default {
@ -15,10 +13,11 @@ export default {
setup() {
let data = ref<FollowingStreamer[]>([])
let status = ref<'ok' | 'error'>()
let loadedImages = ref<Set<string>>(new Set())
return {
data,
status,
loadedImages,
rootBackendUrl: inject('rootBackendUrl')
}
},
@ -38,20 +37,29 @@ export default {
this.data = []
return
}
let cursor = this.data.length / 35
let maxCursor = follows.length / 35
let cursor = Math.floor(this.data.length / 35)
let maxCursor = Math.floor(follows.length / 35)
if (cursor > maxCursor) return
let chunk = await getParsedFollowing(follows, cursor)
this.data = [...this.data, ...chunk]
// Filter out the users that are already in the list
const newItems = chunk.filter(item => !this.data.some(existingItem => existingItem.login === item.login))
this.data = [...this.data, ...newItems]
},
onImageLoad(login: string) {
this.loadedImages.add(login)
},
onImageError(login: string) {
// Remove from loadedImages if it was there
this.loadedImages.delete(login)
}
},
async mounted() {
const follows = getFollows()
window.onscroll = this.getNextFollowingStage
this.data = await getParsedFollowing(follows, 0)
const initialChunk = await getParsedFollowing(follows, 0)
this.data = initialChunk
},
components: {
LoadingScreen,
@ -61,6 +69,7 @@ export default {
}
}
</script>
<template>
<loading-screen v-if="!data && status != 'error'"></loading-screen>
<error-message v-else-if="status == 'error'"></error-message>
@ -81,12 +90,34 @@ export default {
<ul class="m-2 flex flex-wrap justify-center">
<li v-for="streamer in data" :key="streamer.login" class="">
<div class="inline-flex bg-overlay0 p-2.5 m-1 rounded-md w-[22rem]">
<img :src="streamer.pfp" class="w-16 rounded-full" />
<div class="justify-between flex flex-col ml-2 truncate text-ellipsis w-[8rem]">
<h1 class="text-2xl font-bold"><router-link :to="streamer.login">{{ streamer.username }}</router-link></h1>
<span>{{ abbreviate(streamer.followers) }} Followers</span>
<div class="inline-flex bg-overlay0 p-2.5 m-1 rounded-md w-[24rem]">
<div class="w-16 h-16 rounded-full overflow-hidden flex items-center justify-center bg-gray-200 relative">
<svg class="w-full h-full text-gray-400" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
<img
v-if="streamer.username && streamer.followers > 0"
:src="streamer.pfp"
:class="{'opacity-0': !loadedImages.has(streamer.login), 'opacity-100': loadedImages.has(streamer.login)}"
class="absolute inset-0 w-full h-full object-cover transition-opacity duration-300"
@load="onImageLoad(streamer.login)"
@error="onImageError(streamer.login)"
/>
</div>
<div class="justify-between flex flex-col ml-2 truncate text-ellipsis w-[12rem]">
<h1 class="text-2xl font-bold">
<template v-if="streamer.username && streamer.followers > 0">
<router-link :to="streamer.login">{{ streamer.username }}</router-link>
</template>
<template v-else>
<span>{{ streamer.login }}</span>
</template>
</h1>
<span v-if="streamer.followers > 0">{{ abbreviate(streamer.followers) }} Followers</span>
<span v-else class="text-red">Account Suspended</span>
</div>
<div class="m-auto">
<follow-button :username="streamer.login"></follow-button>
</div>