From 5f0cf86fe68550b5e63f5b94f87cbaefd38849bc Mon Sep 17 00:00:00 2001 From: khannurien Date: Wed, 30 Sep 2026 21:19:06 +0000 Subject: [PATCH] =?UTF-8?q?v3:=20the=20dump=20page's=20"In=20collections"?= =?UTF-8?q?=20list=20only=20shows=20the=20owner's=20private=20badge=20?= =?UTF-8?q?=E2=80=94=20every=20card=20there=20said=20"public",=20which=20s?= =?UTF-8?q?ays=20nothing=20on=20a=20list=20of=20playlists=20holding=20the?= =?UTF-8?q?=20dump.=20PlaylistCard=20takes=20privateBadgeOnly,=20passed=20?= =?UTF-8?q?through=20PlaylistCardList,=20which=20hides=20the=20visibility?= =?UTF-8?q?=20badge=20except=20on=20a=20private=20playlist=20of=20the=20si?= =?UTF-8?q?gned-in=20user's;=20the=20other=20lists=20of=20playlists=20keep?= =?UTF-8?q?=20both=20badges.=205=20PlaylistCard=20tests=20pass=20(new:=20p?= =?UTF-8?q?rivateBadgeOnly),=20and=20tsc,=20eslint,=20doc:lint=20and=20den?= =?UTF-8?q?o=20fmt=20are=20clean.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- src/components/playlist/PlaylistCard.tsx | 29 ++++++++++++------- src/components/playlist/PlaylistCardList.tsx | 5 +++- src/pages/Dump.tsx | 2 +- .../components/playlist/PlaylistCard.test.tsx | 21 ++++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/components/playlist/PlaylistCard.tsx b/src/components/playlist/PlaylistCard.tsx index 1e026ffb..c5b9e999 100644 --- a/src/components/playlist/PlaylistCard.tsx +++ b/src/components/playlist/PlaylistCard.tsx @@ -29,6 +29,12 @@ export interface PlaylistCardProps { onDelete?: () => void; /** Hides the owner link and the unread dot. */ isOwner?: boolean; + /** + * Used by dump pages to display "In collections" lists. Prevents the + * visibility badge from showing, except to the owner of a private playlist: + * public badges on every card there would say nothing. + */ + privateBadgeOnly?: boolean; } /** @@ -37,12 +43,13 @@ export interface PlaylistCardProps { * device. The card is an `
  • `, for a `
      `. */ export function PlaylistCard( - { playlist, onDelete, isOwner }: PlaylistCardProps, + { playlist, onDelete, isOwner, privateBadgeOnly }: PlaylistCardProps, ): React.JSX.Element { const navigate = useNavigate(); const { mediaToken } = useAuth(); const unread = !isOwner && isRecent(playlist.createdAt) && !isPlaylistVisited(playlist.id); + const showBadge = !privateBadgeOnly || (!!isOwner && !playlist.isPublic); function handleNavigate() { markPlaylistVisited(playlist.id); @@ -85,15 +92,17 @@ export function PlaylistCard(

      {playlist.description}

      )}
      - - {playlist.isPublic - ? public - : private} - + {showBadge && ( + + {playlist.isPublic + ? public + : private} + + )} {playlist.ownerUsername && !isOwner && ( void; + /** Passed to each {@link PlaylistCard}. */ + privateBadgeOnly?: boolean; } /** @@ -20,7 +22,7 @@ export interface PlaylistCardListProps { * its owner's when the playlist is the signed-in user's. */ export function PlaylistCardList( - { playlists, onDelete }: PlaylistCardListProps, + { playlists, onDelete, privateBadgeOnly }: PlaylistCardListProps, ): React.JSX.Element { const { user } = useAuth(); return ( @@ -31,6 +33,7 @@ export function PlaylistCardList( playlist={p} isOwner={!!user && user.id === p.userId} onDelete={onDelete && (() => onDelete(p))} + privateBadgeOnly={privateBadgeOnly} /> ))}
    diff --git a/src/pages/Dump.tsx b/src/pages/Dump.tsx index 40b064bf..e87f8292 100644 --- a/src/pages/Dump.tsx +++ b/src/pages/Dump.tsx @@ -569,7 +569,7 @@ export function Dump(): React.JSX.Element {

    In collections

    - + )} diff --git a/src/test/components/playlist/PlaylistCard.test.tsx b/src/test/components/playlist/PlaylistCard.test.tsx index abcc6871..6b808639 100644 --- a/src/test/components/playlist/PlaylistCard.test.tsx +++ b/src/test/components/playlist/PlaylistCard.test.tsx @@ -67,6 +67,27 @@ describe("PlaylistCard", () => { expect(again.container.querySelector(".unread-dot")).toBeNull(); }); + test("privateBadgeOnly shows only the owner's private badge", () => { + const cases = [ + { isPublic: true, isOwner: true, shown: false }, + { isPublic: false, isOwner: false, shown: false }, + { isPublic: false, isOwner: true, shown: true }, + ]; + for (const { isPublic, isOwner, shown } of cases) { + const { container, unmount } = renderWithContexts( +
      + +
    , + ); + expect(container.querySelector(".playlist-badge") !== null).toBe(shown); + unmount(); + } + }); + test("delete doesn't open the playlist", async () => { const onDelete = vi.fn(); const user = userEvent.setup();