160 lines
4.8 KiB
TypeScript
160 lines
4.8 KiB
TypeScript
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { AnimatePresence, motion } from "framer-motion";
|
|
import { ArrowUp, X } from "lucide-react";
|
|
import { useCallback, useRef } from "react";
|
|
|
|
import { Detective } from "~/components/deer-flow/icons/detective";
|
|
import MessageInput, {
|
|
type MessageInputRef,
|
|
} from "~/components/deer-flow/message-input";
|
|
import { Tooltip } from "~/components/deer-flow/tooltip";
|
|
import { Button } from "~/components/ui/button";
|
|
import type { Option, Resource } from "~/core/messages";
|
|
import {
|
|
setEnableBackgroundInvestigation,
|
|
useSettingsStore,
|
|
} from "~/core/store";
|
|
import { cn } from "~/lib/utils";
|
|
|
|
export function InputBox({
|
|
className,
|
|
responding,
|
|
feedback,
|
|
onSend,
|
|
onCancel,
|
|
onRemoveFeedback,
|
|
}: {
|
|
className?: string;
|
|
size?: "large" | "normal";
|
|
responding?: boolean;
|
|
feedback?: { option: Option } | null;
|
|
onSend?: (
|
|
message: string,
|
|
options?: {
|
|
interruptFeedback?: string;
|
|
resources?: Array<Resource>;
|
|
},
|
|
) => void;
|
|
onCancel?: () => void;
|
|
onRemoveFeedback?: () => void;
|
|
}) {
|
|
const backgroundInvestigation = useSettingsStore(
|
|
(state) => state.general.enableBackgroundInvestigation,
|
|
);
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
const inputRef = useRef<MessageInputRef>(null);
|
|
const feedbackRef = useRef<HTMLDivElement>(null);
|
|
|
|
const handleSendMessage = useCallback(
|
|
(message: string, resources: Array<Resource>) => {
|
|
console.log(message, resources);
|
|
if (responding) {
|
|
onCancel?.();
|
|
} else {
|
|
if (message.trim() === "") {
|
|
return;
|
|
}
|
|
if (onSend) {
|
|
onSend(message, {
|
|
interruptFeedback: feedback?.option.value,
|
|
resources,
|
|
});
|
|
onRemoveFeedback?.();
|
|
}
|
|
}
|
|
},
|
|
[responding, onCancel, onSend, feedback, onRemoveFeedback],
|
|
);
|
|
|
|
return (
|
|
<div
|
|
className={cn(
|
|
"bg-card relative flex h-full w-full flex-col rounded-[24px] border",
|
|
className,
|
|
)}
|
|
ref={containerRef}
|
|
>
|
|
<div className="w-full">
|
|
<AnimatePresence>
|
|
{feedback && (
|
|
<motion.div
|
|
ref={feedbackRef}
|
|
className="bg-background border-brand absolute top-0 left-0 mt-2 ml-4 flex items-center justify-center gap-1 rounded-2xl border px-2 py-0.5"
|
|
initial={{ opacity: 0, scale: 0 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 0 }}
|
|
transition={{ duration: 0.2, ease: "easeInOut" }}
|
|
>
|
|
<div className="text-brand flex h-full w-full items-center justify-center text-sm opacity-90">
|
|
{feedback.option.text}
|
|
</div>
|
|
<X
|
|
className="cursor-pointer opacity-60"
|
|
size={16}
|
|
onClick={onRemoveFeedback}
|
|
/>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
<MessageInput
|
|
className={cn("h-24 px-4 pt-5", feedback && "pt-9")}
|
|
ref={inputRef}
|
|
onEnter={handleSendMessage}
|
|
/>
|
|
</div>
|
|
<div className="flex items-center px-4 py-2">
|
|
<div className="flex grow">
|
|
<Tooltip
|
|
className="max-w-60"
|
|
title={
|
|
<div>
|
|
<h3 className="mb-2 font-bold">
|
|
Investigation Mode: {backgroundInvestigation ? "On" : "Off"}
|
|
</h3>
|
|
<p>
|
|
When enabled, DeerFlow will perform a quick search before
|
|
planning. This is useful for researches related to ongoing
|
|
events and news.
|
|
</p>
|
|
</div>
|
|
}
|
|
>
|
|
<Button
|
|
className={cn(
|
|
"rounded-2xl",
|
|
backgroundInvestigation && "!border-brand !text-brand",
|
|
)}
|
|
variant="outline"
|
|
onClick={() =>
|
|
setEnableBackgroundInvestigation(!backgroundInvestigation)
|
|
}
|
|
>
|
|
<Detective /> Investigation
|
|
</Button>
|
|
</Tooltip>
|
|
</div>
|
|
<div className="flex shrink-0 items-center gap-2">
|
|
<Tooltip title={responding ? "Stop" : "Send"}>
|
|
<Button
|
|
variant="outline"
|
|
size="icon"
|
|
className={cn("h-10 w-10 rounded-full")}
|
|
onClick={() => inputRef.current?.submit()}
|
|
>
|
|
{responding ? (
|
|
<div className="flex h-10 w-10 items-center justify-center">
|
|
<div className="bg-foreground h-4 w-4 rounded-sm opacity-70" />
|
|
</div>
|
|
) : (
|
|
<ArrowUp />
|
|
)}
|
|
</Button>
|
|
</Tooltip>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|