From ef27670f5c027be87d279b9b32553e980e55d888 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Wed, 24 Dec 2025 15:15:46 +0200 Subject: feat: show bookmark owner icon in shared lists (#2277) * feat: Add owner icon to bookmarks in shared lists Display a small icon showing the bookmark owner's name and email on hover when viewing bookmarks from other users in shared lists. The icon appears in the top-right corner of bookmark cards across all layout types (grid, list, compact). Changes: - Add user field to ZBookmark type to include owner name and email - Update bookmark queries to fetch user information via join - Create BookmarkOwnerIcon component with tooltip showing owner details - Integrate owner indicator into BookmarkLayoutAdaptingCard for all layouts - Only show icon for bookmarks not owned by current user * use icons in more places * remove tooltip providers * fix non list context --------- Co-authored-by: Claude --- apps/web/components/dashboard/lists/ListHeader.tsx | 64 ++++++++++++++++------ 1 file changed, 48 insertions(+), 16 deletions(-) (limited to 'apps/web/components/dashboard/lists/ListHeader.tsx') diff --git a/apps/web/components/dashboard/lists/ListHeader.tsx b/apps/web/components/dashboard/lists/ListHeader.tsx index 8e014e2a..ecbb6431 100644 --- a/apps/web/components/dashboard/lists/ListHeader.tsx +++ b/apps/web/components/dashboard/lists/ListHeader.tsx @@ -6,11 +6,11 @@ import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, - TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; +import { UserAvatar } from "@/components/ui/user-avatar"; import { useTranslation } from "@/lib/i18n/client"; -import { MoreHorizontal, SearchIcon, Users } from "lucide-react"; +import { MoreHorizontal, SearchIcon } from "lucide-react"; import { api } from "@karakeep/shared-react/trpc"; import { parseSearchQuery } from "@karakeep/shared/searchQueryParser"; @@ -35,6 +35,16 @@ export default function ListHeader({ }, ); + const { data: collaboratorsData } = api.lists.getCollaborators.useQuery( + { + listId: initialData.id, + }, + { + refetchOnWindowFocus: false, + enabled: list.hasCollaborators, + }, + ); + const parsedQuery = useMemo(() => { if (!list.query) { return null; @@ -55,22 +65,44 @@ export default function ListHeader({ {list.icon} {list.name} - {list.hasCollaborators && ( - - - - - - -

{t("lists.shared")}

-
-
-
+ {list.hasCollaborators && collaboratorsData && ( +
+ {collaboratorsData.owner && ( + + +
+ +
+
+ +

{collaboratorsData.owner.name}

+
+
+ )} + {collaboratorsData.collaborators.map((collab) => ( + + +
+ +
+
+ +

{collab.user.name}

+
+
+ ))} +
)} {list.description && ( - - {`(${list.description})`} - + {`(${list.description})`} )}
-- cgit v1.2.3-70-g09d2