mirror of
https://github.com/NovaOSS/nova-betterchat.git
synced 2024-11-25 20:24:00 +01:00
feat: auto generate title setting
This commit is contained in:
parent
4c80898078
commit
4313446dd3
|
@ -22,5 +22,6 @@
|
|||
"lightMode": "Light Mode",
|
||||
"darkMode": "Dark Mode",
|
||||
"setting": "Settings",
|
||||
"image": "Image"
|
||||
"image": "Image",
|
||||
"autoTitle": "Auto generate title"
|
||||
}
|
||||
|
|
|
@ -22,5 +22,6 @@
|
|||
"lightMode": "亮色模式",
|
||||
"darkMode": "黑暗模式",
|
||||
"setting": "设置",
|
||||
"image": "图片"
|
||||
"image": "图片",
|
||||
"autoTitle": "自动生成标题"
|
||||
}
|
||||
|
|
28
src/components/SettingsMenu/AutoTitleToggle.tsx
Normal file
28
src/components/SettingsMenu/AutoTitleToggle.tsx
Normal 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;
|
|
@ -6,6 +6,7 @@ import PopupModal from '@components/PopupModal';
|
|||
import SettingIcon from '@icon/SettingIcon';
|
||||
import ThemeSwitcher from '@components/Menu/MenuOptions/ThemeSwitcher';
|
||||
import LanguageSelector from '@components/LanguageSelector';
|
||||
import AutoTitleToggle from './AutoTitleToggle';
|
||||
|
||||
const SettingsMenu = () => {
|
||||
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'>
|
||||
<LanguageSelector />
|
||||
<ThemeSwitcher />
|
||||
<AutoTitleToggle />
|
||||
</div>
|
||||
</PopupModal>
|
||||
)}
|
||||
|
|
30
src/components/Toggle/Toggle.tsx
Normal file
30
src/components/Toggle/Toggle.tsx
Normal 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;
|
1
src/components/Toggle/index.ts
Normal file
1
src/components/Toggle/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { default } from './Toggle';
|
|
@ -119,7 +119,11 @@ const useSubmit = () => {
|
|||
|
||||
// generate title for new 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 assistant_message =
|
||||
currChats[currentChatIndex].messages[messages_length - 1].content;
|
||||
|
|
|
@ -4,13 +4,16 @@ import { Theme } from '@type/theme';
|
|||
export interface ConfigSlice {
|
||||
openConfig: boolean;
|
||||
theme: Theme;
|
||||
autoTitle: boolean;
|
||||
setOpenConfig: (openConfig: boolean) => void;
|
||||
setTheme: (theme: Theme) => void;
|
||||
setAutoTitle: (autoTitle: boolean) => void;
|
||||
}
|
||||
|
||||
export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
|
||||
openConfig: false,
|
||||
theme: 'dark',
|
||||
autoTitle: false,
|
||||
setOpenConfig: (openConfig: boolean) => {
|
||||
set((prev: ConfigSlice) => ({
|
||||
...prev,
|
||||
|
@ -23,4 +26,10 @@ export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
|
|||
theme: theme,
|
||||
}));
|
||||
},
|
||||
setAutoTitle: (autoTitle: boolean) => {
|
||||
set((prev: ConfigSlice) => ({
|
||||
...prev,
|
||||
autoTitle: autoTitle,
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import {
|
||||
LocalStorageInterfaceV0ToV1,
|
||||
LocalStorageInterfaceV1ToV2,
|
||||
LocalStorageInterfaceV2ToV3,
|
||||
} from '@type/chat';
|
||||
import { defaultChatConfig } from '@constants/chat';
|
||||
import { defaultAPIEndpoint, officialAPIEndpoint } from '@constants/auth';
|
||||
import { officialAPIEndpoint } from '@constants/auth';
|
||||
|
||||
export const migrateV0 = (persistedState: LocalStorageInterfaceV0ToV1) => {
|
||||
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) => {
|
||||
chat.config.top_p = defaultChatConfig.top_p;
|
||||
chat.config.frequency_penalty = defaultChatConfig.frequency_penalty;
|
||||
chat.config = {
|
||||
...chat.config,
|
||||
top_p: defaultChatConfig.top_p,
|
||||
frequency_penalty: defaultChatConfig.frequency_penalty,
|
||||
};
|
||||
});
|
||||
persistedState.autoTitle = false;
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ const useStore = create<StoreState>()(
|
|||
apiFree: state.apiFree,
|
||||
apiEndpoint: state.apiEndpoint,
|
||||
theme: state.theme,
|
||||
autoTitle: state.autoTitle,
|
||||
}),
|
||||
version: 3,
|
||||
migrate: (persistedState, version) => {
|
||||
|
|
|
@ -49,4 +49,5 @@ export interface LocalStorageInterfaceV2ToV3 {
|
|||
apiFreeEndpoint: string;
|
||||
apiEndpoint?: string;
|
||||
theme: Theme;
|
||||
autoTitle: boolean;
|
||||
}
|
Loading…
Reference in a new issue