feat: add guarded image generation controls
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
import { ChangeEvent, useCallback, useEffect, useLayoutEffect, useRef, useState, type ClipboardEvent } from 'react';
|
||||
import { BrainCircuit, Database } from 'lucide-react';
|
||||
import { BrainCircuit, Database, Image, ImageOff, ImagePlus } from 'lucide-react';
|
||||
import { useNetworkStatus } from '../hooks/useNetworkStatus';
|
||||
import { openAvatarPicker } from '../utils/userAvatar';
|
||||
import { CHAT_SKILL_OPTIONS, filterChatSkills } from '../utils/chatSkills';
|
||||
import { getMessageSaveActions } from '../utils/messageSave';
|
||||
import { getDisplayText } from '../utils/message';
|
||||
import {
|
||||
IMAGE_GENERATION_MODE_LABELS,
|
||||
nextImageGenerationMode,
|
||||
type ImageGenerationMode,
|
||||
} from '../utils/imageGeneration';
|
||||
import {
|
||||
downloadChatMessageDocx,
|
||||
} from '../api/client';
|
||||
@@ -186,6 +191,7 @@ export function ChatPanel({
|
||||
messageId?: string;
|
||||
forceDeepReasoning?: boolean;
|
||||
pgRequired?: boolean;
|
||||
imageGenerationMode?: ImageGenerationMode;
|
||||
selectedChatSkill?: string;
|
||||
fileAttachments?: ChatFileAttachment[];
|
||||
},
|
||||
@@ -219,6 +225,7 @@ export function ChatPanel({
|
||||
const [voiceNotice, setVoiceNotice] = useState<string | null>(null);
|
||||
const [forceDeepReasoning, setForceDeepReasoning] = useState(false);
|
||||
const [pgRequired, setPgRequired] = useState(false);
|
||||
const [imageGenerationMode, setImageGenerationMode] = useState<ImageGenerationMode>('auto');
|
||||
const [chatControlOnboardingStep, setChatControlOnboardingStep] = useState<0 | 1 | 2 | null>(null);
|
||||
const [pendingImages, setPendingImages] = useState<PendingChatImage[]>([]);
|
||||
const [pendingFiles, setPendingFiles] = useState<PendingChatFile[]>([]);
|
||||
@@ -745,6 +752,7 @@ export function ChatPanel({
|
||||
messageId: outgoingMessageId,
|
||||
forceDeepReasoning,
|
||||
pgRequired,
|
||||
imageGenerationMode,
|
||||
selectedChatSkill,
|
||||
fileAttachments: fileAttachmentsToSend,
|
||||
});
|
||||
@@ -774,6 +782,7 @@ export function ChatPanel({
|
||||
}, [
|
||||
forceDeepReasoning,
|
||||
pgRequired,
|
||||
imageGenerationMode,
|
||||
input,
|
||||
onSubmit,
|
||||
onUploadFile,
|
||||
@@ -1229,6 +1238,27 @@ export function ChatPanel({
|
||||
<span className="chat-control-onboarding-tip" role="status">需要长期使用的数据,放进专属空间</span>
|
||||
)}
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
className={`chat-deep-reasoning-toggle chat-image-generation-toggle is-${imageGenerationMode}${imageGenerationMode === 'required' ? ' is-active' : ''}`}
|
||||
disabled={voiceDisabled}
|
||||
role="checkbox"
|
||||
aria-checked={imageGenerationMode === 'auto' ? 'mixed' : imageGenerationMode === 'required'}
|
||||
aria-label={`AI 配图:${IMAGE_GENERATION_MODE_LABELS[imageGenerationMode]}`}
|
||||
title={`AI 配图:${IMAGE_GENERATION_MODE_LABELS[imageGenerationMode]}。点击切换为${IMAGE_GENERATION_MODE_LABELS[nextImageGenerationMode(imageGenerationMode)]}`}
|
||||
onClick={() => setImageGenerationMode((current) => nextImageGenerationMode(current))}
|
||||
>
|
||||
{imageGenerationMode === 'required' ? (
|
||||
<ImagePlus className="chat-deep-reasoning-toggle-icon" aria-hidden="true" />
|
||||
) : imageGenerationMode === 'disabled' ? (
|
||||
<ImageOff className="chat-deep-reasoning-toggle-icon" aria-hidden="true" />
|
||||
) : (
|
||||
<Image className="chat-deep-reasoning-toggle-icon" aria-hidden="true" />
|
||||
)}
|
||||
<span className="chat-image-generation-state" aria-hidden="true">
|
||||
{imageGenerationMode === 'auto' ? 'A' : imageGenerationMode === 'required' ? '✓' : '×'}
|
||||
</span>
|
||||
</button>
|
||||
<label
|
||||
className={`chat-deep-reasoning-toggle${forceDeepReasoning ? ' is-active' : ''}${chatControlOnboardingStep === 2 ? ' chat-control-onboarding-active' : ''}`}
|
||||
title="勾选后,本轮消息使用深度推理完成"
|
||||
|
||||
@@ -548,6 +548,7 @@ export function ChatView({
|
||||
messageId: options?.messageId,
|
||||
forceDeepReasoning: options?.forceDeepReasoning,
|
||||
pgRequired: options?.pgRequired,
|
||||
imageGenerationMode: options?.imageGenerationMode,
|
||||
selectedChatSkill: options?.selectedChatSkill,
|
||||
fileAttachments: options?.fileAttachments,
|
||||
},
|
||||
|
||||
@@ -148,6 +148,7 @@ export function SpaceChatPanel({
|
||||
messageId: options?.messageId,
|
||||
forceDeepReasoning: options?.forceDeepReasoning,
|
||||
pgRequired: options?.pgRequired,
|
||||
imageGenerationMode: options?.imageGenerationMode,
|
||||
fileAttachments: options?.fileAttachments,
|
||||
},
|
||||
imageUrls,
|
||||
@@ -160,6 +161,7 @@ export function SpaceChatPanel({
|
||||
messageId: options?.messageId,
|
||||
forceDeepReasoning: options?.forceDeepReasoning,
|
||||
pgRequired: options?.pgRequired,
|
||||
imageGenerationMode: options?.imageGenerationMode,
|
||||
fileAttachments: options?.fileAttachments,
|
||||
},
|
||||
imageUrls,
|
||||
|
||||
Reference in New Issue
Block a user