diff --git a/src/app/chat/Background/index.tsx b/src/app/chat/Background/index.tsx deleted file mode 100644 index f25e098a..00000000 --- a/src/app/chat/Background/index.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useGlobalStore } from '@/store/global'; -import { useSettingStore } from '@/store/setting'; - -import { useStyles } from './style'; - -const Background = () => { - const { styles } = useStyles(); - const backgroundUrl = useGlobalStore((s) => s.backgroundUrl); - const backgroundEffect = useSettingStore((s) => s.config.backgroundEffect); - - if (backgroundUrl) { - return ( -
- ); - } - - return backgroundEffect === 'glow' ?
: null; -}; - -export default Background; diff --git a/src/app/chat/CameraMode/Background/index.tsx b/src/app/chat/CameraMode/Background/index.tsx new file mode 100644 index 00000000..e327a524 --- /dev/null +++ b/src/app/chat/CameraMode/Background/index.tsx @@ -0,0 +1,24 @@ +import { useGlobalStore } from '@/store/global'; + +const Background = () => { + const backgroundUrl = useGlobalStore((s) => s.backgroundUrl); + + return backgroundUrl ? ( +
+ ) : null; +}; + +export default Background; diff --git a/src/app/chat/ViewerMode/ChatDialog/index.tsx b/src/app/chat/CameraMode/ChatDialog/index.tsx similarity index 100% rename from src/app/chat/ViewerMode/ChatDialog/index.tsx rename to src/app/chat/CameraMode/ChatDialog/index.tsx diff --git a/src/app/chat/ViewerMode/ChatDialog/style.ts b/src/app/chat/CameraMode/ChatDialog/style.ts similarity index 100% rename from src/app/chat/ViewerMode/ChatDialog/style.ts rename to src/app/chat/CameraMode/ChatDialog/style.ts diff --git a/src/app/chat/CameraMode/Operation/actions/CallOff.tsx b/src/app/chat/CameraMode/Operation/actions/CallOff.tsx new file mode 100644 index 00000000..4112faf7 --- /dev/null +++ b/src/app/chat/CameraMode/Operation/actions/CallOff.tsx @@ -0,0 +1,31 @@ +import { ActionIcon } from '@lobehub/ui'; +import { useTheme } from 'antd-style'; +import { Phone } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; + +import { DESKTOP_OPERATION_ICON_SIZE } from '@/constants/token'; +import { useSessionStore } from '@/store/session'; + +const CallOff = () => { + const [setChatMode] = useSessionStore((s) => [s.setChatMode]); + const setVoiceOn = useSessionStore((s) => s.setVoiceOn); + const theme = useTheme(); + const { t } = useTranslation('chat'); + return ( + { + setVoiceOn(false); + setChatMode('chat'); + }} + title={t('callOff')} + size={DESKTOP_OPERATION_ICON_SIZE} + style={{ + backgroundColor: theme.colorError, + color: theme.colorWhite, + }} + /> + ); +}; + +export default CallOff; diff --git a/src/app/chat/ViewerMode/MessageInput/actions/Record.tsx b/src/app/chat/CameraMode/Operation/actions/Record.tsx similarity index 68% rename from src/app/chat/ViewerMode/MessageInput/actions/Record.tsx rename to src/app/chat/CameraMode/Operation/actions/Record.tsx index fd964983..f6c66378 100644 --- a/src/app/chat/ViewerMode/MessageInput/actions/Record.tsx +++ b/src/app/chat/CameraMode/Operation/actions/Record.tsx @@ -1,14 +1,17 @@ import { ActionIcon } from '@lobehub/ui'; +import { useTheme } from 'antd-style'; import { Mic } from 'lucide-react'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { DESKTOP_OPERATION_ICON_SIZE_LARGE } from '@/constants/token'; import { useSpeechRecognition } from '@/hooks/useSpeechRecognition'; import { useSessionStore } from '@/store/session'; const Record = () => { const [sendMessage, setMessageInput] = useSessionStore((s) => [s.sendMessage, s.setMessageInput]); const { t } = useTranslation('chat'); + const theme = useTheme(); const handleMessageInput = useCallback( (result: string, isFinal: boolean) => { setMessageInput(result); @@ -25,7 +28,16 @@ const Record = () => { }); return ( - + ); }; diff --git a/src/app/chat/CameraMode/Operation/actions/Setting.tsx b/src/app/chat/CameraMode/Operation/actions/Setting.tsx new file mode 100644 index 00000000..f7cc3cd3 --- /dev/null +++ b/src/app/chat/CameraMode/Operation/actions/Setting.tsx @@ -0,0 +1,25 @@ +import { ActionIcon } from '@lobehub/ui'; +import { useTheme } from 'antd-style'; +import { Box } from 'lucide-react'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { DESKTOP_OPERATION_ICON_SIZE } from '@/constants/token'; +import { useGlobalStore } from '@/store/global'; + +export default () => { + const [toggleChatSideBar] = useGlobalStore((s) => [s.toggleChatSideBar]); + const theme = useTheme(); + const { t } = useTranslation('dance'); + return ( + toggleChatSideBar()} + title={t('menu')} + size={DESKTOP_OPERATION_ICON_SIZE} + style={{ + backgroundColor: theme.colorBgElevated, + }} + /> + ); +}; diff --git a/src/app/chat/CameraMode/Operation/index.tsx b/src/app/chat/CameraMode/Operation/index.tsx new file mode 100644 index 00000000..684ee458 --- /dev/null +++ b/src/app/chat/CameraMode/Operation/index.tsx @@ -0,0 +1,20 @@ +'use client'; + +import { memo } from 'react'; +import { Flexbox } from 'react-layout-kit'; + +import CallOff from './actions/CallOff'; +import Record from './actions/Record'; +import Setting from './actions/Setting'; + +const VoiceOperation = memo(() => { + return ( + + + + + + ); +}); + +export default VoiceOperation; diff --git a/src/app/chat/ChatInfo/BackGroundList/index.tsx b/src/app/chat/CameraMode/Settings/BackGroundList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/BackGroundList/index.tsx rename to src/app/chat/CameraMode/Settings/BackGroundList/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/SubscribeButton.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/SubscribeButton.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/SubscribeButton.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/SubscribeButton.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/UnSubscribeButton.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/UnSubscribeButton.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/UnSubscribeButton.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/UnSubscribeButton.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/Card/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/Card/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/AudioUpload.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/AudioUpload.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/AudioUpload.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/AudioUpload.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/CameraUpload.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/CameraUpload.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/CameraUpload.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/CameraUpload.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/CoverImageUpload/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/CoverImageUpload/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/CoverImageUpload/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/CoverImageUpload/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceIdInput/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceIdInput/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceIdInput/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceIdInput/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceName.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceName.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceName.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/DanceName.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/ReadMe/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/ReadMe/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/ReadMe/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/ReadMe/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/SrcUpload.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/SrcUpload.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/SrcUpload.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/SrcUpload.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/CreateDanceModal/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/CreateDanceModal/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/List/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/List/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/List/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/List/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/style.ts b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/style.ts similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/Market/style.ts rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/Market/style.ts diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/DanceMarketModal/style.ts b/src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/style.ts similarity index 100% rename from src/app/chat/ChatInfo/DanceList/DanceMarketModal/style.ts rename to src/app/chat/CameraMode/Settings/DanceList/DanceMarketModal/style.ts diff --git a/src/app/chat/ChatInfo/DanceList/Item/Actions.tsx b/src/app/chat/CameraMode/Settings/DanceList/Item/Actions.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/Item/Actions.tsx rename to src/app/chat/CameraMode/Settings/DanceList/Item/Actions.tsx diff --git a/src/app/chat/ChatInfo/DanceList/Item/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/Item/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/Item/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/Item/index.tsx diff --git a/src/app/chat/ChatInfo/DanceList/Item/style.ts b/src/app/chat/CameraMode/Settings/DanceList/Item/style.ts similarity index 100% rename from src/app/chat/ChatInfo/DanceList/Item/style.ts rename to src/app/chat/CameraMode/Settings/DanceList/Item/style.ts diff --git a/src/app/chat/ChatInfo/DanceList/index.tsx b/src/app/chat/CameraMode/Settings/DanceList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/DanceList/index.tsx rename to src/app/chat/CameraMode/Settings/DanceList/index.tsx diff --git a/src/app/chat/ChatInfo/MotionList/ActionList/index.tsx b/src/app/chat/CameraMode/Settings/MotionList/ActionList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/MotionList/ActionList/index.tsx rename to src/app/chat/CameraMode/Settings/MotionList/ActionList/index.tsx diff --git a/src/app/chat/ChatInfo/MotionList/SideBar/index.tsx b/src/app/chat/CameraMode/Settings/MotionList/SideBar/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/MotionList/SideBar/index.tsx rename to src/app/chat/CameraMode/Settings/MotionList/SideBar/index.tsx diff --git a/src/app/chat/ChatInfo/MotionList/index.tsx b/src/app/chat/CameraMode/Settings/MotionList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/MotionList/index.tsx rename to src/app/chat/CameraMode/Settings/MotionList/index.tsx diff --git a/src/app/chat/ChatInfo/PostureList/ActionList/index.tsx b/src/app/chat/CameraMode/Settings/PostureList/ActionList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/PostureList/ActionList/index.tsx rename to src/app/chat/CameraMode/Settings/PostureList/ActionList/index.tsx diff --git a/src/app/chat/ChatInfo/PostureList/SideBar/filters/CategoryFilter.tsx b/src/app/chat/CameraMode/Settings/PostureList/SideBar/filters/CategoryFilter.tsx similarity index 100% rename from src/app/chat/ChatInfo/PostureList/SideBar/filters/CategoryFilter.tsx rename to src/app/chat/CameraMode/Settings/PostureList/SideBar/filters/CategoryFilter.tsx diff --git a/src/app/chat/ChatInfo/PostureList/SideBar/filters/GenderFilter.tsx b/src/app/chat/CameraMode/Settings/PostureList/SideBar/filters/GenderFilter.tsx similarity index 100% rename from src/app/chat/ChatInfo/PostureList/SideBar/filters/GenderFilter.tsx rename to src/app/chat/CameraMode/Settings/PostureList/SideBar/filters/GenderFilter.tsx diff --git a/src/app/chat/ChatInfo/PostureList/SideBar/index.tsx b/src/app/chat/CameraMode/Settings/PostureList/SideBar/index.tsx similarity index 89% rename from src/app/chat/ChatInfo/PostureList/SideBar/index.tsx rename to src/app/chat/CameraMode/Settings/PostureList/SideBar/index.tsx index e80dcd59..6cba985e 100644 --- a/src/app/chat/ChatInfo/PostureList/SideBar/index.tsx +++ b/src/app/chat/CameraMode/Settings/PostureList/SideBar/index.tsx @@ -3,12 +3,13 @@ import { ReactNode, memo } from 'react'; import { useTranslation } from 'react-i18next'; import { Flexbox } from 'react-layout-kit'; -import CategoryFilter from '@/app/chat/ChatInfo/PostureList/SideBar/filters/CategoryFilter'; -import GenderFilter from '@/app/chat/ChatInfo/PostureList/SideBar/filters/GenderFilter'; import Header from '@/components/Header'; import { GenderEnum } from '@/types/agent'; import { PostureCategoryEnum } from '@/types/touch'; +import CategoryFilter from './filters/CategoryFilter'; +import GenderFilter from './filters/GenderFilter'; + interface IndexProps { categoryOptions: { icon: ReactNode; label: string; value: PostureCategoryEnum | undefined }[]; currentCategory: PostureCategoryEnum | undefined; diff --git a/src/app/chat/ChatInfo/PostureList/index.tsx b/src/app/chat/CameraMode/Settings/PostureList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/PostureList/index.tsx rename to src/app/chat/CameraMode/Settings/PostureList/index.tsx diff --git a/src/app/chat/ChatInfo/PostureList/style.ts b/src/app/chat/CameraMode/Settings/PostureList/style.ts similarity index 100% rename from src/app/chat/ChatInfo/PostureList/style.ts rename to src/app/chat/CameraMode/Settings/PostureList/style.ts diff --git a/src/app/chat/ChatInfo/StageList/index.tsx b/src/app/chat/CameraMode/Settings/StageList/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/StageList/index.tsx rename to src/app/chat/CameraMode/Settings/StageList/index.tsx diff --git a/src/app/chat/ChatInfo/index.tsx b/src/app/chat/CameraMode/Settings/index.tsx similarity index 79% rename from src/app/chat/ChatInfo/index.tsx rename to src/app/chat/CameraMode/Settings/index.tsx index 6d37796c..2bd0b4cd 100644 --- a/src/app/chat/ChatInfo/index.tsx +++ b/src/app/chat/CameraMode/Settings/index.tsx @@ -1,7 +1,8 @@ 'use client'; -import { DraggablePanel, TabsNav } from '@lobehub/ui'; +import { ActionIcon, DraggablePanel, TabsNav } from '@lobehub/ui'; import { createStyles } from 'antd-style'; +import { X } from 'lucide-react'; import dynamic from 'next/dynamic'; import { rgba } from 'polished'; import React, { useState } from 'react'; @@ -20,11 +21,6 @@ const Loading = () => ( ); -const ChatList = dynamic(() => import('./ChatList'), { - ssr: false, - loading: Loading, -}); - const BackGround = dynamic(() => import('./BackGroundList'), { ssr: false, loading: Loading, @@ -56,7 +52,7 @@ const useStyles = createStyles(({ css, token }) => ({ display: flex; flex-direction: column; - background-color: ${rgba(token.colorBgLayout, 0.2)}; + background-color: ${rgba(token.colorBgLayout, 0.8)}; backdrop-filter: saturate(180%) blur(8px); `, header: css` @@ -66,6 +62,15 @@ const useStyles = createStyles(({ css, token }) => ({ player: css` min-width: 480px; `, + closeIcon: css` + cursor: pointer; + margin-right: 12px; + color: ${token.colorTextSecondary}; + + &:hover { + color: ${token.colorText}; + } + `, })); export default () => { @@ -74,7 +79,7 @@ export default () => { s.setChatSidebar, ]); - const [tab, setTab] = useState(Tab.ChatList); + const [tab, setTab] = useState(Tab.DanceList); const { t } = useTranslation('chat'); const { styles } = useStyles(); @@ -84,7 +89,7 @@ export default () => { classNames={{ content: styles.content }} minWidth={CHAT_INFO_WIDTH} maxWidth={CHAT_INFO_MAX_WIDTH} - mode={'fixed'} + mode={'float'} onExpandChange={(expand) => { setChatSidebar(expand); }} @@ -93,12 +98,20 @@ export default () => { > { + setChatSidebar(false); + }} + style={{ marginLeft: 12 }} + /> + ), + }} items={[ - { - label: t('info.chat'), - key: Tab.ChatList, - }, { label: t('info.dance'), key: Tab.DanceList, @@ -125,8 +138,7 @@ export default () => { }} /> - - {tab === Tab.ChatList && } + {tab === Tab.DanceList && } {tab === Tab.Motions && } {tab === Tab.Posture && } diff --git a/src/app/chat/ChatInfo/type.ts b/src/app/chat/CameraMode/Settings/type.ts similarity index 86% rename from src/app/chat/ChatInfo/type.ts rename to src/app/chat/CameraMode/Settings/type.ts index f21b04d6..109388ba 100644 --- a/src/app/chat/ChatInfo/type.ts +++ b/src/app/chat/CameraMode/Settings/type.ts @@ -1,6 +1,5 @@ export enum Tab { Background = 'background', - ChatList = 'chats', DanceList = 'dances', Motions = 'motions', Posture = 'posture', diff --git a/src/app/chat/CameraMode/index.tsx b/src/app/chat/CameraMode/index.tsx new file mode 100644 index 00000000..4ff52cfb --- /dev/null +++ b/src/app/chat/CameraMode/index.tsx @@ -0,0 +1,47 @@ +'use client'; + +import classNames from 'classnames'; +import { isEqual } from 'lodash-es'; +import React, { memo } from 'react'; +import { Flexbox } from 'react-layout-kit'; + +import ChatDialog from '@/app/chat/CameraMode/ChatDialog'; +import { HEADER_HEIGHT } from '@/constants/token'; +import AgentViewer from '@/features/AgentViewer'; +import { sessionSelectors, useSessionStore } from '@/store/session'; + +import Background from './Background'; +import Operation from './Operation'; +import Settings from './Settings'; +import { useStyles } from './style'; + +export default memo(() => { + const { styles } = useStyles(); + const [currentAgent, interactive] = useSessionStore( + (s) => [sessionSelectors.currentAgent(s), s.interactive], + isEqual, + ); + + return ( + + + {currentAgent ? ( +
+ +
+ ) : null} + + + + + + + + +
+ ); +}); diff --git a/src/app/chat/ViewerMode/style.ts b/src/app/chat/CameraMode/style.ts similarity index 60% rename from src/app/chat/ViewerMode/style.ts rename to src/app/chat/CameraMode/style.ts index f59afe7b..c0fe47c6 100644 --- a/src/app/chat/ViewerMode/style.ts +++ b/src/app/chat/CameraMode/style.ts @@ -1,8 +1,6 @@ import { createStyles } from 'antd-style'; -import { CHAT_HEADER_HEIGHT, CHAT_INPUT_WIDTH } from '@/constants/token'; - -export const useStyles = createStyles(({ css, token }) => ({ +export const useStyles = createStyles(({ css, token, responsive }) => ({ viewer: css` position: absolute; top: 0; @@ -16,21 +14,19 @@ export const useStyles = createStyles(({ css, token }) => ({ max-width: 100vw; padding: 0 12px; - @media (max-width: 768px) { + ${responsive.mobile} { width: 100%; } `, dialog: css` z-index: 2; - margin: ${CHAT_HEADER_HEIGHT}px auto 0; + margin: ${token.marginLG}px auto 0; `, docker: css` z-index: 2; width: 100%; + margin-bottom: ${token.marginLG}px; padding: ${token.paddingSM}px; `, - input: css` - width: ${CHAT_INPUT_WIDTH}; - `, mask: css``, })); diff --git a/src/app/chat/ChatHeader/actions/ToggleChatSideBar.tsx b/src/app/chat/ChatHeader/actions/ToggleChatSideBar.tsx deleted file mode 100644 index 97d4462e..00000000 --- a/src/app/chat/ChatHeader/actions/ToggleChatSideBar.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { ActionIcon } from '@lobehub/ui'; -import { PanelRightClose, PanelRightOpen } from 'lucide-react'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { DESKTOP_HEADER_ICON_SIZE } from '@/constants/token'; -import { useGlobalStore } from '@/store/global'; - -export default () => { - const [showChatSidebar, toggleChatSideBar] = useGlobalStore((s) => [ - s.showChatSidebar, - s.toggleChatSideBar, - ]); - const { t } = useTranslation('common'); - return ( - toggleChatSideBar()} - title={t('sideBar')} - size={DESKTOP_HEADER_ICON_SIZE} - /> - ); -}; diff --git a/src/app/chat/ChatHeader/actions/Voice.tsx b/src/app/chat/ChatHeader/actions/Voice.tsx deleted file mode 100644 index 8858f5ee..00000000 --- a/src/app/chat/ChatHeader/actions/Voice.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { ActionIcon } from '@lobehub/ui'; -import { createStyles } from 'antd-style'; -import classNames from 'classnames'; -import { Volume2, VolumeXIcon } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; - -import { DESKTOP_HEADER_ICON_SIZE } from '@/constants/token'; -import { toggleVoice } from '@/services/chat'; -import { useSessionStore } from '@/store/session'; - -const useStyles = createStyles(({ token, css }) => ({ - voice: css` - cursor: pointer; - transition: color 0.3s; - `, - voiceOn: css` - color: ${token.colorLinkActive}; - `, -})); - -const VoiceSwitch = () => { - const { styles } = useStyles(); - const [voiceOn] = useSessionStore((s) => [s.voiceOn]); - const { t } = useTranslation('chat'); - return ( - - ); -}; - -export default VoiceSwitch; diff --git a/src/app/chat/ChatInfo/ChatList/SkeletonList.tsx b/src/app/chat/ChatInfo/ChatList/SkeletonList.tsx deleted file mode 100644 index d3ec5e86..00000000 --- a/src/app/chat/ChatInfo/ChatList/SkeletonList.tsx +++ /dev/null @@ -1,51 +0,0 @@ -'use client'; - -import { Skeleton } from 'antd'; -import { createStyles } from 'antd-style'; -import { memo } from 'react'; -import { Flexbox } from 'react-layout-kit'; - -const useStyles = createStyles(({ css, prefixCls }) => ({ - message: css` - display: flex; - gap: 12px; - .${prefixCls}-skeleton-header { - padding: 0; - } - `, - user: css` - flex-direction: row-reverse; - - .${prefixCls}-skeleton-paragraph { - display: flex; - flex-direction: column; - align-items: flex-end; - } - `, -})); -interface SkeletonListProps { - mobile?: boolean; -} -const SkeletonList = memo(({ mobile }) => { - const { cx, styles } = useStyles(); - - return ( - - - - - ); -}); -export default SkeletonList; diff --git a/src/app/chat/ChatHeader/AgentMeta/index.tsx b/src/app/chat/ChatMode/ChatHeader/AgentMeta/index.tsx similarity index 92% rename from src/app/chat/ChatHeader/AgentMeta/index.tsx rename to src/app/chat/ChatMode/ChatHeader/AgentMeta/index.tsx index 7253324a..f3fe08b3 100644 --- a/src/app/chat/ChatHeader/AgentMeta/index.tsx +++ b/src/app/chat/ChatMode/ChatHeader/AgentMeta/index.tsx @@ -4,7 +4,6 @@ import React from 'react'; import useSessionContext from '@/hooks/useSessionContext'; -import ModelSwitchPanel from './ModelSwitchPanel'; import { useStyles } from './style'; interface AgentMetaProps { @@ -28,7 +27,6 @@ export default (props: AgentMetaProps) => {
{name} -
diff --git a/src/app/chat/ChatHeader/AgentMeta/style.ts b/src/app/chat/ChatMode/ChatHeader/AgentMeta/style.ts similarity index 95% rename from src/app/chat/ChatHeader/AgentMeta/style.ts rename to src/app/chat/ChatMode/ChatHeader/AgentMeta/style.ts index 0d67b0f7..01659d40 100644 --- a/src/app/chat/ChatHeader/AgentMeta/style.ts +++ b/src/app/chat/ChatMode/ChatHeader/AgentMeta/style.ts @@ -10,7 +10,7 @@ export const useStyles = createStyles(({ css, token }) => ({ line-height: 1; `, desc: css` - width: 480px; + max-width: 320px; margin-top: ${token.marginXXS}px; font-size: ${token.fontSizeSM}px; diff --git a/src/app/chat/ChatHeader/actions/Interactive.tsx b/src/app/chat/ChatMode/ChatHeader/actions/Interactive.tsx similarity index 100% rename from src/app/chat/ChatHeader/actions/Interactive.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/Interactive.tsx diff --git a/src/app/chat/ChatHeader/actions/ShareButton/ChatList.tsx b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/ChatList.tsx similarity index 100% rename from src/app/chat/ChatHeader/actions/ShareButton/ChatList.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/ChatList.tsx diff --git a/src/app/chat/ChatHeader/actions/ShareButton/Preview.tsx b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/Preview.tsx similarity index 94% rename from src/app/chat/ChatHeader/actions/ShareButton/Preview.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/Preview.tsx index d9b72472..797c2b6e 100644 --- a/src/app/chat/ChatHeader/actions/ShareButton/Preview.tsx +++ b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/Preview.tsx @@ -5,8 +5,8 @@ import { Flexbox } from 'react-layout-kit'; import { DEFAULT_CHAT_MODEL } from '@/constants/agent'; import useSessionContext from '@/hooks/useSessionContext'; +import { siteUrl } from '@/server/utils/url'; -import pkg from '../../../../../../package.json'; import ChatList from './ChatList'; import { useStyles } from './style'; import { FieldType } from './type'; @@ -41,7 +41,7 @@ const Preview = memo( {withFooter ? ( -
{pkg.homepage}
+
{siteUrl}
) : (
diff --git a/src/app/chat/ChatHeader/actions/ShareButton/ShareModal.tsx b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/ShareModal.tsx similarity index 100% rename from src/app/chat/ChatHeader/actions/ShareButton/ShareModal.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/ShareModal.tsx diff --git a/src/app/chat/ChatHeader/actions/ShareButton/index.tsx b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/index.tsx similarity index 100% rename from src/app/chat/ChatHeader/actions/ShareButton/index.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/index.tsx diff --git a/src/app/chat/ChatHeader/actions/ShareButton/style.ts b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/style.ts similarity index 100% rename from src/app/chat/ChatHeader/actions/ShareButton/style.ts rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/style.ts diff --git a/src/app/chat/ChatHeader/actions/ShareButton/type.ts b/src/app/chat/ChatMode/ChatHeader/actions/ShareButton/type.ts similarity index 100% rename from src/app/chat/ChatHeader/actions/ShareButton/type.ts rename to src/app/chat/ChatMode/ChatHeader/actions/ShareButton/type.ts diff --git a/src/app/chat/ChatHeader/actions/ToggleSessionList.tsx b/src/app/chat/ChatMode/ChatHeader/actions/ToggleSessionList.tsx similarity index 100% rename from src/app/chat/ChatHeader/actions/ToggleSessionList.tsx rename to src/app/chat/ChatMode/ChatHeader/actions/ToggleSessionList.tsx diff --git a/src/app/chat/ChatHeader/index.tsx b/src/app/chat/ChatMode/ChatHeader/index.tsx similarity index 88% rename from src/app/chat/ChatHeader/index.tsx rename to src/app/chat/ChatMode/ChatHeader/index.tsx index ca63266f..90e5e1fc 100644 --- a/src/app/chat/ChatHeader/index.tsx +++ b/src/app/chat/ChatMode/ChatHeader/index.tsx @@ -7,9 +7,7 @@ import React from 'react'; import { Flexbox } from 'react-layout-kit'; import ShareButton from './actions/ShareButton'; -import ToggleChatSideBar from './actions/ToggleChatSideBar'; import ToggleSessionList from './actions/ToggleSessionList'; -import Voice from './actions/Voice'; import { useStyles } from './style'; const AgentMeta = dynamic(() => import('./AgentMeta'), { @@ -48,9 +46,7 @@ export default (props: Props) => {
- -
); diff --git a/src/app/chat/ChatHeader/style.ts b/src/app/chat/ChatMode/ChatHeader/style.ts similarity index 100% rename from src/app/chat/ChatHeader/style.ts rename to src/app/chat/ChatMode/ChatHeader/style.ts diff --git a/src/app/chat/ChatInfo/ChatList/AutoScroll.tsx b/src/app/chat/ChatMode/ChatList/AutoScroll.tsx similarity index 78% rename from src/app/chat/ChatInfo/ChatList/AutoScroll.tsx rename to src/app/chat/ChatMode/ChatList/AutoScroll.tsx index f95064f4..69242b87 100644 --- a/src/app/chat/ChatInfo/ChatList/AutoScroll.tsx +++ b/src/app/chat/ChatMode/ChatList/AutoScroll.tsx @@ -6,14 +6,15 @@ import BackBottom from './BackBottom'; interface AutoScrollProps { atBottom: boolean; + isScrolling: boolean; onScrollToBottom: (type: 'auto' | 'click') => void; } -const AutoScroll = memo(({ atBottom, onScrollToBottom }) => { +const AutoScroll = memo(({ atBottom, isScrolling, onScrollToBottom }) => { const trackVisibility = useSessionStore((s) => !!s.chatLoadingId); const str = useSessionStore(sessionSelectors.currentChatsString); useEffect(() => { - if (atBottom && trackVisibility) { + if (atBottom && trackVisibility && !isScrolling) { onScrollToBottom?.('auto'); } }, [atBottom, trackVisibility, str]); diff --git a/src/app/chat/ChatInfo/ChatList/BackBottom/index.tsx b/src/app/chat/ChatMode/ChatList/BackBottom/index.tsx similarity index 100% rename from src/app/chat/ChatInfo/ChatList/BackBottom/index.tsx rename to src/app/chat/ChatMode/ChatList/BackBottom/index.tsx diff --git a/src/app/chat/ChatInfo/ChatList/BackBottom/style.ts b/src/app/chat/ChatMode/ChatList/BackBottom/style.ts similarity index 100% rename from src/app/chat/ChatInfo/ChatList/BackBottom/style.ts rename to src/app/chat/ChatMode/ChatList/BackBottom/style.ts diff --git a/src/app/chat/ChatMode/ChatList/SkeletonList.tsx b/src/app/chat/ChatMode/ChatList/SkeletonList.tsx new file mode 100644 index 00000000..0cfc04a0 --- /dev/null +++ b/src/app/chat/ChatMode/ChatList/SkeletonList.tsx @@ -0,0 +1,74 @@ +'use client'; + +import { Skeleton } from 'antd'; +import { createStyles } from 'antd-style'; +import { memo } from 'react'; +import { Flexbox } from 'react-layout-kit'; + +import { CHAT_INPUT_WIDTH } from '@/constants/token'; + +const useStyles = createStyles(({ css, prefixCls, responsive }) => ({ + message: css` + display: flex; + gap: 12px; + + width: ${CHAT_INPUT_WIDTH}; + min-width: 480px; + max-width: 100vw; + + .${prefixCls}-skeleton-header { + padding: 0; + } + + ${responsive.mobile} { + width: 100%; + } + `, + user: css` + flex-direction: row-reverse; + width: ${CHAT_INPUT_WIDTH}; + min-width: 480px; + max-width: 100vw; + + .${prefixCls}-skeleton-paragraph { + display: flex; + flex-direction: column; + align-items: flex-end; + } + + ${responsive.mobile} { + width: 100%; + } + `, +})); +interface SkeletonListProps { + count?: number; + mobile?: boolean; +} +const SkeletonList = memo(({ count = 3, mobile }) => { + const { cx, styles } = useStyles(); + + return ( + + {Array.from({ length: count }).map((_, index) => ( +
+ + +
+ ))} +
+ ); +}); +export default SkeletonList; diff --git a/src/app/chat/ChatInfo/ChatList/VirtualizedList.tsx b/src/app/chat/ChatMode/ChatList/VirtualizedList.tsx similarity index 68% rename from src/app/chat/ChatInfo/ChatList/VirtualizedList.tsx rename to src/app/chat/ChatMode/ChatList/VirtualizedList.tsx index 8757262c..aeb889eb 100644 --- a/src/app/chat/ChatInfo/ChatList/VirtualizedList.tsx +++ b/src/app/chat/ChatMode/ChatList/VirtualizedList.tsx @@ -1,28 +1,15 @@ -import { Space } from 'antd'; import classNames from 'classnames'; import isEqual from 'fast-deep-equal'; -import React, { memo, useEffect, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; +import React, { memo, useCallback, useEffect, useRef, useState } from 'react'; import { Flexbox } from 'react-layout-kit'; import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'; -import Header from '@/components/Header'; import Item from '@/features/ChatItem'; import { sessionSelectors, useSessionStore } from '@/store/session'; -import History from './Actions/History'; -import TokenMini from './Actions/TokenMini'; import AutoScroll from './AutoScroll'; import { useStyles } from './style'; -const itemContent = (index: number, id: string) => { - return index === 0 ? ( -
- ) : ( - - ); -}; - interface VirtualizedListProps { className?: string; mobile?: boolean; @@ -31,8 +18,8 @@ interface VirtualizedListProps { const VirtualizedList = memo(({ mobile, className, style }) => { const virtuosoRef = useRef(null); const [atBottom, setAtBottom] = useState(true); + const [isScrolling, setIsScrolling] = useState(false); const { styles } = useStyles(); - const { t } = useTranslation('chat'); const data = useSessionStore( (s) => ['empty', ...sessionSelectors.currentChatIDsWithGreetingMessage(s)], @@ -40,34 +27,47 @@ const VirtualizedList = memo(({ mobile, className, style } ); const [id, chatLoading] = useSessionStore((s) => [s.activeId, !!s.chatLoadingId]); + const prevDataLengthRef = useRef(data.length); + + const getFollowOutput = useCallback(() => { + const newFollowOutput = data.length > prevDataLengthRef.current ? 'auto' : false; + prevDataLengthRef.current = data.length; + return newFollowOutput; + }, [data.length]); + useEffect(() => { if (virtuosoRef.current) { virtuosoRef.current.scrollToIndex({ align: 'end', behavior: 'auto', index: 'LAST' }); } }, [id]); - // overscan should be 1.5 times the height of the window - const overscan = typeof window !== 'undefined' ? window.innerHeight * 1.5 : 0; + const itemContent = useCallback( + (index: number, id: string) => { + // if (id === WELCOME_GUIDE_CHAT_ID) return ; + + return index === 0 ? ( +
+ ) : ( + + ); + }, + [mobile], + ); + + // overscan should be 3 times the height of the window + const overscan = typeof window !== 'undefined' ? window.innerHeight * 3 : 0; // @ts-ignore return chatLoading && data.length === 2 ? null : ( -
- - - - } - /> item} data={data} - followOutput={'auto'} + followOutput={getFollowOutput} + increaseViewportBy={overscan} + isScrolling={setIsScrolling} initialTopMostItemIndex={data?.length - 1} itemContent={itemContent} overscan={overscan} @@ -75,6 +75,7 @@ const VirtualizedList = memo(({ mobile, className, style } /> { const virtuoso = virtuosoRef.current; switch (type) { diff --git a/src/app/chat/ChatInfo/ChatList/index.tsx b/src/app/chat/ChatMode/ChatList/index.tsx similarity index 57% rename from src/app/chat/ChatInfo/ChatList/index.tsx rename to src/app/chat/ChatMode/ChatList/index.tsx index 656cc090..64a3918a 100644 --- a/src/app/chat/ChatInfo/ChatList/index.tsx +++ b/src/app/chat/ChatMode/ChatList/index.tsx @@ -1,12 +1,24 @@ +import dynamic from 'next/dynamic'; import { Flexbox } from 'react-layout-kit'; -import ChatList from './VirtualizedList'; +import SkeletonList from './SkeletonList'; interface ConversationProps { mobile?: boolean; } const Conversation = ({ mobile }: ConversationProps) => { + const Loading = () => ( +
+ +
+ ); + + const ChatList = dynamic(() => import('./VirtualizedList'), { + ssr: false, + loading: Loading, + }); + return ( { const isChineseInput = useRef(false); const onSend = useChatInput(); const { t } = useTranslation('chat'); - const [loading, messageInput, setMessageInput] = useSessionStore((s) => [ !!s.chatLoadingId, s.messageInput, @@ -26,6 +25,7 @@ const InputArea = memo(() => { onBlur={(e) => { setMessageInput?.(e.target.value); }} + // className={styles.input} onChange={(e) => { setMessageInput?.(e.target.value); }} @@ -48,7 +48,8 @@ const InputArea = memo(() => { }} placeholder={t('input.placeholder')} ref={ref} - autoSize={true} + rows={1} + autoSize={{ minRows: 1, maxRows: 10 }} type={'block'} value={messageInput} /> diff --git a/src/app/chat/ChatMode/MessageInput/actions/Camera.tsx b/src/app/chat/ChatMode/MessageInput/actions/Camera.tsx new file mode 100644 index 00000000..84550f9e --- /dev/null +++ b/src/app/chat/ChatMode/MessageInput/actions/Camera.tsx @@ -0,0 +1,26 @@ +import { ActionIcon } from '@lobehub/ui'; +import { message } from 'antd'; +import { Video } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; + +import { useSessionStore } from '@/store/session'; + +const Camera = () => { + const [setChatMode] = useSessionStore((s) => [s.setChatMode]); + const setVoiceOn = useSessionStore((s) => s.setVoiceOn); + const { t } = useTranslation('chat'); + + return ( + { + message.info(t('voiceOn')); + setVoiceOn(true); + setChatMode('camera'); + }} + title={t('camera')} + /> + ); +}; + +export default Camera; diff --git a/src/app/chat/ChatInfo/ChatList/Actions/History.tsx b/src/app/chat/ChatMode/MessageInput/actions/History.tsx similarity index 100% rename from src/app/chat/ChatInfo/ChatList/Actions/History.tsx rename to src/app/chat/ChatMode/MessageInput/actions/History.tsx diff --git a/src/app/chat/ChatHeader/AgentMeta/ModelSwitchPanel.tsx b/src/app/chat/ChatMode/MessageInput/actions/ModelSwitchPanel.tsx similarity index 100% rename from src/app/chat/ChatHeader/AgentMeta/ModelSwitchPanel.tsx rename to src/app/chat/ChatMode/MessageInput/actions/ModelSwitchPanel.tsx diff --git a/src/app/chat/ChatInfo/ChatList/Actions/TokenMini.tsx b/src/app/chat/ChatMode/MessageInput/actions/TokenMini.tsx similarity index 100% rename from src/app/chat/ChatInfo/ChatList/Actions/TokenMini.tsx rename to src/app/chat/ChatMode/MessageInput/actions/TokenMini.tsx diff --git a/src/app/chat/ViewerMode/MessageInput/index.tsx b/src/app/chat/ChatMode/MessageInput/index.tsx similarity index 81% rename from src/app/chat/ViewerMode/MessageInput/index.tsx rename to src/app/chat/ChatMode/MessageInput/index.tsx index c2ef7070..29d372c3 100644 --- a/src/app/chat/ViewerMode/MessageInput/index.tsx +++ b/src/app/chat/ChatMode/MessageInput/index.tsx @@ -1,6 +1,6 @@ import { SendOutlined } from '@ant-design/icons'; import { Icon } from '@lobehub/ui'; -import { Button } from 'antd'; +import { Button, Space } from 'antd'; import { useTheme } from 'antd-style'; import { ChevronUp, CornerDownLeft, LucideCommand } from 'lucide-react'; import React, { memo } from 'react'; @@ -13,7 +13,10 @@ import { useSessionStore } from '@/store/session'; import { isMacOS } from '@/utils/platform'; import TextArea from './TextArea'; -import Record from './actions/Record'; +import Camera from './actions/Camera'; +import History from './actions/History'; +import ModelSwitchPanel from './actions/ModelSwitchPanel'; +import TokenMini from './actions/TokenMini'; import { useStyles } from './style'; interface InputAreaProps { @@ -61,7 +64,14 @@ const InputArea = memo((props: InputAreaProps) => { return ( - + + + + + + + +