Files
Nexus/frontend/src/composables/push/usePushServers.ts
T

170 lines
4.7 KiB
TypeScript
Raw Normal View History

import { ref, computed, type Ref } from 'vue'
import { categoryDisplayLabel } from '@/composables/useServerCategories'
import { useServerSearchHistory } from '@/composables/useServerSearchHistory'
import { fetchPagePerPage } from '@/utils/paginatedFetch'
import type { PushServerItem } from './types'
const PUSH_SEARCH_HISTORY = 5
export function usePushServers(pushStatus: Ref<Record<number, string>>) {
const servers = ref<PushServerItem[]>([])
const serversLoading = ref(false)
const serverSearch = ref('')
const selectedIds = ref<Set<number>>(new Set())
const { items: pushSearchHistory, loadHistoryOnly, record: recordPushSearch } =
useServerSearchHistory('push')
const serverSearchHistory = computed(() =>
pushSearchHistory.value.slice(0, PUSH_SEARCH_HISTORY),
)
function commitServerSearch() {
void recordPushSearch(serverSearch.value)
}
function onServerSearchUpdate(val: string | null) {
serverSearch.value = val ?? ''
if (val == null || val === '') {
void recordPushSearch('')
return
}
const picked = String(val).trim()
if (pushSearchHistory.value.includes(picked)) {
serverSearch.value = picked
void recordPushSearch(picked)
}
}
async function loadSearchHistory() {
await loadHistoryOnly()
}
let refreshTimer: ReturnType<typeof setInterval> | null = null
async function loadServers(silent = false) {
if (!silent) serversLoading.value = true
try {
const res = await fetchPagePerPage<PushServerItem>(
'/servers/',
{ sort_by: 'created_at', sort_order: 'desc' },
1,
-1,
)
servers.value = res.items
} catch {
servers.value = []
} finally {
if (!silent) serversLoading.value = false
}
}
function startAutoRefresh(_isPushing?: () => boolean) {
stopAutoRefresh()
refreshTimer = setInterval(() => {
void loadServers(true)
}, 30_000)
}
function stopAutoRefresh() {
if (refreshTimer) {
clearInterval(refreshTimer)
refreshTimer = null
}
}
const filteredServers = computed(() => {
if (!serverSearch.value) return servers.value
const q = serverSearch.value.toLowerCase()
return servers.value.filter(
s =>
s.name.toLowerCase().includes(q) ||
(s.domain || '').toLowerCase().includes(q) ||
(s.target_path || '').toLowerCase().includes(q),
)
})
const selectAll = computed(() => {
const visible = filteredServers.value
return visible.length > 0 && visible.every(s => selectedIds.value.has(s.id))
})
const serversByCategory = computed(() => {
const groups: Record<string, PushServerItem[]> = {}
for (const s of filteredServers.value) {
const key = s.category?.trim() || 'uncategorized'
if (!groups[key]) groups[key] = []
groups[key].push(s)
}
return Object.entries(groups)
.map(([category, list]) => ({
category,
label: categoryDisplayLabel(category),
servers: list,
}))
.sort((a, b) => {
if (a.category === 'uncategorized') return 1
if (b.category === 'uncategorized') return -1
return a.label.localeCompare(b.label, 'zh')
})
})
function isCategoryAllSelected(category: string): boolean {
const group = serversByCategory.value.find(g => g.category === category)
if (!group || group.servers.length === 0) return false
return group.servers.every(s => selectedIds.value.has(s.id))
}
function toggleCategory(category: string) {
const group = serversByCategory.value.find(g => g.category === category)
if (!group) return
const next = new Set(selectedIds.value)
const allSelected = group.servers.every(srv => next.has(srv.id))
for (const srv of group.servers) {
if (allSelected) next.delete(srv.id)
else next.add(srv.id)
}
selectedIds.value = next
}
function toggleServer(id: number) {
const next = new Set(selectedIds.value)
if (next.has(id)) next.delete(id)
else next.add(id)
selectedIds.value = next
}
function toggleAll() {
const visible = filteredServers.value
const allSelected = visible.length > 0 && visible.every(s => selectedIds.value.has(s.id))
const next = new Set(selectedIds.value)
for (const srv of visible) {
if (allSelected) next.delete(srv.id)
else next.add(srv.id)
}
selectedIds.value = next
}
return {
servers,
serversLoading,
serverSearch,
serverSearchHistory,
selectedIds,
pushStatus,
filteredServers,
selectAll,
serversByCategory,
loadServers,
loadSearchHistory,
commitServerSearch,
onServerSearchUpdate,
startAutoRefresh,
stopAutoRefresh,
isCategoryAllSelected,
toggleCategory,
toggleServer,
toggleAll,
}
}