'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} toggleFav(g.chatroom_id, g.is_favorite)} title={g.is_favorite ? '取消收藏' : '加入收藏'} > ))} )} ); } function GroupsListFallback() { return ( Group Directory 所有群 加载中… 加载中… ); }