refactor: update Settings and Navbar components for improved state management and UI integration
This commit is contained in:
@@ -475,7 +475,7 @@ const Choice = (props: {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (props: { setShow: Dispatch<boolean> }) => {
|
export default (props: {}) => {
|
||||||
const ctx = useContext(AppContext);
|
const ctx = useContext(AppContext);
|
||||||
if (ctx === null) return <></>;
|
if (ctx === null) return <></>;
|
||||||
|
|
||||||
@@ -497,13 +497,14 @@ export default (props: { setShow: Dispatch<boolean> }) => {
|
|||||||
const [totalCost, setTotalCost] = useState(getTotalCost());
|
const [totalCost, setTotalCost] = useState(getTotalCost());
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { langCode, setLangCode } = useContext(langCodeContext);
|
const { langCode, setLangCode } = useContext(langCodeContext);
|
||||||
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
themeChange(false);
|
themeChange(false);
|
||||||
const handleKeyPress = (event: any) => {
|
const handleKeyPress = (event: any) => {
|
||||||
if (event.keyCode === 27) {
|
if (event.keyCode === 27) {
|
||||||
// keyCode for ESC key is 27
|
// keyCode for ESC key is 27
|
||||||
props.setShow(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -514,7 +515,7 @@ export default (props: { setShow: Dispatch<boolean> }) => {
|
|||||||
};
|
};
|
||||||
}, []); // The empty dependency array ensures that the effect runs only once
|
}, []); // The empty dependency array ensures that the effect runs only once
|
||||||
return (
|
return (
|
||||||
<Sheet>
|
<Sheet open={open} onOpenChange={setOpen}>
|
||||||
<SheetTrigger asChild>
|
<SheetTrigger asChild>
|
||||||
<Button variant="outline" className="flex-grow">
|
<Button variant="outline" className="flex-grow">
|
||||||
{Tr("Settings")}
|
{Tr("Settings")}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import {
|
|||||||
WalletIcon,
|
WalletIcon,
|
||||||
ArrowUpDownIcon,
|
ArrowUpDownIcon,
|
||||||
ScissorsIcon,
|
ScissorsIcon,
|
||||||
|
SearchIcon,
|
||||||
|
CogIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { AppContext } from "@/pages/App";
|
import { AppContext } from "@/pages/App";
|
||||||
import { models } from "@/types/models";
|
import { models } from "@/types/models";
|
||||||
@@ -33,6 +35,9 @@ import { getTotalCost } from "@/utils/totalCost";
|
|||||||
import { Tr } from "@/translate";
|
import { Tr } from "@/translate";
|
||||||
|
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
|
import { Button } from "./ui/button";
|
||||||
|
import Search from "@/search";
|
||||||
|
import Settings from "./Settings";
|
||||||
|
|
||||||
const Navbar: React.FC = () => {
|
const Navbar: React.FC = () => {
|
||||||
const ctx = useContext(AppContext);
|
const ctx = useContext(AppContext);
|
||||||
@@ -40,7 +45,8 @@ const Navbar: React.FC = () => {
|
|||||||
const { chatStore, setChatStore } = ctx;
|
const { chatStore, setChatStore } = ctx;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="flex sticky top-0 bg-background h-16 shrink-0 items-center gap-2 border-b z-50">
|
<header className="flex sticky top-0 bg-background h-14 shrink-0 items-center border-b z-50">
|
||||||
|
<div className="flex flex-1 items-center gap-2">
|
||||||
<div className="flex items-center gap-2 px-3">
|
<div className="flex items-center gap-2 px-3">
|
||||||
<SidebarTrigger />
|
<SidebarTrigger />
|
||||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||||
@@ -87,8 +93,8 @@ const Navbar: React.FC = () => {
|
|||||||
<MenubarItem>
|
<MenubarItem>
|
||||||
<ReceiptIcon className="w-4 h-4 mr-2" />
|
<ReceiptIcon className="w-4 h-4 mr-2" />
|
||||||
Price:{" "}
|
Price:{" "}
|
||||||
{models[chatStore.model]?.price?.prompt * 1000 * 1000}$ /
|
{models[chatStore.model]?.price?.prompt * 1000 * 1000}$
|
||||||
1M input tokens
|
/ 1M input tokens
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarItem>
|
<MenubarItem>
|
||||||
<WalletIcon className="w-4 h-4 mr-2" />
|
<WalletIcon className="w-4 h-4 mr-2" />
|
||||||
@@ -103,8 +109,10 @@ const Navbar: React.FC = () => {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<span style={{ color: "gray" }}>{Tr("STREAM")}</span>·
|
<span style={{ color: "gray" }}>
|
||||||
<span>{Tr("FETCH")}</span>
|
{Tr("STREAM")}
|
||||||
|
</span>
|
||||||
|
·<span>{Tr("FETCH")}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
@@ -113,7 +121,9 @@ const Navbar: React.FC = () => {
|
|||||||
{chatStore.postBeginIndex} / {chatStore.history.length}
|
{chatStore.postBeginIndex} / {chatStore.history.length}
|
||||||
</MenubarItem>
|
</MenubarItem>
|
||||||
<MenubarSeparator />
|
<MenubarSeparator />
|
||||||
<MenubarItem disabled>Switch to Model (TODO):</MenubarItem>
|
<MenubarItem disabled>
|
||||||
|
Switch to Model (TODO):
|
||||||
|
</MenubarItem>
|
||||||
<MenubarCheckboxItem checked>gpt-4o</MenubarCheckboxItem>
|
<MenubarCheckboxItem checked>gpt-4o</MenubarCheckboxItem>
|
||||||
<MenubarCheckboxItem>gpt-o1</MenubarCheckboxItem>
|
<MenubarCheckboxItem>gpt-o1</MenubarCheckboxItem>
|
||||||
<MenubarCheckboxItem>gpt-o1-mini</MenubarCheckboxItem>
|
<MenubarCheckboxItem>gpt-o1-mini</MenubarCheckboxItem>
|
||||||
@@ -126,6 +136,11 @@ const Navbar: React.FC = () => {
|
|||||||
<ModeToggle />
|
<ModeToggle />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex ml-auto gap-2 px-3">
|
||||||
|
<Settings />
|
||||||
|
<Search />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -429,18 +429,6 @@ export default function ChatBOX() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col p-2 gap-2 w-full">
|
<div className="flex flex-col p-2 gap-2 w-full">
|
||||||
<div className="flex items-center gap-2 justify-between">
|
|
||||||
{true && <Settings setShow={setShowSettings} />}
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
onClick={() => setShowSearch(true)}
|
|
||||||
>
|
|
||||||
<SearchIcon />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{showSearch && <Search show={showSearch} setShow={setShowSearch} />}
|
|
||||||
|
|
||||||
{!chatStore.apiKey && (
|
{!chatStore.apiKey && (
|
||||||
<Alert>
|
<Alert>
|
||||||
<KeyIcon className="h-4 w-4" />
|
<KeyIcon className="h-4 w-4" />
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
|
|
||||||
import { Input } from "./components/ui/input";
|
import { Input } from "./components/ui/input";
|
||||||
import { AppContext } from "./pages/App";
|
import { AppContext } from "./pages/App";
|
||||||
|
import { Button } from "./components/ui/button";
|
||||||
|
import { SearchIcon } from "lucide-react";
|
||||||
|
|
||||||
interface ChatStoreSearchResult {
|
interface ChatStoreSearchResult {
|
||||||
key: IDBValidKey;
|
key: IDBValidKey;
|
||||||
@@ -33,10 +35,7 @@ interface ChatStoreSearchResult {
|
|||||||
preview: string;
|
preview: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Search(props: {
|
export default function Search() {
|
||||||
show: boolean;
|
|
||||||
setShow: (show: boolean) => void;
|
|
||||||
}) {
|
|
||||||
const ctx = useContext(AppContext);
|
const ctx = useContext(AppContext);
|
||||||
if (ctx === null) return <></>;
|
if (ctx === null) return <></>;
|
||||||
const { setSelectedChatIndex, db } = ctx;
|
const { setSelectedChatIndex, db } = ctx;
|
||||||
@@ -46,9 +45,15 @@ export default function Search(props: {
|
|||||||
const [searchingNow, setSearchingNow] = useState<number>(0);
|
const [searchingNow, setSearchingNow] = useState<number>(0);
|
||||||
const [pageIndex, setPageIndex] = useState<number>(0);
|
const [pageIndex, setPageIndex] = useState<number>(0);
|
||||||
const searchAbortRef = useRef<AbortController | null>(null);
|
const searchAbortRef = useRef<AbortController | null>(null);
|
||||||
|
const [open, setOpen] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={props.show} onOpenChange={props.setShow}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger>
|
||||||
|
<Button variant="outline" size="icon">
|
||||||
|
<SearchIcon />
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-[80%]">
|
<DialogContent className="sm:max-w-[80%]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Search</DialogTitle>
|
<DialogTitle>Search</DialogTitle>
|
||||||
@@ -160,7 +165,7 @@ export default function Search(props: {
|
|||||||
key={result.key as number}
|
key={result.key as number}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedChatIndex(parseInt(result.key.toString()));
|
setSelectedChatIndex(parseInt(result.key.toString()));
|
||||||
props.setShow(false);
|
setOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="m-1 p-1 font-bold">
|
<div className="m-1 p-1 font-bold">
|
||||||
|
|||||||
Reference in New Issue
Block a user