Revert "refactor: responsive menu"

This reverts commit 1dc18645b2.
This commit is contained in:
codytseng 2025-11-29 12:06:13 +08:00
parent 019dbc073c
commit 3eb018f39f
16 changed files with 1097 additions and 1324 deletions

View file

@ -1,15 +1,18 @@
import { Button } from '@/components/ui/button'
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import {
ResponsiveMenu,
ResponsiveMenuContent,
ResponsiveMenuItem,
ResponsiveMenuTrigger
} from '@/components/ui/responsive-menu'
import { useStuff } from '@/hooks/useStuff'
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { useStuffStatsById } from '@/hooks/useStuffStatsById'
import { useStuff } from '@/hooks/useStuff'
import { createRepostDraftEvent } from '@/lib/draft-event'
import { getNoteBech32Id } from '@/lib/event'
import { cn } from '@/lib/utils'
import { useNostr } from '@/providers/NostrProvider'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useUserTrust } from '@/providers/UserTrustProvider'
import stuffStatsService from '@/services/stuff-stats.service'
import { Loader, PencilLine, Repeat } from 'lucide-react'
@ -21,13 +24,14 @@ import { formatCount } from './utils'
export default function RepostButton({ stuff }: { stuff: Event | string }) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { hideUntrustedInteractions, isUserTrusted } = useUserTrust()
const { publish, checkLogin, pubkey } = useNostr()
const { event, stuffKey } = useStuff(stuff)
const noteStats = useStuffStatsById(stuffKey)
const [reposting, setReposting] = useState(false)
const [isPostDialogOpen, setIsPostDialogOpen] = useState(false)
const [open, setOpen] = useState(false)
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
const { repostCount, hasReposted } = useMemo(() => {
// external content
if (!event) return { repostCount: 0, hasReposted: false }
@ -70,39 +74,95 @@ export default function RepostButton({ stuff }: { stuff: Event | string }) {
})
}
const trigger = (
<button
className={cn(
'flex gap-1 items-center px-3 h-full enabled:hover:text-lime-500 disabled:text-muted-foreground/40',
hasReposted ? 'text-lime-500' : 'text-muted-foreground'
)}
disabled={!event}
title={t('Repost')}
onClick={() => {
if (!event) return
if (isSmallScreen) {
setIsDrawerOpen(true)
}
}}
>
{reposting ? <Loader className="animate-spin" /> : <Repeat />}
{!!repostCount && <div className="text-sm">{formatCount(repostCount)}</div>}
</button>
)
if (!event) {
return trigger
}
const postEditor = (
<PostEditor
open={isPostDialogOpen}
setOpen={setIsPostDialogOpen}
defaultContent={'\nnostr:' + getNoteBech32Id(event)}
/>
)
if (isSmallScreen) {
return (
<>
{trigger}
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
<DrawerOverlay onClick={() => setIsDrawerOpen(false)} />
<DrawerContent hideOverlay>
<div className="py-2">
<Button
onClick={(e) => {
e.stopPropagation()
setIsDrawerOpen(false)
repost()
}}
disabled={!canRepost}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
variant="ghost"
>
<Repeat /> {t('Repost')}
</Button>
<Button
onClick={(e) => {
e.stopPropagation()
setIsDrawerOpen(false)
checkLogin(() => {
setIsPostDialogOpen(true)
})
}}
className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
variant="ghost"
>
<PencilLine /> {t('Quote')}
</Button>
</div>
</DrawerContent>
</Drawer>
{postEditor}
</>
)
}
return (
<>
<ResponsiveMenu open={open} onOpenChange={setOpen}>
<ResponsiveMenuTrigger asChild>
<button
className={cn(
'flex gap-1 items-center px-3 h-full enabled:hover:text-lime-500 disabled:text-muted-foreground/40',
hasReposted ? 'text-lime-500' : 'text-muted-foreground'
)}
disabled={!event}
title={t('Repost')}
<DropdownMenu>
<DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation()
if (!event) return
setOpen(true)
}}
>
{reposting ? <Loader className="animate-spin" /> : <Repeat />}
{!!repostCount && <div className="text-sm">{formatCount(repostCount)}</div>}
</button>
</ResponsiveMenuTrigger>
<ResponsiveMenuContent>
<ResponsiveMenuItem
onClick={(e) => {
e?.stopPropagation()
repost()
}}
disabled={!canRepost}
>
<Repeat /> {t('Repost')}
</ResponsiveMenuItem>
<ResponsiveMenuItem
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation()
checkLogin(() => {
@ -111,15 +171,10 @@ export default function RepostButton({ stuff }: { stuff: Event | string }) {
}}
>
<PencilLine /> {t('Quote')}
</ResponsiveMenuItem>
</ResponsiveMenuContent>
</ResponsiveMenu>
<PostEditor
open={isPostDialogOpen}
setOpen={setIsPostDialogOpen}
defaultContent={event ? '\nnostr:' + getNoteBech32Id(event) : undefined}
/>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
{postEditor}
</>
)
}

View file

@ -1,15 +1,18 @@
import { useSecondaryPage } from '@/PageManager'
import { Button } from '@/components/ui/button'
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import {
ResponsiveMenu,
ResponsiveMenuContent,
ResponsiveMenuItem,
ResponsiveMenuLabel,
ResponsiveMenuSeparator,
ResponsiveMenuTrigger
} from '@/components/ui/responsive-menu'
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { useStuff } from '@/hooks/useStuff'
import { toRelay } from '@/lib/link'
import { simplifyUrl } from '@/lib/url'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import client from '@/services/client.service'
import { Server } from 'lucide-react'
import { Event } from 'nostr-tools'
@ -19,56 +22,84 @@ import RelayIcon from '../RelayIcon'
export default function SeenOnButton({ stuff }: { stuff: Event | string }) {
const { t } = useTranslation()
const { isSmallScreen } = useScreenSize()
const { push } = useSecondaryPage()
const { event } = useStuff(stuff)
const [relays, setRelays] = useState<string[]>([])
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
useEffect(() => {
if (!event) return
const seenOn = client.getSeenEventRelayUrls(event.id)
setRelays(seenOn)
}, [event])
}, [])
const trigger = (
<button
className="flex gap-1 items-center text-muted-foreground enabled:hover:text-primary pl-3 h-full disabled:text-muted-foreground/40"
title={t('Seen on')}
disabled={relays.length === 0}
onClick={() => {
if (!event) return
if (isSmallScreen) {
setIsDrawerOpen(true)
}
}}
>
<Server />
{relays.length > 0 && <div className="text-sm">{relays.length}</div>}
</button>
)
if (relays.length === 0) {
return trigger
}
if (isSmallScreen) {
return (
<button
className="flex gap-1 items-center text-muted-foreground enabled:hover:text-primary pl-3 h-full disabled:text-muted-foreground/40"
title={t('Seen on')}
disabled
>
<Server />
</button>
<>
{trigger}
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
<DrawerOverlay onClick={() => setIsDrawerOpen(false)} />
<DrawerContent hideOverlay>
<div className="py-2">
{relays.map((relay) => (
<Button
className="w-full p-6 justify-start text-lg gap-4"
variant="ghost"
key={relay}
onClick={() => {
setIsDrawerOpen(false)
setTimeout(() => {
push(toRelay(relay))
}, 50) // Timeout to allow the drawer to close before navigating
}}
>
<RelayIcon url={relay} /> {simplifyUrl(relay)}
</Button>
))}
</div>
</DrawerContent>
</Drawer>
</>
)
}
return (
<ResponsiveMenu>
<ResponsiveMenuTrigger asChild>
<button
className="flex gap-1 items-center text-muted-foreground enabled:hover:text-primary pl-3 h-full"
title={t('Seen on')}
>
<Server />
<div className="text-sm">{relays.length}</div>
</button>
</ResponsiveMenuTrigger>
<ResponsiveMenuContent>
<ResponsiveMenuLabel>{t('Seen on')}</ResponsiveMenuLabel>
<ResponsiveMenuSeparator />
<DropdownMenu>
<DropdownMenuTrigger asChild>{trigger}</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>{t('Seen on')}</DropdownMenuLabel>
<DropdownMenuSeparator />
{relays.map((relay) => (
<ResponsiveMenuItem
key={relay}
onClick={() => {
setTimeout(() => push(toRelay(relay)), 100) // slight delay to allow menu to close
}}
>
<DropdownMenuItem key={relay} onClick={() => push(toRelay(relay))} className="min-w-52">
<RelayIcon url={relay} />
{simplifyUrl(relay)}
</ResponsiveMenuItem>
</DropdownMenuItem>
))}
</ResponsiveMenuContent>
</ResponsiveMenu>
</DropdownMenuContent>
</DropdownMenu>
)
}