From aadadf83534ee80f49e4a829eacbba1770d5d716 Mon Sep 17 00:00:00 2001 From: icarus Date: Sat, 27 Sep 2025 18:03:42 +0800 Subject: [PATCH] fix(session): remove redundant fulfilled dispatch and add loading indicators Remove the redundant dispatch of setTopicFulfilled in messageThunk since it's now handled in SessionItem. Add visual indicators for pending and fulfilled states in SessionItem to improve user feedback. --- .../home/Tabs/components/SessionItem.tsx | 47 +++++++++++++++++-- .../src/store/thunk/messageThunk.v2.ts | 1 - 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/renderer/src/pages/home/Tabs/components/SessionItem.tsx b/src/renderer/src/pages/home/Tabs/components/SessionItem.tsx index af0a8c037..f71b9ef14 100644 --- a/src/renderer/src/pages/home/Tabs/components/SessionItem.tsx +++ b/src/renderer/src/pages/home/Tabs/components/SessionItem.tsx @@ -8,11 +8,15 @@ import { useSettings } from '@renderer/hooks/useSettings' import { useTimer } from '@renderer/hooks/useTimer' import { SessionSettingsPopup } from '@renderer/pages/settings/AgentSettings' import { SessionLabel } from '@renderer/pages/settings/AgentSettings/shared' +import { useAppDispatch, useAppSelector } from '@renderer/store' +import { newMessagesActions } from '@renderer/store/newMessage' import { AgentSessionEntity } from '@renderer/types' import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from '@renderer/ui/context-menu' +import { buildAgentSessionTopicId } from '@renderer/utils/agentSession' import { XIcon } from 'lucide-react' -import React, { FC, memo, startTransition, useState } from 'react' +import React, { FC, memo, startTransition, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' +import styled from 'styled-components' // const logger = loggerService.withContext('AgentItem') @@ -33,6 +37,7 @@ const SessionItem: FC = ({ session, agentId, isDisabled, isLoa const activeSessionId = chat.activeSessionId[agentId] const [isConfirmingDeletion, setIsConfirmingDeletion] = useState(false) const { setTimeoutTimer } = useTimer() + const dispatch = useAppDispatch() const { isEditing, isSaving, editValue, inputRef, startEdit, handleKeyDown, handleValueChange } = useInPlaceEdit({ onSave: async (value) => { @@ -86,6 +91,11 @@ const SessionItem: FC = ({ session, agentId, isDisabled, isLoa } const isActive = activeSessionId === session.id + const topicLoadingQuery = useAppSelector((state) => state.messages.loadingByTopic) + const topicFulfilledQuery = useAppSelector((state) => state.messages.fulfilledByTopic) + const sessionTopicId = buildAgentSessionTopicId(session.id) + const isPending = useMemo(() => topicLoadingQuery[sessionTopicId], [sessionTopicId, topicLoadingQuery]) + const isFulfilled = useMemo(() => topicFulfilledQuery[sessionTopicId], [sessionTopicId, topicFulfilledQuery]) return ( <> @@ -94,11 +104,16 @@ const SessionItem: FC = ({ session, agentId, isDisabled, isLoa { + dispatch(newMessagesActions.setTopicFulfilled({ topicId: sessionTopicId, fulfilled: false })) + onPress() + }} isActive={isActive} onDoubleClick={() => startEdit(session.name ?? '')} className="group"> - + + {isPending && !isActive && } + {isFulfilled && !isActive && } {isEditing && ( > = ({ /> ) +const PendingIndicator = styled.div.attrs({ + className: 'animation-pulse' +})` + --pulse-size: 5px; + width: 5px; + height: 5px; + position: absolute; + left: 3px; + top: 15px; + border-radius: 50%; + background-color: var(--color-status-warning); +` + +const FulfilledIndicator = styled.div.attrs({ + className: 'animation-pulse' +})` + --pulse-size: 5px; + width: 5px; + height: 5px; + position: absolute; + left: 3px; + top: 15px; + border-radius: 50%; + background-color: var(--color-status-success); +` + export default memo(SessionItem) diff --git a/src/renderer/src/store/thunk/messageThunk.v2.ts b/src/renderer/src/store/thunk/messageThunk.v2.ts index 3dc0ea784..ec0aed947 100644 --- a/src/renderer/src/store/thunk/messageThunk.v2.ts +++ b/src/renderer/src/store/thunk/messageThunk.v2.ts @@ -55,7 +55,6 @@ export const loadTopicMessagesThunkV2 = // Could dispatch an error action here if needed } finally { dispatch(newMessagesActions.setTopicLoading({ topicId, loading: false })) - dispatch(newMessagesActions.setTopicFulfilled({ topicId, fulfilled: true })) } }