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
42 changes: 15 additions & 27 deletions __tests__/hooks/useCommunityCurationsDrops.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,24 +42,12 @@ const getDefaultQueryResult = (
isLoading: false,
});

const buildDrop = ({
id,
mimeType,
}: {
readonly id: string;
readonly mimeType?: string | undefined;
}): ApiDrop =>
const buildDrop = ({ id }: { readonly id: string }): ApiDrop =>
({
id,
metadata: [],
nft_links: [],
parts: mimeType
? [
{
media: [{ mime_type: mimeType }],
},
]
: [],
parts: [],
}) as unknown as ApiDrop;

describe("useCommunityCurationsDrops", () => {
Expand Down Expand Up @@ -105,37 +93,37 @@ describe("useCommunityCurationsDrops", () => {
).toBeUndefined();
});

it("dedupes loaded drops and keeps existing media filtering", () => {
const imageDrop = buildDrop({ id: "image-drop", mimeType: "image/png" });
const videoDrop = buildDrop({ id: "video-drop", mimeType: "video/mp4" });
const duplicateVideoDrop = buildDrop({
id: "video-drop",
mimeType: "video/mp4",
});
it("dedupes loaded drops", () => {
const firstDrop = buildDrop({ id: "first-drop" });
const secondDrop = buildDrop({ id: "second-drop" });
const duplicateSecondDrop = buildDrop({ id: "second-drop" });

mockUseInfiniteQuery.mockReturnValue(
getDefaultQueryResult([
{
data: [imageDrop, videoDrop],
data: [firstDrop, secondDrop],
page: 1,
next: true,
},
{
data: [duplicateVideoDrop],
data: [duplicateSecondDrop],
page: 2,
next: false,
},
])
);

const { result } = renderHook(() =>
useCommunityCurationsDrops({ limit: 12, mediaFilter: "video" })
useCommunityCurationsDrops({ limit: 12 })
);

expect(result.current.allDrops.map((drop) => drop.id)).toEqual([
"image-drop",
"video-drop",
"first-drop",
"second-drop",
]);
expect(result.current.drops.map((drop) => drop.id)).toEqual([
"first-drop",
"second-drop",
]);
expect(result.current.drops.map((drop) => drop.id)).toEqual(["video-drop"]);
});
});
44 changes: 4 additions & 40 deletions components/community-curations/CommunityCurations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,9 @@
import { COMMUNITY_CURATIONS_LIMIT } from "@/components/community-curations/communityCurations.constants";
import CommunityCurationsMasonry from "@/components/community-curations/CommunityCurationsMasonry";
import { useLayout } from "@/components/brain/my-stream/layout/LayoutContext";
import type { CommonSelectItem } from "@/components/utils/select/CommonSelect";
import CommonTabs from "@/components/utils/select/tabs/CommonTabs";
import {
useCommunityCurationsDrops,
type CommunityCurationsMediaFilter,
} from "@/hooks/useCommunityCurationsDrops";
import { useCommunityCurationsDrops } from "@/hooks/useCommunityCurationsDrops";
import { useCallback, useState } from "react";

const MEDIA_FILTER_OPTIONS: CommonSelectItem<CommunityCurationsMediaFilter>[] =
[
{ key: "all", label: "All", value: "all" },
{ key: "image", label: "Images", value: "image" },
{ key: "video", label: "Video", value: "video" },
];

const COMMUNITY_CURATIONS_SKELETON_CARDS = [
{ id: "compact", mediaHeight: 210, lines: 2 },
{ id: "tall", mediaHeight: 320, lines: 4 },
Expand Down Expand Up @@ -111,8 +99,6 @@ export default function CommunityCurations() {
const [scrollContainer, setScrollContainer] = useState<HTMLElement | null>(
null
);
const [mediaFilter, setMediaFilter] =
useState<CommunityCurationsMediaFilter>("all");
const {
allDrops,
drops,
Expand All @@ -122,7 +108,6 @@ export default function CommunityCurations() {
isFetchingNextPage,
isLoading,
} = useCommunityCurationsDrops({
mediaFilter,
limit: COMMUNITY_CURATIONS_LIMIT,
});

Expand All @@ -132,14 +117,6 @@ export default function CommunityCurations() {
!isInitialLoading && !isError && drops.length === 0 && !hasMorePages;
const shouldShowMasonry =
!isInitialLoading && !isError && (drops.length > 0 || hasMorePages);
const emptyStateTitle =
mediaFilter === "all"
? "No curated drops yet"
: `No ${mediaFilter} drops found`;
const emptyStateDescription =
mediaFilter === "all"
? "Community-curated drops will appear here when visible curations have activity."
: "Try All to see every community-curated drop.";
const handleFetchNextPage = useCallback(async () => {
await fetchNextPage();
}, [fetchNextPage]);
Expand All @@ -151,7 +128,7 @@ export default function CommunityCurations() {
style={waveViewStyle}
>
<div className="tw-mx-auto tw-w-full tw-max-w-6xl">
<div className="tw-flex tw-flex-col tw-gap-4 md:tw-flex-row md:tw-items-end md:tw-justify-between">
<div className="tw-flex tw-flex-col tw-gap-4">
<div className="tw-max-w-2xl">
<h1 className="tw-mb-0 tw-text-2xl tw-font-bold tw-text-white">
Community Curations
Expand All @@ -160,19 +137,6 @@ export default function CommunityCurations() {
Community-curated drops from across 6529 Waves.
</p>
</div>

<div className="tw-flex tw-flex-wrap tw-items-center tw-gap-2">
<div className="tw-flex-shrink-0">
<CommonTabs
items={MEDIA_FILTER_OPTIONS}
activeItem={mediaFilter}
filterLabel="Community curation media filter"
setSelected={setMediaFilter}
size="sm"
fill={false}
/>
</div>
</div>
</div>

<div className="tw-mt-6">
Expand All @@ -187,8 +151,8 @@ export default function CommunityCurations() {

{shouldShowEmptyState && (
<CommunityCurationsEmptyState
title={emptyStateTitle}
description={emptyStateDescription}
title="No curated drops yet"
description="Community-curated drops will appear here when visible curations have activity."
/>
)}

Expand Down
6 changes: 5 additions & 1 deletion components/community-curations/CommunityCurationsMasonry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import CircleLoader, {
import { TweetPreviewModeProvider } from "@/components/tweets/TweetPreviewModeContext";
import Drop, { DropLocation } from "@/components/waves/drops/Drop";
import type { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { useNavigateToDropWave } from "@/hooks/useNavigateToDropWave";
import { useIntersectionObserver } from "@/hooks/scroll/useIntersectionObserver";
import {
type RenderComponentProps,
Expand Down Expand Up @@ -239,6 +240,8 @@ function CommunityCurationsInfiniteScrollTrigger({
function CommunityCurationsMasonryItem({
data: drop,
}: RenderComponentProps<ExtendedDrop>) {
const navigateToDropWave = useNavigateToDropWave();

return (
<article className="tw-group tw-relative tw-isolate">
<Drop
Expand All @@ -252,7 +255,8 @@ function CommunityCurationsMasonryItem({
dropViewDropId={null}
onReply={noop}
onReplyClick={noop}
onQuoteClick={noop}
onQuoteClick={navigateToDropWave}
onDropContentClick={navigateToDropWave}
identityMode="default"
showInteractions={false}
/>
Expand Down
103 changes: 0 additions & 103 deletions components/community-curations/communityCurations.helpers.ts

This file was deleted.

10 changes: 6 additions & 4 deletions components/user/waves/UserPageProfileWaveMasonry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import CircleLoader, {
import { Spinner } from "@/components/dotLoader/DotLoader";
import { TweetPreviewModeProvider } from "@/components/tweets/TweetPreviewModeContext";
import CommonIntersectionElement from "@/components/utils/CommonIntersectionElement";
import type { ApiDrop } from "@/generated/models/ApiDrop";
import { ApiDropType } from "@/generated/models/ApiDropType";
import Drop, { DropLocation } from "@/components/waves/drops/Drop";
import DropMinimalIdentityRow from "@/components/waves/drops/DropMinimalIdentityRow";
Expand All @@ -20,6 +19,7 @@ import { areSameProfileIdentity } from "@/helpers/ProfileHelpers";
import type { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { useCurationManagementPermission } from "@/hooks/useCurationManagementPermission";
import { useDropCurationMembershipMutation } from "@/hooks/drops/useDropCurationMembershipMutation";
import { useNavigateToDropWave } from "@/hooks/useNavigateToDropWave";
import useDeviceInfo from "@/hooks/useDeviceInfo";
import useIsTouchDevice from "@/hooks/useIsTouchDevice";
import { XMarkIcon } from "@heroicons/react/24/outline";
Expand Down Expand Up @@ -221,6 +221,7 @@ function UserPageProfileWaveMasonryCard({
const [activePartIndex, setActivePartIndex] = useState(0);
const replyTo = drop.reply_to;
const activePart = drop.parts[activePartIndex] ?? drop.parts[0];
const navigateToDropWave = useNavigateToDropWave();
const layout = getProfileMasonryCardLayout({
activePart,
drop,
Expand All @@ -237,10 +238,10 @@ function UserPageProfileWaveMasonryCard({
drop={drop}
activePartIndex={activePartIndex}
setActivePartIndex={setActivePartIndex}
onQuoteClick={(_quotedDrop: ApiDrop) => {}}
onQuoteClick={navigateToDropWave}
onLongPress={() => {}}
setLongPressTriggered={(_triggered: boolean) => {}}
onDropContentClick={undefined}
onDropContentClick={navigateToDropWave}
mediaImageScale={ImageScale.AUTOx1080}
fullWidthMedia={true}
/>
Expand All @@ -262,7 +263,8 @@ function UserPageProfileWaveMasonryCard({
dropViewDropId={null}
onReply={() => {}}
onReplyClick={() => {}}
onQuoteClick={() => {}}
onQuoteClick={navigateToDropWave}
onDropContentClick={navigateToDropWave}
identityMode={layout.identityMode}
showInteractions={false}
/>
Expand Down
Loading
Loading