diff --git a/e2e/specs/stateless/profileEditor.spec.ts b/e2e/specs/stateless/profileEditor.spec.ts index 546109be3..9e4a8b136 100644 --- a/e2e/specs/stateless/profileEditor.spec.ts +++ b/e2e/specs/stateless/profileEditor.spec.ts @@ -32,6 +32,7 @@ const DEFAULT_RECORDS = { value: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC', }, ], + contentHash: 'ipfs://bafybeico3uuyj3vphxpvbowchdwjlrlrh62awxscrnii7w7flu5z6fk77y', } test.describe('unwrapped', () => { @@ -169,6 +170,7 @@ test.describe('unwrapped', () => { 'ETC_LEGACY0x3C4...293BC', ) await expect(profilePage.record('text', 'email')).toHaveText('fakeemail@fake.com') + await expect(profilePage.contentHash()).toContainText('ipfs://bafybeic...') await profilePage.editProfileButton.click() await profilePage.profileEditor.getByTestId('warning-overlay-next-button').click() diff --git a/playwright/pageObjects/profilePage.ts b/playwright/pageObjects/profilePage.ts index 7cb240fc5..5dccd6d2e 100644 --- a/playwright/pageObjects/profilePage.ts +++ b/playwright/pageObjects/profilePage.ts @@ -63,6 +63,10 @@ export class ProfilePage { return this.page.getByTestId(`other-profile-button-${key}`) } + contentHash(): Locator { + return this.page.getByTestId('other-profile-button-contenthash') + } + async profileEditorAddInputs(keys: string[]) { await this.page.getByTestId('show-add-profile-records-modal-button').click() for (const key of keys) { diff --git a/src/components/pages/profile/ProfileButton.tsx b/src/components/pages/profile/ProfileButton.tsx index 2f19817fd..1232833bd 100644 --- a/src/components/pages/profile/ProfileButton.tsx +++ b/src/components/pages/profile/ProfileButton.tsx @@ -11,6 +11,7 @@ import { DynamicSocialIcon, socialIconTypes } from '@app/assets/social/DynamicSo import { usePrimary } from '@app/hooks/usePrimary' import { getDestination } from '@app/routes' import { useBreakpoint } from '@app/utils/BreakpointProvider' +import { getContentHashLink, getProtocolTypeAndContentId } from '@app/utils/contenthash' import { getSocialData } from '@app/utils/getSocialData' import { shortenAddress } from '@app/utils/utils' @@ -105,10 +106,11 @@ export const OtherProfileButton = ({ }: { iconKey: string value: string - type?: 'text' | 'address' + type?: 'text' | 'address' | 'contenthash' }) => { const breakpoints = useBreakpoint() - const isLink = value?.startsWith('http://') || value?.startsWith('https://') + const isLink = + value?.startsWith('http://') || value?.startsWith('https://') || type === 'contenthash' const formattedValue = useMemo(() => { if (breakpoints.sm) { @@ -122,11 +124,20 @@ export const OtherProfileButton = ({ const linkProps = useMemo(() => { if (!isLink) return {} + if (type === 'contenthash') { + const { protocolType, contentId } = getProtocolTypeAndContentId(value) + const _link = getContentHashLink('', 0, { protocolType, decoded: contentId }) + if (!_link) return {} + return { + as: 'a', + link: _link, + } as const + } return { as: 'a', link: value, } as const - }, [value, isLink]) + }, [value, type, isLink]) return ( ({ + useBreakpoint: () => ({ + xs: true, + sm: true, + md: true, + lg: true, + xl: false, + }) +})) + describe('onwershipInfoCalc', () => { it('should return no owner if PCC is expired', () => { const result = ownershipInfoCalc('', true, [], new Date(), new Date()) @@ -95,3 +108,16 @@ describe('onwershipInfoCalc', () => { ]) }) }) + +describe('ProfileDetails', () => { + it('should show content hash if there is valid contenthash', () => { + render() + expect(screen.getByTestId('other-profile-button-contenthash')).toBeVisible() + expect(screen.getByText('ipfs://QmXoypiz...')).toBeVisible() + }) + + it('should not show content hash if contenthash is empty', () => { + render() + expect(screen.queryByTestId('other-profile-button-contenthash')).toBeNull() + }) +}) \ No newline at end of file diff --git a/src/components/pages/profile/ProfileDetails.tsx b/src/components/pages/profile/ProfileDetails.tsx index 542c043ce..a248f7d7d 100644 --- a/src/components/pages/profile/ProfileDetails.tsx +++ b/src/components/pages/profile/ProfileDetails.tsx @@ -10,7 +10,9 @@ import supportedProfileItems from '@app/constants/supportedGeneralRecordKeys.jso import supportedTexts from '@app/constants/supportedSocialRecordKeys.json' import useOwners from '@app/hooks/useOwners' import { useProfileActions } from '@app/hooks/useProfileActions' +import { ContentHash } from '@app/types' import { useBreakpoint } from '@app/utils/BreakpointProvider' +import { contentHashToString } from '@app/utils/contenthash' import { checkETH2LDFromName, formatExpiry } from '@app/utils/utils' import { @@ -282,6 +284,7 @@ export const ownershipInfoCalc = ( export const ProfileDetails = ({ textRecords = [], addresses = [], + contentHash, expiryDate, pccExpired, owners, @@ -292,6 +295,7 @@ export const ProfileDetails = ({ }: { textRecords: Array> addresses: Array> + contentHash?: ContentHash expiryDate: Date | undefined pccExpired: boolean owners: ReturnType @@ -302,6 +306,7 @@ export const ProfileDetails = ({ }) => { const breakpoint = useBreakpoint() + const _contentHash = contentHashToString(contentHash) const otherRecords = [ ...textRecords .filter( @@ -310,6 +315,7 @@ export const ProfileDetails = ({ !supportedProfileItems.includes(x.key.toLowerCase()), ) .map((x) => ({ ...x, type: 'text' })), + ...(_contentHash ? [{ key: 'contenthash', type: 'contenthash', value: _contentHash }] : []), ] const mappedOwners = ownershipInfoCalc(name, pccExpired, owners, gracePeriodEndDate, expiryDate) diff --git a/src/components/pages/profile/[name]/tabs/ProfileTab.tsx b/src/components/pages/profile/[name]/tabs/ProfileTab.tsx index 8b9d5f0c1..c21ab6e80 100644 --- a/src/components/pages/profile/[name]/tabs/ProfileTab.tsx +++ b/src/components/pages/profile/[name]/tabs/ProfileTab.tsx @@ -127,6 +127,7 @@ const ProfileTab = ({ nameDetails, name }: Props) => { textRecords={(profile?.records?.texts || []) .map((item: any) => ({ key: item.key, value: item.value })) .filter((item: any) => item.value !== null)} + contentHash={profile?.records?.contentHash} owners={owners} name={normalisedName} actions={profileActions.profileActions}