fix: stabilize local edit prompt typing
This commit is contained in:
parent
862c0f2937
commit
9cbbc7f065
@ -994,6 +994,17 @@ const getLocalEditRegionsFromMetadata = (
|
||||
metadata: Record<string, any> | undefined
|
||||
) => normalizeLocalEditRegions(metadata?.[LOCAL_EDIT_METADATA_KEY]);
|
||||
|
||||
const createLocalEditPromptDraftMap = (
|
||||
regions: LocalEditRegion[],
|
||||
draftSource?: Record<string, string>
|
||||
): Record<string, string> =>
|
||||
Object.fromEntries(
|
||||
regions.map((region) => [
|
||||
region.id,
|
||||
draftSource?.[region.id] ?? region.prompt,
|
||||
])
|
||||
);
|
||||
|
||||
const getNormalizedRectOverlayStyle = (
|
||||
rect: NormalizedCropRect,
|
||||
metrics: ImageDisplayMetrics
|
||||
@ -1877,6 +1888,9 @@ export function ImageNode({
|
||||
const [localEditRegions, setLocalEditRegions] = useState<LocalEditRegion[]>(
|
||||
() => getLocalEditRegionsFromMetadata(data.metadata)
|
||||
);
|
||||
const [localEditPromptDrafts, setLocalEditPromptDrafts] = useState<
|
||||
Record<string, string>
|
||||
>({});
|
||||
const [isLocalEditDrawing, setIsLocalEditDrawing] = useState(false);
|
||||
const [localEditDragStart, setLocalEditDragStart] =
|
||||
useState<BoxCutoutPoint | null>(null);
|
||||
@ -2547,11 +2561,14 @@ export function ImageNode({
|
||||
const nextRegions = reindexLocalEditRegions(
|
||||
regions.slice(0, LOCAL_EDIT_MAX_REGIONS)
|
||||
);
|
||||
const nextDrafts = createLocalEditPromptDraftMap(
|
||||
nextRegions,
|
||||
localEditPromptDraftRefs.current
|
||||
);
|
||||
localEditRegionsRef.current = nextRegions;
|
||||
setLocalEditRegions(nextRegions);
|
||||
localEditPromptDraftRefs.current = Object.fromEntries(
|
||||
nextRegions.map((region) => [region.id, region.prompt])
|
||||
);
|
||||
localEditPromptDraftRefs.current = nextDrafts;
|
||||
setLocalEditPromptDrafts(nextDrafts);
|
||||
|
||||
const nextMetadata =
|
||||
data.metadata && typeof data.metadata === "object"
|
||||
@ -2574,6 +2591,21 @@ export function ImageNode({
|
||||
[data, node.id, updateNode]
|
||||
);
|
||||
|
||||
const updateLocalEditPromptDraft = useCallback(
|
||||
(regionId: string, prompt: string) => {
|
||||
localEditPromptDraftRefs.current[regionId] = prompt;
|
||||
setLocalEditPromptDrafts((current) =>
|
||||
current[regionId] === prompt
|
||||
? current
|
||||
: {
|
||||
...current,
|
||||
[regionId]: prompt,
|
||||
}
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const refreshBoxCutoutMetrics = useCallback(() => {
|
||||
const imageElement = displayImageRef.current;
|
||||
if (!imageElement) {
|
||||
@ -2718,7 +2750,11 @@ export function ImageNode({
|
||||
|
||||
useEffect(() => {
|
||||
if (localEditMode) return;
|
||||
setLocalEditRegions(getLocalEditRegionsFromMetadata(data.metadata));
|
||||
const nextRegions = getLocalEditRegionsFromMetadata(data.metadata);
|
||||
const nextDrafts = createLocalEditPromptDraftMap(nextRegions);
|
||||
localEditPromptDraftRefs.current = nextDrafts;
|
||||
setLocalEditPromptDrafts(nextDrafts);
|
||||
setLocalEditRegions(nextRegions);
|
||||
}, [data.metadata, data.src, localEditMode]);
|
||||
|
||||
useEffect(() => {
|
||||
@ -3649,19 +3685,25 @@ export function ImageNode({
|
||||
|
||||
const persistLocalEditRegionPrompt = useCallback(
|
||||
(regionId: string, prompt: string) => {
|
||||
localEditPromptDraftRefs.current[regionId] = prompt;
|
||||
updateLocalEditPromptDraft(regionId, prompt);
|
||||
commitLocalEditRegions(
|
||||
localEditRegions.map((region) =>
|
||||
localEditRegionsRef.current.map((region) =>
|
||||
region.id === regionId ? { ...region, prompt } : region
|
||||
)
|
||||
);
|
||||
},
|
||||
[commitLocalEditRegions, localEditRegions]
|
||||
[commitLocalEditRegions, updateLocalEditPromptDraft]
|
||||
);
|
||||
|
||||
const deleteLocalEditRegion = useCallback(
|
||||
(regionId: string) => {
|
||||
delete localEditPromptDraftRefs.current[regionId];
|
||||
setLocalEditPromptDrafts((current) => {
|
||||
if (!(regionId in current)) return current;
|
||||
const next = { ...current };
|
||||
delete next[regionId];
|
||||
return next;
|
||||
});
|
||||
delete localEditPromptComposingRefs.current[regionId];
|
||||
commitLocalEditRegions(
|
||||
localEditRegionsRef.current.filter((region) => region.id !== regionId)
|
||||
@ -3764,6 +3806,7 @@ export function ImageNode({
|
||||
|
||||
const clearLocalEditRegions = useCallback(() => {
|
||||
localEditPromptDraftRefs.current = {};
|
||||
setLocalEditPromptDrafts({});
|
||||
commitLocalEditRegions([]);
|
||||
setEditingLocalEditRegionId(null);
|
||||
}, [commitLocalEditRegions]);
|
||||
@ -7996,45 +8039,31 @@ export function ImageNode({
|
||||
className="nodrag nopan nowheel h-9 min-w-0 flex-1 resize-none overflow-hidden rounded-full border border-slate-300 bg-white/95 px-3 py-2 text-[12px] font-medium leading-5 text-slate-950 caret-slate-950 shadow-[0_10px_24px_rgba(15,23,42,0.14)] outline-none ring-2 ring-transparent transition placeholder:text-slate-400 focus:border-slate-950 focus:ring-slate-950/15 dark:border-white/20 dark:bg-slate-950/88 dark:text-white dark:caret-white dark:placeholder:text-white/42 dark:focus:border-white/40 dark:focus:ring-white/18"
|
||||
data-canvas-no-drag="true"
|
||||
data-local-edit-control="true"
|
||||
defaultValue={
|
||||
autoComplete="off"
|
||||
enterKeyHint="done"
|
||||
inputMode="text"
|
||||
lang="zh-CN"
|
||||
value={
|
||||
localEditPromptDrafts[region.id] ??
|
||||
localEditPromptDraftRefs.current[region.id] ??
|
||||
region.prompt
|
||||
}
|
||||
autoComplete="off"
|
||||
enterKeyHint="done"
|
||||
lang="zh-CN"
|
||||
onBlur={(event) => {
|
||||
const nextPrompt = event.currentTarget.value;
|
||||
localEditPromptDraftRefs.current[region.id] =
|
||||
nextPrompt;
|
||||
updateLocalEditPromptDraft(region.id, nextPrompt);
|
||||
persistLocalEditRegionPrompt(region.id, nextPrompt);
|
||||
if (isLocalEditControlTarget(event.relatedTarget)) {
|
||||
return;
|
||||
}
|
||||
window.setTimeout(() => {
|
||||
if (
|
||||
isLocalEditControlTarget(document.activeElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
setEditingLocalEditRegionId((current) => {
|
||||
if (current === region.id) {
|
||||
focusLocalEditPromptInput(region.id);
|
||||
}
|
||||
return current;
|
||||
});
|
||||
}, 80);
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
onCompositionEnd={(event) => {
|
||||
stopLocalEditPromptTextEvent(event);
|
||||
localEditPromptComposingRefs.current[region.id] =
|
||||
false;
|
||||
localEditPromptDraftRefs.current[region.id] =
|
||||
event.currentTarget.value;
|
||||
updateLocalEditPromptDraft(
|
||||
region.id,
|
||||
event.currentTarget.value
|
||||
);
|
||||
}}
|
||||
onCompositionStart={(event) => {
|
||||
stopLocalEditPromptTextEvent(event);
|
||||
@ -8052,13 +8081,17 @@ export function ImageNode({
|
||||
}}
|
||||
onInput={(event) => {
|
||||
stopLocalEditPromptTextEvent(event);
|
||||
localEditPromptDraftRefs.current[region.id] =
|
||||
event.currentTarget.value;
|
||||
updateLocalEditPromptDraft(
|
||||
region.id,
|
||||
event.currentTarget.value
|
||||
);
|
||||
}}
|
||||
onChange={(event) => {
|
||||
stopLocalEditPromptTextEvent(event);
|
||||
localEditPromptDraftRefs.current[region.id] =
|
||||
event.currentTarget.value;
|
||||
updateLocalEditPromptDraft(
|
||||
region.id,
|
||||
event.currentTarget.value
|
||||
);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
stopLocalEditPromptTextEvent(event);
|
||||
@ -8095,17 +8128,9 @@ export function ImageNode({
|
||||
onMouseDown={(event) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onMouseDownCapture={(event) => {
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
onPointerDown={(event) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
onPointerDownCapture={(event) => {
|
||||
event.stopPropagation();
|
||||
event.currentTarget.focus({ preventScroll: true });
|
||||
}}
|
||||
placeholder={`区域 ${region.index} 提示词`}
|
||||
ref={(input) => {
|
||||
localEditPromptInputRefs.current[region.id] = input;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user