import React, { useCallback, useMemo } from 'react'; import { Grid, Image, Box, Button, Flex, useTheme, IconButton, GridItem } from '@chakra-ui/react'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useEditTitle } from '@/web/common/hooks/useEditTitle'; import Avatar from '@fastgpt/web/components/common/Avatar'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useTranslation } from 'next-i18next'; import MyMenu from '@fastgpt/web/components/common/MyMenu'; import { useContextSelector } from 'use-context-selector'; import { ChatContext } from '@/web/core/chat/context/chatContext'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { formatTimeToChatTime } from '@fastgpt/global/common/string/time'; import { ChatItemContext } from '@/web/core/chat/context/chatItemContext'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm'; import { ChatSettingContext } from '@/web/core/chat/context/chatSettingContext'; import { ChatSidebarPaneEnum, DEFAULT_LOGO_BANNER_URL } from '@/pageComponents/chat/constants'; import MyDivider from '@fastgpt/web/components/common/MyDivider'; import { useMemoizedFn } from 'ahooks'; import { useUserStore } from '@/web/support/user/useUserStore'; import UserAvatarPopover from '@/pageComponents/chat/UserAvatarPopover'; import { usePathname } from 'next/navigation'; import type { ChatSettingSchema } from '@fastgpt/global/core/chat/setting/type'; type HistoryItemType = { id: string; title: string; customTitle?: string; top?: boolean; updateTime: Date; }; const ChatHistorySlider = ({ confirmClearText, customSliderTitle, pane, chatSettings, onPaneChange }: { confirmClearText: string; customSliderTitle?: string; pane: ChatSidebarPaneEnum; chatSettings: ChatSettingSchema | undefined; onPaneChange?: (pane: ChatSidebarPaneEnum) => void; }) => { const theme = useTheme(); const pathname = usePathname(); const { t } = useTranslation(); const { isPc } = useSystem(); const { userInfo } = useUserStore(); const { chatId: activeChatId, setChatId } = useChatStore(); const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId); const ScrollData = useContextSelector(ChatContext, (v) => v.ScrollData); const histories = useContextSelector(ChatContext, (v) => v.histories); const onDelHistory = useContextSelector(ChatContext, (v) => v.onDelHistory); const onClearHistory = useContextSelector(ChatContext, (v) => v.onClearHistories); const onUpdateHistory = useContextSelector(ChatContext, (v) => v.onUpdateHistory); const onCloseSlider = useContextSelector(ChatContext, (v) => v.onCloseSlider); const appName = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.name); const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.avatar); const setCiteModalData = useContextSelector(ChatItemContext, (v) => v.setCiteModalData); const isActivePane = useCallback((active: ChatSidebarPaneEnum) => active === pane, [pane]); const isShare = pathname === '/chat/share'; const concatHistory = useMemo(() => { const formatHistories: HistoryItemType[] = histories.map((item) => { return { id: item.chatId, title: item.title, customTitle: item.customTitle, top: item.top, updateTime: item.updateTime }; }); const newChat: HistoryItemType = { id: activeChatId, title: t('common:core.chat.New Chat'), updateTime: new Date() }; const activeChat = histories.find((item) => item.chatId === activeChatId); return !activeChat ? [newChat].concat(formatHistories) : formatHistories; }, [activeChatId, histories, t]); // custom title edit const { onOpenModal, EditModal: EditTitleModal } = useEditTitle({ title: t('common:core.chat.Custom History Title'), placeholder: t('common:core.chat.Custom History Title Description') }); return ( {isPc && ( {!customSliderTitle && } {customSliderTitle || appName} )} {!isPc && ( <> banner {!isShare && ( <> { onPaneChange?.(ChatSidebarPaneEnum.HOME); onCloseSlider(); setChatId(); }} > {t('chat:sidebar.home')} { onPaneChange?.(ChatSidebarPaneEnum.TEAM_APPS); onCloseSlider(); }} > {t('chat:sidebar.team_apps')} )} )} {/* menu */} {!isPc && ( {t('common:core.chat.History')} )} {/* Clear */} {isPc && histories.length > 0 && ( } /> } type="delete" content={confirmClearText} onConfirm={() => onClearHistory()} /> )} {/* chat history */} <> {concatHistory.map((item, i) => ( { onChangeChatId(item.id); setCiteModalData(undefined); } })} {...(i !== concatHistory.length - 1 && { mb: '8px' })} > {item.customTitle || item.title} {!!item.id && ( {t(formatTimeToChatTime(item.updateTime) as any).replace('#', ':')} } aria-label={''} /> } menuList={[ { children: [ { label: item.top ? t('common:core.chat.Unpin') : t('common:core.chat.Pin'), icon: 'core/chat/setTopLight', onClick: () => { onUpdateHistory({ chatId: item.id, top: !item.top }); } }, { label: t('common:custom_title'), icon: 'common/customTitleLight', onClick: () => { onOpenModal({ defaultVal: item.customTitle || item.title, onSuccess: (e) => onUpdateHistory({ chatId: item.id, customTitle: e }) }); } }, { label: t('common:Delete'), icon: 'delete', onClick: () => { onDelHistory(item.id); if (item.id === activeChatId) { onChangeChatId(); setCiteModalData(undefined); } }, type: 'danger' } ] } ]} /> )} ))} {!isPc && ( {userInfo?.username} {!isShare && ( { onPaneChange?.(ChatSidebarPaneEnum.SETTING); onCloseSlider(); }} > )} )} ); }; export default ChatHistorySlider;