From 52461e784f1df6f82b0b0434d1b0013c3caeca0d Mon Sep 17 00:00:00 2001 From: Edu Date: Tue, 28 Jan 2025 17:27:03 +0100 Subject: [PATCH] Fix connection screen (#899) --- .../connect/connectionRequest/dappLogo.tsx | 23 ++++++++---- .../connect/connectionRequest/host.tsx | 30 +++++++++++++--- .../connectionRequest/index.styles.tsx | 12 +++++++ .../connect/connectionRequest/index.tsx | 35 ++++++++++++++----- 4 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/app/screens/connect/connectionRequest/dappLogo.tsx b/src/app/screens/connect/connectionRequest/dappLogo.tsx index 7499a1f9..4f79d696 100644 --- a/src/app/screens/connect/connectionRequest/dappLogo.tsx +++ b/src/app/screens/connect/connectionRequest/dappLogo.tsx @@ -1,24 +1,33 @@ /* eslint-disable import/prefer-default-export */ import styled from 'styled-components'; -// eslint-disable-next-line import/prefer-default-export -const Logo = styled('img')((props) => ({ - maxHeight: 48, - maxWidth: 48, - paddingBlockStart: props.theme.space.xxl, +const ImgContainer = styled('div')({ + display: 'flex', + justifyContent: 'center', +}); + +const Img = styled('img')((props) => ({ + height: 48, + width: 48, alignSelf: 'center', + objectFit: 'contain', + borderRadius: props.theme.radius(1), })); type Props = { /** * Any source that can be used as an image source. */ - src?: string; + src?: string | null; }; export function DappLogo({ src }: Props) { if (!src) { return null; } - return ; + return ( + + Dapp Logo + + ); } diff --git a/src/app/screens/connect/connectionRequest/host.tsx b/src/app/screens/connect/connectionRequest/host.tsx index 83e0f40c..d6e4ae83 100644 --- a/src/app/screens/connect/connectionRequest/host.tsx +++ b/src/app/screens/connect/connectionRequest/host.tsx @@ -1,3 +1,6 @@ +import { permissions } from '@secretkeylabs/xverse-core'; +import { useTranslation } from 'react-i18next'; + import styled from 'styled-components'; /* eslint-disable import/prefer-default-export */ @@ -8,12 +11,29 @@ const Container = styled('div')((props) => ({ })); type Props = { - url: ConstructorParameters[0]; + origin: string; }; -export function Host({ url }: Props) { - const parsedUrl = new URL(url); - const { host } = parsedUrl; +export function Host({ origin }: Props) { + const { t } = useTranslation('translation', { keyPrefix: 'AUTH_REQUEST_SCREEN' }); - return {host}; + const { nameFromOrigin } = permissions.utils.originName; + const name = nameFromOrigin(origin); + + const dappName = (() => { + // This means there was no name found for the origin, and the host is used + // as the name instead. + if (name === origin) { + const parsedUrl = new URL(origin); + return parsedUrl.host; + } + + return name; + })(); + + return ( + + {t('REQUEST_TOOLTIP')} {dappName} + + ); } diff --git a/src/app/screens/connect/connectionRequest/index.styles.tsx b/src/app/screens/connect/connectionRequest/index.styles.tsx index acad298d..a0789ae6 100644 --- a/src/app/screens/connect/connectionRequest/index.styles.tsx +++ b/src/app/screens/connect/connectionRequest/index.styles.tsx @@ -56,3 +56,15 @@ export const RequestMessage = styled.p((props) => ({ wordWrap: 'break-word', marginTop: props.theme.space.l, })); + +export const DappInfoContainer = styled('div')((props) => ({ + display: 'flex', + flexDirection: 'column', + rowGap: props.theme.space.m, +})); + +export const DappInfoTextContainer = styled('div')((props) => ({ + display: 'flex', + flexDirection: 'column', + rowGap: props.theme.space.xxs, +})); diff --git a/src/app/screens/connect/connectionRequest/index.tsx b/src/app/screens/connect/connectionRequest/index.tsx index 2a58171e..51389685 100644 --- a/src/app/screens/connect/connectionRequest/index.tsx +++ b/src/app/screens/connect/connectionRequest/index.tsx @@ -23,11 +23,15 @@ import { AddressBoxContainer, Container, ContentContainer, + DappInfoContainer, + DappInfoTextContainer, PermissionDescriptionsContainer, RequestMessage, } from './index.styles'; import useSelectedAccount from '@hooks/useSelectedAccount'; +import { getAppIconFromWebManifest, safePromise } from '@secretkeylabs/xverse-core'; +import { useQuery } from '@tanstack/react-query'; import AddressPurposeBox from '../addressPurposeBox'; import * as Permissions from './permissions'; import { SelectAccountPrompt } from './selectAccount'; @@ -45,6 +49,17 @@ function ConnectionRequestInner({ data, context }: ConnectionRequestInnerProps) }, []); const handleAccept = useMakeHandleAccept({ context, data }); + const { data: appIconSrc } = useQuery({ + queryKey: ['appIcon', context.origin], + queryFn: async () => { + const [error, icon] = await safePromise(getAppIconFromWebManifest(context.origin)); + + if (error) return null; + + return icon; + }, + }); + const AddressPurposeRow = useCallback( (purpose: AddressPurpose) => { if (purpose === AddressPurpose.Payment) { @@ -88,14 +103,18 @@ function ConnectionRequestInner({ data, context }: ConnectionRequestInnerProps) return ( - - - <Host url={context.origin} /> - {(data as ConnectRequestMessage).params?.message && ( - <RequestMessage> - {(data as ConnectRequestMessage).params?.message?.substring(0, 80)} - </RequestMessage> - )} + <DappInfoContainer> + <DappLogo src={appIconSrc} /> + <DappInfoTextContainer> + <Title /> + <Host origin={context.origin} /> + {(data as ConnectRequestMessage).params?.message && ( + <RequestMessage> + {(data as ConnectRequestMessage).params?.message?.substring(0, 80)} + </RequestMessage> + )} + </DappInfoTextContainer> + </DappInfoContainer> <AccountSwitcherContainer> <SelectAccountPrompt /> </AccountSwitcherContainer>