Skip to content

Commit b424aad

Browse files
committed
fix external_url stuff
1 parent 32e71c6 commit b424aad

File tree

13 files changed

+421
-482
lines changed

13 files changed

+421
-482
lines changed

apps/dashboard/src/@/components/blocks/Img.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ export function Img(props: imgElementProps) {
2424
: props.src === ""
2525
? "fallback"
2626
: _status;
27-
const { className, fallback, skeleton, ...restProps } = props;
27+
const { className, fallback, skeleton, containerClassName, ...restProps } =
28+
props;
2829
const defaultSkeleton = <div className="animate-pulse bg-accent" />;
2930
const defaultFallback = <div className="bg-accent" />;
3031
const imgRef = useRef<HTMLImageElement>(null);
@@ -48,7 +49,7 @@ export function Img(props: imgElementProps) {
4849
}, []);
4950

5051
return (
51-
<div className={cn("relative shrink-0", props.containerClassName)}>
52+
<div className={cn("relative shrink-0", containerClassName)}>
5253
<img
5354
{...restProps}
5455
// avoid setting empty src string to prevent request to the entire page

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/BatchMetadata.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const uploadMetadataFormSchema = z.object({
3939
description: z.string().optional(),
4040
image: fileBufferOrStringSchema.optional(),
4141
animationUri: fileBufferOrStringSchema.optional(),
42-
external_url: z.string().optional(),
42+
external_url: fileBufferOrStringSchema.optional(),
4343
background_color: z
4444
.string()
4545
.refine(

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/nft/AdvancedNFTMetadataFormGroup.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export function AdvancedNFTMetadataFormGroup<
2929
const form =
3030
props.form as unknown as UseFormReturn<AdvancedNFTMetadataFormGroupValues>;
3131

32+
const externalUrl = form.watch("external_url");
33+
const externalIsTextFile =
34+
externalUrl instanceof File &&
35+
(externalUrl.type.includes("text") || externalUrl.type.includes("pdf"));
36+
3237
return (
3338
<div className="flex flex-col gap-5">
3439
<FormField
@@ -91,19 +96,21 @@ export function AdvancedNFTMetadataFormGroup<
9196
)}
9297
/>
9398

94-
<FormFieldSetup
95-
errorMessage={form.formState.errors.external_url?.message}
96-
htmlFor="external-url"
97-
isRequired={false}
98-
label="External URL"
99-
helperText="This is the URL that will appear below the asset's image on OpenSea and will allow users to leave OpenSea and view the item on your site."
100-
>
101-
<Input
102-
placeholder="https://"
103-
{...form.register("external_url")}
104-
type="url"
105-
/>
106-
</FormFieldSetup>
99+
{!externalIsTextFile && (
100+
<FormFieldSetup
101+
errorMessage={form.formState.errors.external_url?.message}
102+
htmlFor="external-url"
103+
isRequired={false}
104+
label="External URL"
105+
helperText="This is the URL that will appear below the asset's image on OpenSea and will allow users to leave OpenSea and view the item on your site."
106+
>
107+
<Input
108+
placeholder="https://"
109+
{...form.register("external_url")}
110+
type="url"
111+
/>
112+
</FormFieldSetup>
113+
)}
107114
</div>
108115
);
109116
}

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/nft/NFTMediaFormGroup.tsx

Lines changed: 9 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { FileInput } from "components/shared/FileInput";
44
import type { UseFormReturn } from "react-hook-form";
55
import type { ThirdwebClient } from "thirdweb";
66
import type { NFTInput } from "thirdweb/utils";
7+
import {
8+
getUploadedNFTMediaMeta,
9+
handleNFTMediaUpload,
10+
} from "./handleNFTMediaUpload";
711

812
type NFTMediaFormGroupValues = {
913
image?: NFTInput["image"];
@@ -19,54 +23,15 @@ export function NFTMediaFormGroup<T extends NFTMediaFormGroupValues>(props: {
1923
// T contains all properties of NFTMediaFormGroupValues, so this is a-ok
2024
const form = props.form as unknown as UseFormReturn<NFTMediaFormGroupValues>;
2125

22-
const setFile = (file: File) => {
23-
const animation_url = form.watch("animation_url");
26+
const { media, image, mediaFileError, showCoverImageUpload } =
27+
getUploadedNFTMediaMeta(form);
2428

25-
if (file.type.includes("image")) {
26-
form.setValue("image", file);
29+
const previewMaxWidth = props.previewMaxWidth ?? "200px";
2730

28-
if (animation_url instanceof File) {
29-
form.setValue("animation_url", undefined);
30-
}
31-
} else if (
32-
["audio", "video", "text/html", "model/*"].some((type: string) =>
33-
file.type.includes(type),
34-
) ||
35-
file.name?.endsWith(".glb") ||
36-
file.name?.endsWith(".usdz") ||
37-
file.name?.endsWith(".gltf") ||
38-
file.name.endsWith(".obj")
39-
) {
40-
// audio, video, html, and glb (3d) files
41-
form.setValue("animation_url", file);
42-
} else if (
43-
["text", "application/pdf"].some((type: string) =>
44-
file.type?.includes(type),
45-
)
46-
) {
47-
// text and pdf files
48-
if (animation_url instanceof File) {
49-
form.setValue("animation_url", undefined);
50-
}
51-
}
31+
const setFile = (file: File) => {
32+
handleNFTMediaUpload({ file, form });
5233
};
5334

54-
const _animation_url = form.watch("animation_url");
55-
const _image = form.watch("image");
56-
const _media = _animation_url || _image;
57-
58-
const media =
59-
_media instanceof File || typeof _media === "string" ? _media : undefined;
60-
61-
const image =
62-
_image instanceof File || typeof _image === "string" ? _image : undefined;
63-
64-
const mediaFileError =
65-
form.formState.errors?.animation_url || form.formState.errors?.image;
66-
67-
const showCoverImageUpload = !!_animation_url;
68-
69-
const previewMaxWidth = props.previewMaxWidth ?? "200px";
7035
return (
7136
<div className="flex flex-col gap-6">
7237
<FormFieldSetup
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import type { UseFormReturn } from "react-hook-form";
2+
import type { NFTInput } from "thirdweb/utils";
3+
4+
type MinimalNFTMetadata = {
5+
image?: NFTInput["image"];
6+
animation_url?: NFTInput["animation_url"];
7+
external_url?: NFTInput["external_url"];
8+
};
9+
10+
export function handleNFTMediaUpload<T extends MinimalNFTMetadata>(params: {
11+
file: File;
12+
form: UseFormReturn<T>;
13+
}) {
14+
const { file } = params;
15+
const form = params.form as unknown as UseFormReturn<MinimalNFTMetadata>;
16+
17+
const external_url = form.getValues("external_url");
18+
const animation_url = form.getValues("animation_url");
19+
20+
if (file.type.includes("image")) {
21+
form.setValue("image", file);
22+
23+
if (external_url instanceof File) {
24+
form.setValue("external_url", undefined);
25+
}
26+
27+
if (animation_url instanceof File) {
28+
form.setValue("animation_url", undefined);
29+
}
30+
} else if (
31+
["audio", "video", "text/html", "model/*"].some((type: string) =>
32+
file.type.includes(type),
33+
) ||
34+
file.name?.endsWith(".glb") ||
35+
file.name?.endsWith(".usdz") ||
36+
file.name?.endsWith(".gltf") ||
37+
file.name.endsWith(".obj")
38+
) {
39+
// audio, video, html, and glb (3d) files
40+
form.setValue("animation_url", file);
41+
if (external_url instanceof File) {
42+
form.setValue("external_url", undefined);
43+
}
44+
} else if (
45+
["text", "application/pdf"].some((type: string) =>
46+
file.type?.includes(type),
47+
)
48+
) {
49+
// text and pdf files
50+
form.setValue("external_url", file);
51+
if (animation_url instanceof File) {
52+
form.setValue("animation_url", undefined);
53+
}
54+
}
55+
}
56+
57+
export function getUploadedNFTMediaMeta<T extends MinimalNFTMetadata>(
58+
_form: UseFormReturn<T>,
59+
) {
60+
const form = _form as unknown as UseFormReturn<MinimalNFTMetadata>;
61+
62+
const _animation_url = form.watch("animation_url");
63+
const _external_url = form.watch("external_url");
64+
const _image = form.watch("image");
65+
const _media = _animation_url || _external_url || _image;
66+
const errors = form.formState.errors;
67+
68+
return {
69+
media: stringOrFile(_media),
70+
image: stringOrFile(_image),
71+
mediaFileError:
72+
errors?.animation_url || errors.external_url || errors?.image,
73+
showCoverImageUpload: !!_animation_url || !!_external_url,
74+
animation_url: stringOrFile(_animation_url),
75+
external_url: stringOrFile(_external_url),
76+
};
77+
}
78+
79+
function stringOrFile(value: unknown): string | File | undefined {
80+
if (typeof value === "string" || value instanceof File) {
81+
return value;
82+
}
83+
84+
return undefined;
85+
}

0 commit comments

Comments
 (0)