Skip to content

Commit

Permalink
Update setting page saving UX
Browse files Browse the repository at this point in the history
  • Loading branch information
wong2 committed Dec 22, 2023
1 parent f6d017b commit 156593f
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 116 deletions.
2 changes: 1 addition & 1 deletion src/app/components/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const PagePanel: FC<PropsWithChildren<{ title: string }>> = (props) => {
<div className="text-center border-b border-solid border-primary-border flex flex-col justify-center mx-10 py-2">
<span className="font-semibold text-lg">{props.title}</span>
</div>
<div className="px-10 h-full overflow-auto">{props.children}</div>
<div className="h-full overflow-auto">{props.children}</div>
</div>
)
}
Expand Down
3 changes: 2 additions & 1 deletion src/app/i18n/locales/japanese.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,6 @@
"Login to Claude.ai": "Claude.aiにログインする",
"Login to Bard": "Bardにログインする",
"Recent Updates": "最近の更新",
"Added a separate Gemini Pro bot, can be enabled in the settings": "独立したGemini Proボットを追加しました。設定で有効にできます"
"Added a separate Gemini Pro bot, can be enabled in the settings": "独立したGemini Proボットを追加しました。設定で有効にできます",
"Save changes": "変更を保存する"
}
3 changes: 2 additions & 1 deletion src/app/i18n/locales/simplified-chinese.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,6 @@
"Login to Claude.ai": "登录Claude.ai",
"Login to Bard": "登录Bard",
"Recent Updates": "最近更新",
"Added a separate Gemini Pro bot, can be enabled in the settings": "添加了Gemini Pro,可在设置中启用"
"Added a separate Gemini Pro bot, can be enabled in the settings": "添加了Gemini Pro,可在设置中启用",
"Save changes": "保存更改"
}
223 changes: 110 additions & 113 deletions src/app/pages/SettingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { motion } from 'framer-motion'
import { FC, PropsWithChildren, useCallback, useEffect, useState } from 'react'
import toast, { Toaster } from 'react-hot-toast'
import { useTranslation } from 'react-i18next'
import Browser from 'webextension-polyfill'
import { MotionButton } from '~app/components/Button'
import Button from '~app/components/Button'
import { Input } from '~app/components/Input'
import RadioGroup from '~app/components/RadioGroup'
import Select from '~app/components/Select'
Expand Down Expand Up @@ -93,125 +94,121 @@ function SettingPage() {

return (
<PagePanel title={`${t('Settings')} (v${getVersion()})`}>
<div className="flex flex-row mt-3 mb-5 gap-3">
<div className="flex flex-col gap-5">
<div>
<p className="font-bold mb-2 text-lg">{t('Startup page')}</p>
<div className="w-[200px]">
<Select
options={[
{ name: 'All-In-One', value: ALL_IN_ONE_PAGE_ID },
...Object.entries(CHATBOTS).map(([botId, bot]) => ({ name: bot.name, value: botId })),
]}
value={userConfig.startupPage}
onChange={(v) => updateConfigValue({ startupPage: v })}
/>
</div>
</div>
<div className="flex flex-col gap-2 max-w-[700px]">
<p className="font-bold text-lg">{t('Chatbots')}</p>
<EnabledBotsSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
<div className="flex flex-col gap-5 mt-3 mb-10 px-10">
<div>
<p className="font-bold mb-2 text-lg">{t('Startup page')}</p>
<div className="w-[200px]">
<Select
options={[
{ name: 'All-In-One', value: ALL_IN_ONE_PAGE_ID },
...Object.entries(CHATBOTS).map(([botId, bot]) => ({ name: bot.name, value: botId })),
]}
value={userConfig.startupPage}
onChange={(v) => updateConfigValue({ startupPage: v })}
/>
</div>
<div className="flex flex-col gap-5 w-fit max-w-[700px]">
<ChatBotSettingPanel title="ChatGPT">
<RadioGroup
options={Object.entries(ChatGPTMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.chatgptMode}
onChange={(v) => updateConfigValue({ chatgptMode: v as ChatGPTMode })}
/>
{userConfig.chatgptMode === ChatGPTMode.API ? (
<ChatGPTAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.Azure ? (
<ChatGPTAzureSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.Poe ? (
<ChatGPTPoeSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.OpenRouter ? (
<ChatGPTOpenRouterSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : (
<ChatGPWebSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Claude">
<RadioGroup
options={Object.entries(ClaudeMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.claudeMode}
onChange={(v) => updateConfigValue({ claudeMode: v as ClaudeMode })}
</div>
<div className="flex flex-col gap-2 max-w-[700px]">
<p className="font-bold text-lg">{t('Chatbots')}</p>
<EnabledBotsSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
</div>
<div className="flex flex-col gap-5 w-fit max-w-[700px]">
<ChatBotSettingPanel title="ChatGPT">
<RadioGroup
options={Object.entries(ChatGPTMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.chatgptMode}
onChange={(v) => updateConfigValue({ chatgptMode: v as ChatGPTMode })}
/>
{userConfig.chatgptMode === ChatGPTMode.API ? (
<ChatGPTAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.Azure ? (
<ChatGPTAzureSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.Poe ? (
<ChatGPTPoeSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.chatgptMode === ChatGPTMode.OpenRouter ? (
<ChatGPTOpenRouterSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : (
<ChatGPWebSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Claude">
<RadioGroup
options={Object.entries(ClaudeMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.claudeMode}
onChange={(v) => updateConfigValue({ claudeMode: v as ClaudeMode })}
/>
{userConfig.claudeMode === ClaudeMode.API ? (
<ClaudeAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.claudeMode === ClaudeMode.Webapp ? (
<ClaudeWebappSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.claudeMode === ClaudeMode.OpenRouter ? (
<ClaudeOpenRouterSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : (
<ClaudePoeSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Gemini Pro">
<div className="flex flex-col gap-1">
<p className="font-medium text-sm">
API Key (
<a
href="https://makersuite.google.com/app/apikey"
target="_blank"
rel="noreferrer"
className="underline"
>
how to create key
</a>
)
</p>
<Input
className="w-[400px]"
placeholder="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
value={userConfig.geminiApiKey}
onChange={(e) => updateConfigValue({ geminiApiKey: e.currentTarget.value })}
type="password"
/>
{userConfig.claudeMode === ClaudeMode.API ? (
<ClaudeAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.claudeMode === ClaudeMode.Webapp ? (
<ClaudeWebappSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : userConfig.claudeMode === ClaudeMode.OpenRouter ? (
<ClaudeOpenRouterSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
) : (
<ClaudePoeSettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Gemini Pro">
<div className="flex flex-col gap-1">
<p className="font-medium text-sm">
API Key (
<a
href="https://makersuite.google.com/app/apikey"
target="_blank"
rel="noreferrer"
className="underline"
>
how to create key
</a>
)
</p>
<Input
className="w-[400px]"
placeholder="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
value={userConfig.geminiApiKey}
onChange={(e) => updateConfigValue({ geminiApiKey: e.currentTarget.value })}
type="password"
<Blockquote className="mt-1">{t('Your keys are stored locally')}</Blockquote>
</div>
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Bing">
<div className="flex flex-row gap-5 items-center">
<p className="font-medium">{t('Chat style')}</p>
<div className="w-[150px]">
<Select
options={BING_STYLE_OPTIONS}
value={userConfig.bingConversationStyle}
onChange={(v) => updateConfigValue({ bingConversationStyle: v })}
position="top"
/>
<Blockquote className="mt-1">{t('Your keys are stored locally')}</Blockquote>
</div>
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Bing">
<div className="flex flex-row gap-5 items-center">
<p className="font-medium">{t('Chat style')}</p>
<div className="w-[150px]">
<Select
options={BING_STYLE_OPTIONS}
value={userConfig.bingConversationStyle}
onChange={(v) => updateConfigValue({ bingConversationStyle: v })}
position="top"
/>
</div>
</div>
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Perplexity">
<RadioGroup
options={Object.entries(PerplexityMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.perplexityMode}
onChange={(v) => updateConfigValue({ perplexityMode: v as PerplexityMode })}
/>
{userConfig.perplexityMode === PerplexityMode.API && (
<PerplexityAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
</div>
<ShortcutPanel />
<ExportDataPanel />
</div>
<div>
{dirty && (
<MotionButton
color="primary"
text={t('Save')}
className="w-fit fixed bottom-10"
onClick={save}
animate={{ opacity: [0, 1] }}
transition={{ duration: 0.3 }}
</div>
</ChatBotSettingPanel>
<ChatBotSettingPanel title="Perplexity">
<RadioGroup
options={Object.entries(PerplexityMode).map(([k, v]) => ({ label: `${k} ${t('Mode')}`, value: v }))}
value={userConfig.perplexityMode}
onChange={(v) => updateConfigValue({ perplexityMode: v as PerplexityMode })}
/>
)}
{userConfig.perplexityMode === PerplexityMode.API && (
<PerplexityAPISettings userConfig={userConfig} updateConfigValue={updateConfigValue} />
)}
</ChatBotSettingPanel>
</div>
<ShortcutPanel />
<ExportDataPanel />
</div>
<Toaster position="bottom-right" />
{dirty && (
<motion.div
className="sticky bottom-0 w-full bg-primary-background border-t-2 border-primary-border px-5 py-4 drop-shadow flex flex-row items-center justify-center"
initial={{ y: 100 }}
animate={{ y: 0 }}
transition={{ type: 'tween', ease: 'easeInOut' }}
>
<Button color="primary" size="small" text={t('Save changes')} onClick={save} className="py-2" />
</motion.div>
)}
<Toaster position="bottom-center" />
</PagePanel>
)
}
Expand Down

0 comments on commit 156593f

Please sign in to comment.