diff --git a/__tests__/components/waves/drop/useSingleWaveDropData.test.tsx b/__tests__/components/waves/drop/useSingleWaveDropData.test.tsx
index 0eeb523500..3f6e1e0be8 100644
--- a/__tests__/components/waves/drop/useSingleWaveDropData.test.tsx
+++ b/__tests__/components/waves/drop/useSingleWaveDropData.test.tsx
@@ -1,91 +1,118 @@
-import { renderHook, waitFor } from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
-import React from "react";
+import { renderHook, waitFor } from "@testing-library/react";
+import type { ReactNode } from "react";
import { useSingleWaveDropData } from "@/components/waves/drop/useSingleWaveDropData";
-import { fetchDropV2ById } from "@/services/api/wave-drops-v2-api";
+import { DropSize } from "@/helpers/waves/drop.helpers";
+import {
+ fetchDropMetadataByIdV2,
+ fetchDropV2ById,
+} from "@/services/api/wave-drops-v2-api";
jest.mock("@/services/api/wave-drops-v2-api", () => ({
+ fetchDropMetadataByIdV2: jest.fn(),
fetchDropV2ById: jest.fn(),
}));
+const useWaveDataMock = jest.fn(() => ({ data: { id: "wave-1" } }));
jest.mock("@/hooks/useWaveData", () => ({
- useWaveData: () => ({ data: { id: "wave-1" } }),
+ useWaveData: (props: unknown) => useWaveDataMock(props),
}));
const fetchDropV2ByIdMock = fetchDropV2ById as jest.MockedFunction<
typeof fetchDropV2ById
>;
+const fetchDropMetadataByIdV2Mock =
+ fetchDropMetadataByIdV2 as jest.MockedFunction<
+ typeof fetchDropMetadataByIdV2
+ >;
const createWrapper = () => {
const queryClient = new QueryClient({
- defaultOptions: { queries: { retry: false } },
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
});
- return ({ children }: { children: React.ReactNode }) => (
- {children}
- );
+ return function Wrapper({ children }: { readonly children: ReactNode }) {
+ return (
+ {children}
+ );
+ };
};
const createInitialDrop = (id: string) =>
({
id,
wave: { id: "wave-1" },
+ metadata: [{ data_key: "priority", data_value: id }],
stableHash: `${id}-hash`,
stableKey: `${id}-key`,
+ type: DropSize.FULL,
}) as any;
-const createDeferred = () => {
- let resolve!: (value: T) => void;
- const promise = new Promise((promiseResolve) => {
- resolve = promiseResolve;
- });
-
- return { promise, resolve };
-};
-
describe("useSingleWaveDropData", () => {
beforeEach(() => {
jest.resetAllMocks();
+ useWaveDataMock.mockReturnValue({ data: { id: "wave-1" } });
+ fetchDropMetadataByIdV2Mock.mockResolvedValue([
+ { data_key: "priority", data_value: "drop-1" },
+ { data_key: "title", data_value: "Full Title" },
+ ]);
});
- it("fetches single-drop detail without eager top raters", async () => {
- fetchDropV2ByIdMock.mockResolvedValue({
- id: "drop-1",
- wave: { id: "wave-1" },
- } as any);
-
- renderHook(
- () =>
- useSingleWaveDropData(
- {
- id: "drop-1",
- wave: { id: "wave-1" },
- stableHash: "hash",
- stableKey: "key",
- } as any,
- jest.fn()
- ),
+ it("fetches detail metadata without fetching single-drop detail", async () => {
+ const initialDrop = createInitialDrop("drop-1");
+
+ const { result } = renderHook(
+ () => useSingleWaveDropData(initialDrop, jest.fn()),
{ wrapper: createWrapper() }
);
+ expect(fetchDropV2ByIdMock).not.toHaveBeenCalled();
+ expect(fetchDropMetadataByIdV2Mock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ dropId: "drop-1",
+ priorityMetadata: initialDrop.metadata,
+ })
+ );
+ expect(useWaveDataMock).toHaveBeenCalledWith(
+ expect.objectContaining({ waveId: "wave-1" })
+ );
+ expect(result.current.drop).toEqual(
+ expect.objectContaining({
+ id: "drop-1",
+ metadata: initialDrop.metadata,
+ })
+ );
+
await waitFor(() => {
- expect(fetchDropV2ByIdMock).toHaveBeenCalledWith(
- "drop-1",
- expect.objectContaining({ aborted: false }),
- { includeTopRaters: false }
- );
+ expect(result.current.drop.metadata).toEqual([
+ { data_key: "priority", data_value: "drop-1" },
+ { data_key: "title", data_value: "Full Title" },
+ ]);
});
- });
- it("does not expose the previous drop while a new drop id is loading", async () => {
- const secondDrop = createDeferred();
- fetchDropV2ByIdMock
- .mockResolvedValueOnce({
+ expect(result.current.extendedDrop).toEqual(
+ expect.objectContaining({
id: "drop-1",
- wave: { id: "wave-1" },
- } as any)
- .mockReturnValueOnce(secondDrop.promise);
+ type: DropSize.FULL,
+ stableHash: "drop-1-hash",
+ stableKey: "drop-1-key",
+ metadata: [
+ { data_key: "priority", data_value: "drop-1" },
+ { data_key: "title", data_value: "Full Title" },
+ ],
+ })
+ );
+ });
+
+ it("switches directly to a new initial drop without exposing stale detail data", async () => {
+ fetchDropMetadataByIdV2Mock.mockImplementation(async ({ dropId }) => [
+ { data_key: "full", data_value: dropId },
+ ]);
const { result, rerender } = renderHook(
({ initialDrop }) => useSingleWaveDropData(initialDrop, jest.fn()),
@@ -95,22 +122,34 @@ describe("useSingleWaveDropData", () => {
}
);
+ expect(result.current.drop.id).toBe("drop-1");
+
await waitFor(() => {
- expect(result.current.drop?.id).toBe("drop-1");
+ expect(result.current.drop.metadata).toEqual([
+ { data_key: "full", data_value: "drop-1" },
+ ]);
});
rerender({ initialDrop: createInitialDrop("drop-2") });
- expect(result.current.drop).toBeUndefined();
- expect(result.current.extendedDrop).toBeNull();
-
- secondDrop.resolve({
- id: "drop-2",
- wave: { id: "wave-1" },
- });
+ expect(result.current.drop.id).toBe("drop-2");
+ expect(result.current.extendedDrop.id).toBe("drop-2");
+ expect(result.current.drop.metadata).toEqual([
+ { data_key: "priority", data_value: "drop-2" },
+ ]);
await waitFor(() => {
- expect(result.current.drop?.id).toBe("drop-2");
+ expect(result.current.drop.metadata).toEqual([
+ { data_key: "full", data_value: "drop-2" },
+ ]);
});
+
+ expect(fetchDropMetadataByIdV2Mock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ dropId: "drop-2",
+ priorityMetadata: [{ data_key: "priority", data_value: "drop-2" }],
+ })
+ );
+ expect(fetchDropV2ByIdMock).not.toHaveBeenCalled();
});
});
diff --git a/__tests__/components/waves/drops/WaveDropQuoteWithDropId.test.tsx b/__tests__/components/waves/drops/WaveDropQuoteWithDropId.test.tsx
index fc9f967fde..1ed3409765 100644
--- a/__tests__/components/waves/drops/WaveDropQuoteWithDropId.test.tsx
+++ b/__tests__/components/waves/drops/WaveDropQuoteWithDropId.test.tsx
@@ -11,11 +11,18 @@ jest.mock("@/components/waves/drops/WaveDropQuote", () => (props: any) => {
});
const useQuery = jest.fn();
+const getQueryData = jest.fn();
jest.mock("@tanstack/react-query", () => ({
useQuery: (opts: any) => useQuery(opts),
+ useQueryClient: () => ({ getQueryData }),
keepPreviousData: "keep",
}));
+const useMyStreamOptional = jest.fn();
+jest.mock("@/contexts/wave/MyStreamContext", () => ({
+ useMyStreamOptional: () => useMyStreamOptional(),
+}));
+
jest.mock("@/services/api/drop-api", () => {
const { QueryKey: ActualQueryKey } = jest.requireActual(
"@/components/react-query-wrapper/ReactQueryWrapper"
@@ -36,6 +43,8 @@ describe("WaveDropQuoteWithDropId", () => {
beforeEach(() => {
capturedProps = undefined;
jest.clearAllMocks();
+ getQueryData.mockReturnValue(undefined);
+ useMyStreamOptional.mockReturnValue(null);
});
it("fetches drop by drop ID and renders quote when no maybeDrop exists", async () => {
@@ -62,7 +71,7 @@ describe("WaveDropQuoteWithDropId", () => {
expect(fetchDropByIdBatchedMock).toHaveBeenCalledWith("d1");
});
- it("treats maybeDrop as stale initial data and fetches fresh data", async () => {
+ it("uses maybeDrop without fetching fresh data", () => {
const maybeDrop = { id: "d1", wave: { id: "old-wave" } };
useQuery.mockImplementation((opts: any) => {
return { data: opts.initialData };
@@ -81,11 +90,66 @@ describe("WaveDropQuoteWithDropId", () => {
expect(capturedProps.isNotFound).toBe(false);
const call = useQuery.mock.calls[0][0];
expect(call.queryKey).toEqual([QueryKey.DROP, { drop_id: "d1" }]);
- expect(call.enabled).toBe(true);
+ expect(call.enabled).toBe(false);
expect(call.initialData).toBe(maybeDrop);
- expect(call.initialDataUpdatedAt).toBe(0);
- await call.queryFn();
- expect(fetchDropByIdBatchedMock).toHaveBeenCalledWith("d1");
+ expect(call).not.toHaveProperty("initialDataUpdatedAt");
+ expect(fetchDropByIdBatchedMock).not.toHaveBeenCalled();
+ });
+
+ it("uses an already cached drop without fetching fresh data", () => {
+ const cachedDrop = { id: "d1", wave: { id: "cached-wave" } };
+ getQueryData.mockReturnValue(cachedDrop);
+ useQuery.mockImplementation((opts: any) => {
+ return { data: opts.initialData };
+ });
+
+ render(
+
+ );
+
+ expect(capturedProps.drop).toBe(cachedDrop);
+ const call = useQuery.mock.calls[0][0];
+ expect(call.enabled).toBe(false);
+ expect(call.initialData).toBe(cachedDrop);
+ });
+
+ it("uses a full drop from wave messages without fetching by id", () => {
+ const waveDrop = {
+ id: "d1",
+ wave: { id: "w1" },
+ type: "FULL",
+ stableKey: "d1",
+ stableHash: "d1",
+ };
+ useMyStreamOptional.mockReturnValue({
+ activeWave: { id: "w1" },
+ waveMessagesStore: {
+ getData: jest.fn(() => ({ drops: [waveDrop] })),
+ },
+ });
+ useQuery.mockImplementation((opts: any) => {
+ return { data: opts.initialData };
+ });
+
+ render(
+
+ );
+
+ expect(capturedProps.drop).toBe(waveDrop);
+ const call = useQuery.mock.calls[0][0];
+ expect(call.enabled).toBe(false);
+ expect(call.initialData).toBe(waveDrop);
});
it("passes not-found state when the refresh returns the not-found message", () => {
@@ -130,7 +194,7 @@ describe("WaveDropQuoteWithDropId", () => {
expect(capturedProps.drop).toBeNull();
expect(capturedProps.isNotFound).toBe(true);
const call = useQuery.mock.calls[0][0];
- expect(call.enabled).toBe(true);
+ expect(call.enabled).toBe(false);
});
it("passes not-found state when the refresh returns a 404", () => {
diff --git a/__tests__/services/api/drop-api.test.ts b/__tests__/services/api/drop-api.test.ts
index 740f8d2856..a549c8573b 100644
--- a/__tests__/services/api/drop-api.test.ts
+++ b/__tests__/services/api/drop-api.test.ts
@@ -18,14 +18,17 @@ afterEach(() => {
});
describe("fetchDropsByIds", () => {
- it("fetches drops with the v2 drop detail endpoint", async () => {
+ it("fetches drops with lean v2 drop detail hydration", async () => {
const replyDrop = { id: "reply-1" } as ApiDrop;
fetchDropV2ByIdMock.mockResolvedValue(replyDrop);
const result = await fetchDropsByIds(["reply-1"]);
expect(fetchDropV2ByIdMock).toHaveBeenCalledTimes(1);
- expect(fetchDropV2ByIdMock).toHaveBeenCalledWith("reply-1");
+ expect(fetchDropV2ByIdMock).toHaveBeenCalledWith("reply-1", undefined, {
+ includeFullMetadata: false,
+ includeTopRaters: false,
+ });
expect(result).toEqual([replyDrop]);
});
diff --git a/__tests__/services/api/wave-drops-v2-api.test.ts b/__tests__/services/api/wave-drops-v2-api.test.ts
index 8211df3b38..a14c4cfab5 100644
--- a/__tests__/services/api/wave-drops-v2-api.test.ts
+++ b/__tests__/services/api/wave-drops-v2-api.test.ts
@@ -6,6 +6,7 @@ import type { ApiWaveMin } from "@/generated/models/ApiWaveMin";
import { commonApiFetch } from "@/services/api/common-api";
import {
fetchBoostedDropsV2,
+ fetchDropMetadataByIdV2,
fetchDropRepliesV2,
fetchDropV2ById,
fetchWaveDropsFeedV2,
@@ -385,7 +386,49 @@ describe("fetchDropV2ById", () => {
jest.clearAllMocks();
});
- it("keeps full metadata hydration for single drop details while allowing top raters to be skipped", async () => {
+ it("fetches drop metadata by id without fetching the drop detail", async () => {
+ const fullMetadata = [{ data_key: "artist", data_value: "Alice" }];
+ commonApiFetchMock.mockResolvedValueOnce(fullMetadata);
+
+ const result = await fetchDropMetadataByIdV2({
+ dropId: "drop-1",
+ priorityMetadata,
+ });
+
+ expect(commonApiFetchMock).toHaveBeenCalledTimes(1);
+ expect(commonApiFetchMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ endpoint: "v2/drops/drop-1/metadata",
+ })
+ );
+ expect(commonApiFetchMock).not.toHaveBeenCalledWith(
+ expect.objectContaining({
+ endpoint: "v2/drops/drop-1",
+ })
+ );
+ expect(result).toEqual([...priorityMetadata, ...fullMetadata]);
+ });
+
+ it("keeps by-id drop hydration lean by default", async () => {
+ commonApiFetchMock.mockResolvedValueOnce({
+ wave,
+ drop: createEnrichableDrop(),
+ });
+
+ const result = await fetchDropV2ById("drop-1");
+
+ expect(commonApiFetchMock).toHaveBeenCalledTimes(1);
+ expect(commonApiFetchMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ endpoint: "v2/drops/drop-1",
+ })
+ );
+ expectNoListEnrichmentCalls();
+ expect(result.metadata).toEqual(priorityMetadata);
+ expect(result.top_raters).toEqual([]);
+ });
+
+ it("allows explicit full metadata hydration while top raters are skipped", async () => {
const fullMetadata = [{ data_key: "artist", data_value: "Alice" }];
commonApiFetchMock
.mockResolvedValueOnce({
@@ -395,6 +438,7 @@ describe("fetchDropV2ById", () => {
.mockResolvedValueOnce(fullMetadata);
const result = await fetchDropV2ById("drop-1", undefined, {
+ includeFullMetadata: true,
includeTopRaters: false,
});
diff --git a/components/drops/view/part/dropPartMarkdown/renderers.tsx b/components/drops/view/part/dropPartMarkdown/renderers.tsx
index 5e83adffc2..733d528da8 100644
--- a/components/drops/view/part/dropPartMarkdown/renderers.tsx
+++ b/components/drops/view/part/dropPartMarkdown/renderers.tsx
@@ -120,6 +120,7 @@ const renderSeizeQuote = (
dropId={dropId}
partId={1}
maybeDrop={null}
+ waveId={waveId}
onQuoteClick={onQuoteClick}
embedPath={options?.embedPath}
quotePath={options?.quotePath}
diff --git a/components/waves/drop/useSingleWaveDropData.ts b/components/waves/drop/useSingleWaveDropData.ts
index b9536d2649..012a664369 100644
--- a/components/waves/drop/useSingleWaveDropData.ts
+++ b/components/waves/drop/useSingleWaveDropData.ts
@@ -1,51 +1,61 @@
"use client";
+import { QueryKey } from "@/components/react-query-wrapper/ReactQueryWrapper";
+import type { ApiDrop } from "@/generated/models/ApiDrop";
import { useCallback, useMemo } from "react";
import type { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { DropSize } from "@/helpers/waves/drop.helpers";
-import { QueryKey } from "@/components/react-query-wrapper/ReactQueryWrapper";
import { useWaveData } from "@/hooks/useWaveData";
-import { useQuery } from "@tanstack/react-query";
-import type { ApiDrop } from "@/generated/models/ApiDrop";
import { DROP_DETAIL_STALE_TIME_MS } from "@/services/api/drop-api";
-import { fetchDropV2ById } from "@/services/api/wave-drops-v2-api";
+import { fetchDropMetadataByIdV2 } from "@/services/api/wave-drops-v2-api";
+import { useQuery } from "@tanstack/react-query";
export const useSingleWaveDropData = (
initialDrop: ExtendedDrop,
onClose: () => void
) => {
- const { data: drop } = useQuery({
+ const onWaveNotFound = useCallback(() => {
+ onClose();
+ }, [onClose]);
+
+ const { data: wave } = useWaveData({
+ waveId: initialDrop.wave.id,
+ onWaveNotFound,
+ });
+
+ const { data: hydratedMetadata } = useQuery({
queryKey: [
QueryKey.DROP,
{
drop_id: initialDrop.id,
- view: "single-wave-drop",
+ view: "metadata",
},
],
queryFn: ({ signal }) =>
- fetchDropV2ById(initialDrop.id, signal, { includeTopRaters: false }),
+ fetchDropMetadataByIdV2({
+ dropId: initialDrop.id,
+ priorityMetadata: initialDrop.metadata,
+ signal,
+ }),
+ enabled: initialDrop.id.trim().length > 0,
staleTime: DROP_DETAIL_STALE_TIME_MS,
});
- const onWaveNotFound = useCallback(() => {
- onClose();
- }, [onClose]);
-
- const { data: wave } = useWaveData({
- waveId: drop?.wave.id ?? null,
- onWaveNotFound,
- });
+ const drop = useMemo(
+ () => ({
+ ...initialDrop,
+ metadata: hydratedMetadata ?? initialDrop.metadata,
+ }),
+ [hydratedMetadata, initialDrop]
+ );
const extendedDrop = useMemo(
- () =>
- drop
- ? {
- type: DropSize.FULL as const,
- ...drop,
- stableHash: initialDrop.stableHash,
- stableKey: initialDrop.stableKey,
- }
- : null,
+ () => ({
+ ...drop,
+ type: DropSize.FULL as const,
+ stableHash: initialDrop.stableHash,
+ stableKey: initialDrop.stableKey,
+ }),
[drop, initialDrop.stableHash, initialDrop.stableKey]
);
diff --git a/components/waves/drops/WaveDropPartContentMarkdown.tsx b/components/waves/drops/WaveDropPartContentMarkdown.tsx
index 679e5c83a9..548cb9eba4 100644
--- a/components/waves/drops/WaveDropPartContentMarkdown.tsx
+++ b/components/waves/drops/WaveDropPartContentMarkdown.tsx
@@ -182,6 +182,7 @@ const WaveDropPartContentMarkdown: React.FC<
? { ...part.quoted_drop.drop, wave: wave }
: null
}
+ waveId={wave.id}
onQuoteClick={onQuoteClick}
embedPath={currentDropEmbedPath}
quotePath={currentQuotePath}
diff --git a/components/waves/drops/WaveDropQuoteWithDropId.tsx b/components/waves/drops/WaveDropQuoteWithDropId.tsx
index 84214beb8b..b0b3f4c349 100644
--- a/components/waves/drops/WaveDropQuoteWithDropId.tsx
+++ b/components/waves/drops/WaveDropQuoteWithDropId.tsx
@@ -1,8 +1,14 @@
"use client";
import React from "react";
-import { keepPreviousData, useQuery } from "@tanstack/react-query";
+import {
+ keepPreviousData,
+ useQuery,
+ useQueryClient,
+} from "@tanstack/react-query";
import type { ApiDrop } from "@/generated/models/ApiDrop";
+import { useMyStreamOptional } from "@/contexts/wave/MyStreamContext";
+import { DropSize, type ExtendedDrop } from "@/helpers/waves/drop.helpers";
import {
DROP_DETAIL_STALE_TIME_MS,
fetchDropByIdBatched,
@@ -14,6 +20,7 @@ interface WaveDropQuoteWithDropIdProps {
readonly dropId: string;
readonly partId: number;
readonly maybeDrop: ApiDrop | null;
+ readonly waveId?: string | undefined;
readonly onQuoteClick: (drop: ApiDrop) => void;
readonly embedPath?: readonly string[] | undefined;
readonly quotePath?: readonly string[] | undefined;
@@ -63,6 +70,7 @@ const WaveDropQuoteWithDropId: React.FC = ({
dropId,
partId,
maybeDrop,
+ waveId,
onQuoteClick,
embedPath,
quotePath,
@@ -71,16 +79,29 @@ const WaveDropQuoteWithDropId: React.FC = ({
onLinkCardActionsActiveChange,
}) => {
const normalizedDropId = dropId.trim();
+ const queryClient = useQueryClient();
+ const myStream = useMyStreamOptional();
+ const cachedDrop = queryClient.getQueryData(
+ getDropQueryKey(normalizedDropId)
+ );
+ const targetWaveId = waveId ?? myStream?.activeWave.id ?? null;
+ const waveMessagesDrop = targetWaveId
+ ? myStream?.waveMessagesStore
+ .getData(targetWaveId)
+ ?.drops.find(
+ (drop): drop is ExtendedDrop =>
+ drop.type === DropSize.FULL && drop.id === normalizedDropId
+ )
+ : null;
+ const initialDrop = maybeDrop ?? cachedDrop ?? waveMessagesDrop ?? null;
const { data: drop, error } = useQuery({
queryKey: getDropQueryKey(normalizedDropId),
queryFn: () => fetchDropByIdBatched(normalizedDropId),
placeholderData: keepPreviousData,
- enabled: normalizedDropId.length > 0,
+ enabled: normalizedDropId.length > 0 && initialDrop === null,
staleTime: DROP_DETAIL_STALE_TIME_MS,
- ...(maybeDrop === null
- ? {}
- : { initialData: maybeDrop, initialDataUpdatedAt: 0 }),
+ ...(initialDrop === null ? {} : { initialData: initialDrop }),
});
const isNotFound = isDropNotFoundError(error, normalizedDropId);
diff --git a/services/api/drop-api.ts b/services/api/drop-api.ts
index a598cd93ac..2b925ddcd1 100644
--- a/services/api/drop-api.ts
+++ b/services/api/drop-api.ts
@@ -66,7 +66,12 @@ const fetchDropResultsByIds = async (
}
const results = await Promise.allSettled(
- uniqueDropIds.map((dropId) => fetchDropV2ById(dropId))
+ uniqueDropIds.map((dropId) =>
+ fetchDropV2ById(dropId, undefined, {
+ includeFullMetadata: false,
+ includeTopRaters: false,
+ })
+ )
);
return results.map((result, index) => {
diff --git a/services/api/wave-drops-v2-api.ts b/services/api/wave-drops-v2-api.ts
index cd1a7f77c9..d710b4c3de 100644
--- a/services/api/wave-drops-v2-api.ts
+++ b/services/api/wave-drops-v2-api.ts
@@ -194,8 +194,8 @@ export const fetchDropReactionDetailsV2 = async (
};
const mergeMetadata = (
- priorityMetadata: ApiDropMetadataResponse[],
- metadata: ApiDropMetadataResponse[]
+ priorityMetadata: readonly ApiDropMetadataResponse[],
+ metadata: readonly ApiDropMetadataResponse[]
): ApiDropMetadataResponse[] => {
const priorityKeys = new Set(
priorityMetadata.map((item) => item.data_key.trim()).filter(Boolean)
@@ -207,6 +207,27 @@ const mergeMetadata = (
];
};
+export const fetchDropMetadataByIdV2 = async ({
+ dropId,
+ priorityMetadata = [],
+ signal,
+}: {
+ readonly dropId: string;
+ readonly priorityMetadata?: readonly ApiDropMetadataResponse[] | undefined;
+ readonly signal?: AbortSignal | undefined;
+}): Promise => {
+ try {
+ const metadata = await commonApiFetch({
+ endpoint: `v2/drops/${getDropEndpointId(getNormalizedDropId(dropId))}/metadata`,
+ signal,
+ });
+ return mergeMetadata(priorityMetadata, metadata);
+ } catch (error) {
+ rethrowAbortFetchError(error);
+ return [...priorityMetadata];
+ }
+};
+
const fetchDropMetadataV2 = async (
drop: ApiDropV2,
signal?: AbortSignal,
@@ -218,16 +239,11 @@ const fetchDropMetadataV2 = async (
return priorityMetadata;
}
- try {
- const metadata = await commonApiFetch({
- endpoint: `v2/drops/${getDropEndpointId(drop.id)}/metadata`,
- signal,
- });
- return mergeMetadata(priorityMetadata, metadata);
- } catch (error) {
- rethrowAbortFetchError(error);
- return priorityMetadata;
- }
+ return fetchDropMetadataByIdV2({
+ dropId: drop.id,
+ priorityMetadata,
+ signal,
+ });
};
const fetchTopRatersV2 = async (
@@ -548,8 +564,8 @@ export async function fetchDropV2ById(
drop: data.drop,
wave,
signal,
- includeFullMetadata: options?.includeFullMetadata,
- includeTopRaters: options?.includeTopRaters,
+ includeFullMetadata: options?.includeFullMetadata ?? false,
+ includeTopRaters: options?.includeTopRaters ?? false,
});
}