1
1
import React , { useMemo } from 'react'
2
2
import { useTranslation } from 'react-i18next'
3
- import {
4
- ImageBackground ,
5
- ImageSourcePropType ,
6
- StyleProp ,
7
- StyleSheet ,
8
- ViewStyle ,
9
- VirtualizedList ,
10
- } from 'react-native'
11
3
import { useAppDispatch } from 'src/app/hooks'
12
4
import Trace from 'src/components/Trace/Trace'
13
5
import { openModal } from 'src/features/modals/modalSlice'
14
- import { Flex , Text , TouchableArea , useIsDarkMode } from 'ui/src'
15
- import { CRYPTO_PURCHASE_BACKGROUND_DARK , CRYPTO_PURCHASE_BACKGROUND_LIGHT } from 'ui/src/assets'
16
- import { ArrowDownCircle , Buy as BuyIcon , PaperStack } from 'ui/src/components/icons'
17
- import { borderRadii } from 'ui/src/theme'
6
+ import { Flex , Icons , Text , TouchableArea } from 'ui/src'
7
+ import PaperStackIcon from 'ui/src/assets/icons/paper-stack.svg'
8
+ import { iconSizes , colors as rawColors } from 'ui/src/theme'
18
9
import { FeatureFlags } from 'uniswap/src/features/gating/flags'
19
10
import { useFeatureFlag } from 'uniswap/src/features/gating/hooks'
20
11
import { ScannerModalState } from 'wallet/src/components/QRCodeScanner/constants'
21
- import { useCexTransferProviders } from 'wallet/src/features/fiatOnRamp/api'
22
- import { ImageUri } from 'wallet/src/features/images/ImageUri'
23
12
import { AccountType } from 'wallet/src/features/wallet/accounts/types'
24
13
import { useActiveAccount } from 'wallet/src/features/wallet/hooks'
25
14
import { ElementName , ElementNameType , ModalName } from 'wallet/src/telemetry/constants'
15
+ import { opacify } from 'wallet/src/utils/colors'
26
16
27
17
interface ActionCardItem {
28
18
title : string
29
19
blurb : string
30
20
icon : JSX . Element
31
- backgroundImage ?: ImageSourcePropType
32
21
onPress : ( ) => void
33
22
elementName : ElementNameType
34
23
badgeText ?: string
@@ -40,30 +29,31 @@ enum ActionOption {
40
29
Receive = 'Receive' ,
41
30
}
42
31
43
- const ICON_SIZE = 28
44
- const ICON_SHIFT = - 10
45
-
46
32
export function WalletEmptyState ( ) : JSX . Element {
47
33
const { t } = useTranslation ( )
48
34
const dispatch = useAppDispatch ( )
49
- const isDarkMode = useIsDarkMode ( )
50
35
51
36
const activeAccount = useActiveAccount ( )
52
37
const isViewOnly = activeAccount ?. type === AccountType . Readonly
53
38
const forAggregatorEnabled = useFeatureFlag ( FeatureFlags . ForAggregator )
54
- const cexTransferEnabled = useFeatureFlag ( FeatureFlags . CexTransfers )
55
- const cexTransferProviders = useCexTransferProviders ( cexTransferEnabled )
56
39
57
40
const options : { [ key in ActionOption ] : ActionCardItem } = useMemo (
58
41
( ) => ( {
59
42
[ ActionOption . Buy ] : {
60
43
title : t ( 'home.tokens.empty.action.buy.title' ) ,
61
44
blurb : t ( 'home.tokens.empty.action.buy.description' ) ,
62
45
elementName : ElementName . EmptyStateBuy ,
63
- icon : < BuyIcon color = "$accent1" size = "$icon.28" /> ,
64
- backgroundImage : isDarkMode
65
- ? CRYPTO_PURCHASE_BACKGROUND_DARK
66
- : CRYPTO_PURCHASE_BACKGROUND_LIGHT ,
46
+ icon : (
47
+ < IconContainer
48
+ backgroundColor = { rawColors . green200 }
49
+ icon = {
50
+ < IconContainer
51
+ backgroundColor = { rawColors . green200 }
52
+ icon = { < Icons . Buy color = { rawColors . green200 } size = "$icon.20" /> }
53
+ />
54
+ }
55
+ />
56
+ ) ,
67
57
onPress : ( ) =>
68
58
dispatch (
69
59
openModal ( {
@@ -75,38 +65,45 @@ export function WalletEmptyState(): JSX.Element {
75
65
title : t ( 'home.tokens.empty.action.receive.title' ) ,
76
66
blurb : t ( 'home.tokens.empty.action.receive.description' ) ,
77
67
elementName : ElementName . EmptyStateReceive ,
78
- icon :
79
- cexTransferProviders . length > 0 ? (
80
- < OverlappingLogos
81
- logos = { cexTransferProviders . map ( ( provider ) => provider . logos . lightLogo ) }
82
- />
83
- ) : (
84
- < ArrowDownCircle color = "$accent1" size = "$icon.28" />
85
- ) ,
68
+ icon : (
69
+ < IconContainer
70
+ backgroundColor = { rawColors . gold300 }
71
+ icon = {
72
+ < IconContainer
73
+ backgroundColor = { rawColors . gold300 }
74
+ icon = { < Icons . ArrowDownCircleFilled color = { rawColors . gold300 } size = "$icon.20" /> }
75
+ />
76
+ }
77
+ />
78
+ ) ,
86
79
onPress : ( ) =>
87
80
dispatch (
88
- openModal (
89
- cexTransferProviders . length > 0
90
- ? {
91
- name : ModalName . ReceiveCryptoModal ,
92
- initialState : cexTransferProviders ,
93
- }
94
- : {
95
- name : ModalName . WalletConnectScan ,
96
- initialState : ScannerModalState . WalletQr ,
97
- }
98
- )
81
+ openModal ( {
82
+ name : ModalName . WalletConnectScan ,
83
+ initialState : ScannerModalState . WalletQr ,
84
+ } )
99
85
) ,
100
86
} ,
101
87
[ ActionOption . Import ] : {
102
88
title : t ( 'home.tokens.empty.action.import.title' ) ,
103
89
blurb : t ( 'home.tokens.empty.action.import.description' ) ,
104
90
elementName : ElementName . EmptyStateImport ,
105
- icon : < PaperStack color = "$accent1" size = "$icon.28" /> ,
91
+ icon : (
92
+ < IconContainer
93
+ backgroundColor = { rawColors . violet400 }
94
+ icon = {
95
+ < PaperStackIcon
96
+ color = { rawColors . violet400 }
97
+ height = { iconSizes . icon20 }
98
+ width = { iconSizes . icon20 }
99
+ />
100
+ }
101
+ />
102
+ ) ,
106
103
onPress : ( ) => dispatch ( openModal ( { name : ModalName . AccountSwitcher } ) ) ,
107
104
} ,
108
105
} ) ,
109
- [ t , isDarkMode , cexTransferProviders , dispatch , forAggregatorEnabled ]
106
+ [ dispatch , forAggregatorEnabled , t ]
110
107
)
111
108
112
109
// Order options based on view only status
@@ -121,167 +118,37 @@ export function WalletEmptyState(): JSX.Element {
121
118
)
122
119
}
123
120
124
- const ActionCard = ( {
125
- title,
126
- blurb,
127
- onPress,
128
- icon,
129
- elementName,
130
- backgroundImage,
131
- } : ActionCardItem ) : JSX . Element => (
121
+ const ActionCard = ( { title, blurb, onPress, icon, elementName } : ActionCardItem ) : JSX . Element => (
132
122
< Trace logPress element = { elementName } >
133
- < TouchableArea
134
- backgroundColor = { backgroundImage ? undefined : '$surface1' }
135
- borderColor = "$surface3"
136
- borderRadius = "$rounded24"
137
- borderWidth = { 1 }
138
- onPress = { onPress } >
139
- < BackgroundWrapper backgroundImage = { backgroundImage } >
140
- < Flex centered shrink alignContent = "center" gap = "$spacing4" px = "$spacing20" py = "$spacing12" >
141
- { icon }
142
- < Flex centered shrink alignContent = "center" >
143
- < Text textAlign = "center" variant = "buttonLabel3" >
144
- { title }
145
- </ Text >
146
- < Text color = "$neutral2" textAlign = "center" variant = "body3" >
147
- { blurb }
148
- </ Text >
123
+ < TouchableArea backgroundColor = "$surface2" borderRadius = "$rounded20" onPress = { onPress } >
124
+ < Flex centered row gap = "$spacing16" p = "$spacing16" >
125
+ { icon }
126
+ < Flex shrink gap = "$spacing4" width = "100%" >
127
+ < Flex row alignItems = "center" gap = "$spacing8" >
128
+ < Text variant = "subheading2" > { title } </ Text >
149
129
</ Flex >
130
+ < Text color = "$neutral2" variant = "body2" >
131
+ { blurb }
132
+ </ Text >
150
133
</ Flex >
151
- </ BackgroundWrapper >
134
+ </ Flex >
152
135
</ TouchableArea >
153
136
</ Trace >
154
137
)
155
138
156
- const BackgroundWrapper = ( {
157
- children,
158
- backgroundImage,
159
- } : {
160
- children : React . ReactNode
161
- backgroundImage ?: ImageSourcePropType
162
- } ) : JSX . Element => {
163
- return backgroundImage !== undefined ? (
164
- < ImageBackground borderRadius = { borderRadii . rounded24 } source = { backgroundImage } >
165
- { children }
166
- </ ImageBackground >
167
- ) : (
168
- < Flex > { children } </ Flex >
169
- )
170
- }
171
-
172
- function ReceiveCryptoIcon ( ) : JSX . Element {
173
- return (
174
- < Flex
175
- key = "ReceiveCryptoIcon"
176
- centered
177
- shrink
178
- backgroundColor = "$surface1"
179
- style = { {
180
- ...styles . iconContainer ,
181
- borderRadius : borderRadii . roundedFull ,
182
- } } >
183
- < ArrowDownCircle
184
- color = "$accent1"
185
- style = { {
186
- borderRadius : borderRadii . roundedFull ,
187
- height : ICON_SIZE - 2 ,
188
- width : ICON_SIZE - 2 ,
189
- } }
190
- />
191
- </ Flex >
192
- )
193
- }
194
-
195
- function ServiceProviderLogo ( { uri } : { uri : string } ) : JSX . Element {
196
- return (
197
- < Flex
198
- key = { uri }
199
- centered
200
- shrink
201
- animation = "quick"
202
- backgroundColor = "$surface1"
203
- borderColor = "$surface1"
204
- borderWidth = { 2 }
205
- enterStyle = { { opacity : 0 } }
206
- exitStyle = { { opacity : 0 } }
207
- style = { styles . iconContainer } >
208
- < ImageUri
209
- imageStyle = { {
210
- borderRadius : borderRadii . rounded8 ,
211
- height : ICON_SIZE - 3 ,
212
- overflow : 'hidden' ,
213
- width : ICON_SIZE - 3 ,
214
- } }
215
- resizeMode = "cover"
216
- uri = { uri }
217
- />
218
- </ Flex >
219
- )
220
- }
221
-
222
- function renderItem ( { item } : { item : string } ) : JSX . Element {
223
- return item === 'icon' ? < ReceiveCryptoIcon /> : < ServiceProviderLogo uri = { item } />
224
- }
225
-
226
- function keyExtractor ( item : string ) : string {
227
- return item
228
- }
229
-
230
- /*
231
- * Set the zIndex to -index to reverse the order of the elements.
232
- */
233
- const LogoRendererComponent = ( {
234
- children,
235
- index,
236
- style,
237
- ...props
139
+ const IconContainer = ( {
140
+ backgroundColor,
141
+ icon,
238
142
} : {
239
- children : React . ReactNode
240
- index : number
241
- style : StyleProp < ViewStyle >
242
- } ) : JSX . Element => {
243
- const cellStyle = [ style , { zIndex : - index } ]
244
-
245
- return (
246
- < Flex style = { cellStyle } { ...props } >
247
- { children }
248
- </ Flex >
249
- )
250
- }
251
-
252
- function OverlappingLogos ( { logos } : { logos : string [ ] } ) : JSX . Element {
253
- const getItem = ( _data : unknown , index : number ) : string => {
254
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
255
- return index === 0 ? 'icon' : logos [ index - 1 ] !
256
- }
257
-
258
- const getItemCount = ( ) : number => {
259
- return logos . length + 1
260
- }
261
-
262
- return (
263
- < Flex height = { ICON_SIZE } >
264
- < VirtualizedList < string >
265
- horizontal
266
- CellRendererComponent = { LogoRendererComponent }
267
- contentContainerStyle = { {
268
- paddingRight : - ICON_SHIFT ,
269
- } }
270
- getItem = { getItem }
271
- getItemCount = { getItemCount }
272
- keyExtractor = { keyExtractor }
273
- renderItem = { renderItem }
274
- />
275
- </ Flex >
276
- )
277
- }
278
-
279
- const styles = StyleSheet . create ( {
280
- iconContainer : {
281
- borderRadius : borderRadii . rounded8 ,
282
- height : ICON_SIZE ,
283
- marginRight : ICON_SHIFT ,
284
- overflow : 'hidden' ,
285
- width : ICON_SIZE ,
286
- } ,
287
- } )
143
+ backgroundColor : string
144
+ icon : JSX . Element
145
+ } ) : JSX . Element => (
146
+ < Flex
147
+ centered
148
+ borderRadius = "$roundedFull"
149
+ height = { iconSizes . icon36 }
150
+ style = { { backgroundColor : opacify ( 10 , backgroundColor ) } }
151
+ width = { iconSizes . icon36 } >
152
+ { icon }
153
+ </ Flex >
154
+ )
0 commit comments