feat: implement drawer for profile options on small screens

This commit is contained in:
codytseng 2025-11-02 23:02:37 +08:00
parent 962359dcf5
commit e4f250907f

View file

@ -1,4 +1,5 @@
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -8,56 +9,138 @@ import {
import { pubkeyToNpub } from '@/lib/pubkey' import { pubkeyToNpub } from '@/lib/pubkey'
import { useMuteList } from '@/providers/MuteListProvider' import { useMuteList } from '@/providers/MuteListProvider'
import { useNostr } from '@/providers/NostrProvider' import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { Bell, BellOff, Copy, Ellipsis } from 'lucide-react' import { Bell, BellOff, Copy, Ellipsis } from 'lucide-react'
import { useMemo } from 'react' import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
export default function ProfileOptions({ pubkey }: { pubkey: string }) { export default function ProfileOptions({ pubkey }: { pubkey: string }) {
const { t } = useTranslation() const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { pubkey: accountPubkey } = useNostr() const { pubkey: accountPubkey } = useNostr()
const { mutePubkeySet, mutePubkeyPrivately, mutePubkeyPublicly, unmutePubkey } = useMuteList() const { mutePubkeySet, mutePubkeyPrivately, mutePubkeyPublicly, unmutePubkey } = useMuteList()
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
const isMuted = useMemo(() => mutePubkeySet.has(pubkey), [mutePubkeySet, pubkey]) const isMuted = useMemo(() => mutePubkeySet.has(pubkey), [mutePubkeySet, pubkey])
if (pubkey === accountPubkey) return null if (pubkey === accountPubkey) return null
const trigger = (
<Button
variant="secondary"
size="icon"
className="rounded-full"
onClick={() => {
if (isSmallScreen) {
setIsDrawerOpen(true)
}
}}
>
<Ellipsis />
</Button>
)
if (isSmallScreen) {
return (
<>
{trigger}
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
<DrawerOverlay onClick={() => setIsDrawerOpen(false)} />
<DrawerContent hideOverlay>
<div className="py-2">
<Button
onClick={() => {
setIsDrawerOpen(false)
navigator.clipboard.writeText(pubkeyToNpub(pubkey) ?? '')
}}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
variant="ghost"
>
<Copy />
{t('Copy user ID')}
</Button>
{accountPubkey ? (
isMuted ? (
<Button
onClick={() => {
setIsDrawerOpen(false)
unmutePubkey(pubkey)
}}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 text-destructive focus:text-destructive"
variant="ghost"
>
<Bell />
{t('Unmute user')}
</Button>
) : (
<>
<Button
onClick={() => {
setIsDrawerOpen(false)
mutePubkeyPrivately(pubkey)
}}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 text-destructive focus:text-destructive"
variant="ghost"
>
<BellOff />
{t('Mute user privately')}
</Button>
<Button
onClick={() => {
setIsDrawerOpen(false)
mutePubkeyPublicly(pubkey)
}}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5 text-destructive focus:text-destructive"
variant="ghost"
>
<BellOff />
{t('Mute user publicly')}
</Button>
</>
)
) : null}
</div>
</DrawerContent>
</Drawer>
</>
)
}
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
<Button variant="secondary" size="icon" className="rounded-full">
<Ellipsis />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
<DropdownMenuItem onClick={() => navigator.clipboard.writeText(pubkeyToNpub(pubkey) ?? '')}> <DropdownMenuItem onClick={() => navigator.clipboard.writeText(pubkeyToNpub(pubkey) ?? '')}>
<Copy /> <Copy />
{t('Copy user ID')} {t('Copy user ID')}
</DropdownMenuItem> </DropdownMenuItem>
{isMuted ? ( {accountPubkey ? (
<DropdownMenuItem isMuted ? (
onClick={() => unmutePubkey(pubkey)}
className="text-destructive focus:text-destructive"
>
<Bell />
{t('Unmute user')}
</DropdownMenuItem>
) : (
<>
<DropdownMenuItem <DropdownMenuItem
onClick={() => mutePubkeyPrivately(pubkey)} onClick={() => unmutePubkey(pubkey)}
className="text-destructive focus:text-destructive" className="text-destructive focus:text-destructive"
> >
<BellOff /> <Bell />
{t('Mute user privately')} {t('Unmute user')}
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem ) : (
onClick={() => mutePubkeyPublicly(pubkey)} <>
className="text-destructive focus:text-destructive" <DropdownMenuItem
> onClick={() => mutePubkeyPrivately(pubkey)}
<BellOff /> className="text-destructive focus:text-destructive"
{t('Mute user publicly')} >
</DropdownMenuItem> <BellOff />
</> {t('Mute user privately')}
)} </DropdownMenuItem>
<DropdownMenuItem
onClick={() => mutePubkeyPublicly(pubkey)}
className="text-destructive focus:text-destructive"
>
<BellOff />
{t('Mute user publicly')}
</DropdownMenuItem>
</>
)
) : null}
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
) )