From 151892f7af93250c22bc26bbff7c45810c63ae8b Mon Sep 17 00:00:00 2001 From: robin Date: Thu, 5 Oct 2023 11:51:29 -0400 Subject: [PATCH] Fix communities without a name (#1995) * enable hover cards on nft detail page * fixxxx * fix types --- .../components/Community/CommunityHeader.tsx | 8 ++- .../CommunityProfilePicture.tsx | 6 ++- .../NftDetailScreen/NftDetailSection.tsx | 7 ++- .../Feed/Posts/PostCommunityPill.tsx | 6 ++- .../HoverCard/CommunityHoverCard.tsx | 37 ++++++-------- .../CommunityProfilePicture.tsx | 6 ++- .../CommunityPage/CommunityPageViewHeader.tsx | 9 ++-- .../NftDetailPage/NftDetailAsset.test.tsx | 9 ++++ .../scenes/NftDetailPage/NftDetailText.tsx | 50 +++++++++++-------- .../SharedCommunitiesList.tsx | 7 ++- .../utils/extractRelevantMetadataFromToken.ts | 13 +++-- 11 files changed, 100 insertions(+), 58 deletions(-) diff --git a/apps/mobile/src/components/Community/CommunityHeader.tsx b/apps/mobile/src/components/Community/CommunityHeader.tsx index 2c66ea0677..a9a21754c1 100644 --- a/apps/mobile/src/components/Community/CommunityHeader.tsx +++ b/apps/mobile/src/components/Community/CommunityHeader.tsx @@ -3,6 +3,7 @@ import { View } from 'react-native'; import { graphql, useFragment } from 'react-relay'; import { CommunityHeaderFragment$key } from '~/generated/CommunityHeaderFragment.graphql'; +import { truncateAddress } from '~/shared/utils/wallet'; import { GalleryBottomSheetModalType } from '../GalleryBottomSheet/GalleryBottomSheetModal'; import { GalleryTouchableOpacity } from '../GalleryTouchableOpacity'; @@ -19,6 +20,9 @@ export function CommunityHeader({ communityRef }: Props) { graphql` fragment CommunityHeaderFragment on Community { name + contractAddress { + address + } description ...CommunityProfilePictureFragment ...CommunityBottomSheetFragment @@ -40,6 +44,8 @@ export function CommunityHeader({ communityRef }: Props) { const cleanedSentences = community.description?.trim().replace(/\s+/g, ' '); const formattedDescription = cleanedSentences?.split(/[.!?]\s+/).join(' '); + const displayName = community.name || truncateAddress(community.contractAddress?.address ?? ''); + return ( @@ -56,7 +62,7 @@ export function CommunityHeader({ communityRef }: Props) { font={{ family: 'ABCDiatype', weight: 'Bold' }} className="text-lg leading-5 mb-1" > - {community.name} + {displayName} {formattedDescription && {formattedDescription}} diff --git a/apps/mobile/src/components/ProfilePicture/CommunityProfilePicture.tsx b/apps/mobile/src/components/ProfilePicture/CommunityProfilePicture.tsx index 476c3a5e52..b87b916f09 100644 --- a/apps/mobile/src/components/ProfilePicture/CommunityProfilePicture.tsx +++ b/apps/mobile/src/components/ProfilePicture/CommunityProfilePicture.tsx @@ -17,6 +17,9 @@ export function CommunityProfilePicture({ communityRef, style, ...rest }: Profil graphql` fragment CommunityProfilePictureFragment on Community { name + contractAddress { + address + } profileImageURL } `, @@ -25,7 +28,8 @@ export function CommunityProfilePicture({ communityRef, style, ...rest }: Profil const imageUrl = community?.profileImageURL; - const letter = community?.name?.[0]?.toUpperCase(); + const letter = + community?.name?.[0]?.toUpperCase() || community?.contractAddress?.address?.[0]?.toUpperCase(); const fallbackProfilePicture = ( diff --git a/apps/web/src/components/Feed/Posts/PostCommunityPill.tsx b/apps/web/src/components/Feed/Posts/PostCommunityPill.tsx index 2b2d191b53..bd608f36d6 100644 --- a/apps/web/src/components/Feed/Posts/PostCommunityPill.tsx +++ b/apps/web/src/components/Feed/Posts/PostCommunityPill.tsx @@ -48,7 +48,11 @@ export default function PostCommunityPill({ postRef }: Props) { } return ( - + {contractName} diff --git a/apps/web/src/components/HoverCard/CommunityHoverCard.tsx b/apps/web/src/components/HoverCard/CommunityHoverCard.tsx index 907f606751..e9472cd84b 100644 --- a/apps/web/src/components/HoverCard/CommunityHoverCard.tsx +++ b/apps/web/src/components/HoverCard/CommunityHoverCard.tsx @@ -11,8 +11,6 @@ import { ErrorWithSentryMetadata } from '~/shared/errors/ErrorWithSentryMetadata import { removeNullValues } from '~/shared/relay/removeNullValues'; import { useLoggedInUserId } from '~/shared/relay/useLoggedInUserId'; import colors from '~/shared/theme/colors'; -import { isValidEthereumAddress, truncateAddress } from '~/shared/utils/wallet'; -import handleCustomDisplayName from '~/utils/handleCustomDisplayName'; import InteractiveLink from '../core/InteractiveLink/InteractiveLink'; import Markdown from '../core/Markdown/Markdown'; @@ -27,7 +25,6 @@ const CommunityHoverCardQueryNode = graphql` communityByAddress(communityAddress: $communityAddress) { __typename ... on Community { - name description contractAddress { address @@ -59,14 +56,19 @@ const CommunityHoverCardQueryNode = graphql` type Props = PropsWithChildren<{ communityRef: CommunityHoverCardFragment$key; + communityName: string; onClick?: HoverCardProps['onHoverableElementClick']; }>; -export default function CommunityHoverCard({ children, communityRef, onClick }: Props) { +export default function CommunityHoverCard({ + children, + communityName, + communityRef, + onClick, +}: Props) { const community = useFragment( graphql` fragment CommunityHoverCardFragment on Community { - name contractAddress { address chain @@ -99,20 +101,17 @@ export default function CommunityHoverCard({ children, communityRef, onClick }: }); }, [community.contractAddress?.address, community.contractAddress?.chain, preloadHoverCardQuery]); - if (!community.name) { - return null; - } - - const displayName = handleCustomDisplayName(community.name); - return ( {displayName}} + HoverableElement={children ?? {communityName}} onHoverableElementClick={onClick} hoverableElementHref={communityProfileLink} HoveringContent={ preloadedHoverCardQuery ? ( - + ) : null } preloadQuery={handlePreloadQuery} @@ -123,8 +122,10 @@ export default function CommunityHoverCard({ children, communityRef, onClick }: function CommunityHoverCardContent({ preloadedQuery, + communityName, }: { preloadedQuery: PreloadedQuery; + communityName: string; }) { const communityQuery = usePreloadedQuery(CommunityHoverCardQueryNode, preloadedQuery); @@ -197,10 +198,6 @@ function CommunityHoverCardContent({ }; }, [community]); - if (!community.name) { - return null; - } - const hasDescription = Boolean(community.description); return ( @@ -210,11 +207,7 @@ function CommunityHoverCardContent({
- - {isValidEthereumAddress(community.name) - ? truncateAddress(community.name) - : community.name} - + {communityName} {community.description && ( diff --git a/apps/web/src/components/ProfilePicture/CommunityProfilePicture.tsx b/apps/web/src/components/ProfilePicture/CommunityProfilePicture.tsx index 3a77d702ec..9824b06064 100644 --- a/apps/web/src/components/ProfilePicture/CommunityProfilePicture.tsx +++ b/apps/web/src/components/ProfilePicture/CommunityProfilePicture.tsx @@ -13,6 +13,9 @@ export default function CommunityProfilePicture({ communityRef, ...rest }: Props graphql` fragment CommunityProfilePictureFragment on Community { name + contractAddress { + address + } profileImageURL } `, @@ -24,6 +27,7 @@ export default function CommunityProfilePicture({ communityRef, ...rest }: Props return ; } - const firstLetter = community?.name?.[0]?.toUpperCase(); + const firstLetter = + community?.name?.[0]?.toUpperCase() || community?.contractAddress?.address?.[0]?.toUpperCase(); return ; } diff --git a/apps/web/src/scenes/CommunityPage/CommunityPageViewHeader.tsx b/apps/web/src/scenes/CommunityPage/CommunityPageViewHeader.tsx index a835d7ff37..f24e31e4a3 100644 --- a/apps/web/src/scenes/CommunityPage/CommunityPageViewHeader.tsx +++ b/apps/web/src/scenes/CommunityPage/CommunityPageViewHeader.tsx @@ -19,7 +19,7 @@ import GlobeIcon from '~/icons/GlobeIcon'; import ShareIcon from '~/icons/ShareIcon'; import { useTrack } from '~/shared/contexts/AnalyticsContext'; import { replaceUrlsWithMarkdownFormat } from '~/shared/utils/replaceUrlsWithMarkdownFormat'; -import { getExternalAddressLink } from '~/shared/utils/wallet'; +import { getExternalAddressLink, truncateAddress } from '~/shared/utils/wallet'; import { getBaseUrl } from '~/utils/getBaseUrl'; import CommunityPageMetadata from './CommunityPageMetadata'; @@ -37,6 +37,7 @@ export default function CommunityPageViewHeader({ communityRef, queryRef }: Prop description badgeURL contractAddress { + address ...walletGetExternalAddressLinkFragment } ...CommunityPageMetadataFragment @@ -152,6 +153,8 @@ export default function CommunityPageViewHeader({ communityRef, queryRef }: Prop showExpandedDescription, ]); + const displayName = name || truncateAddress(contractAddress?.address ?? ''); + if (isMobile) { return ( @@ -159,7 +162,7 @@ export default function CommunityPageViewHeader({ communityRef, queryRef }: Prop - {name} + {displayName} {DescriptionContainer} @@ -175,7 +178,7 @@ export default function CommunityPageViewHeader({ communityRef, queryRef }: Prop - {name} + {displayName} {badgeURL && } diff --git a/apps/web/src/scenes/NftDetailPage/NftDetailAsset.test.tsx b/apps/web/src/scenes/NftDetailPage/NftDetailAsset.test.tsx index d65d4a42fe..8c20af75b0 100644 --- a/apps/web/src/scenes/NftDetailPage/NftDetailAsset.test.tsx +++ b/apps/web/src/scenes/NftDetailPage/NftDetailAsset.test.tsx @@ -57,6 +57,7 @@ const UnknownMediaResponse: NftDetailAssetTestQueryQuery = { lastUpdated: '2023-07-25T11:47:41.83653Z', ownerIsCreator: false, owner: { + dbid: 'testOwnerId', id: 'GalleryUser:TestOwnerId', username: 'Test Username', profileImage: { @@ -102,6 +103,14 @@ const UnknownMediaResponse: NftDetailAssetTestQueryQuery = { }, badgeURL: 'http://someurl.com', }, + community: { + __typename: 'Community', + id: 'Contract:someCommunityId', + contractAddress: { + chain: Chain.Ethereum, + address: '0x0Ff979fB365e20c09bE06676D569EF581a46621D', + }, + }, }, }, }; diff --git a/apps/web/src/scenes/NftDetailPage/NftDetailText.tsx b/apps/web/src/scenes/NftDetailPage/NftDetailText.tsx index 21ed7ece5b..95da5cec11 100644 --- a/apps/web/src/scenes/NftDetailPage/NftDetailText.tsx +++ b/apps/web/src/scenes/NftDetailPage/NftDetailText.tsx @@ -10,6 +10,8 @@ import InteractiveLink from '~/components/core/InteractiveLink/InteractiveLink'; import Markdown from '~/components/core/Markdown/Markdown'; import { HStack, VStack } from '~/components/core/Spacer/Stack'; import { BaseM, TitleDiatypeM, TitleM, TitleXS } from '~/components/core/Text/Text'; +import CommunityHoverCard from '~/components/HoverCard/CommunityHoverCard'; +import UserHoverCard from '~/components/HoverCard/UserHoverCard'; import { ClickablePill, NonclickablePill } from '~/components/Pill'; import { PostComposerModal } from '~/components/Posts/PostComposerModal'; import { ProfilePicture } from '~/components/ProfilePicture/ProfilePicture'; @@ -49,6 +51,7 @@ function NftDetailText({ tokenRef, authenticatedUserOwnsAsset }: Props) { owner { username ...ProfilePictureFragment + ...UserHoverCardFragment } ownerIsCreator contract { @@ -59,6 +62,9 @@ function NftDetailText({ tokenRef, authenticatedUserOwnsAsset }: Props) { } badgeURL } + community { + ...CommunityHoverCardFragment + } ...NftAdditionalDetailsFragment ...getCommunityUrlForTokenFragment @@ -159,14 +165,16 @@ function NftDetailText({ tokenRef, authenticatedUserOwnsAsset }: Props) { {token.name && {decodedTokenName}} - {communityUrl ? ( - - - {token.chain === 'POAP' && } - {token.contract?.badgeURL && } - {contractName} - - + {communityUrl && token.community ? ( + + + + {token.chain === 'POAP' && } + {token.contract?.badgeURL && } + {contractName} + + + ) : ( {contractName} @@ -177,18 +185,20 @@ function NftDetailText({ tokenRef, authenticatedUserOwnsAsset }: Props) { {token.owner?.username && ( - - {token.ownerIsCreator ? 'CREATOR' : 'OWNER'} - - - - {token.owner.username} - - - + + + {token.ownerIsCreator ? 'CREATOR' : 'OWNER'} + + + + {token.owner.username} + + + + )} {ENABLED_CREATOR && ( // TODO: Update this to use the creator's username diff --git a/apps/web/src/scenes/UserGalleryPage/UserSharedInfo/UserSharedInfoList/SharedCommunitiesList.tsx b/apps/web/src/scenes/UserGalleryPage/UserSharedInfo/UserSharedInfoList/SharedCommunitiesList.tsx index b43ccb038f..c58715e6e3 100644 --- a/apps/web/src/scenes/UserGalleryPage/UserSharedInfo/UserSharedInfoList/SharedCommunitiesList.tsx +++ b/apps/web/src/scenes/UserGalleryPage/UserSharedInfo/UserSharedInfoList/SharedCommunitiesList.tsx @@ -75,13 +75,16 @@ export default function SharedCommunitiesList({ userRef }: Props) { ) : null; - if (!community.name && !descriptionFirstLine) { + const displayName = + community.name || community.contractAddress?.address || 'Untitled Contract'; + + if (!displayName && !descriptionFirstLine) { return null; } return (
- +