@@ -31,11 +31,15 @@ export default class AdvancedTab extends PureComponent {
31
31
threeBoxSyncingAllowed : PropTypes . bool . isRequired ,
32
32
setThreeBoxSyncingPermission : PropTypes . func . isRequired ,
33
33
threeBoxDisabled : PropTypes . bool . isRequired ,
34
+ setIpfsGateway : PropTypes . func . isRequired ,
35
+ ipfsGateway : PropTypes . string . isRequired ,
34
36
}
35
37
36
38
state = {
37
39
autoLogoutTimeLimit : this . props . autoLogoutTimeLimit ,
38
40
logoutTimeError : '' ,
41
+ ipfsGateway : this . props . ipfsGateway ,
42
+ ipfsGatewayError : '' ,
39
43
}
40
44
41
45
renderMobileSync ( ) {
@@ -354,6 +358,85 @@ export default class AdvancedTab extends PureComponent {
354
358
)
355
359
}
356
360
361
+ handleIpfsGatewayChange ( url ) {
362
+ const { t } = this . context
363
+
364
+ this . setState ( ( ) => {
365
+ let ipfsGatewayError = ''
366
+
367
+ try {
368
+
369
+ const urlObj = new URL ( addUrlProtocolPrefix ( url ) )
370
+ if ( ! urlObj . host ) {
371
+ throw new Error ( )
372
+ }
373
+
374
+ // don't allow the use of this gateway
375
+ if ( urlObj . host === 'gateway.ipfs.io' ) {
376
+ throw new Error ( 'Forbidden gateway' )
377
+ }
378
+
379
+ } catch ( error ) {
380
+ ipfsGatewayError = (
381
+ error . message === 'Forbidden gateway'
382
+ ? t ( 'forbiddenIpfsGateway' )
383
+ : t ( 'invalidIpfsGateway' )
384
+ )
385
+ }
386
+
387
+ return {
388
+ ipfsGateway : url ,
389
+ ipfsGatewayError,
390
+ }
391
+ } )
392
+ }
393
+
394
+ handleIpfsGatewaySave ( ) {
395
+
396
+ const url = new URL ( addUrlProtocolPrefix ( this . state . ipfsGateway ) )
397
+ const host = url . host
398
+
399
+ this . props . setIpfsGateway ( host )
400
+ }
401
+
402
+ renderIpfsGatewayControl ( ) {
403
+ const { t } = this . context
404
+ const { ipfsGatewayError } = this . state
405
+
406
+ return (
407
+ < div className = "settings-page__content-row" >
408
+ < div className = "settings-page__content-item" >
409
+ < span > { t ( 'ipfsGateway' ) } </ span >
410
+ < div className = "settings-page__content-description" >
411
+ { t ( 'ipfsGatewayDescription' ) }
412
+ </ div >
413
+ </ div >
414
+ < div className = "settings-page__content-item" >
415
+ < div className = "settings-page__content-item-col" >
416
+ < TextField
417
+ type = "text"
418
+ value = { this . state . ipfsGateway }
419
+ onChange = { e => this . handleIpfsGatewayChange ( e . target . value ) }
420
+ error = { ipfsGatewayError }
421
+ fullWidth
422
+ margin = "dense"
423
+ />
424
+ < Button
425
+ type = "primary"
426
+ className = "settings-tab__rpc-save-button"
427
+ disabled = { Boolean ( ipfsGatewayError ) }
428
+ onClick = { ( ) => {
429
+ this . handleIpfsGatewaySave ( )
430
+ } }
431
+ >
432
+ { t ( 'save' ) }
433
+ </ Button >
434
+ </ div >
435
+ </ div >
436
+ </ div >
437
+ )
438
+ }
439
+
357
440
renderContent ( ) {
358
441
const { warning } = this . props
359
442
@@ -369,6 +452,7 @@ export default class AdvancedTab extends PureComponent {
369
452
{ this . renderUseNonceOptIn ( ) }
370
453
{ this . renderAutoLogoutTimeLimit ( ) }
371
454
{ this . renderThreeBoxControl ( ) }
455
+ { this . renderIpfsGatewayControl ( ) }
372
456
</ div >
373
457
)
374
458
}
@@ -377,3 +461,12 @@ export default class AdvancedTab extends PureComponent {
377
461
return this . renderContent ( )
378
462
}
379
463
}
464
+
465
+ function addUrlProtocolPrefix ( urlString ) {
466
+ if ( ! urlString . match (
467
+ / ( ^ h t t p : \/ \/ ) | ( ^ h t t p s : \/ \/ ) /
468
+ ) ) {
469
+ return 'https://' + urlString
470
+ }
471
+ return urlString
472
+ }
0 commit comments