feat: auto generate title setting

This commit is contained in:
Jing Hua 2023-03-13 13:22:48 +08:00
parent 4c80898078
commit 4313446dd3
11 changed files with 91 additions and 8 deletions

View file

@ -22,5 +22,6 @@
"lightMode": "Light Mode", "lightMode": "Light Mode",
"darkMode": "Dark Mode", "darkMode": "Dark Mode",
"setting": "Settings", "setting": "Settings",
"image": "Image" "image": "Image",
"autoTitle": "Auto generate title"
} }

View file

@ -22,5 +22,6 @@
"lightMode": "亮色模式", "lightMode": "亮色模式",
"darkMode": "黑暗模式", "darkMode": "黑暗模式",
"setting": "设置", "setting": "设置",
"image": "图片" "image": "图片",
"autoTitle": "自动生成标题"
} }

View file

@ -0,0 +1,28 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import useStore from '@store/store';
import Toggle from '@components/Toggle';
const AutoTitleToggle = () => {
const { t } = useTranslation();
const setAutoTitle = useStore((state) => state.setAutoTitle);
const [isChecked, setIsChecked] = useState<boolean>(
useStore.getState().autoTitle
);
useEffect(() => {
setAutoTitle(isChecked);
}, [isChecked]);
return (
<Toggle
label={t('autoTitle') as string}
isChecked={isChecked}
setIsChecked={setIsChecked}
/>
);
};
export default AutoTitleToggle;

View file

@ -6,6 +6,7 @@ import PopupModal from '@components/PopupModal';
import SettingIcon from '@icon/SettingIcon'; import SettingIcon from '@icon/SettingIcon';
import ThemeSwitcher from '@components/Menu/MenuOptions/ThemeSwitcher'; import ThemeSwitcher from '@components/Menu/MenuOptions/ThemeSwitcher';
import LanguageSelector from '@components/LanguageSelector'; import LanguageSelector from '@components/LanguageSelector';
import AutoTitleToggle from './AutoTitleToggle';
const SettingsMenu = () => { const SettingsMenu = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -35,6 +36,7 @@ const SettingsMenu = () => {
<div className='p-6 border-b border-gray-200 dark:border-gray-600 flex flex-col items-center gap-4'> <div className='p-6 border-b border-gray-200 dark:border-gray-600 flex flex-col items-center gap-4'>
<LanguageSelector /> <LanguageSelector />
<ThemeSwitcher /> <ThemeSwitcher />
<AutoTitleToggle />
</div> </div>
</PopupModal> </PopupModal>
)} )}

View file

@ -0,0 +1,30 @@
import React from 'react';
const Toggle = ({
label,
isChecked,
setIsChecked,
}: {
label: string;
isChecked: boolean;
setIsChecked: React.Dispatch<React.SetStateAction<boolean>>;
}) => {
return (
<label className='relative flex items-center cursor-pointer'>
<input
type='checkbox'
className='sr-only peer'
checked={isChecked}
onChange={() => {
setIsChecked((prev) => !prev);
}}
/>
<div className="w-9 h-5 bg-gray-200 dark:bg-gray-600 rounded-full peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-4 after:w-4 after:transition-all dark:border-gray-600 peer-checked:bg-green-500/70"></div>
<span className='ml-3 text-sm font-medium text-gray-900 dark:text-gray-300'>
{label}
</span>
</label>
);
};
export default Toggle;

View file

@ -0,0 +1 @@
export { default } from './Toggle';

View file

@ -119,7 +119,11 @@ const useSubmit = () => {
// generate title for new chats // generate title for new chats
const currChats = useStore.getState().chats; const currChats = useStore.getState().chats;
if (currChats && !currChats[currentChatIndex]?.titleSet) { if (
useStore.getState().autoTitle &&
currChats &&
!currChats[currentChatIndex]?.titleSet
) {
const messages_length = currChats[currentChatIndex].messages.length; const messages_length = currChats[currentChatIndex].messages.length;
const assistant_message = const assistant_message =
currChats[currentChatIndex].messages[messages_length - 1].content; currChats[currentChatIndex].messages[messages_length - 1].content;

View file

@ -4,13 +4,16 @@ import { Theme } from '@type/theme';
export interface ConfigSlice { export interface ConfigSlice {
openConfig: boolean; openConfig: boolean;
theme: Theme; theme: Theme;
autoTitle: boolean;
setOpenConfig: (openConfig: boolean) => void; setOpenConfig: (openConfig: boolean) => void;
setTheme: (theme: Theme) => void; setTheme: (theme: Theme) => void;
setAutoTitle: (autoTitle: boolean) => void;
} }
export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({ export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
openConfig: false, openConfig: false,
theme: 'dark', theme: 'dark',
autoTitle: false,
setOpenConfig: (openConfig: boolean) => { setOpenConfig: (openConfig: boolean) => {
set((prev: ConfigSlice) => ({ set((prev: ConfigSlice) => ({
...prev, ...prev,
@ -23,4 +26,10 @@ export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
theme: theme, theme: theme,
})); }));
}, },
setAutoTitle: (autoTitle: boolean) => {
set((prev: ConfigSlice) => ({
...prev,
autoTitle: autoTitle,
}));
},
}); });

View file

@ -1,9 +1,10 @@
import { import {
LocalStorageInterfaceV0ToV1, LocalStorageInterfaceV0ToV1,
LocalStorageInterfaceV1ToV2, LocalStorageInterfaceV1ToV2,
LocalStorageInterfaceV2ToV3,
} from '@type/chat'; } from '@type/chat';
import { defaultChatConfig } from '@constants/chat'; import { defaultChatConfig } from '@constants/chat';
import { defaultAPIEndpoint, officialAPIEndpoint } from '@constants/auth'; import { officialAPIEndpoint } from '@constants/auth';
export const migrateV0 = (persistedState: LocalStorageInterfaceV0ToV1) => { export const migrateV0 = (persistedState: LocalStorageInterfaceV0ToV1) => {
persistedState.chats.forEach((chat) => { persistedState.chats.forEach((chat) => {
@ -20,9 +21,13 @@ export const migrateV1 = (persistedState: LocalStorageInterfaceV1ToV2) => {
} }
}; };
export const migrateV2 = (persistedState: LocalStorageInterfaceV1ToV2) => { export const migrateV2 = (persistedState: LocalStorageInterfaceV2ToV3) => {
persistedState.chats.forEach((chat) => { persistedState.chats.forEach((chat) => {
chat.config.top_p = defaultChatConfig.top_p; chat.config = {
chat.config.frequency_penalty = defaultChatConfig.frequency_penalty; ...chat.config,
top_p: defaultChatConfig.top_p,
frequency_penalty: defaultChatConfig.frequency_penalty,
};
}); });
persistedState.autoTitle = false;
}; };

View file

@ -35,6 +35,7 @@ const useStore = create<StoreState>()(
apiFree: state.apiFree, apiFree: state.apiFree,
apiEndpoint: state.apiEndpoint, apiEndpoint: state.apiEndpoint,
theme: state.theme, theme: state.theme,
autoTitle: state.autoTitle,
}), }),
version: 3, version: 3,
migrate: (persistedState, version) => { migrate: (persistedState, version) => {

View file

@ -49,4 +49,5 @@ export interface LocalStorageInterfaceV2ToV3 {
apiFreeEndpoint: string; apiFreeEndpoint: string;
apiEndpoint?: string; apiEndpoint?: string;
theme: Theme; theme: Theme;
autoTitle: boolean;
} }