mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-16 11:37:47 +01:00
fix: chat params (#164)
This commit is contained in:
@@ -8,7 +8,6 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
useMemo,
|
useMemo,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { MessageSquarePlus, PanelLeft } from "lucide-react";
|
|
||||||
import { isTauri } from "@tauri-apps/api/core";
|
import { isTauri } from "@tauri-apps/api/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { debounce } from "lodash-es";
|
import { debounce } from "lodash-es";
|
||||||
@@ -20,7 +19,7 @@ import { useWebSocket } from "@/hooks/useWebSocket";
|
|||||||
import { useChatStore } from "@/stores/chatStore";
|
import { useChatStore } from "@/stores/chatStore";
|
||||||
import { useWindows } from "@/hooks/useWindows";
|
import { useWindows } from "@/hooks/useWindows";
|
||||||
import { clientEnv } from "@/utils/env";
|
import { clientEnv } from "@/utils/env";
|
||||||
|
import { ChatHeader } from "./ChatHeader";
|
||||||
interface ChatAIProps {
|
interface ChatAIProps {
|
||||||
isTransitioned: boolean;
|
isTransitioned: boolean;
|
||||||
isSearchActive?: boolean;
|
isSearchActive?: boolean;
|
||||||
@@ -249,7 +248,7 @@ const ChatAI = memo(
|
|||||||
console.error("Failed to fetch user data:", error);
|
console.error("Failed to fetch user data:", error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[activeChat?._id]
|
[activeChat?._id, isSearchActive, isDeepThinkActive]
|
||||||
);
|
);
|
||||||
|
|
||||||
const chatClose = async () => {
|
const chatClose = async () => {
|
||||||
@@ -327,26 +326,10 @@ const ChatAI = memo(
|
|||||||
className={`h-full flex flex-col rounded-xl overflow-hidden`}
|
className={`h-full flex flex-col rounded-xl overflow-hidden`}
|
||||||
>
|
>
|
||||||
{isChatPage ? null : (
|
{isChatPage ? null : (
|
||||||
<header
|
<ChatHeader
|
||||||
data-tauri-drag-region
|
onCreateNewChat={createNewChat}
|
||||||
className={`flex items-center justify-between py-2 px-1`}
|
onOpenChatAI={openChatAI}
|
||||||
>
|
/>
|
||||||
<button
|
|
||||||
onClick={() => openChatAI()}
|
|
||||||
className={`p-2 rounded-lg transition-colors text-[#333] dark:text-[#d8d8d8]`}
|
|
||||||
>
|
|
||||||
<PanelLeft className="h-4 w-4" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
createNewChat();
|
|
||||||
}}
|
|
||||||
className={`p-2 rounded-lg transition-colors text-[#333] dark:text-[#d8d8d8]`}
|
|
||||||
>
|
|
||||||
<MessageSquarePlus className="h-4 w-4" />
|
|
||||||
</button>
|
|
||||||
</header>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Chat messages */}
|
{/* Chat messages */}
|
||||||
|
|||||||
127
src/components/Assistant/ChatHeader.tsx
Normal file
127
src/components/Assistant/ChatHeader.tsx
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import { MessageSquarePlus, PanelLeft, Pin, MoreHorizontal } from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Listbox, Popover } from "@headlessui/react";
|
||||||
|
|
||||||
|
interface Server {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
status: 'online' | 'offline';
|
||||||
|
assistantCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ChatHeaderProps {
|
||||||
|
onCreateNewChat: () => void;
|
||||||
|
onOpenChatAI: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ChatHeader({ onCreateNewChat, onOpenChatAI }: ChatHeaderProps) {
|
||||||
|
const [isPinned, setIsPinned] = useState(false);
|
||||||
|
const [showAI] = useState(false);
|
||||||
|
const [servers] = useState<Server[]>([
|
||||||
|
{ id: '1', name: 'Coco Cloud', status: 'online', assistantCount: 3 },
|
||||||
|
{ id: '2', name: 'Searchkit', status: 'online', assistantCount: 3 },
|
||||||
|
{ id: '3', name: 'INFINI Labs', status: 'online', assistantCount: 2 },
|
||||||
|
{ id: '4', name: 'Test server', status: 'offline', assistantCount: 1 },
|
||||||
|
]);
|
||||||
|
const [selectedServer, setSelectedServer] = useState(servers[0]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="flex items-center justify-between py-2 px-3" data-tauri-drag-region>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={onOpenChatAI}
|
||||||
|
className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||||
|
>
|
||||||
|
<PanelLeft className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{showAI ? <Listbox value={selectedServer} onChange={setSelectedServer}>
|
||||||
|
<div className="relative">
|
||||||
|
<Listbox.Button className="relative w-48 h-8 px-3 py-1 text-left bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<img src="/path-to-server-icon.png" className="w-4 h-4 rounded-full" />
|
||||||
|
<span className="block truncate">{selectedServer.name}</span>
|
||||||
|
</div>
|
||||||
|
</Listbox.Button>
|
||||||
|
<Listbox.Options className="absolute w-full mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
{servers.map((server) => (
|
||||||
|
<Listbox.Option
|
||||||
|
key={server.id}
|
||||||
|
value={server}
|
||||||
|
className={({ active }) =>
|
||||||
|
`relative cursor-pointer select-none py-2 px-3 ${
|
||||||
|
active ? 'bg-gray-100 dark:bg-gray-700' : ''
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<img src="/path-to-server-icon.png" className="w-4 h-4 rounded-full" />
|
||||||
|
<span>{server.name}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<span className={`w-2 h-2 rounded-full ${
|
||||||
|
server.status === 'online' ? 'bg-green-500' : 'bg-gray-400'
|
||||||
|
}`} />
|
||||||
|
<span className="text-xs text-gray-500">
|
||||||
|
AI Assistant: {server.assistantCount}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Listbox.Option>
|
||||||
|
))}
|
||||||
|
</Listbox.Options>
|
||||||
|
</div>
|
||||||
|
</Listbox> : null}
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={onCreateNewChat}
|
||||||
|
className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||||
|
>
|
||||||
|
<MessageSquarePlus className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setIsPinned(!isPinned)}
|
||||||
|
className={`p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 ${
|
||||||
|
isPinned ? 'text-blue-500' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Pin className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Popover className="relative">
|
||||||
|
<Popover.Button className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800">
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</Popover.Button>
|
||||||
|
|
||||||
|
<Popover.Panel className="absolute right-0 mt-2 w-60 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="p-2">
|
||||||
|
<h3 className="font-medium mb-2">Servers</h3>
|
||||||
|
<div className="space-y-2">
|
||||||
|
{servers.map(server => (
|
||||||
|
<div key={server.id} className="flex items-center justify-between p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<img src="/path-to-server-icon.png" className="w-6 h-6 rounded-full" />
|
||||||
|
<div>
|
||||||
|
<div className="font-medium">{server.name}</div>
|
||||||
|
<div className="text-xs text-gray-500">
|
||||||
|
AI Assistant: {server.assistantCount}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span className={`w-2 h-2 rounded-full ${
|
||||||
|
server.status === 'online' ? 'bg-green-500' : 'bg-gray-400'
|
||||||
|
}`} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Popover.Panel>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -76,10 +76,10 @@ export function SourceResult({ text }: SourceResultProps) {
|
|||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
onClick={() => item.url && OpenURLWithBrowser(item.url)}
|
onClick={() => item.url && OpenURLWithBrowser(item.url)}
|
||||||
className="group flex items-center px-2 py-1 hover:bg-[#F7F7F7] dark:hover:bg-[#2C2C2C] border-b border-[#E6E6E6] dark:border-[#272626] last:border-b-0 cursor-pointer transition-colors"
|
className="group flex items-center p-2 hover:bg-[#F7F7F7] dark:hover:bg-[#2C2C2C] border-b border-[#E6E6E6] dark:border-[#272626] last:border-b-0 cursor-pointer transition-colors"
|
||||||
>
|
>
|
||||||
<div className="flex-1 min-w-0 flex items-center gap-2">
|
<div className="flex-1 min-w-0 flex items-center gap-2">
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0 flex items-center gap-1">
|
||||||
<File className="w-3 h-3" />
|
<File className="w-3 h-3" />
|
||||||
<div className="text-xs text-[#333333] dark:text-[#D8D8D8] truncate font-normal group-hover:text-[#0072FF] dark:group-hover:text-[#0072FF]">
|
<div className="text-xs text-[#333333] dark:text-[#D8D8D8] truncate font-normal group-hover:text-[#0072FF] dark:group-hover:text-[#0072FF]">
|
||||||
{item.title || item.category}
|
{item.title || item.category}
|
||||||
|
|||||||
Reference in New Issue
Block a user