Add simple mode (#113)

* Add simple mode

The current UI is too complicated for some first time users.
This commit adds a "Advanced mode" toggle that defaults on but can be
turned off. When the toggle if switched off, the simple mode is
activated and following UI elements are hided:

- Model parameters setting
- Role switch
- Save button (This means user must save *and* submit in simple mode.)

* Simple mode: Fix ctrl-enter in non-sticky blocks

* i18n

* hide token count

* add back save button

* remove unused variables

---------

Co-authored-by: Jing Hua <tohjinghua123@gmail.com>
This commit is contained in:
Peng Guanwen 2023-04-15 22:03:33 +08:00 committed by GitHub
parent f5f777b54b
commit c2d833b332
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 68 additions and 10 deletions

View file

@ -24,6 +24,7 @@
"setting": "Indstillinger", "setting": "Indstillinger",
"image": "Billede", "image": "Billede",
"autoTitle": "Auto generer titel", "autoTitle": "Auto generer titel",
"advancedMode": "Avanceret tilstand",
"prompt": "Opgave", "prompt": "Opgave",
"promptLibrary": "Opgavebibliotek", "promptLibrary": "Opgavebibliotek",
"name": "Navn", "name": "Navn",

View file

@ -24,6 +24,7 @@
"setting": "Settings", "setting": "Settings",
"image": "Image", "image": "Image",
"autoTitle": "Auto generate title", "autoTitle": "Auto generate title",
"advancedMode": "Advanced mode",
"prompt": "Prompt", "prompt": "Prompt",
"promptLibrary": "Prompt Library", "promptLibrary": "Prompt Library",
"name": "Name", "name": "Name",

View file

@ -24,6 +24,7 @@
"setting": "Settings", "setting": "Settings",
"image": "Image", "image": "Image",
"autoTitle": "Auto generate title", "autoTitle": "Auto generate title",
"advancedMode": "Advanced mode",
"prompt": "Prompt", "prompt": "Prompt",
"promptLibrary": "Prompt Library", "promptLibrary": "Prompt Library",
"name": "Name", "name": "Name",

View file

@ -24,6 +24,7 @@
"setting": "Ajustes", "setting": "Ajustes",
"image": "Imagen", "image": "Imagen",
"autoTitle": "Generar automáticamente el título de la conversación.", "autoTitle": "Generar automáticamente el título de la conversación.",
"advancedMode": "Modo avanzado",
"prompt": "Prompt", "prompt": "Prompt",
"promptLibrary": "Librería de Prompts", "promptLibrary": "Librería de Prompts",
"name": "Nombre", "name": "Nombre",

View file

@ -24,6 +24,7 @@
"setting": "Paramètres", "setting": "Paramètres",
"image": "Image", "image": "Image",
"autoTitle": "Générer le titre automatiquement", "autoTitle": "Générer le titre automatiquement",
"advancedMode": "Mode avancé",
"prompt": "Incitation", "prompt": "Incitation",
"promptLibrary": "Bibliothèque de prompt", "promptLibrary": "Bibliothèque de prompt",
"name": "Nom", "name": "Nom",

View file

@ -24,6 +24,7 @@
"setting": "Impostazioni", "setting": "Impostazioni",
"image": "Immagine", "image": "Immagine",
"autoTitle": "Genera automaticamente il titolo", "autoTitle": "Genera automaticamente il titolo",
"advancedMode": "Modalità avanzata",
"prompt": "Prompt", "prompt": "Prompt",
"promptLibrary": "Libreria Prompt", "promptLibrary": "Libreria Prompt",
"name": "Nome", "name": "Nome",

View file

@ -24,6 +24,7 @@
"setting": "設定", "setting": "設定",
"image": "画像", "image": "画像",
"autoTitle": "タイトルを自動生成", "autoTitle": "タイトルを自動生成",
"advancedMode": "上級モード",
"prompt": "プロンプト", "prompt": "プロンプト",
"promptLibrary": "プロンプトライブラリ", "promptLibrary": "プロンプトライブラリ",
"name": "名前", "name": "名前",

View file

@ -24,6 +24,7 @@
"setting": "Tetapan", "setting": "Tetapan",
"image": "Imej", "image": "Imej",
"autoTitle": "Jana tajuk secara automatik", "autoTitle": "Jana tajuk secara automatik",
"advancedMode": "Mod lanjutan",
"prompt": "Arahan", "prompt": "Arahan",
"promptLibrary": "Pustaka Arahan", "promptLibrary": "Pustaka Arahan",
"name": "Nama", "name": "Nama",

View file

@ -24,6 +24,7 @@
"setting": "Innstillinger", "setting": "Innstillinger",
"image": "Bilde", "image": "Bilde",
"autoTitle": "Auto generer tittel", "autoTitle": "Auto generer tittel",
"advancedMode": "Avansert modus",
"prompt": "Oppgave", "prompt": "Oppgave",
"promptLibrary": "Oppgavebibliotek", "promptLibrary": "Oppgavebibliotek",
"name": "Navn", "name": "Navn",

View file

@ -24,6 +24,7 @@
"setting": "Inställningar", "setting": "Inställningar",
"image": "Bild", "image": "Bild",
"autoTitle": "Auto generera titel", "autoTitle": "Auto generera titel",
"advancedMode": "Avancerat läge",
"prompt": "Uppmaning", "prompt": "Uppmaning",
"promptLibrary": "Uppmaningsbibliotek", "promptLibrary": "Uppmaningsbibliotek",
"name": "Namn", "name": "Namn",

View file

@ -24,6 +24,7 @@
"setting": "设置", "setting": "设置",
"image": "图片", "image": "图片",
"autoTitle": "自动生成标题", "autoTitle": "自动生成标题",
"advancedMode": "高级模式",
"prompt": "提示词", "prompt": "提示词",
"promptLibrary": "提示词资料库", "promptLibrary": "提示词资料库",
"name": "名称", "name": "名称",

View file

@ -24,6 +24,7 @@
"setting": "設定", "setting": "設定",
"image": "圖片", "image": "圖片",
"autoTitle": "自動生成標題", "autoTitle": "自動生成標題",
"advancedMode": "高級模式",
"prompt": "Prompt", "prompt": "Prompt",
"promptLibrary": "Prompt 資料庫", "promptLibrary": "Prompt 資料庫",
"name": "名", "name": "名",

View file

@ -24,6 +24,7 @@
"setting": "設定", "setting": "設定",
"image": "圖片", "image": "圖片",
"autoTitle": "自動生成標題", "autoTitle": "自動生成標題",
"advancedMode": "高級模式",
"prompt": "提示詞", "prompt": "提示詞",
"promptLibrary": "提示詞資料庫", "promptLibrary": "提示詞資料庫",
"name": "名稱", "name": "名稱",

View file

@ -32,6 +32,7 @@ const ChatContent = () => {
? state.chats[state.currentChatIndex].messages.length ? state.chats[state.currentChatIndex].messages.length
: 0 : 0
); );
const advancedMode = useStore((state) => state.advancedMode);
const generating = useStore.getState().generating; const generating = useStore.getState().generating;
const hideSideMenu = useStore((state) => state.hideSideMenu); const hideSideMenu = useStore((state) => state.hideSideMenu);
@ -58,8 +59,8 @@ const ChatContent = () => {
className='flex flex-col items-center text-sm dark:bg-gray-800 w-full' className='flex flex-col items-center text-sm dark:bg-gray-800 w-full'
ref={saveRef} ref={saveRef}
> >
<ChatTitle /> {advancedMode && <ChatTitle />}
{!generating && messages?.length === 0 && ( {!generating && advancedMode && messages?.length === 0 && (
<NewMessageButton messageIndex={-1} /> <NewMessageButton messageIndex={-1} />
)} )}
{messages?.map((message, index) => ( {messages?.map((message, index) => (
@ -69,7 +70,7 @@ const ChatContent = () => {
content={message.content} content={message.content}
messageIndex={index} messageIndex={index}
/> />
{!generating && <NewMessageButton messageIndex={index} />} {!generating && advancedMode && <NewMessageButton messageIndex={index} />}
</React.Fragment> </React.Fragment>
))} ))}
</div> </div>

View file

@ -27,6 +27,7 @@ const Message = React.memo(
sticky?: boolean; sticky?: boolean;
}) => { }) => {
const hideSideMenu = useStore((state) => state.hideSideMenu); const hideSideMenu = useStore((state) => state.hideSideMenu);
const advancedMode = useStore((state) => state.advancedMode);
return ( return (
<div <div
@ -43,11 +44,12 @@ const Message = React.memo(
> >
<Avatar role={role} /> <Avatar role={role} />
<div className='w-[calc(100%-50px)] '> <div className='w-[calc(100%-50px)] '>
<RoleSelector {advancedMode &&
role={role} <RoleSelector
messageIndex={messageIndex} role={role}
sticky={sticky} messageIndex={messageIndex}
/> sticky={sticky}
/>}
<MessageContent <MessageContent
role={role} role={role}
content={content} content={content}

View file

@ -43,10 +43,11 @@ const MessageContent = ({
sticky?: boolean; sticky?: boolean;
}) => { }) => {
const [isEdit, setIsEdit] = useState<boolean>(sticky); const [isEdit, setIsEdit] = useState<boolean>(sticky);
const advancedMode = useStore((state) => state.advancedMode);
return ( return (
<div className='relative flex flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]'> <div className='relative flex flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)]'>
<div className='flex flex-grow flex-col gap-3'></div> {advancedMode && <div className='flex flex-grow flex-col gap-3'></div>}
{isEdit ? ( {isEdit ? (
<EditView <EditView
content={content} content={content}
@ -483,6 +484,7 @@ const EditViewButtons = React.memo(
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const generating = useStore.getState().generating; const generating = useStore.getState().generating;
const advancedMode = useStore((state) => state.advancedMode);
return ( return (
<div className='flex'> <div className='flex'>
@ -539,7 +541,7 @@ const EditViewButtons = React.memo(
</button> </button>
)} )}
</div> </div>
{sticky && <TokenCount />} {sticky && advancedMode && <TokenCount />}
<CommandPrompt _setContent={_setContent} /> <CommandPrompt _setContent={_setContent} />
</div> </div>
); );

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 AdvancedModeToggle = () => {
const { t } = useTranslation();
const setAdvancedMode = useStore((state) => state.setAdvancedMode);
const [isChecked, setIsChecked] = useState<boolean>(
useStore.getState().advancedMode
);
useEffect(() => {
setAdvancedMode(isChecked);
}, [isChecked]);
return (
<Toggle
label={t('advancedMode') as string}
isChecked={isChecked}
setIsChecked={setIsChecked}
/>
);
};
export default AdvancedModeToggle;

View file

@ -8,6 +8,7 @@ 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'; import AutoTitleToggle from './AutoTitleToggle';
import AdvancedModeToggle from './AdvencedModeToggle';
import PromptLibraryMenu from '@components/PromptLibraryMenu'; import PromptLibraryMenu from '@components/PromptLibraryMenu';
import ChatConfigMenu from '@components/ChatConfigMenu'; import ChatConfigMenu from '@components/ChatConfigMenu';
import EnterToSubmitToggle from './EnterToSubmitToggle'; import EnterToSubmitToggle from './EnterToSubmitToggle';
@ -44,6 +45,7 @@ const SettingsMenu = () => {
<div className='flex flex-col gap-3'> <div className='flex flex-col gap-3'>
<AutoTitleToggle /> <AutoTitleToggle />
<EnterToSubmitToggle /> <EnterToSubmitToggle />
<AdvancedModeToggle />
</div> </div>
<PromptLibraryMenu /> <PromptLibraryMenu />
<ChatConfigMenu /> <ChatConfigMenu />

View file

@ -8,6 +8,7 @@ export interface ConfigSlice {
theme: Theme; theme: Theme;
autoTitle: boolean; autoTitle: boolean;
hideMenuOptions: boolean; hideMenuOptions: boolean;
advancedMode: boolean;
defaultChatConfig: ConfigInterface; defaultChatConfig: ConfigInterface;
defaultSystemMessage: string; defaultSystemMessage: string;
hideSideMenu: boolean; hideSideMenu: boolean;
@ -15,6 +16,7 @@ export interface ConfigSlice {
setOpenConfig: (openConfig: boolean) => void; setOpenConfig: (openConfig: boolean) => void;
setTheme: (theme: Theme) => void; setTheme: (theme: Theme) => void;
setAutoTitle: (autoTitle: boolean) => void; setAutoTitle: (autoTitle: boolean) => void;
setAdvancedMode: (advancedMode: boolean) => void;
setDefaultChatConfig: (defaultChatConfig: ConfigInterface) => void; setDefaultChatConfig: (defaultChatConfig: ConfigInterface) => void;
setDefaultSystemMessage: (defaultSystemMessage: string) => void; setDefaultSystemMessage: (defaultSystemMessage: string) => void;
setHideMenuOptions: (hideMenuOptions: boolean) => void; setHideMenuOptions: (hideMenuOptions: boolean) => void;
@ -29,6 +31,7 @@ export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
hideSideMenu: false, hideSideMenu: false,
autoTitle: false, autoTitle: false,
enterToSubmit: true, enterToSubmit: true,
advancedMode: true,
defaultChatConfig: _defaultChatConfig, defaultChatConfig: _defaultChatConfig,
defaultSystemMessage: _defaultSystemMessage, defaultSystemMessage: _defaultSystemMessage,
setOpenConfig: (openConfig: boolean) => { setOpenConfig: (openConfig: boolean) => {
@ -49,6 +52,12 @@ export const createConfigSlice: StoreSlice<ConfigSlice> = (set, get) => ({
autoTitle: autoTitle, autoTitle: autoTitle,
})); }));
}, },
setAdvancedMode: (advancedMode: boolean) => {
set((prev: ConfigSlice) => ({
...prev,
advancedMode: advancedMode,
}));
},
setDefaultChatConfig: (defaultChatConfig: ConfigInterface) => { setDefaultChatConfig: (defaultChatConfig: ConfigInterface) => {
set((prev: ConfigSlice) => ({ set((prev: ConfigSlice) => ({
...prev, ...prev,

View file

@ -46,6 +46,7 @@ export const createPartializedState = (state: StoreState) => ({
apiEndpoint: state.apiEndpoint, apiEndpoint: state.apiEndpoint,
theme: state.theme, theme: state.theme,
autoTitle: state.autoTitle, autoTitle: state.autoTitle,
advancedMode: state.advancedMode,
prompts: state.prompts, prompts: state.prompts,
defaultChatConfig: state.defaultChatConfig, defaultChatConfig: state.defaultChatConfig,
defaultSystemMessage: state.defaultSystemMessage, defaultSystemMessage: state.defaultSystemMessage,