feat: label image references in generation

This commit is contained in:
stupid-h4er
2026-05-31 00:54:54 +08:00
parent 78738e060f
commit c3b1ba2943
6 changed files with 57 additions and 10 deletions
+23 -2
View File
@@ -1,6 +1,6 @@
"use client";
import { BookOpen, CheckSquare, ClipboardPaste, Download, FolderPlus, History, ImagePlus, LoaderCircle, PenLine, Plus, SlidersHorizontal, Sparkles, Trash2, Upload } from "lucide-react";
import { ArrowLeft, ArrowRight, BookOpen, CheckSquare, ClipboardPaste, Download, FolderPlus, History, ImagePlus, LoaderCircle, PenLine, Plus, SlidersHorizontal, Sparkles, Trash2, Upload } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { App, Button, Checkbox, Drawer, Empty, Image, Input, Modal, Tag, Typography } from "antd";
import localforage from "localforage";
@@ -11,6 +11,7 @@ import { ModelPicker } from "@/components/model-picker";
import { PromptSelectDialog } from "@/components/prompts/prompt-select-dialog";
import { AssetPickerModal, type InsertAssetPayload } from "@/app/(user)/canvas/components/asset-picker-modal";
import { canvasThemes } from "@/lib/canvas-theme";
import { imageReferenceLabel } from "@/lib/image-reference-prompt";
import { useConfigStore, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
import { useThemeStore } from "@/stores/use-theme-store";
import { nanoid } from "nanoid";
@@ -373,9 +374,11 @@ export default function ImagePage() {
event.currentTarget.scrollLeft += event.deltaY;
}}
>
{references.map((item) => (
{references.map((item, index) => (
<div key={item.id} className="group relative size-20 shrink-0 overflow-hidden rounded-md border border-stone-200 dark:border-stone-800">
<img src={item.dataUrl} alt={item.name} className="size-full object-cover" />
<span className="absolute left-1 top-1 rounded bg-black/60 px-1.5 py-0.5 text-[10px] font-medium text-white">{imageReferenceLabel(index)}</span>
<ReferenceOrderButtons index={index} total={references.length} onMove={(offset) => setReferences((value) => moveListItem(value, index, offset))} />
<button
type="button"
className="absolute right-1 top-1 hidden size-6 items-center justify-center rounded bg-black/60 text-white group-hover:flex"
@@ -742,6 +745,24 @@ function normalizeLogConfig(log: Partial<GenerationLog>): GenerationLogConfig {
};
}
function moveListItem<T>(items: T[], index: number, offset: number) {
const targetIndex = index + offset;
if (targetIndex < 0 || targetIndex >= items.length) return items;
const next = [...items];
[next[index], next[targetIndex]] = [next[targetIndex], next[index]];
return next;
}
function ReferenceOrderButtons({ index, total, onMove }: { index: number; total: number; onMove: (offset: number) => void }) {
if (total <= 1) return null;
return (
<div className="absolute inset-x-1 bottom-1 flex justify-between">
<Button size="small" className="!h-6 !w-6 !min-w-6 !rounded-full !bg-white/85 !p-0 !shadow-sm" icon={<ArrowLeft className="size-3" />} disabled={index <= 0} onClick={() => onMove(-1)} />
<Button size="small" className="!h-6 !w-6 !min-w-6 !rounded-full !bg-white/85 !p-0 !shadow-sm" icon={<ArrowRight className="size-3" />} disabled={index >= total - 1} onClick={() => onMove(1)} />
</div>
);
}
function buildLog({
prompt,
model,