From 3f6c3fb02d32d1c6a6e3f9262fe69ff126e33ceb Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 1 Apr 2026 13:10:05 +0400 Subject: [PATCH] fix(post): show the user name without overlaping --- .../social/components/ReplyToFeedItem.tsx | 136 +++++++++--------- .../components/TokenCreatedFeedItem.tsx | 64 +++++---- .../components/useCompactFeedItemLayout.ts | 35 +++++ 3 files changed, 143 insertions(+), 92 deletions(-) create mode 100644 src/features/social/components/useCompactFeedItemLayout.ts diff --git a/src/features/social/components/ReplyToFeedItem.tsx b/src/features/social/components/ReplyToFeedItem.tsx index 537968b6..e8a9b2b1 100644 --- a/src/features/social/components/ReplyToFeedItem.tsx +++ b/src/features/social/components/ReplyToFeedItem.tsx @@ -16,6 +16,7 @@ import SharePopover from './SharePopover'; import PostTipButton from './PostTipButton'; import { useWallet } from '../../../hooks'; import { compactTime, fullTimestamp } from '../../../utils/time'; +import { useCompactFeedItemLayout } from './useCompactFeedItemLayout'; interface ReplyToFeedItemProps { item: PostDto; @@ -81,6 +82,7 @@ const ReplyToFeedItem = memo(({ const { chainNames, profileDisplayNames } = useWallet(); const displayName = (profileDisplayNames?.[authorAddress] ?? chainNames?.[authorAddress] ?? '').trim(); const hasDisplayName = Boolean(displayName); + const { containerRef, isCompact } = useCompactFeedItemLayout(item.tx_hash ? 700 : 620); const parentId = useParentId(item); const [parent, setParent] = useState(null); @@ -130,6 +132,66 @@ const ReplyToFeedItem = memo(({ const media = Array.isArray(item.media) ? item.media.filter((m) => (typeof m === 'string' ? !m.startsWith('comment:') : true)) : []; + const unnamedHeader = isCompact ? ( + <> +
+
+ {formatAddress(authorAddress, 6, true)} +
+ · + {item.tx_hash ? ( + + {compactTime(item.created_at as unknown as string)} + + )} + /> + ) : ( +
{compactTime(item.created_at as unknown as string)}
+ )} +
+
+ {formatAddress(authorAddress, 10, false)} + +
+ + ) : ( + <> +
+ {authorAddress} +
+
+ {item.tx_hash ? ( + + {compactTime(item.created_at as unknown as string)} + {' '} + ago + + )} + /> + ) : ( +
+ {compactTime(item.created_at as unknown as string)} + {' '} + ago +
+ )} +
+ + ); // Compute total descendant comments (all levels) for this item const { data: descendantCount } = useQuery({ @@ -180,6 +242,7 @@ const ReplyToFeedItem = memo(({ return (
)} {/* Main row: avatar left, content right */}
-
+ {isCompact ? ( -
-
+ ) : ( -
+ )}
-
+
{/* Header: keep named-user layout; show address-first layout for unnamed users */}
{hasDisplayName ? ( <> -
-
+
+
{displayName}
· @@ -255,61 +317,7 @@ const ReplyToFeedItem = memo(({
) : ( - <> -
-
- {formatAddress(authorAddress, 6, true)} -
- · - {item.tx_hash ? ( - - {compactTime(item.created_at as unknown as string)} - - )} - /> - ) : ( -
{compactTime(item.created_at as unknown as string)}
- )} -
-
- {formatAddress(authorAddress, 10, false)} - -
-
- {authorAddress} -
-
- {item.tx_hash ? ( - - {compactTime(item.created_at as unknown as string)} - {' '} - ago - - )} - /> - ) : ( -
- {compactTime(item.created_at as unknown as string)} - {' '} - ago -
- )} -
- + unnamedHeader )}
diff --git a/src/features/social/components/TokenCreatedFeedItem.tsx b/src/features/social/components/TokenCreatedFeedItem.tsx index baf96361..5cbefd0d 100644 --- a/src/features/social/components/TokenCreatedFeedItem.tsx +++ b/src/features/social/components/TokenCreatedFeedItem.tsx @@ -11,6 +11,7 @@ import SharePopover from './SharePopover'; import { useWallet } from '../../../hooks'; import type { PostDto } from '../../../api/generated'; import { compactTime, fullTimestamp } from '../../../utils/time'; +import { useCompactFeedItemLayout } from './useCompactFeedItemLayout'; interface TokenCreatedFeedItemProps { item: PostDto; @@ -42,6 +43,31 @@ const TokenCreatedFeedItem = memo(({ item, onOpenPost }: TokenCreatedFeedItemPro const authorLabel = displayName || formatAddress(authorAddress, 6, true); const tokenName = useTokenName(item); const tokenLink = tokenName ? `/trends/tokens/${tokenName}` : undefined; + const { containerRef, isCompact } = useCompactFeedItemLayout(item.tx_hash ? 700 : 620); + const unnamedHeader = isCompact ? ( + <> +
+
+ {formatAddress(authorAddress, 6, true)} +
+ · +
{compactTime(item.created_at as unknown as string)}
+
+
+ {authorAddress} + +
+ + ) : ( + <> +
+ {authorAddress} +
+
+ {compactTime(item.created_at as unknown as string)} +
+ + ); const handleOpen = useCallback(() => onOpenPost(postId), [onOpenPost, postId]); const navigate = useNavigate(); @@ -49,6 +75,7 @@ const TokenCreatedFeedItem = memo(({ item, onOpenPost }: TokenCreatedFeedItemPro return ( // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
)}
-
+ {isCompact ? ( -
-
+ ) : ( -
+ )}
-
+
{/* Header: keep named-user layout; show address-first layout for unnamed users */} {hasDisplayName ? ( <>
-
-
{displayName}
+
+
{displayName}
·
{compactTime(item.created_at as unknown as string)}
@@ -104,25 +130,7 @@ const TokenCreatedFeedItem = memo(({ item, onOpenPost }: TokenCreatedFeedItemPro
) : ( - <> -
-
- {formatAddress(authorAddress, 6, true)} -
- · -
{compactTime(item.created_at as unknown as string)}
-
-
- {authorAddress} - -
-
- {authorAddress} -
-
- {compactTime(item.created_at as unknown as string)} -
- + unnamedHeader )} {/* Tokenized trend header */} diff --git a/src/features/social/components/useCompactFeedItemLayout.ts b/src/features/social/components/useCompactFeedItemLayout.ts new file mode 100644 index 00000000..ddc1a399 --- /dev/null +++ b/src/features/social/components/useCompactFeedItemLayout.ts @@ -0,0 +1,35 @@ +import { + useEffect, useLayoutEffect, useRef, useState, +} from 'react'; + +const useIsomorphicLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect; + +export function useCompactFeedItemLayout(threshold: number) { + const containerRef = useRef(null); + const [isCompact, setIsCompact] = useState(false); + + useIsomorphicLayoutEffect(() => { + const node = containerRef.current; + if (!node) return () => {}; + + const update = (width: number) => { + setIsCompact(width > 0 && width < threshold); + }; + + update(node.getBoundingClientRect().width); + + if (typeof ResizeObserver === 'function') { + const observer = new ResizeObserver((entries) => { + update(entries[0]?.contentRect.width ?? node.getBoundingClientRect().width); + }); + observer.observe(node); + return () => observer.disconnect(); + } + + const handleResize = () => update(node.getBoundingClientRect().width); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [threshold]); + + return { containerRef, isCompact }; +}