fix(web): load most recent session instead of creating new chat
When clicking on the chat page, now loads the most recent conversation instead of always creating a new empty chat. This improves UX by showing users their last conversation context. Changes: - Modified usePicoChat hook to load recent session on mount - Added isLoadingSession state to show loading indicator - Added 'loading' translation key for both en and zh Fixes #1373
This commit is contained in:
parent
19835b2f60
commit
01b3c5b131
4 changed files with 47 additions and 4 deletions
|
|
@ -26,6 +26,7 @@ export function ChatPage() {
|
||||||
messages,
|
messages,
|
||||||
isTyping,
|
isTyping,
|
||||||
activeSessionId,
|
activeSessionId,
|
||||||
|
isLoadingSession,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
switchSession,
|
switchSession,
|
||||||
newChat,
|
newChat,
|
||||||
|
|
@ -122,13 +123,19 @@ export function ChatPage() {
|
||||||
className="min-h-0 flex-1 overflow-y-auto px-4 py-6 md:px-8 lg:px-24 xl:px-48"
|
className="min-h-0 flex-1 overflow-y-auto px-4 py-6 md:px-8 lg:px-24 xl:px-48"
|
||||||
>
|
>
|
||||||
<div className="mx-auto flex w-full max-w-250 flex-col gap-8 pb-8">
|
<div className="mx-auto flex w-full max-w-250 flex-col gap-8 pb-8">
|
||||||
{messages.length === 0 && !isTyping && (
|
{isLoadingSession ? (
|
||||||
|
<div className="flex flex-1 items-center justify-center py-20">
|
||||||
|
<div className="text-muted-foreground animate-pulse">
|
||||||
|
{t("chat.loading")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : messages.length === 0 && !isTyping ? (
|
||||||
<ChatEmptyState
|
<ChatEmptyState
|
||||||
hasConfiguredModels={hasConfiguredModels}
|
hasConfiguredModels={hasConfiguredModels}
|
||||||
defaultModelName={defaultModelName}
|
defaultModelName={defaultModelName}
|
||||||
isConnected={isConnected}
|
isConnected={isConnected}
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
|
|
||||||
{messages.map((msg) => (
|
{messages.map((msg) => (
|
||||||
<div key={msg.id} className="flex w-full">
|
<div key={msg.id} className="flex w-full">
|
||||||
|
|
|
||||||
|
|
@ -108,8 +108,8 @@ export function usePicoChat() {
|
||||||
const [connectionState, setConnectionState] =
|
const [connectionState, setConnectionState] =
|
||||||
useState<ConnectionState>("disconnected")
|
useState<ConnectionState>("disconnected")
|
||||||
const [isTyping, setIsTyping] = useState(false)
|
const [isTyping, setIsTyping] = useState(false)
|
||||||
const [activeSessionId, setActiveSessionId] =
|
const [activeSessionId, setActiveSessionId] = useState<string>("")
|
||||||
useState<string>(generateSessionId)
|
const [isLoadingSession, setIsLoadingSession] = useState(true)
|
||||||
|
|
||||||
const wsRef = useRef<WebSocket | null>(null)
|
const wsRef = useRef<WebSocket | null>(null)
|
||||||
const isConnectingRef = useRef(false)
|
const isConnectingRef = useRef(false)
|
||||||
|
|
@ -290,6 +290,39 @@ export function usePicoChat() {
|
||||||
return () => disconnect()
|
return () => disconnect()
|
||||||
}, [disconnect])
|
}, [disconnect])
|
||||||
|
|
||||||
|
// Load most recent session on initial mount
|
||||||
|
useEffect(() => {
|
||||||
|
const loadRecentSession = async () => {
|
||||||
|
try {
|
||||||
|
const sessions = await getSessions(0, 1)
|
||||||
|
if (sessions.length > 0) {
|
||||||
|
const recentSession = sessions[0]
|
||||||
|
const detail = await getSessionHistory(recentSession.id)
|
||||||
|
const fallbackTime = detail.updated
|
||||||
|
const historyMessages = detail.messages.map((m, i) => ({
|
||||||
|
id: `hist-${i}-${Date.now()}`,
|
||||||
|
role: m.role as "user" | "assistant",
|
||||||
|
content: m.content,
|
||||||
|
timestamp: fallbackTime,
|
||||||
|
}))
|
||||||
|
setActiveSessionId(recentSession.id)
|
||||||
|
setMessages(historyMessages)
|
||||||
|
} else {
|
||||||
|
// No existing sessions, create a new one
|
||||||
|
setActiveSessionId(generateSessionId())
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to load recent session:", err)
|
||||||
|
// Fall back to new session on error
|
||||||
|
setActiveSessionId(generateSessionId())
|
||||||
|
} finally {
|
||||||
|
setIsLoadingSession(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadRecentSession()
|
||||||
|
}, [])
|
||||||
|
|
||||||
const sendMessage = useCallback((content: string) => {
|
const sendMessage = useCallback((content: string) => {
|
||||||
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
|
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {
|
||||||
console.warn("WebSocket not connected")
|
console.warn("WebSocket not connected")
|
||||||
|
|
@ -379,6 +412,7 @@ export function usePicoChat() {
|
||||||
connectionState,
|
connectionState,
|
||||||
isTyping,
|
isTyping,
|
||||||
activeSessionId,
|
activeSessionId,
|
||||||
|
isLoadingSession,
|
||||||
sendMessage,
|
sendMessage,
|
||||||
switchSession,
|
switchSession,
|
||||||
newChat,
|
newChat,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"historyLoadFailed": "Failed to load chat history",
|
"historyLoadFailed": "Failed to load chat history",
|
||||||
"historyOpenFailed": "Failed to open this chat history",
|
"historyOpenFailed": "Failed to open this chat history",
|
||||||
"loadingMore": "Loading more...",
|
"loadingMore": "Loading more...",
|
||||||
|
"loading": "Loading...",
|
||||||
"deleteSession": "Delete session",
|
"deleteSession": "Delete session",
|
||||||
"messagesCount": "{{count}} messages",
|
"messagesCount": "{{count}} messages",
|
||||||
"noModel": "Select model",
|
"noModel": "Select model",
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
"historyLoadFailed": "加载历史记录失败",
|
"historyLoadFailed": "加载历史记录失败",
|
||||||
"historyOpenFailed": "打开该历史会话失败",
|
"historyOpenFailed": "打开该历史会话失败",
|
||||||
"loadingMore": "加载更多...",
|
"loadingMore": "加载更多...",
|
||||||
|
"loading": "加载中...",
|
||||||
"deleteSession": "删除会话",
|
"deleteSession": "删除会话",
|
||||||
"messagesCount": "{{count}} 条消息",
|
"messagesCount": "{{count}} 条消息",
|
||||||
"noModel": "选择模型",
|
"noModel": "选择模型",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue