Skip to content

Commit

Permalink
💄 style: improve loading state (lobehub#2767)
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx authored Jun 3, 2024
1 parent 3fc975b commit fbdfde9
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useSendMessage } from '@/features/ChatInput/useSend';
import { useAgentStore } from '@/store/agent';
import { agentSelectors } from '@/store/agent/slices/chat';
import { useChatStore } from '@/store/chat';
import { chatSelectors } from '@/store/chat/selectors';
import { chatSelectors, topicSelectors } from '@/store/chat/selectors';
import { filesSelectors, useFileStore } from '@/store/file';
import { useUserStore } from '@/store/user';
import { modelProviderSelectors, preferenceSelectors } from '@/store/user/selectors';
Expand Down Expand Up @@ -61,10 +61,20 @@ const Footer = memo<FooterProps>(({ setExpand }) => {

const { theme, styles } = useStyles();

const [isAIGenerating, stopGenerateMessage] = useChatStore((s) => [
const [
isAIGenerating,
isHasMessageLoading,
isCreatingMessage,
isCreatingTopic,
stopGenerateMessage,
] = useChatStore((s) => [
chatSelectors.isAIGenerating(s),
chatSelectors.isHasMessageLoading(s),
chatSelectors.isCreatingMessage(s),
topicSelectors.isCreatingTopic(s),
s.stopGenerateMessage,
]);

const isImageUploading = useFileStore(filesSelectors.isImageUploading);

const model = useAgentStore(agentSelectors.currentAgentModel);
Expand Down Expand Up @@ -93,6 +103,9 @@ const Footer = memo<FooterProps>(({ setExpand }) => {

const wrapperShortcut = useCmdEnterToSend ? enter : cmdEnter;

const buttonDisabled =
isImageUploading || isHasMessageLoading || isCreatingTopic || isCreatingMessage;

return (
<Flexbox
align={'end'}
Expand Down Expand Up @@ -136,7 +149,8 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
) : (
<Space.Compact>
<Button
disabled={isImageUploading}
disabled={buttonDisabled}
loading={buttonDisabled}
onClick={() => {
sendMessage();
setExpand?.(false);
Expand All @@ -145,7 +159,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
>
{t('input.send')}
</Button>
<SendMore disabled={isImageUploading} />
<SendMore disabled={buttonDisabled} />
</Space.Compact>
)}
</Flexbox>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
container: css`
cursor: pointer;
width: calc(100% - 16px);
margin-block: 2px;
margin-inline: 8px;
padding: 8px;
border-radius: ${token.borderRadius}px;
&.topic-item {
width: calc(100% - 16px);
}
&:hover {
background: ${token.colorFillSecondary};
}
Expand All @@ -52,7 +55,7 @@ const TopicItem = memo<ConfigCellProps>(({ title, active, id, fav }) => {
return (
<Flexbox
align={'center'}
className={cx(styles.container, active && styles.active)}
className={cx(styles.container, 'topic-item', active && styles.active)}
distribution={'space-between'}
horizontal
onClick={() => {
Expand Down
6 changes: 3 additions & 3 deletions src/store/chat/slices/message/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export const chatMessage: StateCreator<

// if message is empty or no files, then stop
if (!message && isNoFile) return;
set({ isCreatingMessage: true }, false, 'creatingMessage/start');

const newMessage: CreateMessageParams = {
content: message,
Expand Down Expand Up @@ -310,9 +311,10 @@ export const chatMessage: StateCreator<

// Get the current messages to generate AI response
const messages = chatSelectors.currentChats(get());

await internal_coreProcessMessage(messages, id, { isWelcomeQuestion });

set({ isCreatingMessage: false }, false, 'creatingMessage/stop');

// if autoCreateTopic is false, then stop
if (!agentConfig.enableAutoCreateTopic) return;

Expand Down Expand Up @@ -707,7 +709,6 @@ export const chatMessage: StateCreator<
internal_createMessage: async (message, context) => {
const { internal_createTmpMessage, refreshMessages, internal_toggleMessageLoading } = get();
let tempId = context?.tempMessageId;

if (!tempId) {
// use optimistic update to avoid the slow waiting
tempId = internal_createTmpMessage(message);
Expand All @@ -721,7 +722,6 @@ export const chatMessage: StateCreator<
}

internal_toggleMessageLoading(false, tempId);

return id;
},

Expand Down
2 changes: 2 additions & 0 deletions src/store/chat/slices/message/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface ChatMessageState {
*/
chatLoadingIds: string[];
inputMessage: string;
isCreatingMessage: boolean;
/**
* is the message is editing
*/
Expand All @@ -35,6 +36,7 @@ export const initialMessageState: ChatMessageState = {
activeId: 'inbox',
chatLoadingIds: [],
inputMessage: '',
isCreatingMessage: false,
messageEditingIds: [],
messageLoadingIds: [],
messagesInit: false,
Expand Down
5 changes: 5 additions & 0 deletions src/store/chat/slices/message/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ const isCurrentChatLoaded = (s: ChatStore) => !!s.messagesMap[currentChatKey(s)]

const isMessageEditing = (id: string) => (s: ChatStore) => s.messageEditingIds.includes(id);
const isMessageLoading = (id: string) => (s: ChatStore) => s.messageLoadingIds.includes(id);
const isHasMessageLoading = (s: ChatStore) => s.messageLoadingIds.length > 0;
const isCreatingMessage = (s: ChatStore) => s.isCreatingMessage;

const isMessageGenerating = (id: string) => (s: ChatStore) => s.chatLoadingIds.includes(id);
const isToolCallStreaming = (id: string, index: number) => (s: ChatStore) => {
const isLoading = s.toolCallingStreamIds[id];
Expand All @@ -146,7 +149,9 @@ export const chatSelectors = {
getMessageById,
getTraceIdByMessageId,
isAIGenerating,
isCreatingMessage,
isCurrentChatLoaded,
isHasMessageLoading,
isMessageEditing,
isMessageGenerating,
isMessageLoading,
Expand Down
5 changes: 3 additions & 2 deletions src/store/chat/slices/topic/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,14 @@ export const chatTopic: StateCreator<
const { activeId, internal_createTopic } = get();

const messages = chatSelectors.currentChats(get());

set({ creatingTopic: true }, false, n('creatingTopic/start'));
const topicId = await internal_createTopic({
sessionId: activeId,
title: t('topic.defaultTitle', { ns: 'chat' }),
messages: messages.map((m) => m.id),
});

// get().internal_updateTopicLoading(topicId, true);
set({ creatingTopic: false }, false, n('creatingTopic/end'));

return topicId;
},
Expand Down
2 changes: 2 additions & 0 deletions src/store/chat/slices/topic/initialState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ChatTopic } from '@/types/topic';
export interface ChatTopicState {
// TODO: need to add the null to the type
activeTopicId?: string;
creatingTopic: boolean;
isSearchingTopic: boolean;
searchTopics: ChatTopic[];
topicLoadingIds: string[];
Expand All @@ -17,6 +18,7 @@ export interface ChatTopicState {

export const initialTopicState: ChatTopicState = {
activeTopicId: null as any,
creatingTopic: false,
isSearchingTopic: false,
searchTopics: [],
topicLoadingIds: [],
Expand Down
2 changes: 2 additions & 0 deletions src/store/chat/slices/topic/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const getTopicById =
(id: string) =>
(s: ChatStore): ChatTopic | undefined =>
currentTopics(s)?.find((topic) => topic.id === id);
const isCreatingTopic = (s: ChatStore) => s.creatingTopic;

export const topicSelectors = {
currentActiveTopic,
Expand All @@ -29,5 +30,6 @@ export const topicSelectors = {
currentUnFavTopics,
displayTopics,
getTopicById,
isCreatingTopic,
searchTopics,
};

0 comments on commit fbdfde9

Please sign in to comment.