From 62ea6de3a7928052cc5aa40cd7384546e6d2eb84 Mon Sep 17 00:00:00 2001 From: ooodc <549496103@qq.com> Date: Sun, 7 Jun 2026 18:17:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=88=B3=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E4=BB=8E=E6=B6=88=E6=81=AF=E4=B8=AD=E6=8F=90=E5=8F=96?= =?UTF-8?q?=E5=B9=B6=E6=A0=BC=E5=BC=8F=E5=8C=96=E6=97=B6=E9=97=B4=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E4=B8=BA=E8=AF=9D=E9=A2=98=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=86=E9=A1=B5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gateway/ws.rs | 10 +-- web/src/components/Chat/MessageBubble.tsx | 2 +- web/src/components/Sidebar/TopicList.tsx | 77 +++++++++++++++++++++-- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/gateway/ws.rs b/src/gateway/ws.rs index c0d8e06..6c4c20f 100644 --- a/src/gateway/ws.rs +++ b/src/gateway/ws.rs @@ -718,7 +718,7 @@ fn chat_message_to_ws_outbound(msg: &crate::bus::ChatMessage) -> Option Option { @@ -745,7 +745,7 @@ fn chat_message_to_ws_outbound(msg: &crate::bus::ChatMessage) -> Option Some(WsOutbound::ToolPending { id: msg.id.clone(), @@ -756,7 +756,7 @@ fn chat_message_to_ws_outbound(msg: &crate::bus::ChatMessage) -> Option Option None, } diff --git a/web/src/components/Chat/MessageBubble.tsx b/web/src/components/Chat/MessageBubble.tsx index a620488..510f0f0 100644 --- a/web/src/components/Chat/MessageBubble.tsx +++ b/web/src/components/Chat/MessageBubble.tsx @@ -76,7 +76,7 @@ function getFileName(path: string): string { } function formatTime(timestamp: number) { - return new Date(timestamp).toLocaleTimeString('zh-CN', { + return new Date(timestamp * 1000).toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', }) diff --git a/web/src/components/Sidebar/TopicList.tsx b/web/src/components/Sidebar/TopicList.tsx index 370c0ff..12f805d 100644 --- a/web/src/components/Sidebar/TopicList.tsx +++ b/web/src/components/Sidebar/TopicList.tsx @@ -1,5 +1,5 @@ -import { useState } from 'react' -import { Plus, MessageSquare, Layers, Hash, Clock, RefreshCw, Trash2, Check, X } from 'lucide-react' +import { useState, useEffect, useMemo, useRef, useCallback } from 'react' +import { Plus, MessageSquare, Layers, Hash, Clock, RefreshCw, Trash2, Check, X, ChevronLeft, ChevronRight } from 'lucide-react' import type { Topic } from '../../types/protocol' interface TopicListProps { @@ -41,6 +41,50 @@ export function TopicList({ }: TopicListProps) { const [confirmDeleteId, setConfirmDeleteId] = useState(null) + // Pagination — dynamically sized to fill one screen without scrolling + const ESTIMATED_ITEM_HEIGHT = 64 // py-3(24px) + title(20px) + mt-1.5(6px) + meta(14px) + const LIST_PADDING = 24 // p-3 top + bottom + const [pageSize, setPageSize] = useState(8) // fallback before measurement + const [currentPage, setCurrentPage] = useState(0) + const listRef = useRef(null) + + const measurePageSize = useCallback(() => { + const el = listRef.current + if (!el) return + const available = el.clientHeight - LIST_PADDING + setPageSize(Math.max(1, Math.floor(available / ESTIMATED_ITEM_HEIGHT) - 1)) + }, []) + + useEffect(() => { + measurePageSize() + const el = listRef.current + if (!el) return + const observer = new ResizeObserver(() => measurePageSize()) + observer.observe(el) + return () => observer.disconnect() + }, [measurePageSize]) + + const totalPages = useMemo( + () => Math.max(1, Math.ceil(topics.length / pageSize)), + [topics.length, pageSize] + ) + const pagedTopics = useMemo( + () => topics.slice(currentPage * pageSize, (currentPage + 1) * pageSize), + [topics, currentPage, pageSize] + ) + + // Reset page when topics list changes (e.g., new data loaded) + useEffect(() => { + setCurrentPage(0) + }, [topics]) + + // Clamp currentPage when it exceeds totalPages (e.g., after deletion on last page) + useEffect(() => { + if (currentPage >= totalPages) { + setCurrentPage(Math.max(0, totalPages - 1)) + } + }, [currentPage, totalPages]) + return (
{/* Header */} @@ -83,7 +127,7 @@ export function TopicList({
{/* Topics 列表 */} -
+
{!sessionId ? (
@@ -97,7 +141,7 @@ export function TopicList({
) : (
- {topics.map((topic, index) => ( + {pagedTopics.map((topic, index) => (
+ + {currentPage + 1} / {totalPages} + + +
+ )}
) }