"use client"; import { useContext, useState } from "react"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { useToast } from "@/components/ui/use-toast"; import { useClientConfig } from "@/lib/clientConfig"; import { BookmarkListContext } from "@/lib/hooks/list-context"; import { api } from "@/lib/trpc"; import { Archive, Link, List, ListX, MoreHorizontal, Pencil, RotateCw, Star, Tags, Trash2, } from "lucide-react"; import type { ZBookmark, ZBookmarkedLink } from "@hoarder/trpc/types/bookmarks"; import { useAddToListModal } from "./AddToListModal"; import { BookmarkedTextEditor } from "./BookmarkedTextEditor"; import { useTagModel } from "./TagModal"; export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) { const { toast } = useToast(); const linkId = bookmark.id; const demoMode = !!useClientConfig().demoMode; const { setOpen: setTagModalIsOpen, content: tagModal } = useTagModel(bookmark); const { setOpen: setAddToListModalOpen, content: addToListModal } = useAddToListModal(bookmark.id); const [isTextEditorOpen, setTextEditorOpen] = useState(false); const { listId } = useContext(BookmarkListContext); const invalidateAllBookmarksCache = api.useUtils().bookmarks.getBookmarks.invalidate; const invalidateBookmarkCache = api.useUtils().bookmarks.getBookmark.invalidate; const invalidateSearchCache = api.useUtils().bookmarks.searchBookmarks.invalidate; const onError = () => { toast({ variant: "destructive", title: "Something went wrong", description: "There was a problem with your request.", }); }; const deleteBookmarkMutator = api.bookmarks.deleteBookmark.useMutation({ onSuccess: () => { toast({ description: "The bookmark has been deleted!", }); }, onError, onSettled: () => { invalidateAllBookmarksCache(); invalidateSearchCache(); }, }); const updateBookmarkMutator = api.bookmarks.updateBookmark.useMutation({ onSuccess: () => { toast({ description: "The bookmark has been updated!", }); }, onError, onSettled: () => { invalidateBookmarkCache({ bookmarkId: bookmark.id }); invalidateAllBookmarksCache(); invalidateSearchCache(); }, }); const crawlBookmarkMutator = api.bookmarks.recrawlBookmark.useMutation({ onSuccess: () => { toast({ description: "Re-fetch has been enqueued!", }); }, onError, onSettled: () => { invalidateBookmarkCache({ bookmarkId: bookmark.id }); }, }); const removeFromListMutator = api.lists.removeFromList.useMutation({ onSuccess: (_resp, req) => { invalidateAllBookmarksCache({ listId: req.listId }); toast({ description: "The bookmark has been deleted from the list", }); }, onError, }); return ( <> {tagModal} {addToListModal} {bookmark.content.type === "text" && ( setTextEditorOpen(true)}> Edit )} updateBookmarkMutator.mutate({ bookmarkId: linkId, favourited: !bookmark.favourited, }) } > {bookmark.favourited ? "Un-favourite" : "Favourite"} updateBookmarkMutator.mutate({ bookmarkId: linkId, archived: !bookmark.archived, }) } > {bookmark.archived ? "Un-archive" : "Archive"} {bookmark.content.type === "link" && ( { navigator.clipboard.writeText( (bookmark.content as ZBookmarkedLink).url, ); toast({ description: "Link was added to your clipboard!", }); }} > Copy Link )} setTagModalIsOpen(true)}> Edit Tags setAddToListModalOpen(true)}> Add to List {listId && ( removeFromListMutator.mutate({ listId, bookmarkId: bookmark.id, }) } > Remove from List )} {bookmark.content.type === "link" && ( crawlBookmarkMutator.mutate({ bookmarkId: bookmark.id }) } > Refresh )} deleteBookmarkMutator.mutate({ bookmarkId: bookmark.id }) } > Delete ); }