feat: broadcast
This commit is contained in:
62
src/components/NoteOptions/DesktopMenu.tsx
Normal file
62
src/components/NoteOptions/DesktopMenu.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { MenuAction } from './useMenuActions'
|
||||
|
||||
interface DesktopMenuProps {
|
||||
menuActions: MenuAction[]
|
||||
trigger: React.ReactNode
|
||||
}
|
||||
|
||||
export function DesktopMenu({ menuActions, trigger }: DesktopMenuProps) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="max-h-screen overflow-y-auto">
|
||||
{menuActions.map((action, index) => {
|
||||
const Icon = action.icon
|
||||
return (
|
||||
<div key={index}>
|
||||
{action.separator && index > 0 && <DropdownMenuSeparator />}
|
||||
{action.subMenu ? (
|
||||
<DropdownMenuSub>
|
||||
<DropdownMenuSubTrigger className={action.className}>
|
||||
<Icon />
|
||||
{action.label}
|
||||
</DropdownMenuSubTrigger>
|
||||
<DropdownMenuSubContent className="max-h-screen overflow-y-auto">
|
||||
{action.subMenu.map((subAction, subIndex) => (
|
||||
<>
|
||||
{subAction.separator && subIndex > 0 && <DropdownMenuSeparator />}
|
||||
<DropdownMenuItem
|
||||
key={subIndex}
|
||||
onClick={subAction.onClick}
|
||||
className={cn('w-64', subAction.className)}
|
||||
>
|
||||
{subAction.label}
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
))}
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
) : (
|
||||
<DropdownMenuItem onClick={action.onClick} className={action.className}>
|
||||
<Icon />
|
||||
{action.label}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
79
src/components/NoteOptions/MobileMenu.tsx
Normal file
79
src/components/NoteOptions/MobileMenu.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
|
||||
import { ArrowLeft } from 'lucide-react'
|
||||
import { MenuAction, SubMenuAction } from './useMenuActions'
|
||||
|
||||
interface MobileMenuProps {
|
||||
menuActions: MenuAction[]
|
||||
trigger: React.ReactNode
|
||||
isDrawerOpen: boolean
|
||||
setIsDrawerOpen: (open: boolean) => void
|
||||
showSubMenu: boolean
|
||||
activeSubMenu: SubMenuAction[]
|
||||
subMenuTitle: string
|
||||
closeDrawer: () => void
|
||||
goBackToMainMenu: () => void
|
||||
}
|
||||
|
||||
export function MobileMenu({
|
||||
menuActions,
|
||||
trigger,
|
||||
isDrawerOpen,
|
||||
setIsDrawerOpen,
|
||||
showSubMenu,
|
||||
activeSubMenu,
|
||||
subMenuTitle,
|
||||
closeDrawer,
|
||||
goBackToMainMenu
|
||||
}: MobileMenuProps) {
|
||||
return (
|
||||
<>
|
||||
{trigger}
|
||||
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
|
||||
<DrawerOverlay onClick={closeDrawer} />
|
||||
<DrawerContent hideOverlay className="max-h-screen">
|
||||
<div className="overflow-y-auto overscroll-contain py-2" style={{ touchAction: 'pan-y' }}>
|
||||
{!showSubMenu ? (
|
||||
menuActions.map((action, index) => {
|
||||
const Icon = action.icon
|
||||
return (
|
||||
<Button
|
||||
key={index}
|
||||
onClick={action.onClick}
|
||||
className={`w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 ${action.className || ''}`}
|
||||
variant="ghost"
|
||||
>
|
||||
<Icon />
|
||||
{action.label}
|
||||
</Button>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
onClick={goBackToMainMenu}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 mb-2"
|
||||
variant="ghost"
|
||||
>
|
||||
<ArrowLeft />
|
||||
{subMenuTitle}
|
||||
</Button>
|
||||
<div className="border-t border-border mb-2" />
|
||||
{activeSubMenu.map((subAction, index) => (
|
||||
<Button
|
||||
key={index}
|
||||
onClick={subAction.onClick}
|
||||
className={`w-full p-6 justify-start text-lg gap-4 ${subAction.className || ''}`}
|
||||
variant="ghost"
|
||||
>
|
||||
{subAction.label}
|
||||
</Button>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,32 +1,42 @@
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu'
|
||||
import { getNoteBech32Id } from '@/lib/event'
|
||||
import { toNjump } from '@/lib/link'
|
||||
import { pubkeyToNpub } from '@/lib/pubkey'
|
||||
import { useMuteList } from '@/providers/MuteListProvider'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import { Bell, BellOff, Code, Copy, Ellipsis, Link } from 'lucide-react'
|
||||
import { Ellipsis } from 'lucide-react'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useState } from 'react'
|
||||
import { DesktopMenu } from './DesktopMenu'
|
||||
import { MobileMenu } from './MobileMenu'
|
||||
import RawEventDialog from './RawEventDialog'
|
||||
import { SubMenuAction, useMenuActions } from './useMenuActions'
|
||||
|
||||
export default function NoteOptions({ event, className }: { event: Event; className?: string }) {
|
||||
const { t } = useTranslation()
|
||||
const { isSmallScreen } = useScreenSize()
|
||||
const { pubkey } = useNostr()
|
||||
const [isRawEventDialogOpen, setIsRawEventDialogOpen] = useState(false)
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
|
||||
const { mutePubkeyPublicly, mutePubkeyPrivately, unmutePubkey, mutePubkeys } = useMuteList()
|
||||
const isMuted = useMemo(() => mutePubkeys.includes(event.pubkey), [mutePubkeys, event])
|
||||
const [showSubMenu, setShowSubMenu] = useState(false)
|
||||
const [activeSubMenu, setActiveSubMenu] = useState<SubMenuAction[]>([])
|
||||
const [subMenuTitle, setSubMenuTitle] = useState('')
|
||||
|
||||
const closeDrawer = () => {
|
||||
setIsDrawerOpen(false)
|
||||
setShowSubMenu(false)
|
||||
}
|
||||
|
||||
const goBackToMainMenu = () => {
|
||||
setShowSubMenu(false)
|
||||
}
|
||||
|
||||
const showSubMenuActions = (subMenu: SubMenuAction[], title: string) => {
|
||||
setActiveSubMenu(subMenu)
|
||||
setSubMenuTitle(title)
|
||||
setShowSubMenu(true)
|
||||
}
|
||||
|
||||
const menuActions = useMenuActions({
|
||||
event,
|
||||
closeDrawer,
|
||||
showSubMenuActions,
|
||||
setIsRawEventDialogOpen,
|
||||
isSmallScreen
|
||||
})
|
||||
|
||||
const trigger = (
|
||||
<button
|
||||
@@ -37,175 +47,29 @@ export default function NoteOptions({ event, className }: { event: Event; classN
|
||||
</button>
|
||||
)
|
||||
|
||||
const rawEventDialog = (
|
||||
<RawEventDialog
|
||||
event={event}
|
||||
isOpen={isRawEventDialogOpen}
|
||||
onClose={() => setIsRawEventDialogOpen(false)}
|
||||
/>
|
||||
)
|
||||
|
||||
if (isSmallScreen) {
|
||||
return (
|
||||
<div className={className} onClick={(e) => e.stopPropagation()}>
|
||||
{trigger}
|
||||
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
|
||||
<DrawerOverlay onClick={() => setIsDrawerOpen(false)} />
|
||||
<DrawerContent hideOverlay>
|
||||
<div className="py-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
navigator.clipboard.writeText(getNoteBech32Id(event))
|
||||
}}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<Copy />
|
||||
{t('Copy event ID')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(pubkeyToNpub(event.pubkey) ?? '')
|
||||
setIsDrawerOpen(false)
|
||||
}}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<Copy />
|
||||
{t('Copy user ID')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
navigator.clipboard.writeText(toNjump(getNoteBech32Id(event)))
|
||||
}}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<Link />
|
||||
{t('Copy share link')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
setIsRawEventDialogOpen(true)
|
||||
}}
|
||||
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
|
||||
variant="ghost"
|
||||
>
|
||||
<Code />
|
||||
{t('View raw event')}
|
||||
</Button>
|
||||
{pubkey &&
|
||||
(isMuted ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
unmutePubkey(event.pubkey)
|
||||
}}
|
||||
className="w-full p-6 justify-start text-destructive text-lg gap-4 [&_svg]:size-5 focus:text-destructive"
|
||||
variant="ghost"
|
||||
>
|
||||
<Bell />
|
||||
{t('Unmute user')}
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
mutePubkeyPrivately(event.pubkey)
|
||||
}}
|
||||
className="w-full p-6 justify-start text-destructive text-lg gap-4 [&_svg]:size-5 focus:text-destructive"
|
||||
variant="ghost"
|
||||
>
|
||||
<BellOff />
|
||||
{t('Mute user privately')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setIsDrawerOpen(false)
|
||||
mutePubkeyPublicly(event.pubkey)
|
||||
}}
|
||||
className="w-full p-6 justify-start text-destructive text-lg gap-4 [&_svg]:size-5 focus:text-destructive"
|
||||
variant="ghost"
|
||||
>
|
||||
<BellOff />
|
||||
{t('Mute user publicly')}
|
||||
</Button>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
{rawEventDialog}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className} onClick={(e) => e.stopPropagation()}>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={() => navigator.clipboard.writeText(getNoteBech32Id(event))}>
|
||||
<Copy />
|
||||
{t('Copy event ID')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => navigator.clipboard.writeText(pubkeyToNpub(event.pubkey) ?? '')}
|
||||
>
|
||||
<Copy />
|
||||
{t('Copy user ID')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => navigator.clipboard.writeText(toNjump(getNoteBech32Id(event)))}
|
||||
>
|
||||
<Link />
|
||||
{t('Copy share link')}
|
||||
</DropdownMenuItem>
|
||||
{isSmallScreen ? (
|
||||
<MobileMenu
|
||||
menuActions={menuActions}
|
||||
trigger={trigger}
|
||||
isDrawerOpen={isDrawerOpen}
|
||||
setIsDrawerOpen={setIsDrawerOpen}
|
||||
showSubMenu={showSubMenu}
|
||||
activeSubMenu={activeSubMenu}
|
||||
subMenuTitle={subMenuTitle}
|
||||
closeDrawer={closeDrawer}
|
||||
goBackToMainMenu={goBackToMainMenu}
|
||||
/>
|
||||
) : (
|
||||
<DesktopMenu menuActions={menuActions} trigger={trigger} />
|
||||
)}
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem onClick={() => setIsRawEventDialogOpen(true)}>
|
||||
<Code />
|
||||
{t('View raw event')}
|
||||
</DropdownMenuItem>
|
||||
{pubkey && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
{isMuted ? (
|
||||
<DropdownMenuItem
|
||||
onClick={() => unmutePubkey(event.pubkey)}
|
||||
className="text-destructive focus:text-destructive"
|
||||
>
|
||||
<Bell />
|
||||
{t('Unmute user')}
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
<>
|
||||
<DropdownMenuItem
|
||||
onClick={() => mutePubkeyPrivately(event.pubkey)}
|
||||
className="text-destructive focus:text-destructive"
|
||||
>
|
||||
<BellOff />
|
||||
{t('Mute user privately')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => mutePubkeyPublicly(event.pubkey)}
|
||||
className="text-destructive focus:text-destructive"
|
||||
>
|
||||
<BellOff />
|
||||
{t('Mute user publicly')}
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
{rawEventDialog}
|
||||
<RawEventDialog
|
||||
event={event}
|
||||
isOpen={isRawEventDialogOpen}
|
||||
onClose={() => setIsRawEventDialogOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
255
src/components/NoteOptions/useMenuActions.tsx
Normal file
255
src/components/NoteOptions/useMenuActions.tsx
Normal file
@@ -0,0 +1,255 @@
|
||||
import { getNoteBech32Id, isProtectedEvent } from '@/lib/event'
|
||||
import { toNjump } from '@/lib/link'
|
||||
import { pubkeyToNpub } from '@/lib/pubkey'
|
||||
import { simplifyUrl } from '@/lib/url'
|
||||
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
|
||||
import { useMuteList } from '@/providers/MuteListProvider'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import client from '@/services/client.service'
|
||||
import { Bell, BellOff, Code, Copy, Globe, Link, Mail, Server } from 'lucide-react'
|
||||
import { Event } from 'nostr-tools'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
import RelayIcon from '../RelayIcon'
|
||||
|
||||
export interface SubMenuAction {
|
||||
label: React.ReactNode
|
||||
onClick: () => void
|
||||
className?: string
|
||||
separator?: boolean
|
||||
}
|
||||
|
||||
export interface MenuAction {
|
||||
icon: React.ComponentType
|
||||
label: string
|
||||
onClick?: () => void
|
||||
className?: string
|
||||
separator?: boolean
|
||||
subMenu?: SubMenuAction[]
|
||||
}
|
||||
|
||||
interface UseMenuActionsProps {
|
||||
event: Event
|
||||
closeDrawer: () => void
|
||||
showSubMenuActions: (subMenu: SubMenuAction[], title: string) => void
|
||||
setIsRawEventDialogOpen: (open: boolean) => void
|
||||
isSmallScreen: boolean
|
||||
}
|
||||
|
||||
export function useMenuActions({
|
||||
event,
|
||||
closeDrawer,
|
||||
showSubMenuActions,
|
||||
setIsRawEventDialogOpen,
|
||||
isSmallScreen
|
||||
}: UseMenuActionsProps) {
|
||||
const { t } = useTranslation()
|
||||
const { pubkey, relayList } = useNostr()
|
||||
const { relaySets, favoriteRelays } = useFavoriteRelays()
|
||||
const { mutePubkeyPublicly, mutePubkeyPrivately, unmutePubkey, mutePubkeys } = useMuteList()
|
||||
const isMuted = useMemo(() => mutePubkeys.includes(event.pubkey), [mutePubkeys, event])
|
||||
|
||||
const broadcastSubMenu: SubMenuAction[] = useMemo(() => {
|
||||
const items = []
|
||||
if (pubkey) {
|
||||
items.push({
|
||||
label: (
|
||||
<div className="flex items-center gap-2 w-full pl-1">
|
||||
<Mail />
|
||||
<div className="flex-1 truncate text-left">{t('Write relays')}</div>
|
||||
</div>
|
||||
),
|
||||
onClick: async () => {
|
||||
closeDrawer()
|
||||
const relays = relayList?.write.slice(0, 10)
|
||||
if (relays?.length) {
|
||||
await client
|
||||
.publishEvent(relays, event)
|
||||
.then(() => {
|
||||
toast.success(t('Successfully broadcasted to your write relays'))
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(
|
||||
t('Failed to broadcast to your write relays: {{error}}', { error: error.message })
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (relaySets.length) {
|
||||
items.push(
|
||||
...relaySets
|
||||
.filter((set) => set.relayUrls.length)
|
||||
.map((set, index) => ({
|
||||
label: (
|
||||
<div className="flex items-center gap-2 w-full pl-1">
|
||||
<Server />
|
||||
<div className="flex-1 truncate text-left">{set.name}</div>
|
||||
</div>
|
||||
),
|
||||
onClick: async () => {
|
||||
closeDrawer()
|
||||
await client
|
||||
.publishEvent(set.relayUrls, event)
|
||||
.then(() => {
|
||||
toast.success(
|
||||
t('Successfully broadcasted to relay set: {{name}}', { name: set.name })
|
||||
)
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(
|
||||
t('Failed to broadcast to relay set: {{name}}. Error: {{error}}', {
|
||||
name: set.name,
|
||||
error: error.message
|
||||
})
|
||||
)
|
||||
})
|
||||
},
|
||||
separator: index === 0
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
if (favoriteRelays.length) {
|
||||
items.push(
|
||||
...favoriteRelays.map((relay, index) => ({
|
||||
label: (
|
||||
<div className="flex items-center gap-2 w-full">
|
||||
<RelayIcon url={relay} />
|
||||
<div className="flex-1 truncate text-left">{simplifyUrl(relay)}</div>
|
||||
</div>
|
||||
),
|
||||
onClick: async () => {
|
||||
closeDrawer()
|
||||
await client
|
||||
.publishEvent([relay], event)
|
||||
.then(() => {
|
||||
toast.success(
|
||||
t('Successfully broadcasted to relay: {{url}}', { url: simplifyUrl(relay) })
|
||||
)
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(
|
||||
t('Failed to broadcast to relay: {{url}}. Error: {{error}}', {
|
||||
url: simplifyUrl(relay),
|
||||
error: error.message
|
||||
})
|
||||
)
|
||||
})
|
||||
},
|
||||
separator: index === 0
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
return items
|
||||
}, [pubkey, favoriteRelays, relaySets])
|
||||
|
||||
const menuActions: MenuAction[] = useMemo(() => {
|
||||
const actions: MenuAction[] = [
|
||||
{
|
||||
icon: Copy,
|
||||
label: t('Copy event ID'),
|
||||
onClick: () => {
|
||||
navigator.clipboard.writeText(getNoteBech32Id(event))
|
||||
closeDrawer()
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: Copy,
|
||||
label: t('Copy user ID'),
|
||||
onClick: () => {
|
||||
navigator.clipboard.writeText(pubkeyToNpub(event.pubkey) ?? '')
|
||||
closeDrawer()
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: Link,
|
||||
label: t('Copy share link'),
|
||||
onClick: () => {
|
||||
navigator.clipboard.writeText(toNjump(getNoteBech32Id(event)))
|
||||
closeDrawer()
|
||||
}
|
||||
},
|
||||
{
|
||||
icon: Code,
|
||||
label: t('View raw event'),
|
||||
onClick: () => {
|
||||
closeDrawer()
|
||||
setIsRawEventDialogOpen(true)
|
||||
},
|
||||
separator: true
|
||||
}
|
||||
]
|
||||
|
||||
const isProtected = isProtectedEvent(event)
|
||||
if (!isProtected || event.pubkey === pubkey) {
|
||||
actions.push({
|
||||
icon: Globe,
|
||||
label: t('Broadcast to ...'),
|
||||
onClick: isSmallScreen
|
||||
? () => showSubMenuActions(broadcastSubMenu, t('Broadcast to ...'))
|
||||
: undefined,
|
||||
subMenu: isSmallScreen ? undefined : broadcastSubMenu,
|
||||
separator: true
|
||||
})
|
||||
}
|
||||
|
||||
if (pubkey) {
|
||||
if (isMuted) {
|
||||
actions.push({
|
||||
icon: Bell,
|
||||
label: t('Unmute user'),
|
||||
onClick: () => {
|
||||
closeDrawer()
|
||||
unmutePubkey(event.pubkey)
|
||||
},
|
||||
className: 'text-destructive focus:text-destructive',
|
||||
separator: true
|
||||
})
|
||||
} else {
|
||||
actions.push(
|
||||
{
|
||||
icon: BellOff,
|
||||
label: t('Mute user privately'),
|
||||
onClick: () => {
|
||||
closeDrawer()
|
||||
mutePubkeyPrivately(event.pubkey)
|
||||
},
|
||||
className: 'text-destructive focus:text-destructive',
|
||||
separator: true
|
||||
},
|
||||
{
|
||||
icon: BellOff,
|
||||
label: t('Mute user publicly'),
|
||||
onClick: () => {
|
||||
closeDrawer()
|
||||
mutePubkeyPublicly(event.pubkey)
|
||||
},
|
||||
className: 'text-destructive focus:text-destructive'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return actions
|
||||
}, [
|
||||
t,
|
||||
event,
|
||||
pubkey,
|
||||
isMuted,
|
||||
isSmallScreen,
|
||||
broadcastSubMenu,
|
||||
closeDrawer,
|
||||
showSubMenuActions,
|
||||
setIsRawEventDialogOpen,
|
||||
mutePubkeyPrivately,
|
||||
mutePubkeyPublicly,
|
||||
unmutePubkey
|
||||
])
|
||||
|
||||
return menuActions
|
||||
}
|
||||
Reference in New Issue
Block a user