Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(recipient): add new recipient picker #4433

Merged
merged 6 commits into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions branding/celo/src/icons/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react'
import { View, ViewStyle } from 'react-native'
import colors from 'src/styles/colors'
import Svg, { Path } from 'svgs'

Expand All @@ -12,10 +13,11 @@ export enum LogoTypes {
interface Props {
height?: number
type?: LogoTypes
style?: ViewStyle
testID?: string
}

export default function Logo({ height = 25, type = LogoTypes.COLOR, testID }: Props) {
export default function Logo({ height = 25, type = LogoTypes.COLOR, testID, style }: Props) {
let mainColor
switch (type) {
case LogoTypes.DARK:
Expand All @@ -29,19 +31,21 @@ export default function Logo({ height = 25, type = LogoTypes.COLOR, testID }: Pr
}

return (
<Svg testID={testID} width={height} height={height} viewBox="0 0 25 25" fill="none">
<Path
d="M9.86842 22.3684C13.8653 22.3684 17.1053 19.1284 17.1053 15.1316C17.1053 11.1348 13.8653 7.89476 9.86842 7.89476C5.87158 7.89476 2.63158 11.1348 2.63158 15.1316C2.63158 19.1284 5.87158 22.3684 9.86842 22.3684ZM9.86842 25C4.41842 25 0 20.5816 0 15.1316C0 9.6816 4.41842 5.26318 9.86842 5.26318C15.3184 5.26318 19.7368 9.6816 19.7368 15.1316C19.7368 20.5816 15.3184 25 9.86842 25Z"
fill={type === LogoTypes.COLOR ? colors.goldBrand : mainColor}
/>
<Path
d="M15.1316 17.1053C19.1284 17.1053 22.3684 13.8653 22.3684 9.86842C22.3684 5.87158 19.1284 2.63158 15.1316 2.63158C11.1348 2.63158 7.89476 5.87158 7.89476 9.86842C7.89476 13.8653 11.1348 17.1053 15.1316 17.1053ZM15.1316 19.7368C9.6816 19.7368 5.26318 15.3184 5.26318 9.86842C5.26318 4.41842 9.6816 0 15.1316 0C20.5816 0 25 4.41842 25 9.86842C25 15.3184 20.5816 19.7368 15.1316 19.7368Z"
fill={type === LogoTypes.COLOR ? colors.greenBrand : mainColor}
/>
<Path
d="M15.4577 19.7369C16.1419 18.9077 16.6324 17.9361 16.8932 16.8932C17.9361 16.6324 18.9077 16.1421 19.7369 15.4579C19.699 16.6658 19.439 17.8563 18.9695 18.9698C17.8561 19.439 16.6656 19.6992 15.4577 19.7369ZM8.10687 8.10687C7.06397 8.36766 6.09239 8.85792 5.26318 9.54213C5.30108 8.33424 5.56108 7.14371 6.03055 6.03029C7.14397 5.56108 8.3345 5.30082 9.54239 5.26318C8.85818 6.09239 8.36766 7.06397 8.10687 8.10687Z"
fill={type === LogoTypes.COLOR ? '#5EA33B' : mainColor}
/>
</Svg>
<View testID={testID} style={style}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style prop was supported on the Valora branding Logo
https://github.com/valora-inc/valora-app-branding/blob/48a6e3363ad7c9befbf0567f3dc370a427fce87b/src/icons/Logo.tsx#L38

CI uses celo branding, this update matches the valora logo implementation (even though its not strictly required, because the final app build doesn't use this)

<Svg width={height} height={height} viewBox="0 0 25 25" fill="none">
<Path
d="M9.86842 22.3684C13.8653 22.3684 17.1053 19.1284 17.1053 15.1316C17.1053 11.1348 13.8653 7.89476 9.86842 7.89476C5.87158 7.89476 2.63158 11.1348 2.63158 15.1316C2.63158 19.1284 5.87158 22.3684 9.86842 22.3684ZM9.86842 25C4.41842 25 0 20.5816 0 15.1316C0 9.6816 4.41842 5.26318 9.86842 5.26318C15.3184 5.26318 19.7368 9.6816 19.7368 15.1316C19.7368 20.5816 15.3184 25 9.86842 25Z"
fill={type === LogoTypes.COLOR ? colors.goldBrand : mainColor}
/>
<Path
d="M15.1316 17.1053C19.1284 17.1053 22.3684 13.8653 22.3684 9.86842C22.3684 5.87158 19.1284 2.63158 15.1316 2.63158C11.1348 2.63158 7.89476 5.87158 7.89476 9.86842C7.89476 13.8653 11.1348 17.1053 15.1316 17.1053ZM15.1316 19.7368C9.6816 19.7368 5.26318 15.3184 5.26318 9.86842C5.26318 4.41842 9.6816 0 15.1316 0C20.5816 0 25 4.41842 25 9.86842C25 15.3184 20.5816 19.7368 15.1316 19.7368Z"
fill={type === LogoTypes.COLOR ? colors.greenBrand : mainColor}
/>
<Path
d="M15.4577 19.7369C16.1419 18.9077 16.6324 17.9361 16.8932 16.8932C17.9361 16.6324 18.9077 16.1421 19.7369 15.4579C19.699 16.6658 19.439 17.8563 18.9695 18.9698C17.8561 19.439 16.6656 19.6992 15.4577 19.7369ZM8.10687 8.10687C7.06397 8.36766 6.09239 8.85792 5.26318 9.54213C5.30108 8.33424 5.56108 7.14371 6.03055 6.03029C7.14397 5.56108 8.3345 5.30082 9.54239 5.26318C8.85818 6.09239 8.36766 7.06397 8.10687 8.10687Z"
fill={type === LogoTypes.COLOR ? '#5EA33B' : mainColor}
/>
</Svg>
</View>
)
}
1 change: 1 addition & 0 deletions src/account/__snapshots__/Profile.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ exports[`Profile renders correctly 1`] = `
"height": 64,
"width": 64,
},
undefined,
]
}
>
Expand Down
26 changes: 21 additions & 5 deletions src/components/ContactCircle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import * as React from 'react'
import { Image, StyleSheet, Text, View, ViewStyle } from 'react-native'
import DefaultAvatar from 'src/icons/DefaultAvatar'
import { Recipient } from 'src/recipients/recipient'
import Colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'

interface Props {
style?: ViewStyle
size?: number
recipient: Recipient
backgroundColor?: Colors
foregroundColor?: Colors
borderColor?: Colors
DefaultIcon?: React.ComponentType<{ foregroundColor: string; backgroundColor: string }>
}

const DEFAULT_ICON_SIZE = 40
Expand All @@ -18,10 +23,17 @@ const getAddressForegroundColor = (address: string) =>
`hsl(${parseInt(address.substring(0, 5), 16) % 360}, 67%, 24%)`
const getNameInitial = (name: string) => name.charAt(0).toLocaleUpperCase()

function ContactCircle({ size, recipient, style }: Props) {
function ContactCircle({
size: iconSize = DEFAULT_ICON_SIZE,
recipient,
style,
backgroundColor,
foregroundColor,
borderColor,
DefaultIcon = DefaultAvatar,
}: Props) {
const address = recipient.address
const iconSize = size || DEFAULT_ICON_SIZE
const iconBackgroundColor = getAddressBackgroundColor(address || '0x0')
const iconBackgroundColor = backgroundColor ?? getAddressBackgroundColor(address || '0x0')

const renderThumbnail = () => {
if (recipient.thumbnailPath) {
Expand All @@ -37,7 +49,7 @@ function ContactCircle({ size, recipient, style }: Props) {
)
}

const fontColor = getAddressForegroundColor(address || '0x0')
const fontColor = foregroundColor ?? getAddressForegroundColor(address || '0x0')
if (recipient.name) {
const initial = getNameInitial(recipient.name)
return (
Expand All @@ -50,7 +62,7 @@ function ContactCircle({ size, recipient, style }: Props) {
)
}

return <DefaultAvatar foregroundColor={fontColor} backgroundColor={iconBackgroundColor} />
return <DefaultIcon foregroundColor={fontColor} backgroundColor={iconBackgroundColor} />
}

return (
Expand All @@ -64,6 +76,10 @@ function ContactCircle({ size, recipient, style }: Props) {
width: iconSize,
borderRadius: iconSize / 2,
},
borderColor && {
borderColor,
borderWidth: 1,
},
]}
>
{renderThumbnail()}
Expand Down
4 changes: 4 additions & 0 deletions src/components/__snapshots__/Avatar.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ exports[`Avatar renders correctly with address and name but no number 1`] = `
"height": 40,
"width": 40,
},
undefined,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The undefined snapshot updates are because the borderColor style on the ContactCirle component

]
}
>
Expand Down Expand Up @@ -140,6 +141,7 @@ exports[`Avatar renders correctly with address but no name nor number 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down Expand Up @@ -222,6 +224,7 @@ exports[`Avatar renders correctly with just number 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down Expand Up @@ -343,6 +346,7 @@ exports[`Avatar renders correctly with number and name 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down
1 change: 1 addition & 0 deletions src/components/__snapshots__/ContactCircle.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ exports[`ContactCircle when given recipient with only address uses DefaultAvatar
"height": 30,
"width": 30,
},
undefined,
]
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ exports[`EscrowedPaymentReminderNotification renders correctly 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ exports[`EscrowedPaymentListScreen renders correctly with payments 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down Expand Up @@ -464,6 +465,7 @@ exports[`EscrowedPaymentListScreen renders correctly with payments 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down Expand Up @@ -742,6 +744,7 @@ exports[`EscrowedPaymentListScreen renders correctly with payments 1`] = `
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ exports[`EscrowedPaymentReminderSummaryNotification when more 1 requests renders
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ exports[`ReclaimPaymentConfirmationCard renders correctly for send payment confi
"height": 40,
"width": 40,
},
undefined,
]
}
>
Expand Down
39 changes: 11 additions & 28 deletions src/icons/QuestionIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
import * as React from 'react'
import colors from 'src/styles/colors'
import Svg, { Circle, Path } from 'svgs'
import Svg, { Path } from 'svgs'

interface Props {
size?: number
color?: string
color?: colors
}
const QuestionIcon = ({ color = colors.dark }: Props) => (
<Svg width={9} height={15} viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<Path
d="M3.64648 10.2351V10.1136C3.65501 9.32102 3.73384 8.69034 3.88299 8.22159C4.0364 7.75284 4.25373 7.37358 4.53498 7.08381C4.81623 6.79403 5.15501 6.52983 5.55131 6.29119C5.807 6.12926 6.03711 5.94815 6.24166 5.74787C6.4462 5.54758 6.60813 5.31747 6.72745 5.05753C6.84677 4.79758 6.90643 4.50994 6.90643 4.1946C6.90643 3.81534 6.81694 3.48722 6.63796 3.21023C6.45898 2.93324 6.22035 2.72017 5.92205 2.57102C5.62802 2.41761 5.29989 2.34091 4.93768 2.34091C4.60955 2.34091 4.29634 2.40909 3.99805 2.54545C3.69975 2.68182 3.45259 2.89489 3.25657 3.18466C3.06055 3.47017 2.94762 3.83878 2.91779 4.29048H0.974609C1.00444 3.52344 1.19833 2.87571 1.55629 2.3473C1.91424 1.81463 2.38725 1.41193 2.97532 1.1392C3.56765 0.866477 4.22177 0.730113 4.93768 0.730113C5.72177 0.730113 6.40785 0.87713 6.99592 1.17116C7.58398 1.46094 8.03995 1.8679 8.36381 2.39205C8.69194 2.91193 8.856 3.51918 8.856 4.21378C8.856 4.69105 8.78143 5.12145 8.63228 5.50497C8.48313 5.88423 8.27006 6.22301 7.99308 6.52131C7.72035 6.8196 7.39222 7.08381 7.0087 7.31392C6.64648 7.53977 6.35245 7.77415 6.1266 8.01705C5.90501 8.25994 5.74308 8.54758 5.6408 8.87997C5.53853 9.21236 5.48313 9.62358 5.47461 10.1136V10.2351H3.64648ZM4.61168 14.1214C4.26225 14.1214 3.96183 13.9979 3.7104 13.7507C3.45898 13.4993 3.33327 13.1967 3.33327 12.843C3.33327 12.4936 3.45898 12.1953 3.7104 11.9482C3.96183 11.6967 4.26225 11.571 4.61168 11.571C4.95685 11.571 5.25515 11.6967 5.50657 11.9482C5.76225 12.1953 5.89009 12.4936 5.89009 12.843C5.89009 13.0774 5.83043 13.2926 5.71112 13.4886C5.59606 13.6804 5.44265 13.8338 5.25089 13.9489C5.05913 14.0639 4.84606 14.1214 4.61168 14.1214Z"
fill={color}
/>
</Svg>
)

export default class QuestionIcon extends React.PureComponent<Props> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This icon was no longer used (was also flagged by knip). Replaced with the new QuestionIcon

static defaultProps = {
size: 32,
color: colors.gray5,
}

render() {
return (
<Svg
testID="QuestionIcon"
width={this.props.size}
height={this.props.size}
viewBox="0 0 32 32"
fill="none"
>
<Circle cx="16" cy="16" r="11" stroke={this.props.color} strokeWidth="2" />
<Path
d="M15.7528 19.5455C15.3071 19.5455 14.936 19.1843 14.917 18.739C14.8965 18.2574 14.8941 17.777 15.0399 17.3239C15.2103 16.7943 15.4524 16.3654 15.7662 16.0373C16.0801 15.7093 16.4567 15.4069 16.8961 15.1304C17.2907 14.882 17.6224 14.5563 17.8915 14.1532C18.1605 13.7501 18.295 13.2697 18.295 12.712C18.295 12.2527 18.1919 11.8543 17.9856 11.5168C17.7794 11.1794 17.5036 10.9193 17.1584 10.7365C16.8132 10.5537 16.4298 10.4623 16.0083 10.4623C15.6407 10.4623 15.2865 10.542 14.9457 10.7013C14.605 10.8607 14.3203 11.1114 14.0916 11.4536C13.9836 11.6152 13.897 11.8004 13.832 12.0092C13.6981 12.4393 13.3444 12.7964 12.8939 12.7964C12.4068 12.7964 12.0076 12.386 12.1168 11.9113C12.2156 11.482 12.3739 11.0951 12.5918 10.7505C12.955 10.1834 13.4325 9.7499 14.0244 9.44994C14.6207 9.14998 15.282 9 16.0083 9C16.7975 9 17.4835 9.16404 18.0663 9.49212C18.6537 9.8202 19.1065 10.2701 19.4249 10.8419C19.7477 11.4137 19.9091 12.0652 19.9091 12.7964C19.9091 13.5744 19.7432 14.2399 19.4114 14.793C19.0796 15.346 18.6178 15.81 18.026 16.185C17.6314 16.4427 17.3153 16.7146 17.0777 17.0005C16.8401 17.2817 16.6674 17.6168 16.5598 18.0058C16.4936 18.2451 16.4912 18.4916 16.5065 18.7404C16.5338 19.1853 16.1985 19.5455 15.7528 19.5455Z"
fill={this.props.color}
/>
<Circle cx="15.7347" cy="22.0985" r="1.09848" fill={this.props.color} />
</Svg>
)
}
}
export default QuestionIcon
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ exports[`PictureInputScreen renders correctly 1`] = `
"height": 64,
"width": 64,
},
undefined,
]
}
>
Expand Down
2 changes: 2 additions & 0 deletions src/qrcode/__snapshots__/QRCode.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ exports[`QRCode renders correctly 1`] = `
"height": 64,
"width": 64,
},
undefined,
]
}
>
Expand Down Expand Up @@ -219,6 +220,7 @@ exports[`QRCode renders correctly 2`] = `
"height": 64,
"width": 64,
},
undefined,
]
}
>
Expand Down
3 changes: 3 additions & 0 deletions src/recipients/RecipientItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ interface Props {
loading: boolean
}

/**
* @deprecated new recipient screen should use RecipientItemV2
*/
function RecipientItem({ recipient, onSelectRecipient, loading }: Props) {
const { t } = useTranslation()

Expand Down
60 changes: 60 additions & 0 deletions src/recipients/RecipientItemV2.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { fireEvent, render } from '@testing-library/react-native'
import * as React from 'react'
import 'react-native'
import RecipientItem from 'src/recipients/RecipientItemV2'
import { mockRecipient } from 'test/values'

describe('RecipientItemV2', () => {
it('renders correctly with no icon or loading state', () => {
const { queryByTestId, getByText } = render(
<RecipientItem recipient={mockRecipient} onSelectRecipient={jest.fn()} loading={false} />
)
expect(getByText(mockRecipient.name)).toBeTruthy()
expect(getByText(mockRecipient.displayNumber)).toBeTruthy()
expect(queryByTestId('RecipientItem/ValoraIcon')).toBeFalsy()
expect(queryByTestId('RecipientItem/ActivityIndicator')).toBeFalsy()
})

it('renders correctly with icon and no loading state', () => {
const { queryByTestId, getByText, getByTestId } = render(
<RecipientItem
recipient={mockRecipient}
onSelectRecipient={jest.fn()}
loading={false}
showValoraIcon={true}
/>
)
expect(getByText(mockRecipient.name)).toBeTruthy()
expect(getByText(mockRecipient.displayNumber)).toBeTruthy()
expect(getByTestId('RecipientItem/ValoraIcon')).toBeTruthy()
expect(queryByTestId('RecipientItem/ActivityIndicator')).toBeFalsy()
})

it('renders correctly with no icon and loading state', () => {
const { queryByTestId, getByText, getByTestId } = render(
<RecipientItem
recipient={mockRecipient}
onSelectRecipient={jest.fn()}
loading={true}
showValoraIcon={false}
/>
)
expect(getByText(mockRecipient.name)).toBeTruthy()
expect(getByText(mockRecipient.displayNumber)).toBeTruthy()
expect(getByTestId('RecipientItem/ActivityIndicator')).toBeTruthy()
expect(queryByTestId('RecipientItem/ValoraIcon')).toBeFalsy()
})

it('tapping item invokes onSelectRecipient', () => {
const mockSelectRecipient = jest.fn()
const { getByTestId } = render(
<RecipientItem
recipient={mockRecipient}
onSelectRecipient={mockSelectRecipient}
loading={false}
/>
)
fireEvent.press(getByTestId('RecipientItem'))
expect(mockSelectRecipient).toHaveBeenLastCalledWith(mockRecipient)
})
})
Loading