diff --git a/src/components/App.tsx b/src/components/App.tsx
index a9bceff..da31ff0 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -6,7 +6,7 @@ import {
import { useHotkeys, useLocalStorage } from "@mantine/hooks";
import { Notifications } from "@mantine/notifications";
import {
- createHashHistory,
+ createBrowserHistory,
ReactLocation,
Router,
} from "@tanstack/react-location";
@@ -14,7 +14,7 @@ import { ChatRoute } from "../routes/ChatRoute";
import { IndexRoute } from "../routes/IndexRoute";
import { Layout } from "./Layout";
-const history = createHashHistory();
+const history = createBrowserHistory();
const location = new ReactLocation({ history });
export function App() {
diff --git a/src/components/ChatItem.tsx b/src/components/ChatItem.tsx
index 4dc2fb1..52c769f 100644
--- a/src/components/ChatItem.tsx
+++ b/src/components/ChatItem.tsx
@@ -6,10 +6,12 @@ import { EditChatModal } from "./EditChatModal";
import { MainLink } from "./MainLink";
import { useHover } from "@mantine/hooks";
import { Chat } from "../db";
+import { useIncognitoMode } from "../hooks/contexts";
export function ChatItem({ chat, active = false }: { chat: Chat, active?: boolean }) {
const { hovered, ref } = useHover();
const theme = useMantineTheme();
+ const { incognitoMode } = useIncognitoMode()
return (
diff --git a/src/components/EditChatModal.tsx b/src/components/EditChatModal.tsx
index 0fb020b..2304319 100644
--- a/src/components/EditChatModal.tsx
+++ b/src/components/EditChatModal.tsx
@@ -27,25 +27,24 @@ export function EditChatModal({
const [writingTone, setWritingTone] = useState(null);
const [writingStyle, setWritingStyle] = useState(null);
const [writingFormat, setWritingFormat] = useState(null);
-
const [model, setModel] = useState('default');
const [value, setValue] = useState("");
useEffect(() => {
setValue(chat?.description ?? "");
+ setModel(chat.model ?? 'default')
+ setWritingInstructions(chat.writingInstructions ?? null)
+ setWritingCharacter(chat.writingCharacter ?? null)
+ setWritingTone(chat.writingTone ?? null)
+ setWritingStyle(chat.writingStyle ?? null)
+ setWritingFormat(chat.writingFormat ?? null)
- if (chat.model) setModel(chat.model)
if (chat.prompt) {
setPromptKey(chat.prompt)
} else {
setPromptKey(null)
- if (chat.writingInstructions) setWritingInstructions(chat.writingInstructions)
- if (chat.writingCharacter) setWritingCharacter(chat.writingCharacter)
- if (chat.writingTone) setWritingTone(chat.writingTone)
- if (chat.writingStyle) setWritingStyle(chat.writingStyle)
- if (chat.writingFormat) setWritingFormat(chat.writingFormat)
}
- }, [chat]);
+ }, [chat, opened]);
useEffect(() => {
const prompt = prompts.find(prompt => prompt.key === promptKey)
@@ -73,6 +72,17 @@ export function EditChatModal({
}
}, [writingInstructions, writingCharacter, writingFormat, writingStyle, writingTone]);
+ // const handleClose = () => {
+ // close()
+ // setPromptKey(null)
+ // setWritingInstructions(null)
+ // setWritingCharacter(null)
+ // setWritingTone(null)
+ // setWritingStyle(null)
+ // setWritingFormat(null)
+ // setModel('default')
+ // }
+
return (
<>
{cloneElement(children, { onClick: open })}
diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx
index 32b970e..109f66e 100644
--- a/src/components/Layout.tsx
+++ b/src/components/Layout.tsx
@@ -18,6 +18,8 @@ import {
IconPlus,
IconSearch,
IconSettings,
+ IconSpy,
+ IconSpyOff,
IconX,
} from "@tabler/icons-react";
import { Link, Outlet, useNavigate, useRouter } from "@tanstack/react-location";
@@ -30,9 +32,10 @@ import { LogoText } from "./Logo";
import { Prompts } from "./Prompts";
import { SettingsModal } from "./SettingsModal";
import { config } from "../utils/config";
-import { ChatContext, ChatsContext, PromptsContext, SettingsContext } from "../hooks/contexts";
+import { ChatContext, ChatsContext, IncognitoModeContext, PromptsContext, SettingsContext } from "../hooks/contexts";
import { ChatHeader } from "./ChatHeader";
import { notifications } from "@mantine/notifications";
+import { useLocalStorage } from "@mantine/hooks";
declare global {
interface Window {
@@ -44,13 +47,17 @@ export function Layout() {
const theme = useMantineTheme();
const [opened, setOpened] = useState(false);
const [tab, setTab] = useState<"Chats" | "Prompts">("Chats");
- const { colorScheme } = useMantineColorScheme();
+ const { colorScheme, toggleColorScheme } = useMantineColorScheme();
const navigate = useNavigate();
const router = useRouter();
const [search, setSearch] = useState("");
const chatId = useChatId();
+ const [incognitoMode, setIncognitoMode] = useLocalStorage({
+ key: 'incognito-mode', defaultValue: false
+ });
+
const [settings, setSettings] = useState(null);
useEffect(() => {
const dataFetch = async () => {
@@ -119,172 +126,209 @@ export function Layout() {
setOpened(false);
}, [router.state.location]);
+ const handleIncognito = () => {
+ if (incognitoMode) {
+ setIncognitoMode(false)
+ if (colorScheme === 'dark') {
+ toggleColorScheme()
+ }
+ } else {
+ setIncognitoMode(true)
+ if (colorScheme !== 'dark') {
+ toggleColorScheme()
+ }
+ }
+ }
+
return (
-
-
-
-
+
+
+
-
-
-
-
- ({
- [theme.fn.smallerThan('md')]: {
- marginRight: '2.5rem',
- },
- })}
- >
-
-
-
-
-
-
- ({
- padding: rem(4),
- background:
- theme.colorScheme === "dark"
- ? theme.colors.dark[8]
- : theme.colors.gray[1],
- borderBottom: border,
- })}
- >
- setTab(value as typeof tab)}
- data={["Chats", "Prompts"]}
- />
-
- ({
- padding: rem(4),
- background:
- theme.colorScheme === "dark"
- ? theme.colors.dark[7]
- : theme.white,
- borderBottom: border,
- })}
- >
-
- setSearch(event.currentTarget.value.toLowerCase())
- }
- sx={{ paddingInline: 4 }}
- icon={ }
- rightSection={
- !!search && (
- setSearch("")}>
- {" "}
-
- )
- }
- />
-
-
- {tab === "Chats" && }
- {tab === "Prompts" && (
- setTab("Chats")} />
- )}
-
-
-
- {tab === "Chats" && (
- }
- onClick={async () => {
- if (!settings?.openAiApiKey) {
- notifications.show({
- title: "Error",
- color: "red",
- message: "OpenAI API Key is not defined. Please set your API Key",
- });
- return;
- };
-
- const item = await detaDB.chats.put({
- description: "New Chat",
- prompt: null,
- totalTokens: 0,
- createdAt: new Date().toISOString(),
- }, generateKey())
-
- setChats(chats => ([...(chats || []), item as unknown as Chat]))
-
- const id = item!.key as string
- // const id = nanoid();
- // db.chats.add({
- // id,
- // description: "New Chat",
- // totalTokens: 0,
- // createdAt: new Date(),
- // });
- navigate({ to: `/chats/${id}`, replace: true });
- }}
+
- New Chat
-
+
+
+
+ {incognitoMode ? (
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ )}
+
+
+ ({
+ [theme.fn.smallerThan('md')]: {
+ marginRight: '2.5rem',
+ },
+ })}
+ >
+
+
+
+
+
+
+
+ ({
+ padding: rem(4),
+ background:
+ theme.colorScheme === "dark"
+ ? theme.colors.dark[8]
+ : theme.colors.gray[1],
+ borderBottom: border,
+ })}
+ >
+ setTab(value as typeof tab)}
+ data={["Chats", "Prompts"]}
+ />
+
+ ({
+ padding: rem(4),
+ background:
+ theme.colorScheme === "dark"
+ ? theme.colors.dark[7]
+ : theme.white,
+ borderBottom: border,
+ })}
+ >
+
+ setSearch(event.currentTarget.value.toLowerCase())
+ }
+ sx={{ paddingInline: 4 }}
+ icon={ }
+ rightSection={
+ !!search && (
+ setSearch("")}>
+ {" "}
+
+ )
+ }
+ />
+
+
+ {tab === "Chats" && }
+ {tab === "Prompts" && (
+ setTab("Chats")} />
)}
- {tab === "Prompts" && }
-
-
-
- }
- header={
- chat ? (
-
- ) : undefined
- }
- layout="alt"
- padding={0}
- >
-
- setOpened((o) => !o)}
- size="sm"
- color={theme.colors.gray[6]}
- className="app-region-no-drag"
- sx={{ position: "fixed", top: 16, right: 16, zIndex: 100 }}
- />
-
-
-
+
+
+
+ {tab === "Chats" && (
+ }
+ onClick={async () => {
+ if (!settings?.openAiApiKey) {
+ notifications.show({
+ title: "Error",
+ color: "red",
+ message: "OpenAI API Key is not defined. Please set your API Key",
+ });
+ return;
+ };
+
+ const item = await detaDB.chats.put({
+ description: "New Chat",
+ prompt: null,
+ totalTokens: 0,
+ createdAt: new Date().toISOString(),
+ }, generateKey())
+
+ setChats(chats => ([...(chats || []), item as unknown as Chat]))
+
+ const id = item!.key as string
+ // const id = nanoid();
+ // db.chats.add({
+ // id,
+ // description: "New Chat",
+ // totalTokens: 0,
+ // createdAt: new Date(),
+ // });
+ navigate({ to: `/chats/${id}`, replace: true });
+ }}
+ >
+ {incognitoMode ? "New Incognito Chat" : "New Chat"}
+
+ )}
+ {tab === "Prompts" && }
+
+
+
+ }
+ header={
+ chat ? (
+
+ ) : undefined
+ }
+ layout="alt"
+ padding={0}
+ >
+
+ setOpened((o) => !o)}
+ size="sm"
+ color={theme.colors.gray[6]}
+ className="app-region-no-drag"
+ sx={{ position: "fixed", top: 16, right: 16, zIndex: 100 }}
+ />
+
+
+
+
diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx
index 91dc3be..6ebc894 100644
--- a/src/components/SettingsModal.tsx
+++ b/src/components/SettingsModal.tsx
@@ -3,13 +3,16 @@ import {
Anchor,
Button,
Flex,
- List,
Modal,
PasswordInput,
TextInput,
Select,
Stack,
Text,
+ useMantineColorScheme,
+ Box,
+ SegmentedControl,
+ Center,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { notifications } from "@mantine/notifications";
@@ -18,6 +21,7 @@ import { Settings, detaDB } from "../db";
import { config } from "../utils/config";
import { checkOpenAIKey } from "../utils/openai";
import { useSettings } from "../hooks/contexts";
+import { IconMoonStars, IconSunHigh } from "@tabler/icons-react";
export function SettingsModal({ children }: { children: ReactElement }) {
const [opened, { open, close }] = useDisclosure(false);
@@ -31,6 +35,7 @@ export function SettingsModal({ children }: { children: ReactElement }) {
const [version, setVersion] = useState("");
const { settings, setSettings } = useSettings()
+ const { colorScheme, toggleColorScheme } = useMantineColorScheme();
useEffect(() => {
if (settings?.openAiApiKey) {
@@ -58,6 +63,33 @@ export function SettingsModal({ children }: { children: ReactElement }) {
{cloneElement(children, { onClick: open })}
+
+ Theme
+ toggleColorScheme()}
+ data={[
+ {
+ value: 'light',
+ label: (
+
+
+ Light
+
+ ),
+ },
+ {
+ value: 'dark',
+ label: (
+
+
+ Dark
+
+ ),
+ },
+ ]}
+ />
+
-
-
-
-
- Get your OpenAI API key
-
-
-
-
-
- The API Key is stored locally on your browser and never sent
- anywhere else.
-
-
-
+
+
+ Get your OpenAI API key
+
+
>
+}>({ incognitoMode: false, setIncognitoMode: () => {} });
+
+export function useIncognitoMode() {
+ return useContext(IncognitoModeContext);
+}
\ No newline at end of file