-
Notifications
You must be signed in to change notification settings - Fork 284
/
Copy pathchat-topbar.tsx
121 lines (112 loc) · 3.53 KB
/
chat-topbar.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"use client";
import React, { useEffect, useState } from "react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Sheet,
SheetContent,
SheetTrigger,
} from "@/components/ui/sheet";
import { Button } from "../ui/button";
import { CaretSortIcon, HamburgerMenuIcon } from "@radix-ui/react-icons";
import { Sidebar } from "../sidebar";
import { Message } from "ai/react";
import { getSelectedModel } from "@/lib/model-helper";
import useChatStore from "@/app/hooks/useChatStore";
import { useTranslation } from "react-i18next";
interface ChatTopbarProps {
isLoading: boolean;
chatId?: string;
messages: Message[];
setMessages: (messages: Message[]) => void;
}
export default function ChatTopbar({
isLoading,
chatId,
messages,
setMessages,
}: ChatTopbarProps) {
const [models, setModels] = useState<string[]>([]);
const [open, setOpen] = useState(false);
const [sheetOpen, setSheetOpen] = useState(false);
const selectedModel = useChatStore((state) => state.selectedModel);
const setSelectedModel = useChatStore((state) => state.setSelectedModel);
const { t } = useTranslation("translation");
const [isClient, setIsClient] = useState(false); // 客户端标记
useEffect(() => {
setIsClient(true); // 在客户端渲染时设置 isClient
(async () => {
try {
const res = await fetch("/api/tags");
if (!res.ok) throw new Error(`HTTP Error: ${res.status}`);
const data = await res.json().catch(() => null);
if (!data?.models?.length) return;
setModels(data.models.map(({ name }: { name: string }) => name));
} catch (error) {
console.error("Error fetching models:", error);
}
})();
}, []);
const handleModelChange = (model: string) => {
setSelectedModel(model);
setOpen(false);
};
const handleCloseSidebar = () => {
setSheetOpen(false);
};
return (
<div className="w-full flex px-4 py-6 items-center justify-between lg:justify-center ">
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
<SheetTrigger>
<HamburgerMenuIcon className="lg:hidden w-5 h-5" />
</SheetTrigger>
<SheetContent side="left">
<Sidebar
chatId={chatId || ""}
isCollapsed={false}
isMobile={false}
messages={messages}
closeSidebar={handleCloseSidebar}
/>
</SheetContent>
</Sheet>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
disabled={isLoading}
variant="outline"
role="combobox"
aria-expanded={open}
className="w-[300px] justify-between"
>
{selectedModel || (isClient ? t("chat.model_select") : "chat.model_select")}
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[300px] p-1">
{models.length > 0 ? (
models.map((model) => (
<Button
key={model}
variant="ghost"
className="w-full"
onClick={() => {
handleModelChange(model);
}}
>
{model}
</Button>
))
) : (
<Button variant="ghost" disabled className=" w-full">
{t("chat.no_models_available")}
</Button>
)}
</PopoverContent>
</Popover>
</div>
);
}