From c5c71ba9507f1c739773cf2677c53f83d29300bc Mon Sep 17 00:00:00 2001
From: Mohamed Bassem <me@mbassem.com>
Date: Sun, 23 Nov 2025 12:25:56 +0000
Subject: feat(mobile): proper handling for shared list permissions (#2165)

* feat(mobile): Restrict bookmark editing in shared lists

Apply the same ownership-based restrictions that exist in the web app
to the mobile app. Users can now only edit, delete, and manage their
own bookmarks, even when viewing them in shared lists.

Changes:
- BottomActions: Hide edit actions (lists, tags, info, delete) for non-owners
- BookmarkCard: Hide favorite button and action menu for non-owners
- Info page: Make title, notes, tags, and lists read-only for non-owners
- NotePreview: Hide "Edit Notes" button for non-owners

All restrictions are based on comparing the current user ID (from useWhoAmI)
with the bookmark's userId field.

* some fixes

* make tags non clickable for collaborators

* add leave list

---------

Co-authored-by: Claude <noreply@anthropic.com>
---
 apps/mobile/components/bookmarks/BottomActions.tsx | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'apps/mobile/components/bookmarks/BottomActions.tsx')

diff --git a/apps/mobile/components/bookmarks/BottomActions.tsx b/apps/mobile/components/bookmarks/BottomActions.tsx
index 8cfa27c9..64653779 100644
--- a/apps/mobile/components/bookmarks/BottomActions.tsx
+++ b/apps/mobile/components/bookmarks/BottomActions.tsx
@@ -5,6 +5,7 @@ import { useToast } from "@/components/ui/Toast";
 import { ClipboardList, Globe, Info, Tag, Trash2 } from "lucide-react-native";
 
 import { useDeleteBookmark } from "@karakeep/shared-react/hooks/bookmarks";
+import { useWhoAmI } from "@karakeep/shared-react/hooks/users";
 import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks";
 
 interface BottomActionsProps {
@@ -14,6 +15,10 @@ interface BottomActionsProps {
 export default function BottomActions({ bookmark }: BottomActionsProps) {
   const { toast } = useToast();
   const router = useRouter();
+  const { data: currentUser } = useWhoAmI();
+
+  // Check if the current user owns this bookmark
+  const isOwner = currentUser?.id === bookmark.userId;
 
   const { mutate: deleteBookmark, isPending: isDeletionPending } =
     useDeleteBookmark({
@@ -56,7 +61,7 @@ export default function BottomActions({ bookmark }: BottomActionsProps) {
           comp={(styles) => <ClipboardList color={styles?.color?.toString()} />}
         />
       ),
-      shouldRender: true,
+      shouldRender: isOwner,
       onClick: () =>
         router.push(`/dashboard/bookmarks/${bookmark.id}/manage_lists`),
       disabled: false,
@@ -69,7 +74,7 @@ export default function BottomActions({ bookmark }: BottomActionsProps) {
           comp={(styles) => <Tag color={styles?.color?.toString()} />}
         />
       ),
-      shouldRender: true,
+      shouldRender: isOwner,
       onClick: () =>
         router.push(`/dashboard/bookmarks/${bookmark.id}/manage_tags`),
       disabled: false,
@@ -94,7 +99,7 @@ export default function BottomActions({ bookmark }: BottomActionsProps) {
           comp={(styles) => <Trash2 color={styles?.color?.toString()} />}
         />
       ),
-      shouldRender: true,
+      shouldRender: isOwner,
       onClick: deleteBookmarkAlert,
       disabled: isDeletionPending,
     },
-- 
cgit v1.2.3-70-g09d2

