78 lines
1.6 KiB
TypeScript
78 lines
1.6 KiB
TypeScript
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
|
|
|
import { fetchUnreadChatCount } from '@/features/chats/api/chats'
|
|
import { useSessionStore } from '@/stores/session'
|
|
|
|
export function useChatUnreadCount(route: RouteLocationNormalizedLoaded) {
|
|
const session = useSessionStore()
|
|
const unreadCount = ref(0)
|
|
let timer: number | null = null
|
|
let requestID = 0
|
|
|
|
const unreadLabel = computed(() => (unreadCount.value > 99 ? '99+' : String(unreadCount.value)))
|
|
|
|
function stopPolling() {
|
|
if (timer) {
|
|
window.clearInterval(timer)
|
|
timer = null
|
|
}
|
|
}
|
|
|
|
async function loadUnreadCount() {
|
|
if (!session.isLoggedIn) {
|
|
unreadCount.value = 0
|
|
return
|
|
}
|
|
|
|
const currentID = ++requestID
|
|
try {
|
|
const count = await fetchUnreadChatCount()
|
|
if (currentID === requestID) {
|
|
unreadCount.value = count
|
|
}
|
|
} catch {
|
|
// 底部导航不弹错误提示,保持上一次未读数即可。
|
|
}
|
|
}
|
|
|
|
function startPolling() {
|
|
stopPolling()
|
|
void loadUnreadCount()
|
|
timer = window.setInterval(loadUnreadCount, 30_000)
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (session.isLoggedIn) {
|
|
startPolling()
|
|
}
|
|
})
|
|
|
|
onBeforeUnmount(stopPolling)
|
|
|
|
watch(
|
|
() => session.isLoggedIn,
|
|
loggedIn => {
|
|
if (loggedIn) {
|
|
startPolling()
|
|
return
|
|
}
|
|
stopPolling()
|
|
unreadCount.value = 0
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => route.fullPath,
|
|
() => {
|
|
void loadUnreadCount()
|
|
}
|
|
)
|
|
|
|
return {
|
|
unreadCount,
|
|
unreadLabel,
|
|
refreshUnreadCount: loadUnreadCount,
|
|
}
|
|
}
|