Skip to content

Commit

Permalink
Merge pull request #3 from lukso-network/feature/display-up-names
Browse files Browse the repository at this point in the history
Feature: display up names
  • Loading branch information
Wolmin authored Nov 3, 2023
2 parents b61bb60 + 46ef717 commit e3802d3
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 79 deletions.
13 changes: 13 additions & 0 deletions types/api/universalProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export type UPResponse = {
type: string;
hasProfileName: boolean;
hasProfileImage: boolean;
LSP3Profile: {
name: string;
profileImage: {
[key: number]: {
url: string;
};
};
};
}
48 changes: 20 additions & 28 deletions ui/shared/entities/address/AddressEntity.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { As } from '@chakra-ui/react';
import { Box, Flex, Skeleton, Tooltip, chakra, VStack } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import _omit from 'lodash/omit';
import React, { useEffect, useState } from 'react';

Expand All @@ -14,7 +15,7 @@ import * as EntityBase from 'ui/shared/entities/base/components';

import { getIconProps } from '../base/utils';
import AddressIdenticon from './AddressIdenticon';
import makeUniversalProfileIdenticon from './IdenticonUniversalProfile';
import { getUniversalProfile, IdenticonUniversalProfile } from './IdenticonUniversalProfileQuery';
if (process.browser) {
import('@lukso/web-components/dist/components/lukso-profile');
}
Expand All @@ -39,17 +40,6 @@ type IconProps = Pick<EntityProps, 'address' | 'isLoading' | 'iconSize' | 'noIco
};

const Icon = (props: IconProps) => {
const [ upUrl, setUpUrl ] = useState('');
useEffect(() => {
(async() => {
const result = await makeUniversalProfileIdenticon(props.address.hash);

setUpUrl(result);

return;
})();
});

if (props.noIcon) {
return null;
}
Expand Down Expand Up @@ -88,21 +78,7 @@ const Icon = (props: IconProps) => {
);
}

if (upUrl !== '' && process.browser) {
console.log(`Generating profile for url ${ upUrl } and ${ props.address.hash }`);
return (
<Box mr={ 2 } ml={ 1 }>
<lukso-profile
size="x-small"
profile-url={ upUrl }
profile-address={ props.address.hash }
has-identicon={ true }
></lukso-profile>
</Box>
);
}

return (
const contractIcon = (
<Tooltip label="Contract">
<span>
<EntityBase.Icon
Expand All @@ -113,6 +89,8 @@ const Icon = (props: IconProps) => {
</span>
</Tooltip>
);

return <IdenticonUniversalProfile address={ props.address.hash } fallbackIcon={ contractIcon }/>;
}

return (
Expand All @@ -130,6 +108,8 @@ const Icon = (props: IconProps) => {
type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps, 'address'>;

const Content = chakra((props: ContentProps) => {
const queryClient = useQueryClient();
const [ upName, setUpName ] = useState('');
if (props.address.name) {
const label = (
<VStack gap={ 0 } py={ 1 } color="inherit">
Expand All @@ -146,11 +126,23 @@ const Content = chakra((props: ContentProps) => {
</Tooltip>
);
}
useEffect(() => { // this causes a sort of loading state where the address suddenly switches to up name - needs fix?
(async() => {
const upData = await getUniversalProfile(props.address.hash, queryClient);
if (upData === undefined) {
return;
}
if (upData.LSP3Profile !== undefined) {
setUpName(upData.LSP3Profile.name);
}
})();
}, [ props.address.hash, queryClient ]);

const displayedName = upName !== '' ? `@${ upName } (${ props.address.hash })` : props.address.hash;
return (
<EntityBase.Content
{ ...props }
text={ props.address.hash }
text={ displayedName }
/>
);
});
Expand Down
45 changes: 0 additions & 45 deletions ui/shared/entities/address/IdenticonUniversalProfile.tsx

This file was deleted.

76 changes: 76 additions & 0 deletions ui/shared/entities/address/IdenticonUniversalProfileQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Box } from '@chakra-ui/react';
import type { QueryClient } from '@tanstack/react-query';
import { useQueryClient } from '@tanstack/react-query';
import React, { useEffect, useState } from 'react';

import type { UPResponse } from '../../../../types/api/universalProfile';

import config from '../../../../configs/app';
import { getEnvValue } from '../../../../configs/app/utils';

interface Props {
address: string;
fallbackIcon: JSX.Element;
}

export const getUniversalProfile = async(address: string, queryClient: QueryClient) => {
if (config.UI.views.address.identiconType !== 'universal_profile') {
return undefined;
}
const query = queryClient.getQueryData<UPResponse>([ 'universalProfile', { address: address } ]);
if (query !== undefined) {
return query;
}

return await queryClient.fetchQuery({
queryKey: [ 'universalProfile', { address: address } ],
queryFn: async() => {
const upApiUrl = getEnvValue('NEXT_PUBLIC_UP_API_URL') || '';
const networkId = getEnvValue('NEXT_PUBLIC_NETWORK_ID') || '42';

const url = `${ upApiUrl }/v1/${ networkId }/address/${ address }`;
try {
const resp = await fetch(url);
const json = await resp.json();
return json as UPResponse;
} catch (err) {
return undefined;
}
},
});
};

export const IdenticonUniversalProfile: React.FC<Props> = ({ address, fallbackIcon }) => {
const [ up, setUp ] = useState({} as UPResponse);
const queryClient = useQueryClient();
useEffect(() => {
(async() => {
const upData = await getUniversalProfile(address, queryClient);
if (upData !== undefined) {
setUp(upData);

return;
}
})();
}, [ address, up, setUp, queryClient ]);

if (up === undefined || up.LSP3Profile === undefined) {
return fallbackIcon;
}

const lastImageIndex = Object.values(up.LSP3Profile.profileImage).length - 1;

const profileImageUrl = up.hasProfileImage ? up.LSP3Profile.profileImage[lastImageIndex].url : '';
return (
<Box mr={ 2 }>
<lukso-profile
size="x-small"
profile-url={ profileImageUrl }
profile-address={ address }
has-identicon={ true }
></lukso-profile>
</Box>
);
};

export default IdenticonUniversalProfile;
6 changes: 3 additions & 3 deletions ui/shared/entities/address/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ declare global {
}

interface Window {
ethereum?: any;
lukso?: any;
grecaptcha?: any;
ethereum?: never;
lukso?: never;
grecaptcha?: never;
}
}
1 change: 0 additions & 1 deletion ui/shared/entities/base/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ const Link = chakra(({ isLoading, children, isExternal, onClick, href, noLink }:
const Component = isExternal ? LinkExternal : LinkInternal;

return (
// @ts-ignore
<Component

Check failure on line 67 in ui/shared/entities/base/components.tsx

View workflow job for this annotation

GitHub Actions / Code quality

Expression produces a union type that is too complex to represent.
{ ...styles }
href={ href }
Expand Down
21 changes: 19 additions & 2 deletions ui/snippets/searchBar/SearchBarSuggest/SearchBarSuggestAddress.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,40 @@
import { Box, Text, Flex } from '@chakra-ui/react';
import React from 'react';
import { useQueryClient } from '@tanstack/react-query';
import React, { useEffect, useState } from 'react';

import type { SearchResultAddressOrContract } from 'types/api/search';

import highlightText from 'lib/highlightText';
import * as AddressEntity from 'ui/shared/entities/address/AddressEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';

import { getUniversalProfile } from '../../../shared/entities/address/IdenticonUniversalProfileQuery';

interface Props {
data: SearchResultAddressOrContract;
isMobile: boolean | undefined;
searchTerm: string;
}

const SearchBarSuggestAddress = ({ data, isMobile, searchTerm }: Props) => {
const queryClient = useQueryClient();
const [ type, setType ] = useState(data.type);
useEffect(() => { // this causes a sort of loading state where the address suddenly switches to up name - needs fix?
(async() => {
const upData = await getUniversalProfile(data.address, queryClient);
if (upData === undefined) {
return;
}
if (upData.LSP3Profile !== undefined) {
setType('contract'); // when the type is contract the icon will know that it needs to get UP profile picture
}
})();
}, [ data, queryClient, setType ]);

const shouldHighlightHash = data.address.toLowerCase() === searchTerm.toLowerCase();
const icon = (
<AddressEntity.Icon
address={{ hash: data.address, is_contract: data.type === 'contract', name: '', is_verified: data.is_smart_contract_verified, implementation_name: null }}
address={{ hash: data.address, is_contract: type === 'contract', name: '', is_verified: data.is_smart_contract_verified, implementation_name: null }}
/>
);
const name = data.name && (
Expand Down

0 comments on commit e3802d3

Please sign in to comment.