feat : dreamgineer ask me try to use this and now im ran out of token sad [no ci]

This commit is contained in:
2026-09-14 18:54:32 +07:00 Unverified
parent dc7f61aa6e
commit 4a6bfd599a
34 changed files with 3222 additions and 332 deletions
+5 -15
View File
@@ -11,7 +11,7 @@ import { saveGuideOverview } from "@/app/admin/actions";
import { AutosaveStatus } from "@/components/admin/autosave-status";
import { MediaUploader } from "@/components/admin/media-uploader";
import { MaterialPoster, type PosterBlendMode } from "@/components/public/material-poster";
import { GuideImageExport } from "@/components/public/guide-image-export";
import { TakumiImageExport } from "@/components/public/takumi-image-export";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -458,26 +458,16 @@ export function GuideOverviewForm({
ลบภาพตัวละคร
</Button>
) : null}
<GuideImageExport
<TakumiImageExport
width={1600}
height={2000}
format="png"
disabled={!posterArt.url}
fileName={`${guide.name}-materials.png`}
allowWithoutNotes={false}
captureClassName="p-0"
>
<MaterialPoster
character={guide.character}
characterArtUrl={posterArt.url}
artworkOffsetX={posterArtOffset.x}
artworkOffsetY={posterArtOffset.y}
artworkScale={posterArtScale}
topColors={posterTopColors}
bottomColors={posterBottomColors}
bleeding={bleeding}
/>
</GuideImageExport>
preview
template={{ kind: "materials", data: { character: guide.character, characterArtUrl: posterArt.url, artworkOffsetX: posterArtOffset.x, artworkOffsetY: posterArtOffset.y, artworkScale: posterArtScale, topColors: posterTopColors, bottomColors: posterBottomColors, bleeding } }}
/>
</div>
<div className="flex flex-col gap-2 rounded-lg border p-3">
<div className="flex items-center justify-between gap-2">
+7 -81
View File
@@ -21,7 +21,6 @@ import {
import { CSS } from "@dnd-kit/utilities";
import {
CropIcon,
DownloadIcon,
GripVerticalIcon,
ImageIcon,
PlusIcon,
@@ -41,6 +40,7 @@ import {
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { TakumiImageExport } from "@/components/public/takumi-image-export";
import {
Card,
CardContent,
@@ -80,7 +80,6 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Spinner } from "@/components/ui/spinner";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { elementIconFilter } from "@/lib/catalog/element";
import { rarityGradientClass } from "@/lib/catalog/rarity";
@@ -699,7 +698,6 @@ export function OverviewImageGenerator({
characters: Character[];
elementIconUrls: Record<string, string | null>;
}) {
const captureRef = useRef<HTMLDivElement>(null);
const [character, setCharacter] = useState<Character | null>(null);
const [artworkUrl, setArtworkUrl] = useState<string | null>(null);
const [artworkError, setArtworkError] = useState<string | null>(null);
@@ -735,7 +733,6 @@ export function OverviewImageGenerator({
coordinateGetter: sortableKeyboardCoordinates,
}),
);
const [exporting, setExporting] = useState(false);
const [backgroundUrl, setBackgroundUrl] = useState<string | null>(null);
const [fadeColor, setFadeColor] = useState("#0E0200");
const [fadeTint, setFadeTint] = useState(100);
@@ -998,49 +995,6 @@ export function OverviewImageGenerator({
}
}
async function download() {
const node = captureRef.current;
if (
!node ||
!character ||
!artworkUrl ||
!normalizeHex(topColorStart) ||
!normalizeHex(topColorEnd) ||
!normalizeHex(bottomColorStart) ||
!normalizeHex(bottomColorEnd) ||
!normalizeHex(elementColorStart) ||
!normalizeHex(elementColorEnd) ||
!normalizeHex(fadeColor)
)
return;
setExporting(true);
try {
const { domToBlob, waitUntilLoad } = await import("modern-screenshot");
await Promise.all([document.fonts.ready, waitUntilLoad(node)]);
const blob = await domToBlob(node, {
backgroundColor: "#000000",
type: "image/png",
width: 1000,
height: 1000,
scale: 3,
});
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = overviewFileName(character.key, displayRole);
document.body.append(link);
link.click();
link.remove();
window.setTimeout(() => URL.revokeObjectURL(url), 0);
toast.success("ดาวน์โหลดภาพ Overview แล้ว");
} catch {
toast.error("ส่งออกภาพไม่สำเร็จ กรุณาลองอีกครั้ง");
} finally {
setExporting(false);
}
}
const ready = Boolean(
character &&
artworkUrl &&
@@ -1335,18 +1289,12 @@ export function OverviewImageGenerator({
</FieldGroup>
</CardContent>
<CardFooter className="flex flex-col gap-2">
<Button
className="w-full"
disabled={!ready || exporting}
onClick={() => void download()}
>
{exporting ? (
<Spinner data-icon="inline-start" />
) : (
<DownloadIcon data-icon="inline-start" />
)}
{exporting ? "กำลังส่งออก…" : "ดาวน์โหลด PNG 3000×3000"}
</Button>
<TakumiImageExport
width={3000} height={3000} allowWithoutNotes={false} preview disabled={!ready}
fileName={overviewFileName(character?.key ?? "overview", displayRole)}
buttonLabel="ดาวน์โหลด PNG 3000×3000"
template={{ kind: "overview", data: { composition, artworkUrl, character, role: displayRole, topColors: [topColorStart, topColorEnd], bottomColors: [bottomColorStart, bottomColorEnd], elementColors: [elementColorStart, elementColorEnd], elementGradientAngle, blendLayers, nameCardCrop, nameCardSize, elementIconUrls, disclaimerFontSize } }}
/>
</CardFooter>
</Card>
</div>
@@ -1469,28 +1417,6 @@ export function OverviewImageGenerator({
</CardContent>
</Card>
<div
ref={captureRef}
aria-hidden="true"
className="pointer-events-none fixed top-0 -left-[10000px] order-5 size-[1000px]"
>
<OverviewPoster
composition={composition}
artworkUrl={artworkUrl}
character={character}
role={displayRole}
topColors={[topColorStart, topColorEnd]}
bottomColors={[bottomColorStart, bottomColorEnd]}
elementColors={[elementColorStart, elementColorEnd]}
elementGradientAngle={elementGradientAngle}
blendLayers={blendLayers}
nameCardCrop={nameCardCrop}
nameCardSize={nameCardSize}
elementIconUrls={elementIconUrls}
disclaimerFontSize={disclaimerFontSize}
/>
</div>
<Dialog
open={Boolean(pendingCrop)}
onOpenChange={(open) => {