1
+ import React , { FC } from "react"
1
2
import type { InjectedExtension } from "polkadot-api/pjs-signer"
2
3
import { connectInjectedExtension } from "polkadot-api/pjs-signer"
3
4
import type { Dispatch , PropsWithChildren , SetStateAction } from "react"
4
- import { useSyncExternalStore } from "react"
5
+ import { useEffect , useState , useSyncExternalStore } from "react"
5
6
import { extensionCtx } from "./extensionCtx"
6
7
import { getExtensionIcon } from "@polkadot-ui/assets/extensions"
7
8
import { useAvailableExtensions } from "./hooks"
8
- import type { SelectedAccountType } from "./types"
9
+ import type { CommonConfigType , SelectedAccountType } from "./types"
9
10
import { Any } from "../../utils"
10
11
11
12
const { Provider } = extensionCtx
@@ -62,58 +63,107 @@ const getExtensionsStore = () => {
62
63
}
63
64
}
64
65
66
+ type NameUrlType = {
67
+ name : string
68
+ url : string
69
+ }
70
+
71
+ const allExtensions : NameUrlType [ ] = [
72
+ {
73
+ name : "enkrypt" ,
74
+ url : "https://www.enkrypt.com/download" ,
75
+ } ,
76
+ {
77
+ name : "subwallet-js" ,
78
+ url : "https://www.subwallet.app/download.html" ,
79
+ } ,
80
+ {
81
+ name : "talisman" ,
82
+ url : "https://www.talisman.xyz/" ,
83
+ } ,
84
+ { name : "polkagate" , url : "https://polkagate.xyz/" } ,
85
+ {
86
+ name : "polkadot-js" ,
87
+ url : "https://polkadot.js.org/extension/" ,
88
+ } ,
89
+ {
90
+ name : "fearless-wallet" ,
91
+ url : "https://fearlesswallet.io/download" ,
92
+ } ,
93
+ ]
65
94
const extensionsStore = getExtensionsStore ( )
66
95
extensionsStore . subscribe ( Function . prototype as Any )
67
96
68
- export const ExtensionProvider : React . FC <
97
+ type ConfigType = {
98
+ notInstalled ?: Any
99
+ downloadIcon ?: Any
100
+ }
101
+
102
+ export const ExtensionProvider : FC <
69
103
PropsWithChildren < {
70
104
setSelected : Dispatch < SetStateAction < SelectedAccountType > >
105
+ config ?: ConfigType & CommonConfigType
71
106
} >
72
- > = ( { children, setSelected } ) => {
107
+ > = ( { children, setSelected, config } ) => {
108
+ const [ nonInstalledXts , setNonInstalledXts ] = useState < NameUrlType [ ] > ( [ ] )
73
109
const availXts = useAvailableExtensions ( )
74
110
const selXts = useSyncExternalStore (
75
111
extensionsStore . subscribe ,
76
112
extensionsStore . getSnapshot
77
113
)
78
114
79
- if ( availXts . length === 0 ) return < div > No extension detected</ div >
115
+ useEffect ( ( ) => {
116
+ setNonInstalledXts (
117
+ allExtensions . filter ( ( a ) => availXts . indexOf ( a . name ) < 0 )
118
+ )
119
+ } , [ availXts ] )
120
+
121
+ const borderDesc = config ?. border
122
+ ? config ?. border ?. size . concat (
123
+ ` ${ config ?. border ?. type } ` ,
124
+ ` ${ config ?. border ?. color } `
125
+ )
126
+ : "0.1rem solid #8A8A8A"
80
127
81
128
return (
82
129
< div style = { { display : "flex" , flexDirection : "column" } } >
83
130
< div
84
131
style = { {
85
- display : "flex" ,
86
132
flexWrap : "wrap" ,
133
+ display : "flex" ,
87
134
gap : "1rem" ,
88
135
} }
89
136
>
90
137
{ availXts . map ( ( xtName ) => {
91
138
const ExtensionIcon = getExtensionIcon ( xtName )
92
139
return (
93
- < div key = { xtName } style = { { flex : "1 1 5rem " } } >
140
+ < div key = { xtName } style = { { width : "100% " } } >
94
141
< button
95
142
style = { {
96
143
display : "flex" ,
97
144
padding : "1rem 0" ,
98
- flexDirection : "column " ,
99
- alignItems : "normal " ,
100
- width : "11rem " ,
101
- height : "9rem " ,
102
- border : "0.1rem solid #8A8A8A" ,
145
+ flexDirection : "row " ,
146
+ alignItems : "center " ,
147
+ width : "100% " ,
148
+ height : "5rem " ,
149
+ border : borderDesc ,
103
150
borderRadius : "0.5rem" ,
104
- background : selXts . has ( xtName ) ? "#CACACA" : "" ,
151
+ background : selXts . has ( xtName )
152
+ ? config ?. selectedBgColor || "#CACACA"
153
+ : config ?. bgColor || "" ,
105
154
} }
106
155
onClick = { ( ) => {
107
156
extensionsStore . onToggleExtension ( xtName , setSelected )
108
157
} }
109
158
key = { xtName }
110
159
>
111
- { ExtensionIcon && < ExtensionIcon /> }
160
+ < div style = { { width : "5rem" , height : "3rem" } } >
161
+ { ExtensionIcon && < ExtensionIcon /> }
162
+ </ div >
112
163
< div
113
164
style = { {
114
165
position : "relative" ,
115
- bottom : "-0.5rem" ,
116
- fontSize : "1rem" ,
166
+ fontSize : "1.2rem" ,
117
167
} }
118
168
>
119
169
{ xtName === "subwallet-js"
@@ -124,6 +174,53 @@ export const ExtensionProvider: React.FC<
124
174
</ div >
125
175
)
126
176
} ) }
177
+ < p > { config ?. notInstalled || "-- Not installed --" } </ p >
178
+ { nonInstalledXts . map ( ( { name, url } ) => {
179
+ const ExtensionIcon = getExtensionIcon ( name )
180
+ return (
181
+ < div key = { name } style = { { width : "100%" } } >
182
+ < button
183
+ style = { {
184
+ justifyContent : "space-between" ,
185
+ display : "flex" ,
186
+ padding : "1rem 0" ,
187
+ flexDirection : "row" ,
188
+ alignItems : "center" ,
189
+ width : "100%" ,
190
+ height : "5rem" ,
191
+ border : borderDesc ,
192
+ borderRadius : "0.5rem" ,
193
+ background : selXts . has ( name )
194
+ ? config ?. bgColor || "#CACACA"
195
+ : "" ,
196
+ } }
197
+ onClick = { ( ) => {
198
+ window . open ( url , "_blank" )
199
+ } }
200
+ key = { name }
201
+ >
202
+ < div style = { { display : "flex" , alignItems : "center" } } >
203
+ < div style = { { width : "5rem" , height : "3rem" } } >
204
+ { ExtensionIcon && < ExtensionIcon /> }
205
+ </ div >
206
+ < div
207
+ style = { {
208
+ position : "relative" ,
209
+ fontSize : "1.2rem" ,
210
+ } }
211
+ >
212
+ { name === "subwallet-js"
213
+ ? "Subwallet"
214
+ : name . charAt ( 0 ) . toUpperCase ( ) + name . slice ( 1 ) }
215
+ </ div >
216
+ </ div >
217
+ < div style = { { paddingRight : "1rem" } } >
218
+ { config ?. downloadIcon || "Download" }
219
+ </ div >
220
+ </ button >
221
+ </ div >
222
+ )
223
+ } ) }
127
224
</ div >
128
225
< Provider value = { [ ...selXts . values ( ) ] } >
129
226
{ selXts . size ? children : null }
0 commit comments