diff --git a/src/components/NoteMoreMenu.tsx b/src/components/NoteMoreMenu.tsx index 030c7b8b..3c0a557a 100644 --- a/src/components/NoteMoreMenu.tsx +++ b/src/components/NoteMoreMenu.tsx @@ -14,6 +14,7 @@ import { Trash2, StickyNote, ListPlus, + PanelLeft, Copy, Check, } from 'lucide-react'; @@ -48,6 +49,7 @@ import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useAuthor } from '@/hooks/useAuthor'; import { useMuteList } from '@/hooks/useMuteList'; import { useDeleteEvent } from '@/hooks/useDeleteEvent'; +import { useFeedSettings } from '@/hooks/useFeedSettings'; import { genUserName } from '@/lib/genUserName'; import { timeAgo } from '@/lib/timeAgo'; import { toast } from '@/hooks/useToast'; @@ -241,9 +243,12 @@ function NoteMoreMenuContent({ event, open, onOpenChange, onReport, onMention, o const { addMute, removeMute, isMuted } = useMuteList(); const userMuted = isMuted('pubkey', event.pubkey); const { mutate: deleteEvent, isPending: isDeleting } = useDeleteEvent(); + const { addToSidebar, removeFromSidebar, orderedItems } = useFeedSettings(); const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false); const nip19Id = encodeEventNip19(event); + const nostrUri = `nostr:${nip19Id}`; + const isInSidebar = orderedItems.includes(nostrUri); const close = () => onOpenChange(false); @@ -264,6 +269,17 @@ function NoteMoreMenuContent({ event, open, onOpenChange, onReport, onMention, o close(); }; + const handleToggleSidebar = () => { + if (isInSidebar) { + removeFromSidebar(nostrUri); + toast({ title: 'Removed from sidebar' }); + } else { + addToSidebar(nostrUri); + toast({ title: 'Added to sidebar' }); + } + close(); + }; + const handleTogglePin = () => { togglePin.mutate(event.id, { onSuccess: () => { @@ -383,6 +399,11 @@ function NoteMoreMenuContent({ event, open, onOpenChange, onReport, onMention, o onClick={() => { onAddToList(); }} /> )} + : } + label={isInSidebar ? 'Remove from sidebar' : 'Add to sidebar'} + onClick={handleToggleSidebar} + /> diff --git a/src/pages/ExternalContentPage.tsx b/src/pages/ExternalContentPage.tsx index 7375379e..da3b835b 100644 --- a/src/pages/ExternalContentPage.tsx +++ b/src/pages/ExternalContentPage.tsx @@ -1,6 +1,6 @@ import { useCallback, useMemo, useRef, useState } from 'react'; import { useSeoMeta } from '@unhead/react'; -import { ArrowLeft, Globe, Heart, MessageSquare, Repeat2, Star, AlertTriangle } from 'lucide-react'; +import { ArrowLeft, Globe, Heart, MessageSquare, MoreHorizontal, Repeat2, Star, AlertTriangle, PanelLeft, Trash2 } from 'lucide-react'; import { Link, useLocation, useParams } from 'react-router-dom'; import { Skeleton } from '@/components/ui/skeleton'; import { Badge } from '@/components/ui/badge'; @@ -9,6 +9,9 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import { getAvatarShape } from '@/lib/avatarShape'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { + DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; import { ThreadedReplyList } from '@/components/ThreadedReplyList'; import { ComposeBox } from '@/components/ComposeBox'; import { ReplyComposeModal } from '@/components/ReplyComposeModal'; @@ -36,6 +39,7 @@ import { useLinkPreview } from '@/hooks/useLinkPreview'; import { useLayoutOptions } from '@/contexts/LayoutContext'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useNostrPublish } from '@/hooks/useNostrPublish'; +import { useFeedSettings } from '@/hooks/useFeedSettings'; import { useQueryClient } from '@tanstack/react-query'; import { useToast } from '@/hooks/useToast'; import { getDisplayName } from '@/lib/getDisplayName'; @@ -73,6 +77,19 @@ function ExternalActionBar({ content }: { content: ExternalContent }) { const queryClient = useQueryClient(); const { toast } = useToast(); const identifier = content.value; + const { addToSidebar, removeFromSidebar, orderedItems } = useFeedSettings(); + + const isInSidebar = orderedItems.includes(identifier); + + const handleAddToSidebar = useCallback(() => { + addToSidebar(identifier); + toast({ title: 'Added to sidebar' }); + }, [identifier, addToSidebar, toast]); + + const handleRemoveFromSidebar = useCallback(() => { + removeFromSidebar(identifier); + toast({ title: 'Removed from sidebar' }); + }, [identifier, removeFromSidebar, toast]); const userReactionData = useExternalUserReaction(content); const reactionCount = useExternalReactionCount(content); @@ -224,6 +241,34 @@ function ExternalActionBar({ content }: { content: ExternalContent }) { )} + {/* Spacer pushes the 3-dots menu to the right */} +
+ + {/* 3-dots menu with sidebar action */} + + + + + + {isInSidebar ? ( + + + Remove from sidebar + + ) : ( + + + Add to sidebar + + )} + + + {shareOpen && (