af9f0f15d1
历史视频快速编辑在规划与恢复提交边界统一失败关闭 删除退役的快速编辑重绘状态和新产物提交分支 统一图片编辑原位替换与其它生成产物改造文档合同 补齐历史对话框和Native换行回归验证
178 lines
6.6 KiB
TypeScript
178 lines
6.6 KiB
TypeScript
import {
|
|
type CSSProperties,
|
|
type Dispatch,
|
|
type ReactNode,
|
|
type RefObject,
|
|
type SetStateAction,
|
|
} from 'react';
|
|
|
|
import { ImageCanvasBasicGenerationComposerView } from './ImageCanvasBasicGenerationComposerView';
|
|
import type {
|
|
GenerateDialogState,
|
|
QuickEditPanelState,
|
|
UploadTarget,
|
|
} from './ImageCanvasEditorTypes';
|
|
import {
|
|
QUICK_EDIT_REFERENCE_LIMIT,
|
|
resolveExtraImageReferenceLimit,
|
|
} from './ImageCanvasGenerationModel';
|
|
|
|
export type ImageCanvasQuickEditPanelViewProps = {
|
|
panel: QuickEditPanelState;
|
|
style: CSSProperties;
|
|
referenceButtonRef?: RefObject<HTMLButtonElement | null>;
|
|
isReferenceMenuOpen?: boolean;
|
|
setIsReferenceMenuOpen?: Dispatch<SetStateAction<boolean>>;
|
|
setIsPickingQuickEditReferenceFromCanvas?: Dispatch<SetStateAction<boolean>>;
|
|
setQuickEditPanel: Dispatch<SetStateAction<QuickEditPanelState | null>>;
|
|
renderEditorPortal?: (node: ReactNode) => ReactNode;
|
|
buildPortalMenuStyle?: (
|
|
anchor: HTMLElement | null,
|
|
placement: 'above' | 'below',
|
|
) => CSSProperties;
|
|
onRequestUpload?: (target: UploadTarget) => void;
|
|
onRememberImageModel?: (model: string) => void;
|
|
hasPendingImageReferenceUploads?: boolean;
|
|
onSubmit: () => void;
|
|
};
|
|
|
|
function resetFailedPanelStatus<
|
|
T extends { status: string; errorMessage?: string },
|
|
>(panel: T) {
|
|
return {
|
|
...panel,
|
|
status: panel.status === 'failed' ? 'idle' : panel.status,
|
|
errorMessage: panel.status === 'failed' ? undefined : panel.errorMessage,
|
|
};
|
|
}
|
|
|
|
function createQuickEditDialog(
|
|
panel: QuickEditPanelState,
|
|
): GenerateDialogState {
|
|
return {
|
|
mode: 'quick-edit',
|
|
prompt: panel.prompt,
|
|
status: panel.status,
|
|
errorMessage: panel.errorMessage,
|
|
sourceLayerId: panel.sourceLayerId,
|
|
generationReferences: panel.quickEditReferences,
|
|
assetLabel: panel.assetLabel,
|
|
imageModel: panel.model,
|
|
aspectRatio: panel.aspectRatio,
|
|
imageSize: panel.imageSize,
|
|
};
|
|
}
|
|
|
|
function syncPanelFromDialogUpdate(
|
|
panel: QuickEditPanelState,
|
|
dialog: GenerateDialogState,
|
|
) {
|
|
const normalizedPanel = resetFailedPanelStatus(panel);
|
|
const normalizedDialog = resetFailedPanelStatus(dialog);
|
|
return {
|
|
...normalizedPanel,
|
|
size: panel.size,
|
|
prompt: dialog.prompt,
|
|
aspectRatio:
|
|
normalizedDialog.aspectRatio ?? normalizedPanel.aspectRatio ?? '1:1',
|
|
imageSize: normalizedDialog.imageSize ?? normalizedPanel.imageSize ?? '1K',
|
|
model: normalizedDialog.imageModel ?? normalizedPanel.model,
|
|
quickEditReferences: normalizedDialog.generationReferences,
|
|
assetLabel: normalizedDialog.assetLabel,
|
|
// 中文注释:dialog 由 createQuickEditDialog 从面板自身派生,组合器只会做
|
|
// failed→idle 的重置,不会写入 'pending-confirmation' 这类完美像素专属状态。
|
|
// 因此归一化后的 dialog 状态恒等于归一化后的面板状态,直接取面板侧即可,
|
|
// 也让面板的三态联合类型不必在这里做运行时收窄。
|
|
status: normalizedPanel.status,
|
|
errorMessage: normalizedDialog.errorMessage,
|
|
};
|
|
}
|
|
|
|
export function ImageCanvasQuickEditPanelView({
|
|
panel,
|
|
style,
|
|
referenceButtonRef,
|
|
isReferenceMenuOpen = false,
|
|
setIsReferenceMenuOpen,
|
|
setIsPickingQuickEditReferenceFromCanvas,
|
|
setQuickEditPanel,
|
|
renderEditorPortal = (node) => node,
|
|
buildPortalMenuStyle = () => ({}),
|
|
onRequestUpload,
|
|
onRememberImageModel = () => {},
|
|
hasPendingImageReferenceUploads = false,
|
|
onSubmit,
|
|
}: ImageCanvasQuickEditPanelViewProps) {
|
|
const referenceCount = panel.quickEditReferences?.length ?? 0;
|
|
const canAddReferences =
|
|
referenceCount <
|
|
resolveExtraImageReferenceLimit(panel.model, QUICK_EDIT_REFERENCE_LIMIT, 1);
|
|
const quickEditDialog = createQuickEditDialog(panel);
|
|
|
|
return (
|
|
<ImageCanvasBasicGenerationComposerView
|
|
dialog={quickEditDialog}
|
|
style={style}
|
|
setGenerateDialog={(valueOrUpdater) => {
|
|
setQuickEditPanel((currentPanel) => {
|
|
if (!currentPanel) {
|
|
return currentPanel;
|
|
}
|
|
const currentDialog = createQuickEditDialog(currentPanel);
|
|
const nextDialog =
|
|
typeof valueOrUpdater === 'function'
|
|
? valueOrUpdater(currentDialog)
|
|
: valueOrUpdater;
|
|
if (!nextDialog) {
|
|
return currentPanel;
|
|
}
|
|
return syncPanelFromDialogUpdate(currentPanel, nextDialog);
|
|
});
|
|
}}
|
|
generationReferenceButtonRef={referenceButtonRef}
|
|
isGenerationReferenceMenuOpen={isReferenceMenuOpen}
|
|
setIsGenerationReferenceMenuOpen={setIsReferenceMenuOpen}
|
|
setIsPickingGenerationReferenceFromCanvas={
|
|
setIsPickingQuickEditReferenceFromCanvas
|
|
}
|
|
onRequestUpload={onRequestUpload ?? (() => {})}
|
|
onPickReferenceFromCanvas={() =>
|
|
setIsPickingQuickEditReferenceFromCanvas?.(true)
|
|
}
|
|
onToggleReferenceMenu={() => setIsReferenceMenuOpen?.((open) => !open)}
|
|
onRememberImageModel={onRememberImageModel}
|
|
hasPendingImageReferenceUploads={hasPendingImageReferenceUploads}
|
|
onSubmit={onSubmit}
|
|
dialogLabel="快速编辑图片"
|
|
includeDimensions={true}
|
|
includeModel={true}
|
|
includeReferences={false}
|
|
promptLabel="快速编辑提示词"
|
|
promptPlaceholder="你希望素材如何修改?"
|
|
optionLabelPrefix="快速编辑"
|
|
dimensionRatioAriaLabelPrefix="比例"
|
|
dimensionSizeAriaLabelPrefix="尺寸"
|
|
referenceUploadTarget="quick-edit-reference"
|
|
referenceButtonLabel="添加快速编辑参考图"
|
|
referenceButtonAriaLabel="添加快速编辑参考图"
|
|
referenceMenuLabel="快速编辑参考图来源"
|
|
referenceSlotTone="quick-edit"
|
|
referenceSlotDisabled={!canAddReferences}
|
|
showReferenceAddButton={false}
|
|
referenceLabelFormatter={(_, index) => `图${index + 1}`}
|
|
referenceAriaLabelFormatter={(_, index) => `图${index + 1}`}
|
|
referenceRemoveLabelFormatter={(_, index) => `删除图${index + 1}`}
|
|
panelClassName="image-canvas-editor__quick-edit-panel image-canvas-editor__generation-composer image-canvas-editor__generation-composer--image image-canvas-editor__generation-composer--quick-edit"
|
|
footerClassName="image-canvas-editor__generation-composer-footer image-canvas-editor__quick-edit-footer"
|
|
promptClassName="image-canvas-editor__generation-prompt image-canvas-editor__quick-edit-prompt"
|
|
referenceSlotClassName="image-canvas-editor__quick-edit-reference"
|
|
submitButtonClassName="image-canvas-editor__generation-submit image-canvas-editor__quick-edit-submit"
|
|
submitLabel="修改"
|
|
submitAriaLabel="修改"
|
|
submittingStatusLabel="修改中"
|
|
renderEditorPortal={renderEditorPortal}
|
|
buildPortalMenuStyle={buildPortalMenuStyle}
|
|
/>
|
|
);
|
|
}
|