mirror of
https://github.com/NovaOSS/nova-betterchat.git
synced 2024-11-25 19:43:59 +01:00
improve caching
This commit is contained in:
parent
16caec5076
commit
6222bb58f3
27
src/App.tsx
27
src/App.tsx
|
@ -1,39 +1,18 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import useStore from '@store/store';
|
||||
|
||||
import Chat from './components/Chat';
|
||||
import Menu from './components/Menu';
|
||||
import ConfigMenu from './components/ConfigMenu';
|
||||
|
||||
import useSaveToLocalStorage from '@hooks/useSaveToLocalStorage';
|
||||
import useInitialiseNewChat from '@hooks/useInitialiseNewChat';
|
||||
|
||||
import { ChatInterface } from '@type/chat';
|
||||
|
||||
function App() {
|
||||
useSaveToLocalStorage();
|
||||
const initialiseNewChat = useInitialiseNewChat();
|
||||
|
||||
const setChats = useStore((state) => state.setChats);
|
||||
const setCurrentChatIndex = useStore((state) => state.setCurrentChatIndex);
|
||||
|
||||
useEffect(() => {
|
||||
const storedChats = localStorage.getItem('chats');
|
||||
if (storedChats) {
|
||||
try {
|
||||
const chats: ChatInterface[] = JSON.parse(storedChats);
|
||||
if (chats.length > 0) {
|
||||
setChats(chats);
|
||||
setCurrentChatIndex(0);
|
||||
} else {
|
||||
initialiseNewChat();
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
setChats([]);
|
||||
setCurrentChatIndex(-1);
|
||||
console.log(e);
|
||||
}
|
||||
} else {
|
||||
const chats = useStore.getState().chats;
|
||||
if (!chats || chats.length === 0) {
|
||||
initialiseNewChat();
|
||||
}
|
||||
}, []);
|
||||
|
|
|
@ -23,7 +23,6 @@ const ConfigMenu = () => {
|
|||
|
||||
if (valid) {
|
||||
setApiKey(_apiKey);
|
||||
localStorage.setItem('apiKey', _apiKey);
|
||||
setError(false);
|
||||
setOpenConfig(false);
|
||||
} else {
|
||||
|
@ -40,11 +39,9 @@ const ConfigMenu = () => {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
const storedApiKey = localStorage.getItem('apiKey');
|
||||
if (storedApiKey) {
|
||||
if (apiKey) {
|
||||
setApiFree(false);
|
||||
setApiKey(storedApiKey);
|
||||
_setApiKey(storedApiKey);
|
||||
_setApiKey(apiKey);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import useStore from '@store/store';
|
||||
import SunIcon from '@icon/SunIcon';
|
||||
import MoonIcon from '@icon/MoonIcon';
|
||||
|
||||
type Theme = 'light' | 'dark';
|
||||
import { Theme } from '@type/theme';
|
||||
|
||||
const getOppositeTheme = (theme: Theme): Theme => {
|
||||
if (theme === 'dark') {
|
||||
|
@ -12,26 +12,15 @@ const getOppositeTheme = (theme: Theme): Theme => {
|
|||
}
|
||||
};
|
||||
const ThemeSwitcher = () => {
|
||||
const [theme, setTheme] = useState<Theme>();
|
||||
const theme = useStore((state) => state.theme);
|
||||
const setTheme = useStore((state) => state.setTheme);
|
||||
|
||||
const switchTheme = () => {
|
||||
setTheme(getOppositeTheme(theme!));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const _theme = localStorage.getItem('theme');
|
||||
if (_theme === 'light' || _theme === 'dark') {
|
||||
setTheme(_theme);
|
||||
} else {
|
||||
setTheme('dark');
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (theme) {
|
||||
document.documentElement.className = theme;
|
||||
localStorage.setItem('theme', theme);
|
||||
}
|
||||
document.documentElement.className = theme;
|
||||
}, [theme]);
|
||||
|
||||
return theme ? (
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
import { StoreSlice } from './store';
|
||||
import { Theme } from '@type/theme';
|
||||
|
||||
export interface ConfigSlice {
|
||||
openConfig: boolean;
|
||||
theme: Theme;
|
||||
setOpenConfig: (openConfig: boolean) => void;
|
||||
setTheme: (theme: Theme) => void;
|
||||
}
|
||||
|
||||
export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
|
||||
openConfig: false,
|
||||
theme: 'dark',
|
||||
setOpenConfig: (openConfig: boolean) => {
|
||||
set((prev: ConfigSlice) => ({
|
||||
...prev,
|
||||
openConfig: openConfig,
|
||||
}));
|
||||
},
|
||||
setTheme: (theme: Theme) => {
|
||||
set((prev: ConfigSlice) => ({
|
||||
...prev,
|
||||
theme: theme,
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import create, { SetState, GetState } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { ChatSlice, createChatSlice } from './chat-slice';
|
||||
import { InputSlice, createInputSlice } from './input-slice';
|
||||
import { AuthSlice, createAuthSlice } from './auth-slice';
|
||||
|
@ -11,11 +12,24 @@ export type StoreSlice<T> = (
|
|||
get: GetState<StoreState>
|
||||
) => T;
|
||||
|
||||
const useStore = create<StoreState>((set, get) => ({
|
||||
...createChatSlice(set, get),
|
||||
...createInputSlice(set, get),
|
||||
...createAuthSlice(set, get),
|
||||
...createConfigSlice(set, get),
|
||||
}));
|
||||
const useStore = create<StoreState>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
...createChatSlice(set, get),
|
||||
...createInputSlice(set, get),
|
||||
...createAuthSlice(set, get),
|
||||
...createConfigSlice(set, get),
|
||||
}),
|
||||
{
|
||||
name: 'free-chat-gpt',
|
||||
partialize: (state) => ({
|
||||
chats: state.chats,
|
||||
currentChatIndex: state.currentChatIndex,
|
||||
apiKey: state.apiKey,
|
||||
theme: state.theme,
|
||||
}),
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
export default useStore;
|
||||
|
|
1
src/types/theme.ts
Normal file
1
src/types/theme.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export type Theme = 'light' | 'dark';
|
Loading…
Reference in a new issue