|
@@ -279,6 +279,52 @@ function ClearContextDivider() {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
+function ChatAction(props: {
|
|
|
+ text: string;
|
|
|
+ icon: JSX.Element;
|
|
|
+ onClick: () => void;
|
|
|
+}) {
|
|
|
+ const iconRef = useRef<HTMLDivElement>(null);
|
|
|
+ const textRef = useRef<HTMLDivElement>(null);
|
|
|
+ const [hovering, setHovering] = useState(false);
|
|
|
+ const [width, setWidth] = useState(20);
|
|
|
+
|
|
|
+ const updateWidth = () => {
|
|
|
+ if (!iconRef.current || !textRef.current) return;
|
|
|
+ const getWidth = (dom: HTMLDivElement) => dom.getBoundingClientRect().width;
|
|
|
+ const textWidth = getWidth(textRef.current);
|
|
|
+ const iconWidth = getWidth(iconRef.current);
|
|
|
+ setWidth(hovering ? textWidth + iconWidth : iconWidth);
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ updateWidth();
|
|
|
+ // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
+ }, [hovering]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div
|
|
|
+ className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ onMouseEnter={() => setHovering(true)}
|
|
|
+ onMouseLeave={() => setHovering(false)}
|
|
|
+ style={{
|
|
|
+ width,
|
|
|
+ }}
|
|
|
+ onClick={() => {
|
|
|
+ props.onClick();
|
|
|
+ setTimeout(updateWidth, 1);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div ref={iconRef} className={chatStyle["icon"]}>
|
|
|
+ {props.icon}
|
|
|
+ </div>
|
|
|
+ <div className={chatStyle["text"]} ref={textRef}>
|
|
|
+ {props.text}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
function useScrollToBottom() {
|
|
|
// for auto-scroll
|
|
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
@@ -330,61 +376,60 @@ export function ChatActions(props: {
|
|
|
return (
|
|
|
<div className={chatStyle["chat-input-actions"]}>
|
|
|
{couldStop && (
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={stopAll}
|
|
|
- >
|
|
|
- <StopIcon />
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.Stop}
|
|
|
+ icon={<StopIcon />}
|
|
|
+ />
|
|
|
)}
|
|
|
{!props.hitBottom && (
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={props.scrollToBottom}
|
|
|
- >
|
|
|
- <BottomIcon />
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.ToBottom}
|
|
|
+ icon={<BottomIcon />}
|
|
|
+ />
|
|
|
)}
|
|
|
{props.hitBottom && (
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={props.showPromptModal}
|
|
|
- >
|
|
|
- <SettingsIcon />
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.Settings}
|
|
|
+ icon={<SettingsIcon />}
|
|
|
+ />
|
|
|
)}
|
|
|
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={nextTheme}
|
|
|
- >
|
|
|
- {theme === Theme.Auto ? (
|
|
|
- <AutoIcon />
|
|
|
- ) : theme === Theme.Light ? (
|
|
|
- <LightIcon />
|
|
|
- ) : theme === Theme.Dark ? (
|
|
|
- <DarkIcon />
|
|
|
- ) : null}
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.Theme[theme]}
|
|
|
+ icon={
|
|
|
+ <>
|
|
|
+ {theme === Theme.Auto ? (
|
|
|
+ <AutoIcon />
|
|
|
+ ) : theme === Theme.Light ? (
|
|
|
+ <LightIcon />
|
|
|
+ ) : theme === Theme.Dark ? (
|
|
|
+ <DarkIcon />
|
|
|
+ ) : null}
|
|
|
+ </>
|
|
|
+ }
|
|
|
+ />
|
|
|
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={props.showPromptHints}
|
|
|
- >
|
|
|
- <PromptIcon />
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.Prompt}
|
|
|
+ icon={<PromptIcon />}
|
|
|
+ />
|
|
|
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
onClick={() => {
|
|
|
navigate(Path.Masks);
|
|
|
}}
|
|
|
- >
|
|
|
- <MaskIcon />
|
|
|
- </div>
|
|
|
+ text={Locale.Chat.InputActions.Masks}
|
|
|
+ icon={<MaskIcon />}
|
|
|
+ />
|
|
|
|
|
|
- <div
|
|
|
- className={`${chatStyle["chat-input-action"]} clickable`}
|
|
|
+ <ChatAction
|
|
|
+ text={Locale.Chat.InputActions.Clear}
|
|
|
+ icon={<BreakIcon />}
|
|
|
onClick={() => {
|
|
|
chatStore.updateCurrentSession((session) => {
|
|
|
if (session.clearContextIndex === session.messages.length) {
|
|
@@ -395,9 +440,7 @@ export function ChatActions(props: {
|
|
|
}
|
|
|
});
|
|
|
}}
|
|
|
- >
|
|
|
- <BreakIcon />
|
|
|
- </div>
|
|
|
+ />
|
|
|
</div>
|
|
|
);
|
|
|
}
|