Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions __tests__/components/header/AppHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jest.mock("@/components/header/HeaderActionButtons", () => ({
jest.mock("@/contexts/NavigationHistoryContext", () => ({
useNavigationHistoryContext: jest.fn(),
}));
jest.mock("@/components/ipfs/IPFSContext", () => ({
resolveIpfsUrlSync: (url: string) => url,
}));

const {
useSeizeConnectContext,
Expand Down
47 changes: 45 additions & 2 deletions __tests__/components/waves/drop/WaveDropAdditionalInfo.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe("WaveDropAdditionalInfo", () => {
/>
);

expect(screen.getByText("Process")).toBeInTheDocument();
expect(screen.getByText("Artwork Commentary")).toBeInTheDocument();
expect(screen.getByText("Process notes here.")).toBeInTheDocument();
});

Expand All @@ -58,7 +58,50 @@ describe("WaveDropAdditionalInfo", () => {
/>
);

expect(screen.getByText("Process")).toBeInTheDocument();
expect(screen.getByText("Additional Media")).toBeInTheDocument();
expect(screen.getAllByRole("img")).toHaveLength(4);
});

it("renders promo video when provided", () => {
const additionalMedia = JSON.stringify({
artist_profile_media: [],
artwork_commentary_media: [],
preview_image: "",
promo_video: "https://example.com/promo.mp4",
});

render(
<WaveDropAdditionalInfo
drop={buildDrop([
{
data_key: MemesSubmissionAdditionalInfoKey.ADDITIONAL_MEDIA,
data_value: additionalMedia,
},
])}
/>
);

expect(screen.getByText("Promo Video")).toBeInTheDocument();
});

it("does not render promo video section when not provided", () => {
const additionalMedia = JSON.stringify({
artist_profile_media: [],
artwork_commentary_media: [],
preview_image: "https://example.com/preview.jpg",
});

render(
<WaveDropAdditionalInfo
drop={buildDrop([
{
data_key: MemesSubmissionAdditionalInfoKey.ADDITIONAL_MEDIA,
data_value: additionalMedia,
},
])}
/>
);

expect(screen.queryByText("Promo Video")).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ describe("AdditionalMediaUpload", () => {
artworkCommentary: "",
aboutArtist: "",
previewImage: "",
promoVideo: "",
requiresPreviewImage: false,
requiresPromoVideoOption: false,
previewRequiredMediaType: null,
onSupportingMediaChange: jest.fn(),
onPreviewImageChange: jest.fn(),
onPromoVideoChange: jest.fn(),
onArtworkCommentaryChange: jest.fn(),
onAboutArtistChange: jest.fn(),
};
Expand All @@ -24,17 +27,30 @@ describe("AdditionalMediaUpload", () => {
).toBeInTheDocument();
});

it("shows preview image section when video submission", () => {
it("shows preview section when video submission", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage previewRequiredMediaType="Video" />);
expect(screen.getByText(/Preview Image \*/i)).toBeInTheDocument();
expect(screen.getByText(/Preview \*/i)).toBeInTheDocument();
expect(
screen.getByText(/Video submissions require a preview image/i)
).toBeInTheDocument();
});

it("does not show preview image section for regular submissions", () => {
it("does not show preview section for regular submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage={false} />);
expect(screen.queryByText(/Preview Image \*/i)).not.toBeInTheDocument();
expect(screen.queryByText(/Preview \*/i)).not.toBeInTheDocument();
});

it("shows promo video section for HTML submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage requiresPromoVideoOption previewRequiredMediaType="HTML" />);
expect(screen.getByText("Promo Video")).toBeInTheDocument();
expect(
screen.getByText(/For HTML submissions, we recommend providing a promo video/i)
).toBeInTheDocument();
});

it("does not show promo video section for video submissions", () => {
render(<AdditionalMediaUpload {...defaultProps} requiresPreviewImage requiresPromoVideoOption={false} previewRequiredMediaType="Video" />);
expect(screen.queryByText("Promo Video")).not.toBeInTheDocument();
});

it("calls onArtworkCommentaryChange when commentary is updated", async () => {
Expand Down
43 changes: 42 additions & 1 deletion __tests__/helpers/waves/drop.helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getStableDropKey, DropSize, convertApiDropToExtendedDrop, getFeedItemKey, getDropPreviewImageUrl } from '@/helpers/waves/drop.helpers';
import { getStableDropKey, DropSize, convertApiDropToExtendedDrop, getFeedItemKey, getDropPreviewImageUrl, getDropPromoVideoUrl } from '@/helpers/waves/drop.helpers';
import { ApiFeedItemType } from '@/generated/models/ApiFeedItemType';
import { MemesSubmissionAdditionalInfoKey } from '@/components/waves/memes/submission/types/OperationalData';

Expand Down Expand Up @@ -72,4 +72,45 @@ describe('drop.helpers', () => {
expect(getDropPreviewImageUrl(metadata as any)).toBeNull();
});
});

describe('getDropPromoVideoUrl', () => {
it('returns null when metadata is undefined', () => {
expect(getDropPromoVideoUrl(undefined)).toBeNull();
});

it('returns null when metadata is empty', () => {
expect(getDropPromoVideoUrl([])).toBeNull();
});

it('returns null when additional_media entry is missing', () => {
const metadata = [{ data_key: 'other_key', data_value: 'value' }];
expect(getDropPromoVideoUrl(metadata as any)).toBeNull();
});

it('returns null when promo_video is not in additional_media', () => {
const metadata = [{
data_key: MemesSubmissionAdditionalInfoKey.ADDITIONAL_MEDIA,
data_value: JSON.stringify({ artist_profile_media: [] })
}];
expect(getDropPromoVideoUrl(metadata as any)).toBeNull();
});

it('returns parsed IPFS URL when promo_video exists', () => {
const ipfsHash = 'QmPromoVideo123';
const metadata = [{
data_key: MemesSubmissionAdditionalInfoKey.ADDITIONAL_MEDIA,
data_value: JSON.stringify({ promo_video: `ipfs://${ipfsHash}` })
}];
const result = getDropPromoVideoUrl(metadata as any);
expect(result).toContain(ipfsHash);
});

it('returns null when JSON parsing fails', () => {
const metadata = [{
data_key: MemesSubmissionAdditionalInfoKey.ADDITIONAL_MEDIA,
data_value: 'invalid json'
}];
expect(getDropPromoVideoUrl(metadata as any)).toBeNull();
});
});
});
4 changes: 2 additions & 2 deletions components/brain/BrainMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ const BrainMobile: React.FC<Props> = ({ children }) => {
};

const dropOverlayClass = isApp
? "tw-fixed tw-inset-0 tw-z-50 tw-bg-black tailwind-scope"
: "tw-absolute tw-inset-0 tw-z-50";
? "tw-fixed tw-inset-0 tw-z-[1010] tw-bg-black tailwind-scope"
: "tw-absolute tw-inset-0 tw-z-[1010]";

return (
<div className="tw-relative tw-flex tw-flex-col tw-h-full">
Expand Down
3 changes: 2 additions & 1 deletion components/header/AppHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import { capitalizeEveryWord, formatAddress } from "@/helpers/Helpers";
import { resolveIpfsUrlSync } from "@/components/ipfs/IPFSContext";
import Image from "next/image";
import { useIdentity } from "@/hooks/useIdentity";
import { useWaveById } from "@/hooks/useWaveById";
Expand Down Expand Up @@ -127,7 +128,7 @@ export default function AppHeader() {
{address ? (
pfp ? (
<Image
src={pfp}
src={resolveIpfsUrlSync(pfp)}
alt="pfp"
width={40}
height={40}
Expand Down
2 changes: 1 addition & 1 deletion components/shared/WavesMessagesWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const WavesMessagesWrapper: React.FC<WavesMessagesWrapperProps> = ({
<div className="tw-flex tw-h-full tw-min-w-0 tw-flex-grow tw-flex-col tw-border-y-0 tw-border-l-0 tw-border-r tw-border-solid tw-border-iron-800">
{children}
{shouldShowDropOverlay && (
<div className="tw-fixed tw-inset-y-0 tw-left-[var(--left-rail,0px)] tw-right-0 tw-z-[60] lg:tw-absolute lg:tw-inset-0 lg:tw-z-[49]">
<div className="tw-fixed tw-inset-y-0 tw-left-[var(--left-rail,0px)] tw-right-0 tw-z-[1010] lg:tw-absolute lg:tw-inset-0 lg:tw-z-[1010]">
<BrainDesktopDrop
drop={{
type: DropSize.FULL,
Expand Down
32 changes: 31 additions & 1 deletion components/waves/drop/MemesSingleWaveDropInfoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ImageScale } from "@/helpers/image.helpers";
import {
ExtendedDrop,
getDropPreviewImageUrl,
getDropPromoVideoUrl,
} from "@/helpers/waves/drop.helpers";
import { useDropInteractionRules } from "@/hooks/drops/useDropInteractionRules";
import useIsMobileScreen from "@/hooks/isMobileScreen";
Expand Down Expand Up @@ -84,6 +85,16 @@ export const MemesSingleWaveDropInfoPanel = ({
return { url, fileInfo: info };
}, [drop.metadata]);

const promoVideoData = useMemo(() => {
const url = getDropPromoVideoUrl(drop.metadata);
if (!url) return null;

const info = getFileInfoFromUrl(url);
if (!info) return null;

return { url, fileInfo: info };
}, [drop.metadata]);

const fileName = useMemo(() => {
let name = title;
if (wave?.name) {
Expand Down Expand Up @@ -195,7 +206,9 @@ export const MemesSingleWaveDropInfoPanel = ({
<SingleWaveDropInfoDetails drop={drop} />
<WaveDropAdditionalInfo drop={drop} />

{(artworkMedia && fileInfo) || previewImageData ? (
{(artworkMedia && fileInfo) ||
previewImageData ||
promoVideoData ? (
<div className="tw-mt-8 tw-border-x-0 tw-border-b-0 tw-border-t tw-border-solid tw-border-iron-800 tw-pt-8">
<div className="tw-inline-grid tw-grid-cols-[auto_auto_auto] tw-items-center tw-gap-x-3 tw-gap-y-2">
{artworkMedia && fileInfo && (
Expand Down Expand Up @@ -232,6 +245,23 @@ export const MemesSingleWaveDropInfoPanel = ({
/>
</>
)}
{promoVideoData && (
<>
<span className="tw-text-xs tw-font-medium tw-text-iron-600">
Promo Video:
</span>
<span className="tw-text-xs tw-font-medium tw-text-iron-400">
{promoVideoData.fileInfo.extension.toUpperCase()}
</span>
<Download
href={promoVideoData.url}
name={`${fileName ?? "promo"}-promo-video`}
extension={promoVideoData.fileInfo.extension}
variant="text"
alwaysShowText
/>
</>
)}
</div>
</div>
) : null}
Expand Down
Loading