void;
@@ -34,8 +36,11 @@ export function ChatActions(props: {
showPromptModal: () => void;
scrollToBottom: () => void;
showPromptHints: () => void;
+ showModelSelector: (show: boolean) => void;
hitBottom: boolean;
uploading: boolean;
+ isMobileScreen: boolean;
+ className?: string;
}) {
const config = useAppConfig();
const navigate = useNavigate();
@@ -62,7 +67,6 @@ export function ChatActions(props: {
() => allModels.filter((m) => m.available),
[allModels],
);
- const [showModelSelector, setShowModelSelector] = useState(false);
const [showUploadImage, setShowUploadImage] = useState(false);
useEffect(() => {
@@ -85,106 +89,159 @@ export function ChatActions(props: {
}
}, [chatStore, currentModel, models]);
+ const actions = [
+ {
+ onClick: stopAll,
+ text: Locale.Chat.InputActions.Stop,
+ isShow: couldStop,
+ icon:
,
+ placement: "left",
+ },
+ {
+ onClick: props.scrollToBottom,
+ text: Locale.Chat.InputActions.ToBottom,
+ isShow: !props.hitBottom,
+ icon:
,
+ placement: "left",
+ },
+ {
+ onClick: props.showPromptModal,
+ text: Locale.Chat.InputActions.Settings,
+ isShow: props.hitBottom,
+ icon:
,
+ placement: "right",
+ },
+ {
+ onClick: props.uploadImage,
+ text: Locale.Chat.InputActions.UploadImage,
+ isShow: showUploadImage,
+ icon: props.uploading ?
:
,
+ placement: "left",
+ },
+ {
+ onClick: nextTheme,
+ text: Locale.Chat.InputActions.Theme[theme],
+ isShow: true,
+ icon: (
+ <>
+ {theme === Theme.Auto ? (
+
+ ) : theme === Theme.Light ? (
+
+ ) : theme === Theme.Dark ? (
+
+ ) : null}
+ >
+ ),
+ placement: "left",
+ },
+ {
+ onClick: props.showPromptHints,
+ text: Locale.Chat.InputActions.Prompt,
+ isShow: true,
+ icon:
,
+ placement: "left",
+ },
+ {
+ onClick: () => {
+ navigate(Path.Masks);
+ },
+ text: Locale.Chat.InputActions.Masks,
+ isShow: true,
+ icon:
,
+ placement: "left",
+ },
+ {
+ onClick: () => {
+ chatStore.updateCurrentSession((session) => {
+ if (session.clearContextIndex === session.messages.length) {
+ session.clearContextIndex = undefined;
+ } else {
+ session.clearContextIndex = session.messages.length;
+ session.memoryPrompt = ""; // will clear memory
+ }
+ });
+ },
+ text: Locale.Chat.InputActions.Clear,
+ isShow: true,
+ icon:
,
+ placement: "right",
+ },
+ {
+ onClick: () => props.showModelSelector(true),
+ text: currentModel,
+ isShow: true,
+ icon:
,
+ placement: "left",
+ },
+ ] as const;
+
+ if (props.isMobileScreen) {
+ const content = (
+
+ {actions.map((act) => {
+ return (
+
+ {act.icon}
+ {act.text}
+
+ );
+ })}
+
+ );
+ return (
+
+
+
+ );
+ }
+
+ const popoverClassName = `bg-gray-800 whitespace-nowrap px-3 py-2.5 text-white text-sm-title rounded-md`;
+
return (
-
- {couldStop && (
-
}
- />
- )}
- {!props.hitBottom && (
-
}
- />
- )}
- {props.hitBottom && (
-
}
- />
- )}
-
- {showUploadImage && (
-
:
}
- />
- )}
-
- {theme === Theme.Auto ? (
-
- ) : theme === Theme.Light ? (
-
- ) : theme === Theme.Dark ? (
-
- ) : null}
- >
- }
- />
-
- }
- />
-
- {
- navigate(Path.Masks);
- }}
- text={Locale.Chat.InputActions.Masks}
- icon={}
- />
-
- }
- onClick={() => {
- chatStore.updateCurrentSession((session) => {
- if (session.clearContextIndex === session.messages.length) {
- session.clearContextIndex = undefined;
- } else {
- session.clearContextIndex = session.messages.length;
- session.memoryPrompt = ""; // will clear memory
- }
- });
- }}
- />
-
- setShowModelSelector(true)}
- text={currentModel}
- icon={}
- />
-
- {showModelSelector && (
- ({
- title: m.displayName,
- value: m.name,
- }))}
- onClose={() => setShowModelSelector(false)}
- onSelection={(s) => {
- if (s.length === 0) return;
- chatStore.updateCurrentSession((session) => {
- session.mask.modelConfig.model = s[0] as ModelType;
- session.mask.syncGlobalConfig = false;
- });
- showToast(s[0]);
- }}
- />
- )}
+
+ {actions
+ .filter((v) => v.placement === "left" && v.isShow)
+ .map((act, ind) => {
+ return (
+
+
+ {act.icon}
+
+
+ );
+ })}
+
+ {actions
+ .filter((v) => v.placement === "right" && v.isShow)
+ .map((act, ind, arr) => {
+ return (
+
+
+ {act.icon}
+
+
+ );
+ })}
);
}
diff --git a/app/containers/Chat/ChatHeader.tsx b/app/containers/Chat/ChatHeader.tsx
index ac21afc37..f99152559 100644
--- a/app/containers/Chat/ChatHeader.tsx
+++ b/app/containers/Chat/ChatHeader.tsx
@@ -1,75 +1,88 @@
import { useNavigate } from "react-router-dom";
-import { IconButton } from "@/app/components/button";
import Locale from "@/app/locales";
import { Path } from "@/app/constant";
import { DEFAULT_TOPIC, useChatStore } from "@/app/store/chat";
-import RenameIcon from "@/app/icons/rename.svg";
-import ExportIcon from "@/app/icons/share.svg";
-import ReturnIcon from "@/app/icons/return.svg";
-
-import styles from "./index.module.scss";
+import LogIcon from "@/app/icons/logIcon.svg";
+import GobackIcon from "@/app/icons/goback.svg";
+import ShareIcon from "@/app/icons/shareIcon.svg";
+import BottomArrow from "@/app/icons/bottomArrow.svg";
export interface ChatHeaderProps {
isMobileScreen: boolean;
setIsEditingMessage: (v: boolean) => void;
setShowExport: (v: boolean) => void;
+ showModelSelector: (v: boolean) => void;
}
export default function ChatHeader(props: ChatHeaderProps) {
- const { isMobileScreen, setIsEditingMessage, setShowExport } = props;
+ const {
+ isMobileScreen,
+ setIsEditingMessage,
+ setShowExport,
+ showModelSelector,
+ } = props;
const navigate = useNavigate();
const chatStore = useChatStore();
const session = chatStore.currentSession();
+ const currentModel = chatStore.currentSession().mask.modelConfig.model;
+
+ let containerClassName = "";
+ let titleClassName = "mr-4";
+ let mainTitleClassName = "";
+ let subTitleClassName = "";
+
+ if (isMobileScreen) {
+ containerClassName = "h-menu-title-mobile";
+ titleClassName = "flex flex-col items-center justify-center gap-0.5 text";
+ mainTitleClassName = "text-sm-title h-[19px] leading-5";
+ subTitleClassName = "text-sm-mobile-tab leading-4";
+ }
+
return (
-
- {isMobileScreen && (
-
-
- }
- bordered
- title={Locale.Chat.Actions.ChatList}
- onClick={() => navigate(Path.Home)}
- />
-
+
+ {isMobileScreen ? (
+
navigate(Path.Home)}>
+
+ ) : (
+
)}
-
+
setIsEditingMessage(true)}
>
{!session.topic ? DEFAULT_TOPIC : session.topic}
-
- {Locale.Chat.SubTitle(session.messages.length)}
+
+ {isMobileScreen ? (
+
showModelSelector(true)}
+ >
+ {currentModel}
+
+
+ ) : (
+ Locale.Chat.SubTitle(session.messages.length)
+ )}
-
- {!isMobileScreen && (
-
- }
- bordered
- onClick={() => setIsEditingMessage(true)}
- />
-
- )}
-
- }
- bordered
- title={Locale.Chat.Actions.Export}
- onClick={() => {
- setShowExport(true);
- }}
- />
-
+
+
{
+ setShowExport(true);
+ }}
+ >
+
);
diff --git a/app/containers/Chat/ChatInputPanel.tsx b/app/containers/Chat/ChatInputPanel.tsx
index 09b35bbef..58638db6a 100644
--- a/app/containers/Chat/ChatInputPanel.tsx
+++ b/app/containers/Chat/ChatInputPanel.tsx
@@ -36,6 +36,7 @@ export interface ChatInputPanelProps {
setIsLoading: (value: boolean) => void;
setShowPromptModal: (value: boolean) => void;
_setMsgRenderIndex: (value: number) => void;
+ showModelSelector: (value: boolean) => void;
}
export interface ChatInputPanelInstance {
@@ -72,6 +73,7 @@ export default forwardRef
(
_setMsgRenderIndex,
hitBottom,
inputRows,
+ showModelSelector,
} = props;
const [uploading, setUploading] = useState(false);
@@ -222,86 +224,107 @@ export default forwardRef(
setUploading,
});
+ let inputClassName = " flex flex-col px-5 pb-5";
+ let actionsClassName = "py-2.5";
+ let inputTextAreaClassName = "";
+
+ if (isMobileScreen) {
+ inputClassName = "flex flex-row-reverse items-center gap-2 p-3";
+ actionsClassName = "";
+ inputTextAreaClassName = "";
+ }
+
return (
-
-
-
-
setShowPromptModal(true)}
- scrollToBottom={scrollToBottom}
- hitBottom={hitBottom}
- uploading={uploading}
- showPromptHints={() => {
- // Click again to close
- if (promptHints.length > 0) {
- setPromptHints([]);
- return;
- }
-
- inputRef.current?.focus();
- setUserInput("/");
- onSearch("");
- }}
+