feat: 💨
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { FormattedTimestamp } from '@/components/FormattedTimestamp'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import UserAvatar from '@/components/UserAvatar'
|
||||
import Username from '@/components/Username'
|
||||
import UserAvatar, { SimpleUserAvatar } from '@/components/UserAvatar'
|
||||
import Username, { SimpleUsername } from '@/components/Username'
|
||||
import { isMentioningMutedUsers } from '@/lib/event'
|
||||
import { toNote, toUserAggregationDetail } from '@/lib/link'
|
||||
import { cn, isTouchDevice } from '@/lib/utils'
|
||||
@@ -371,6 +371,7 @@ function UserAggregationItem({
|
||||
onClick: () => void
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const supportTouch = useMemo(() => isTouchDevice(), [])
|
||||
const [hasNewEvents, setHasNewEvents] = useState(true)
|
||||
const [isPinned, setIsPinned] = useState(userAggregationService.isPinned(aggregation.pubkey))
|
||||
|
||||
@@ -418,14 +419,26 @@ function UserAggregationItem({
|
||||
className="group relative flex items-center gap-4 px-4 py-3 border-b hover:bg-accent/30 cursor-pointer transition-all duration-200"
|
||||
onClick={onClick}
|
||||
>
|
||||
<UserAvatar userId={aggregation.pubkey} />
|
||||
{supportTouch ? (
|
||||
<SimpleUserAvatar userId={aggregation.pubkey} />
|
||||
) : (
|
||||
<UserAvatar userId={aggregation.pubkey} />
|
||||
)}
|
||||
|
||||
<div className="flex-1 min-w-0 flex flex-col">
|
||||
<Username
|
||||
userId={aggregation.pubkey}
|
||||
className="font-semibold text-base truncate max-w-fit"
|
||||
skeletonClassName="h-4"
|
||||
/>
|
||||
{supportTouch ? (
|
||||
<SimpleUsername
|
||||
userId={aggregation.pubkey}
|
||||
className="font-semibold text-base truncate max-w-fit"
|
||||
skeletonClassName="h-4"
|
||||
/>
|
||||
) : (
|
||||
<Username
|
||||
userId={aggregation.pubkey}
|
||||
className="font-semibold text-base truncate max-w-fit"
|
||||
skeletonClassName="h-4"
|
||||
/>
|
||||
)}
|
||||
<FormattedTimestamp
|
||||
timestamp={aggregation.lastEventTime}
|
||||
className="text-sm text-muted-foreground"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { useFetchProfile } from '@/hooks'
|
||||
import { toProfile } from '@/lib/link'
|
||||
import { generateImageByPubkey } from '@/lib/pubkey'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { cn, isTouchDevice } from '@/lib/utils'
|
||||
import { SecondaryPageLink } from '@/PageManager'
|
||||
import { useMemo } from 'react'
|
||||
import Image from '../Image'
|
||||
@@ -29,13 +29,21 @@ export default function UserAvatar({
|
||||
className?: string
|
||||
size?: 'large' | 'big' | 'semiBig' | 'normal' | 'medium' | 'small' | 'xSmall' | 'tiny'
|
||||
}) {
|
||||
const supportTouch = useMemo(() => isTouchDevice(), [])
|
||||
|
||||
const trigger = (
|
||||
<SecondaryPageLink to={toProfile(userId)} onClick={(e) => e.stopPropagation()}>
|
||||
<SimpleUserAvatar userId={userId} size={size} className={className} />
|
||||
</SecondaryPageLink>
|
||||
)
|
||||
|
||||
if (supportTouch) {
|
||||
return trigger
|
||||
}
|
||||
|
||||
return (
|
||||
<HoverCard>
|
||||
<HoverCardTrigger>
|
||||
<SecondaryPageLink to={toProfile(userId)} onClick={(e) => e.stopPropagation()}>
|
||||
<SimpleUserAvatar userId={userId} size={size} className={className} />
|
||||
</SecondaryPageLink>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardTrigger>{trigger}</HoverCardTrigger>
|
||||
<HoverCardContent className="w-72">
|
||||
<ProfileCard userId={userId} />
|
||||
</HoverCardContent>
|
||||
|
||||
@@ -2,10 +2,11 @@ import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/h
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { useFetchProfile } from '@/hooks'
|
||||
import { toProfile } from '@/lib/link'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { cn, isTouchDevice } from '@/lib/utils'
|
||||
import { SecondaryPageLink } from '@/PageManager'
|
||||
import ProfileCard from '../ProfileCard'
|
||||
import TextWithEmojis from '../TextWithEmojis'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
export default function Username({
|
||||
userId,
|
||||
@@ -21,6 +22,7 @@ export default function Username({
|
||||
withoutSkeleton?: boolean
|
||||
}) {
|
||||
const { profile, isFetching } = useFetchProfile(userId)
|
||||
const supportTouch = useMemo(() => isTouchDevice(), [])
|
||||
if (!profile && isFetching && !withoutSkeleton) {
|
||||
return (
|
||||
<div className="py-1">
|
||||
@@ -30,20 +32,26 @@ export default function Username({
|
||||
}
|
||||
if (!profile) return null
|
||||
|
||||
const trigger = (
|
||||
<div className={className}>
|
||||
<SecondaryPageLink
|
||||
to={toProfile(userId)}
|
||||
className="truncate hover:underline"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{showAt && '@'}
|
||||
<TextWithEmojis text={profile.username} emojis={profile.emojis} emojiClassName="mb-1" />
|
||||
</SecondaryPageLink>
|
||||
</div>
|
||||
)
|
||||
|
||||
if (supportTouch) {
|
||||
return trigger
|
||||
}
|
||||
|
||||
return (
|
||||
<HoverCard>
|
||||
<HoverCardTrigger asChild>
|
||||
<div className={className}>
|
||||
<SecondaryPageLink
|
||||
to={toProfile(userId)}
|
||||
className="truncate hover:underline"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{showAt && '@'}
|
||||
<TextWithEmojis text={profile.username} emojis={profile.emojis} emojiClassName="mb-1" />
|
||||
</SecondaryPageLink>
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardTrigger asChild>{trigger}</HoverCardTrigger>
|
||||
<HoverCardContent className="w-80">
|
||||
<ProfileCard userId={userId} />
|
||||
</HoverCardContent>
|
||||
|
||||
Reference in New Issue
Block a user