Browse Source

尺寸修改

feature/remove
TianYun 3 weeks ago
parent
commit
284594ab9a
  1. 15
      src/components/MyCreationPickerModal.tsx
  2. 71
      src/utils/__tests__/smartMediaNode.test.ts
  3. 17
      src/utils/smartMediaNode.ts

15
src/components/MyCreationPickerModal.tsx

@ -38,6 +38,7 @@ interface HistoryItem {
resultList?: { resultList?: {
images?: string[] | null; images?: string[] | null;
originImages?: string[] | null; originImages?: string[] | null;
thumbs?: string[] | null;
video?: string | null; video?: string | null;
voice?: string | null; voice?: string | null;
cover?: string | null; cover?: string | null;
@ -165,7 +166,7 @@ function getHistoryMediaUrl(item: HistoryItem, kind: HistoryTabKey): string | nu
const mediaKind = getHistoryKind(item, kind); const mediaKind = getHistoryKind(item, kind);
const result = firstResult(item); const result = firstResult(item);
if (mediaKind === "image") { if (mediaKind === "image") {
return firstString(result?.originImages || undefined) || firstString(result?.images || undefined) || firstString(item.images) || null; return firstString(result?.images || undefined) || firstString(result?.originImages || undefined) || firstString(item.images) || null;
} }
if (mediaKind === "video") return result?.video || item.video || result?.cover || item.cover || null; if (mediaKind === "video") return result?.video || item.video || result?.cover || item.cover || null;
return result?.voice || item.voice || item.audio || firstString(item.audios) || null; return result?.voice || item.voice || item.audio || firstString(item.audios) || null;
@ -175,7 +176,7 @@ function getHistoryPreviewUrl(item: HistoryItem, kind: HistoryTabKey): string |
const mediaKind = getHistoryKind(item, kind); const mediaKind = getHistoryKind(item, kind);
const result = firstResult(item); const result = firstResult(item);
if (mediaKind === "image") { if (mediaKind === "image") {
return firstString(result?.images || undefined) || firstString(item.thumbs) || firstString(item.images) || null; return firstString(result?.thumbs || undefined) || firstString(item.thumbs) || firstString(result?.images || undefined) || firstString(item.images) || null;
} }
if (mediaKind === "video") return result?.cover || item.coverThumb || item.cover || result?.video || item.video || null; if (mediaKind === "video") return result?.cover || item.coverThumb || item.cover || result?.video || item.video || null;
return null; return null;
@ -460,15 +461,7 @@ export function MyCreationPickerModal({ onClose }: MyCreationPickerModalProps) {
mimeType: mediaKind === "audio" ? "audio/asset" : mediaKind === "video" ? "video/asset" : "image/asset", mimeType: mediaKind === "audio" ? "audio/asset" : mediaKind === "video" ? "video/asset" : "image/asset",
duration: item.duration ?? null, duration: item.duration ?? null,
dimensions: item.width && item.height ? { width: item.width, height: item.height } : undefined, dimensions: item.width && item.height ? { width: item.width, height: item.height } : undefined,
resolver: mediaKind === "image" resolver: null,
? {
type: "popi-asset",
id: item.id,
name: title,
url: mediaUrl,
thumbUrl: previewUrl || undefined,
}
: null,
}, },
position: getCanvasPosition(), position: getCanvasPosition(),
addNode, addNode,

71
src/utils/__tests__/smartMediaNode.test.ts

@ -1,8 +1,27 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createSmartMediaNode } from "@/utils/smartMediaNode"; import { createSmartMediaNode } from "@/utils/smartMediaNode";
class MockImage {
static shouldError = false;
onload: (() => void) | null = null;
onerror: (() => void) | null = null;
width = 1200;
height = 800;
set src(_value: string) {
setTimeout(() => {
if (MockImage.shouldError) {
this.onerror?.();
return;
}
this.onload?.();
}, 0);
}
}
describe("createSmartMediaNode", () => { describe("createSmartMediaNode", () => {
beforeEach(() => { beforeEach(() => {
MockImage.shouldError = false;
vi.stubGlobal("fetch", vi.fn(async () => ({ vi.stubGlobal("fetch", vi.fn(async () => ({
ok: true, ok: true,
json: async () => ({ success: true }), json: async () => ({ success: true }),
@ -13,7 +32,33 @@ describe("createSmartMediaNode", () => {
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });
it("passes media dimensions in node data", async () => { it("uses read image dimensions before supplied dimensions", async () => {
vi.stubGlobal("Image", MockImage);
const addNode = vi.fn(() => "smartImage-1");
await createSmartMediaNode({
source: {
kind: "image",
url: "data:image/png;base64,test",
filename: "test.png",
dimensions: { width: 1600, height: 900 },
},
position: { x: 100, y: 200 },
addNode,
});
expect(addNode).toHaveBeenCalledWith(
"smartImage",
{ x: 100, y: 200 },
expect.objectContaining({
dimensions: { width: 1200, height: 800 },
})
);
});
it("falls back to supplied dimensions when image dimensions cannot be read", async () => {
MockImage.shouldError = true;
vi.stubGlobal("Image", MockImage);
const addNode = vi.fn(() => "smartImage-1"); const addNode = vi.fn(() => "smartImage-1");
await createSmartMediaNode({ await createSmartMediaNode({
@ -36,6 +81,30 @@ describe("createSmartMediaNode", () => {
); );
}); });
it("reads image dimensions when dimensions are null", async () => {
vi.stubGlobal("Image", MockImage);
const addNode = vi.fn(() => "smartImage-1");
await createSmartMediaNode({
source: {
kind: "image",
url: "https://example.com/test.png",
filename: "test.png",
dimensions: null,
},
position: { x: 100, y: 200 },
addNode,
});
expect(addNode).toHaveBeenCalledWith(
"smartImage",
{ x: 100, y: 200 },
expect.objectContaining({
dimensions: { width: 1200, height: 800 },
})
);
});
it("keeps default node size when media has no dimensions", async () => { it("keeps default node size when media has no dimensions", async () => {
const addNode = vi.fn(() => "smartAudio-1"); const addNode = vi.fn(() => "smartAudio-1");

17
src/utils/smartMediaNode.ts

@ -158,6 +158,18 @@ function resolveSmartImageNode(options: CreateSmartMediaNodeOptions, nodeId: str
}); });
} }
function isValidMediaDimensions(
dimensions: SmartMediaSource["dimensions"] | undefined
): dimensions is { width: number; height: number } {
return Boolean(
dimensions &&
Number.isFinite(dimensions.width) &&
Number.isFinite(dimensions.height) &&
dimensions.width > 0 &&
dimensions.height > 0
);
}
export async function readSmartImageDimensions(src: string): Promise<{ width: number; height: number } | null> { export async function readSmartImageDimensions(src: string): Promise<{ width: number; height: number } | null> {
if (typeof window === "undefined") return null; if (typeof window === "undefined") return null;
@ -224,9 +236,8 @@ export async function buildSmartMediaNodeData(source: SmartMediaSource): Promise
const defaults = await buildDefaultGenerationNodeData(nodeType); const defaults = await buildDefaultGenerationNodeData(nodeType);
if (source.kind === "image") { if (source.kind === "image") {
const dimensions = source.dimensions === undefined const readDimensions = await readSmartImageDimensions(source.url);
? await readSmartImageDimensions(source.url) const dimensions = readDimensions ?? (isValidMediaDimensions(source.dimensions) ? source.dimensions : null);
: source.dimensions;
return { return {
nodeType, nodeType,
data: { data: {

Loading…
Cancel
Save