Browse Source

got rid of profile drawer and hover

imwald
Silberengel 5 months ago
parent
commit
93612879f2
  1. 81
      src/PageManager.tsx
  2. 67
      src/components/UserAvatar/index.tsx
  3. 63
      src/components/Username/index.tsx

81
src/PageManager.tsx

@ -172,15 +172,14 @@ export function useSmartProfileNavigation() { @@ -172,15 +172,14 @@ export function useSmartProfileNavigation() {
const { setPrimaryNoteView } = usePrimaryNoteView()
const navigateToProfile = (url: string) => {
if (!showRecommendedRelaysPanel) {
// When right panel is hidden, show profile in primary area
// Extract profile ID from URL (e.g., "/users/npub1..." -> "npub1...")
if (showRecommendedRelaysPanel) {
// Secondary panel is available - show profile in secondary panel
pushSecondary(url)
} else {
// Secondary panel is not available - show profile in primary panel
const profileId = url.replace('/users/', '')
window.history.replaceState(null, '', url)
setPrimaryNoteView(<SecondaryProfilePage id={profileId} index={0} hideTitlebar={true} />, 'profile')
} else {
// Normal behavior - use secondary navigation
pushSecondary(url)
}
}
@ -678,28 +677,58 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) { @@ -678,28 +677,58 @@ export function PageManager({ maxStackSize = 5 }: { maxStackSize?: number }) {
<CurrentRelaysProvider>
<NotificationProvider>
<PrimaryNoteViewContext.Provider value={{ setPrimaryNoteView, primaryViewType }}>
{!!secondaryStack.length &&
secondaryStack.map((item, index) => (
<div
key={item.index}
style={{
display: index === secondaryStack.length - 1 ? 'block' : 'none'
}}
>
{item.component}
{primaryNoteView ? (
// Show primary note view with back button on mobile
<div className="flex flex-col h-full w-full">
<div className="flex gap-1 p-1 items-center justify-between font-semibold border-b">
<div className="flex items-center flex-1 w-0">
<Button
className="flex gap-1 items-center w-fit max-w-full justify-start pl-2 pr-3"
variant="ghost"
size="titlebar-icon"
title="Back to feed"
onClick={() => setPrimaryNoteView(null)}
>
<ChevronLeft />
<div className="truncate text-lg font-semibold">
{primaryViewType === 'settings' ? 'Settings' :
primaryViewType === 'settings-sub' ? 'Settings' :
primaryViewType === 'profile' ? 'Back' :
primaryViewType === 'hashtag' ? 'Hashtag' : 'Note'}
</div>
</Button>
</div>
</div>
<div className="flex-1 overflow-auto">
{primaryNoteView}
</div>
))}
{primaryPages.map(({ name, element, props }) => (
<div
key={name}
style={{
display:
secondaryStack.length === 0 && currentPrimaryPage === name ? 'block' : 'none'
}}
>
{props ? cloneElement(element as React.ReactElement, props) : element}
</div>
))}
) : (
<>
{!!secondaryStack.length &&
secondaryStack.map((item, index) => (
<div
key={item.index}
style={{
display: index === secondaryStack.length - 1 ? 'block' : 'none'
}}
>
{item.component}
</div>
))}
{primaryPages.map(({ name, element, props }) => (
<div
key={name}
style={{
display:
secondaryStack.length === 0 && currentPrimaryPage === name ? 'block' : 'none'
}}
>
{props ? cloneElement(element as React.ReactElement, props) : element}
</div>
))}
</>
)}
<BottomNavigationBar />
<TooManyRelaysAlertDialog />
<CreateWalletGuideToast />

67
src/components/UserAvatar/index.tsx

@ -1,13 +1,11 @@ @@ -1,13 +1,11 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'
import { Skeleton } from '@/components/ui/skeleton'
import { useFetchProfile } from '@/hooks'
import { generateImageByPubkey } from '@/lib/pubkey'
import { toProfile } from '@/lib/link'
import { cn } from '@/lib/utils'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useMemo, useState } from 'react'
import ProfileCard from '../ProfileCard'
import { useSmartProfileNavigation } from '@/PageManager'
import { useMemo } from 'react'
const UserAvatarSizeCnMap = {
large: 'w-24 h-24',
@ -30,8 +28,7 @@ export default function UserAvatar({ @@ -30,8 +28,7 @@ export default function UserAvatar({
size?: 'large' | 'big' | 'semiBig' | 'normal' | 'medium' | 'small' | 'xSmall' | 'tiny'
}) {
const { profile } = useFetchProfile(userId)
const { isSmallScreen } = useScreenSize()
const [drawerOpen, setDrawerOpen] = useState(false)
const { navigateToProfile } = useSmartProfileNavigation()
const defaultAvatar = useMemo(
() => (profile?.pubkey ? generateImageByPubkey(profile.pubkey) : ''),
[profile]
@ -42,59 +39,30 @@ export default function UserAvatar({ @@ -42,59 +39,30 @@ export default function UserAvatar({
<Skeleton className={cn('shrink-0', UserAvatarSizeCnMap[size], 'rounded-full', className)} />
)
}
const { avatar, pubkey } = profile
if (isSmallScreen) {
return (
<>
<Avatar
className={cn('shrink-0 cursor-pointer', UserAvatarSizeCnMap[size], className)}
onClick={() => setDrawerOpen(true)}
>
<AvatarImage src={avatar} className="object-cover object-center" />
<AvatarFallback>
<img src={defaultAvatar} alt={pubkey} />
</AvatarFallback>
</Avatar>
<Drawer open={drawerOpen} onOpenChange={setDrawerOpen}>
<DrawerOverlay onClick={() => setDrawerOpen(false)} />
<DrawerContent hideOverlay className="max-h-[90vh]">
<div className="overflow-y-auto overscroll-contain p-4" style={{ touchAction: 'pan-y' }}>
<ProfileCard pubkey={pubkey} />
</div>
</DrawerContent>
</Drawer>
</>
)
}
const { avatar, pubkey } = profile
return (
<HoverCard>
<HoverCardTrigger asChild>
<Avatar className={cn('shrink-0 cursor-pointer', UserAvatarSizeCnMap[size], className)}>
<AvatarImage src={avatar} className="object-cover object-center" />
<AvatarFallback>
<img src={defaultAvatar} alt={pubkey} />
</AvatarFallback>
</Avatar>
</HoverCardTrigger>
<HoverCardContent className="w-72">
<ProfileCard pubkey={pubkey} />
</HoverCardContent>
</HoverCard>
<Avatar
className={cn('shrink-0 cursor-pointer', UserAvatarSizeCnMap[size], className)}
onClick={() => navigateToProfile(toProfile(pubkey))}
>
<AvatarImage src={avatar} className="object-cover object-center" />
<AvatarFallback>
<img src={defaultAvatar} alt={pubkey} />
</AvatarFallback>
</Avatar>
)
}
export function SimpleUserAvatar({
userId,
size = 'normal',
className,
onClick
className
}: {
userId: string
size?: 'large' | 'big' | 'normal' | 'medium' | 'small' | 'xSmall' | 'tiny'
size?: 'large' | 'big' | 'semiBig' | 'normal' | 'medium' | 'small' | 'xSmall' | 'tiny'
className?: string
onClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void
}) {
const { profile } = useFetchProfile(userId)
const defaultAvatar = useMemo(
@ -107,10 +75,11 @@ export function SimpleUserAvatar({ @@ -107,10 +75,11 @@ export function SimpleUserAvatar({
<Skeleton className={cn('shrink-0', UserAvatarSizeCnMap[size], 'rounded-full', className)} />
)
}
const { avatar, pubkey } = profile
return (
<Avatar className={cn('shrink-0', UserAvatarSizeCnMap[size], className)} onClick={onClick}>
<Avatar className={cn('shrink-0', UserAvatarSizeCnMap[size], className)}>
<AvatarImage src={avatar} className="object-cover object-center" />
<AvatarFallback>
<img src={defaultAvatar} alt={pubkey} />

63
src/components/Username/index.tsx

@ -1,11 +1,8 @@ @@ -1,11 +1,8 @@
import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'
import { Skeleton } from '@/components/ui/skeleton'
import { useFetchProfile } from '@/hooks'
import { toProfile } from '@/lib/link'
import { cn } from '@/lib/utils'
import { useScreenSize } from '@/providers/ScreenSizeProvider'
import { useState } from 'react'
import ProfileCard from '../ProfileCard'
import { useSmartProfileNavigation } from '@/PageManager'
export default function Username({
userId,
@ -21,8 +18,7 @@ export default function Username({ @@ -21,8 +18,7 @@ export default function Username({
withoutSkeleton?: boolean
}) {
const { profile } = useFetchProfile(userId)
const { isSmallScreen } = useScreenSize()
const [drawerOpen, setDrawerOpen] = useState(false)
const { navigateToProfile } = useSmartProfileNavigation()
if (!profile && !withoutSkeleton) {
return (
@ -31,44 +27,21 @@ export default function Username({ @@ -31,44 +27,21 @@ export default function Username({
</div>
)
}
if (!profile) return null
const { username, pubkey } = profile
if (isSmallScreen) {
return (
<>
<div
className={cn('truncate hover:underline cursor-pointer', className)}
onClick={() => setDrawerOpen(true)}
>
{showAt && '@'}
{username}
</div>
<Drawer open={drawerOpen} onOpenChange={setDrawerOpen}>
<DrawerOverlay onClick={() => setDrawerOpen(false)} />
<DrawerContent hideOverlay className="max-h-[90vh]">
<div className="overflow-y-auto overscroll-contain p-4" style={{ touchAction: 'pan-y' }}>
<ProfileCard pubkey={pubkey} />
</div>
</DrawerContent>
</Drawer>
</>
)
if (!profile) {
return null
}
const { username, pubkey } = profile
return (
<HoverCard>
<HoverCardTrigger asChild>
<div className={cn('truncate hover:underline cursor-pointer', className)}>
{showAt && '@'}
{username}
</div>
</HoverCardTrigger>
<HoverCardContent className="w-80">
<ProfileCard pubkey={pubkey} />
</HoverCardContent>
</HoverCard>
<div
className={cn('truncate hover:underline cursor-pointer', className)}
onClick={() => navigateToProfile(toProfile(pubkey))}
>
{showAt && '@'}
{username}
</div>
)
}
@ -86,6 +59,7 @@ export function SimpleUsername({ @@ -86,6 +59,7 @@ export function SimpleUsername({
withoutSkeleton?: boolean
}) {
const { profile } = useFetchProfile(userId)
if (!profile && !withoutSkeleton) {
return (
<div className="py-1">
@ -93,12 +67,15 @@ export function SimpleUsername({ @@ -93,12 +67,15 @@ export function SimpleUsername({
</div>
)
}
if (!profile) return null
if (!profile) {
return null
}
const { username } = profile
return (
<div className={className}>
<div className={cn('truncate', className)}>
{showAt && '@'}
{username}
</div>

Loading…
Cancel
Save