'use client'; import { Suspense, useCallback, useEffect, useMemo, useState } from 'react'; import Link from 'next/link'; import { useSearchParams } from 'next/navigation'; import Sidebar from '@/components/Sidebar'; import { Star, ChevronRight, Search } from 'lucide-react'; type Group = { chatroom_id: string; name: string; summary: string; time: string; timestamp: number; unread: number; is_favorite: boolean; group_ids: number[]; }; type SessionsResp = { ok: boolean; total: number; groups: Group[]; categories: Array<{ id: number; name: string; color: string; emoji: string | null }>; }; export default function GroupsListPage() { return ( }> ); } function GroupsListContent() { const params = useSearchParams(); const filter = params.get('filter') ?? 'all'; const groupId = params.get('group_id'); const [data, setData] = useState(null); const [q, setQ] = useState(''); const [bumping, setBumping] = useState(null); const reload = useCallback(async () => { const r = await fetch('/api/sessions'); setData(await r.json()); }, []); useEffect(() => { let cancelled = false; (async () => { const r = await fetch('/api/sessions'); const json = (await r.json()) as SessionsResp; if (!cancelled) setData(json); })(); return () => { cancelled = true; }; }, []); const filtered = useMemo(() => { if (!data) return []; let list = data.groups; if (filter === 'favorites') list = list.filter((g) => g.is_favorite); if (filter === 'unsorted') list = list.filter((g) => g.group_ids.length === 0); if (filter === 'group' && groupId) list = list.filter((g) => g.group_ids.includes(Number(groupId))); if (q.trim()) { const k = q.trim().toLowerCase(); list = list.filter( (g) => g.name.toLowerCase().includes(k) || g.summary.toLowerCase().includes(k), ); } return [...list].sort((a, b) => b.timestamp - a.timestamp); }, [data, filter, groupId, q]); const title = useMemo(() => { if (filter === 'favorites') return '收藏的群'; if (filter === 'unsorted') return '未分组的群'; if (filter === 'group' && groupId && data) { const c = data.categories.find((c) => c.id === Number(groupId)); return c ? `分组:${c.emoji ?? ''} ${c.name}` : '分组'; } return '所有群'; }, [filter, groupId, data]); const toggleFav = async (chatroomId: string, current: boolean) => { setBumping(chatroomId); await fetch('/api/group-tags', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ chatroom_id: chatroomId, fav: !current }), }); setBumping(null); reload(); }; return (
Group Directory
{title}
{filtered.length} / {data?.total ?? 0} 个群
setQ(e.target.value)} placeholder="搜索群名或最近消息…" className="w-60 bg-transparent text-[12px] outline-none placeholder:text-[var(--text-3)]" />
{!data ? (
加载中…
) : filtered.length === 0 ? (
没有匹配的群
) : (
{filtered.map((g) => (
{g.name}
{g.unread > 0 && ( {g.unread} )}
{g.summary}
{g.time}
))}
)}
); } function GroupsListFallback() { return (
Group Directory
所有群
加载中…
加载中…
); }