Skip to content

Commit 0a5bb53

Browse files
chore: chat optimize
1 parent 196e524 commit 0a5bb53

File tree

9 files changed

+402
-288
lines changed

9 files changed

+402
-288
lines changed

app/(chat)/(routes)/chat/[[...slug]]/_components/chat-main/chat-body.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ArrowDown, LoaderPinwheel } from 'lucide-react';
44
import { useTranslations } from 'next-intl';
55
import React, {
66
createContext,
7+
memo,
78
SyntheticEvent,
89
useContext,
910
useEffect,
@@ -67,7 +68,7 @@ type ChatBodyProps = {
6768
) => void;
6869
};
6970

70-
export const ChatBody = ({
71+
const ChatBodyComponent = ({
7172
assistantImage,
7273
assistantMessage,
7374
introMessages,
@@ -170,3 +171,7 @@ export const ChatBody = ({
170171
</ChatScrollContext.Provider>
171172
);
172173
};
174+
175+
ChatBodyComponent.displayName = 'ChatBody';
176+
177+
export const ChatBody = memo(ChatBodyComponent);

app/(chat)/(routes)/chat/[[...slug]]/_components/chat-main/chat-input-footer.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { ImageIcon, SendHorizonal, StopCircle } from 'lucide-react';
44
import { useTranslations } from 'next-intl';
5+
import { useMemo } from 'react';
56

67
import { Badge, Button, Separator } from '@/components/ui';
78
import { useAppConfigStore } from '@/hooks/store/use-app-config-store';
@@ -29,7 +30,10 @@ export const ChatInputFooter = ({
2930
config: state.config,
3031
}));
3132

32-
const IMAGE_MODELS = appConfig?.ai.flatMap((ai) => ai['image-models']) ?? [];
33+
const IMAGE_MODELS = useMemo(
34+
() => appConfig?.ai.flatMap((ai) => ai['image-models']) ?? [],
35+
[appConfig?.ai],
36+
);
3337

3438
return (
3539
<div className="flex justify-between px-2 py-2 items-center">

app/(chat)/(routes)/chat/[[...slug]]/_components/chat-main/chat-shared-top-bar.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { format } from 'date-fns';
44
import { useTranslations } from 'next-intl';
5+
import { memo } from 'react';
56

67
import { TIMESTAMP_PREVIEW_TEMPLATE } from '@/constants/common';
78

@@ -10,7 +11,7 @@ type ChatSharedTopBarProps = {
1011
title: string;
1112
};
1213

13-
export const ChatSharedTopBar = ({ expiredAt, title }: ChatSharedTopBarProps) => {
14+
const ChatSharedTopBarComponent = ({ expiredAt, title }: ChatSharedTopBarProps) => {
1415
const t = useTranslations('chat.shared');
1516

1617
return (
@@ -28,3 +29,7 @@ export const ChatSharedTopBar = ({ expiredAt, title }: ChatSharedTopBarProps) =>
2829
</div>
2930
);
3031
};
32+
33+
ChatSharedTopBarComponent.displayName = 'ChatSharedTopBar';
34+
35+
export const ChatSharedTopBar = memo(ChatSharedTopBarComponent);

app/(chat)/(routes)/chat/[[...slug]]/_components/chat-main/chat-top-bar.tsx

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { Check, ChevronDown } from 'lucide-react';
44
import { useTranslations } from 'next-intl';
5-
import { useState } from 'react';
5+
import { memo, useCallback, useMemo, useState } from 'react';
66

77
import { GetAppConfig } from '@/actions/configs/get-app-config';
88
import {
@@ -33,7 +33,7 @@ type ChatTopBarProps = {
3333
isEmbed?: boolean;
3434
};
3535

36-
const CommandItems = ({ callback, currentModel, models }: CommandItemsProps) => {
36+
const CommandItems = memo(({ callback, currentModel, models }: CommandItemsProps) => {
3737
const { user } = useCurrentUser();
3838

3939
return models.map((model) => (
@@ -43,7 +43,6 @@ const CommandItems = ({ callback, currentModel, models }: CommandItemsProps) =>
4343
value={model.value}
4444
onSelect={(currentValue) => {
4545
const value = currentValue === currentModel ? '' : currentValue;
46-
4746
callback({ currentModel: value, currentModelLabel: model.label, isOpen: false });
4847
}}
4948
>
@@ -61,9 +60,9 @@ const CommandItems = ({ callback, currentModel, models }: CommandItemsProps) =>
6160
</div>
6261
</CommandItem>
6362
));
64-
};
63+
});
6564

66-
export const ChatTopBar = ({ isEmbed = false }: ChatTopBarProps) => {
65+
const ChatTopBarComponent = ({ isEmbed = false }: ChatTopBarProps) => {
6766
const t = useTranslations('chat.top-bar');
6867

6968
const { chatMessages, conversationId, currentModel, setCurrentModel, setCurrentModelLabel } =
@@ -74,42 +73,51 @@ export const ChatTopBar = ({ isEmbed = false }: ChatTopBarProps) => {
7473

7574
const [open, setOpen] = useState(false);
7675

77-
const [paidModels, freeModels] = (appConfig?.ai?.flatMap((ai) => ai['text-models']) ?? []).reduce<
78-
[Model[], Model[], Model[]]
79-
>(
80-
(acc, model) => {
81-
if (model.isSubscription) {
82-
acc[0].push(model);
83-
} else {
84-
acc[1].push(model);
85-
}
86-
return acc;
87-
},
88-
[[], [], []],
76+
const [paidModels, freeModels] = useMemo(
77+
() =>
78+
(appConfig?.ai?.flatMap((ai) => ai['text-models']) ?? []).reduce<[Model[], Model[]]>(
79+
(acc, model) => {
80+
if (model.isSubscription) {
81+
acc[0].push(model);
82+
} else {
83+
acc[1].push(model);
84+
}
85+
return acc;
86+
},
87+
[[], []],
88+
),
89+
[appConfig?.ai],
8990
);
9091

9192
const messages = chatMessages[conversationId] ?? [];
9293

93-
const handleCommandItemsCallback = ({
94-
currentModel,
95-
currentModelLabel,
96-
isOpen,
97-
}: {
98-
currentModel: string;
99-
currentModelLabel: string;
100-
isOpen: boolean;
101-
}) => {
102-
setCurrentModel(currentModel);
103-
setCurrentModelLabel(currentModelLabel);
104-
setOpen(isOpen);
105-
};
94+
const handleCommandItemsCallback = useCallback(
95+
({
96+
currentModel,
97+
currentModelLabel,
98+
isOpen,
99+
}: {
100+
currentModel: string;
101+
currentModelLabel: string;
102+
isOpen: boolean;
103+
}) => {
104+
setCurrentModel(currentModel);
105+
setCurrentModelLabel(currentModelLabel);
106+
setOpen(isOpen);
107+
},
108+
[setCurrentModel, setCurrentModelLabel],
109+
);
110+
111+
const handleOpenChange = useCallback((value: boolean) => {
112+
setOpen(value);
113+
}, []);
106114

107115
return (
108116
<div className={cn('w-full h-[75px]', !messages.length && 'h-full')}>
109117
<div className="flex flex-1 flex-col text-base md:px-5 lg:px-1 xl:px-5 mx-auto gap-3 md:max-w-3xl lg:max-w-[40rem] xl:max-w-4xl pt-4 px-4">
110118
<div className="flex items-center justify-center w-full gap-x-2">
111119
{!isEmbed && (
112-
<Popover open={open} onOpenChange={setOpen}>
120+
<Popover open={open} onOpenChange={handleOpenChange}>
113121
<PopoverTrigger asChild>
114122
<Button
115123
variant="ghost"
@@ -151,3 +159,8 @@ export const ChatTopBar = ({ isEmbed = false }: ChatTopBarProps) => {
151159
</div>
152160
);
153161
};
162+
163+
CommandItems.displayName = 'CommandItems';
164+
ChatTopBarComponent.displayName = 'ChatTopBar';
165+
166+
export const ChatTopBar = memo(ChatTopBarComponent);

0 commit comments

Comments
 (0)