improve preset editor
This commit is contained in:
parent
edf55843e4
commit
d6b536ace9
@ -351,5 +351,7 @@
|
||||
"Create a new user or AI message content. You can prepare a chat record with AI here, and fill in the responses you want to get from AI in the tone of AI. When you use this preset, the chat record will be processed, and at this point, AI will better understand what you want it to do or what role to play.": "新しいユーザーまたはAIメッセージコンテンツを作成します。ここでAIとのチャット記録を準備し、AIから得たい応答をAIのトーンで記入することができます。このプリセットを使用すると、チャット記録が処理され、この時点でAIはあなたが望むことやどのような役割を果たすかをよりよく理解することができます。",
|
||||
"The name used internally by the model when processing user message, changing this value helps improve the role-playing effect.": "ユーザーメッセージを処理する際にモデルが内部で使用する名前、この値を変更することで、役割演技の効果を向上させることができます。",
|
||||
"The name used internally by the model when processing AI message, changing this value helps improve the role-playing effect.": "AIメッセージを処理する際にモデルが内部で使用する名前、この値を変更することで、役割演技の効果を向上させることができます。",
|
||||
"Inside the model, there is a default prompt to improve the model's handling of common issues, but it may degrade the role-playing effect. You can disable this option to achieve a better role-playing effect.": "モデル内部には、一般的な問題の処理を改善するためのデフォルトのプロンプトがありますが、役割演技の効果を低下させる可能性があります。このオプションを無効にすることで、より良い役割演技効果を得ることができます。"
|
||||
"Inside the model, there is a default prompt to improve the model's handling of common issues, but it may degrade the role-playing effect. You can disable this option to achieve a better role-playing effect.": "モデル内部には、一般的な問題の処理を改善するためのデフォルトのプロンプトがありますが、役割演技の効果を低下させる可能性があります。このオプションを無効にすることで、より良い役割演技効果を得ることができます。",
|
||||
"Exit without saving": "保存せずに終了",
|
||||
"Content has been changed, are you sure you want to exit without saving?": "コンテンツが変更されています、保存せずに終了してもよろしいですか?"
|
||||
}
|
@ -351,5 +351,7 @@
|
||||
"Create a new user or AI message content. You can prepare a chat record with AI here, and fill in the responses you want to get from AI in the tone of AI. When you use this preset, the chat record will be processed, and at this point, AI will better understand what you want it to do or what role to play.": "新建一个 用户 或 AI 的发言内容. 你可以在这里准备好一段你与 AI 的聊天记录, 并用 AI 的口吻正确填写你想得到的 AI 的回复, 这样你在使用这个预设时, 这些聊天记录也会被处理, 并且此时 AI 能更好地理解你希望它做什么 / 扮演什么样的角色",
|
||||
"The name used internally by the model when processing user message, changing this value helps improve the role-playing effect.": "模型内部处理用户发言时使用的名称, 更改此值有助于改善角色扮演效果",
|
||||
"The name used internally by the model when processing AI message, changing this value helps improve the role-playing effect.": "模型内部处理AI发言时使用的名称, 更改此值有助于改善角色扮演效果",
|
||||
"Inside the model, there is a default prompt to improve the model's handling of common issues, but it may degrade the role-playing effect. You can disable this option to achieve a better role-playing effect.": "模型内部有一个默认提示来改善模型处理常规问题的效果, 但它可能会让角色扮演的效果变差, 你可以关闭此选项来获得更好的角色扮演效果"
|
||||
"Inside the model, there is a default prompt to improve the model's handling of common issues, but it may degrade the role-playing effect. You can disable this option to achieve a better role-playing effect.": "模型内部有一个默认提示来改善模型处理常规问题的效果, 但它可能会让角色扮演的效果变差, 你可以关闭此选项来获得更好的角色扮演效果",
|
||||
"Exit without saving": "退出而不保存",
|
||||
"Content has been changed, are you sure you want to exit without saving?": "内容已经被修改, 你确定要退出而不保存吗?"
|
||||
}
|
@ -650,7 +650,7 @@ const ChatPanel: FC = observer(() => {
|
||||
}
|
||||
chatSseControllers = {};
|
||||
}
|
||||
setActivePreset(commonStore.activePreset);
|
||||
setActivePreset(commonStore.activePreset, commonStore.activePresetIndex);
|
||||
}} />
|
||||
<div className="relative flex grow">
|
||||
<Textarea
|
||||
|
@ -4,6 +4,7 @@ import React, { FC, lazy, PropsWithChildren, ReactElement, useState } from 'reac
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogBody,
|
||||
DialogContent,
|
||||
DialogSurface,
|
||||
@ -60,10 +61,15 @@ const MessagesEditor = lazy(() => import('./MessagesEditor'));
|
||||
|
||||
const PresetCardFrame: FC<PropsWithChildren & {
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>
|
||||
highlight?: boolean
|
||||
}> = (props) => {
|
||||
return <Button
|
||||
className="flex flex-col gap-1 w-32 h-56 break-all"
|
||||
style={{ minWidth: 0, borderRadius: '0.75rem', justifyContent: 'unset' }}
|
||||
style={{
|
||||
minWidth: 0,
|
||||
borderRadius: '0.75rem',
|
||||
justifyContent: 'unset', ...(props.highlight ? { borderColor: '#115ea3', borderWidth: '2px' } : {})
|
||||
}}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
{props.children}
|
||||
@ -71,31 +77,28 @@ const PresetCardFrame: FC<PropsWithChildren & {
|
||||
};
|
||||
|
||||
const PresetCard: FC<{
|
||||
avatarImg: string,
|
||||
name: string,
|
||||
desc: string,
|
||||
tag: string,
|
||||
editable: boolean,
|
||||
preset: Preset,
|
||||
presetIndex: number,
|
||||
onClick?: () => void
|
||||
}> = observer(({
|
||||
avatarImg, name, desc, tag, editable, presetIndex, onClick
|
||||
editable, preset, presetIndex
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return <PresetCardFrame onClick={(e) => {
|
||||
if (onClick && e.currentTarget.contains(e.target as Node))
|
||||
onClick();
|
||||
}}>
|
||||
<img src={absPathAsset(avatarImg)} className="rounded-xl select-none ml-auto mr-auto h-28" />
|
||||
<Text size={400}>{name}</Text>
|
||||
return <PresetCardFrame highlight={commonStore.activePresetIndex === presetIndex}
|
||||
onClick={(e) => {
|
||||
if (e.currentTarget.contains(e.target as Node))
|
||||
setActivePreset(presetIndex === -1 ? defaultPreset : preset, presetIndex);
|
||||
}}>
|
||||
<img src={absPathAsset(preset.avatarImg)} className="rounded-xl select-none ml-auto mr-auto h-28" />
|
||||
<Text size={400}>{preset.name}</Text>
|
||||
<Text size={200} style={{
|
||||
overflow: 'hidden', textOverflow: 'ellipsis',
|
||||
display: '-webkit-box', WebkitLineClamp: 3, WebkitBoxOrient: 'vertical'
|
||||
}}>{desc}</Text>
|
||||
}}>{preset.desc}</Text>
|
||||
<div className="grow" />
|
||||
<div className="flex justify-between w-full items-end">
|
||||
<div className="text-xs font-thin text-gray-500">{t(tag)}</div>
|
||||
<div className="text-xs font-thin text-gray-500">{t(preset.tag)}</div>
|
||||
{editable ?
|
||||
<ChatPresetEditor presetIndex={presetIndex} triggerButton={
|
||||
<ToolTipButton size="small" appearance="transparent" desc={t('Edit')} icon={<Edit20Regular />}
|
||||
@ -115,9 +118,11 @@ const ChatPresetEditor: FC<{
|
||||
presetIndex: number
|
||||
}> = observer(({ triggerButton, presetIndex }) => {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [showExitConfirm, setShowExitConfirm] = React.useState(false);
|
||||
const [editingMessages, setEditingMessages] = useState(false);
|
||||
|
||||
if (!commonStore.editingPreset)
|
||||
if (open && !commonStore.editingPreset)
|
||||
commonStore.setEditingPreset({ ...defaultPreset });
|
||||
const editingPreset = commonStore.editingPreset!;
|
||||
|
||||
@ -168,26 +173,46 @@ const ChatPresetEditor: FC<{
|
||||
};
|
||||
|
||||
const savePreset = () => {
|
||||
setOpen(false);
|
||||
setShowExitConfirm(false);
|
||||
if (presetIndex === -1) {
|
||||
commonStore.setPresets([...commonStore.presets, { ...editingPreset }]);
|
||||
setEditingPreset(defaultPreset);
|
||||
} else {
|
||||
commonStore.presets[presetIndex] = editingPreset;
|
||||
commonStore.setPresets(commonStore.presets);
|
||||
}
|
||||
commonStore.setEditingPreset(null);
|
||||
};
|
||||
|
||||
const activatePreset = () => {
|
||||
savePreset();
|
||||
setActivePreset(editingPreset);
|
||||
setActivePreset(editingPreset, presetIndex === -1 ? commonStore.presets.length - 1 : presetIndex);
|
||||
};
|
||||
|
||||
const deletePreset = () => {
|
||||
if (commonStore.activePresetIndex === presetIndex) {
|
||||
setActivePreset(defaultPreset, -1);
|
||||
}
|
||||
commonStore.presets.splice(presetIndex, 1);
|
||||
commonStore.setPresets(commonStore.presets);
|
||||
setOpen(false);
|
||||
setShowExitConfirm(false);
|
||||
commonStore.setEditingPreset(null);
|
||||
};
|
||||
|
||||
return <Dialog>
|
||||
return <Dialog open={open} onOpenChange={(e, data) => {
|
||||
if (data.open) {
|
||||
setOpen(true);
|
||||
} else if (!commonStore.editingPreset ||
|
||||
(presetIndex === -1 && JSON.stringify(editingPreset) === JSON.stringify(defaultPreset)) ||
|
||||
(presetIndex !== -1 && JSON.stringify(editingPreset) === JSON.stringify(commonStore.presets[presetIndex]))) {
|
||||
setOpen(false);
|
||||
setShowExitConfirm(false);
|
||||
commonStore.setEditingPreset(null);
|
||||
} else {
|
||||
setShowExitConfirm(true);
|
||||
}
|
||||
}}>
|
||||
<DialogTrigger disableButtonEnhancement>
|
||||
{triggerButton}
|
||||
</DialogTrigger>
|
||||
@ -200,14 +225,31 @@ const ChatPresetEditor: FC<{
|
||||
transform: 'unset' // override the style for the new version of @fluentui/react-components to avoid conflicts with react-beautiful-dnd
|
||||
}}>
|
||||
<DialogBody style={{ height: '100%', overflow: 'hidden' }}>
|
||||
<DialogContent className="flex flex-col gap-1 overflow-hidden">
|
||||
{editingPreset && <DialogContent className="flex flex-col gap-1 overflow-hidden">
|
||||
<CustomToastContainer />
|
||||
<Dialog open={showExitConfirm}>
|
||||
<DialogSurface style={{ transform: 'unset' }}>
|
||||
<DialogBody>
|
||||
<DialogContent>
|
||||
{t('Content has been changed, are you sure you want to exit without saving?')}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button appearance="secondary" onClick={() => {
|
||||
setShowExitConfirm(false);
|
||||
}}>{t('Cancel')}</Button>
|
||||
<Button appearance="primary" onClick={() => {
|
||||
setOpen(false);
|
||||
setShowExitConfirm(false);
|
||||
commonStore.setEditingPreset(null);
|
||||
}}>{t('Exit without saving')}</Button>
|
||||
</DialogActions>
|
||||
</DialogBody>
|
||||
</DialogSurface>
|
||||
</Dialog>
|
||||
<div className="flex justify-between">{
|
||||
presetIndex === -1
|
||||
? <div />
|
||||
: <DialogTrigger disableButtonEnhancement>
|
||||
<Button appearance="subtle" icon={<Delete20Regular />} onClick={deletePreset} />
|
||||
</DialogTrigger>
|
||||
: <Button appearance="subtle" icon={<Delete20Regular />} onClick={deletePreset} />
|
||||
}
|
||||
<DialogTrigger disableButtonEnhancement>
|
||||
<Button appearance="subtle" icon={<Dismiss20Regular />} />
|
||||
@ -310,14 +352,10 @@ const ChatPresetEditor: FC<{
|
||||
<Button onClick={copyPreset}>{t('Copy')}</Button>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<DialogTrigger disableButtonEnhancement>
|
||||
<Button appearance="primary" onClick={savePreset}>{t('Save')}</Button>
|
||||
</DialogTrigger>
|
||||
<DialogTrigger disableButtonEnhancement>
|
||||
<Button appearance="primary" onClick={activatePreset}>{t('Activate')}</Button>
|
||||
</DialogTrigger>
|
||||
<Button appearance="primary" onClick={savePreset}>{t('Save')}</Button>
|
||||
<Button appearance="primary" onClick={activatePreset}>{t('Activate')}</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</DialogContent>}
|
||||
</DialogBody>
|
||||
</DialogSurface>
|
||||
</Dialog>;
|
||||
@ -340,20 +378,16 @@ const ChatPresets: FC = observer(() => {
|
||||
{/* </div>*/}
|
||||
{/*</PresetCardFrame>*/}
|
||||
<PresetCard
|
||||
preset={defaultPreset}
|
||||
presetIndex={-1}
|
||||
editable={false}
|
||||
onClick={() => {
|
||||
setActivePreset(defaultPreset);
|
||||
}} avatarImg={defaultPreset.avatarImg} name={defaultPreset.name} desc={defaultPreset.desc} tag={defaultPreset.tag}
|
||||
/>
|
||||
{commonStore.presets.map((preset, index) => {
|
||||
return <PresetCard
|
||||
key={index}
|
||||
preset={preset}
|
||||
presetIndex={index}
|
||||
editable={true}
|
||||
onClick={() => {
|
||||
setActivePreset(preset);
|
||||
}}
|
||||
key={index} avatarImg={preset.avatarImg} name={preset.name} desc={preset.desc} tag={preset.tag}
|
||||
/>;
|
||||
})}
|
||||
</div>;
|
||||
|
@ -74,6 +74,7 @@ class CommonStore {
|
||||
conversation: Conversation = {};
|
||||
conversationOrder: string[] = [];
|
||||
activePreset: Preset | null = null;
|
||||
activePresetIndex: number = -1;
|
||||
attachmentUploading: boolean = false;
|
||||
attachments: {
|
||||
[uuid: string]: Attachment[]
|
||||
@ -342,7 +343,7 @@ class CommonStore {
|
||||
this.lastUnfinishedModelDownloads = value;
|
||||
}
|
||||
|
||||
setEditingPreset(value: Preset) {
|
||||
setEditingPreset(value: Preset | null) {
|
||||
this.editingPreset = value;
|
||||
}
|
||||
|
||||
@ -356,6 +357,10 @@ class CommonStore {
|
||||
this.activePreset = value;
|
||||
}
|
||||
|
||||
setActivePresetIndex(value: number) {
|
||||
this.activePresetIndex = value;
|
||||
}
|
||||
|
||||
setCompletionSubmittedPrompt(value: string) {
|
||||
this.completionSubmittedPrompt = value;
|
||||
}
|
||||
|
@ -581,8 +581,9 @@ export async function getSoundFont() {
|
||||
return soundUrl;
|
||||
}
|
||||
|
||||
export const setActivePreset = (preset: Preset | null) => {
|
||||
export const setActivePreset = (preset: Preset | null, index: number) => {
|
||||
commonStore.setActivePreset(preset);
|
||||
commonStore.setActivePresetIndex(index);
|
||||
//TODO if (preset.displayPresetMessages) {
|
||||
const { pushMessage, saveConversation } = newChatConversation();
|
||||
if (preset)
|
||||
|
Loading…
Reference in New Issue
Block a user