1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Connect Screen Multi Select (#8078)

* Add UI for selecting multiple accounts on the first permissions connect screen

* Make accounts list scrollable on connect screen

* Change title wording on connect screen to 'select your accounts'

* Add select all tooltip to info circle on top of connect screen account list

* Add security info footer to the first screen of the connect flow

* Apply redesigns to page 2 of connect flow

* Display number of accounts on connect flow second screen if there are multiple to connect

* Update e2e tests for connect screen multi-select changes

* Remove unused chooseAnAcount message

* Fix styling/display of redirect elements on second page of connect flow

* Assorted small fixes in permissions connect

* Remove unnecessary tiny delays in spec files

* Remove incorrect use of bem modified in choose-account

* Remove unused locale

* Use Set for managing selected accounts in choose-acount and permissions-connect componets

* Compone!

* Move connect flow header into a reusable component, and implement new header designs

* Update locales and add missing locales

* Improve permission list item design (second screen of connect flow)

* Check box component improvements

* Fixes in variables.scss

* Simplfy code in selectAll of choose-account.component

* Hide checkboxes on first pages on connect flow when there is only one account

* Allow autofill of default new account modal text with right arrow

* Disable next button on first screen of connect flow when no accounts selected

* Improve choose-account/index.scss

* Remove metamask secure graphic

* Fix connect flow redirect screen

* Fix connectToMultiple locale

* Remove locales no longer used after connect flow multiple connect updates

* Fix size of dapp icon on redirect screen of connect flow

* Clean up choose-account code

* Stop using placeholder in new-account-modal

* Remove unused styles in permission-page-container/index.scss

* Pass origin instead of site name to PermissionsConnectHeader in connect flow

* Make iconName a required prop in permissions-connect-header

* Show checkbox in cases where there is one account in the choose-account list

* Do not render select all checkbox when only 1 list item, instead of just hiding it

* Small cleanup in choose-account/index.scss
This commit is contained in:
Dan J Miller 2020-04-02 06:39:53 -02:30 committed by GitHub
parent 4efa6caec7
commit d8179ff030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 635 additions and 521 deletions

View File

@ -8,9 +8,6 @@
"reject": {
"message": "አይቀበሉ"
},
"likeToConnect": {
"message": "$1ከመለያዎ ጋር ለመገናኘት ይፈልጋል"
},
"about": {
"message": "ስለ"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "رفض"
},
"likeToConnect": {
"message": "يرغب $1 في الاتصال بحسابك"
},
"about": {
"message": "حول"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Отхвърляне"
},
"likeToConnect": {
"message": "$1 би искал да се свърже с вашия акаунт"
},
"about": {
"message": "Информация"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "প্রত্যাখ্যান"
},
"likeToConnect": {
"message": "$1 আপনার অ্যাকাউন্টের সাথে সংযোগ করতে চায়"
},
"about": {
"message": "সম্পর্কে"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Rebutja"
},
"likeToConnect": {
"message": "a $1 li agradaria connectar-se al teu compte"
},
"about": {
"message": "Informació"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Afvis"
},
"likeToConnect": {
"message": "$1 ønsker at forbinde til din konto"
},
"about": {
"message": "Om"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Ablehnen"
},
"likeToConnect": {
"message": "$1 möchte sich mit deinem Account verbinden"
},
"about": {
"message": "Über"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Απόρριψη"
},
"likeToConnect": {
"message": "Αίτημα σύνδεσης στον λογαριασμό σας από $1"
},
"about": {
"message": "Σχετικά με"
},

View File

@ -32,17 +32,31 @@
"showIncomingTransactionsDescription": {
"message": "Select this to use Etherscan to show incoming transactions in the transactions list"
},
"cancelling": {
"message": "Cancelling..."
},
"cancelledConnectionWithMetaMask": {
"message": "Cancelled Connection With MetaMask"
},
"chartOnlyAvailableEth": {
"message": "Chart only available on Ethereum networks."
},
"connecting": {
"message": "Connecting..."
},
"connectWithMetaMask": {
"message": "Connect With MetaMask"
},
"connectingWithMetaMask": {
"message": "Connecting With MetaMask..."
},
"chooseAnAcount": {
"message": "Choose an account"
"connectTo": {
"message": "Connect to $1",
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
},
"connectToMultiple": {
"message": "Connect to $1 accounts",
"description": "$1 is the number of accounts to connect to"
},
"contractInteraction": {
"message": "Contract Interaction"
@ -50,9 +64,6 @@
"reject": {
"message": "Reject"
},
"redirectingBackToDapp": {
"message": "Redirecting back to dapp..."
},
"about": {
"message": "About"
},
@ -266,6 +277,9 @@
"chainId": {
"message": "Chain ID"
},
"chooseAccountsToUse": {
"message": "Choose the account(s) to use on this site"
},
"clickToRevealSeed": {
"message": "Click here to reveal secret words"
},
@ -290,6 +304,9 @@
"congratulations": {
"message": "Congratulations"
},
"connectAccountOrCreate": {
"message": "Connect account or create new"
},
"connectHardwareWallet": {
"message": "Connect Hardware Wallet"
},
@ -788,9 +805,6 @@
"learnMore": {
"message": "Learn more"
},
"learnAboutRisks": {
"message": "Learn about the risks here."
},
"ledgerAccountRestriction": {
"message": "You need to make use your last account before you can add a new one."
},
@ -800,10 +814,6 @@
"likeToAddTokens": {
"message": "Would you like to add these tokens?"
},
"likeToConnect": {
"message": "$1 would like to connect to your MetaMask account",
"description": "$1 is the name/url of a site/dapp asking to connect to MetaMask"
},
"links": {
"message": "Links"
},
@ -1006,6 +1016,12 @@
"pending": {
"message": "pending"
},
"permissionCheckedIconDescription": {
"message": "You have approved this permission"
},
"permissionUncheckedIconDescription": {
"message": "You have not approved this permission"
},
"personalAddressDetected": {
"message": "Personal address detected. Input the token contract address."
},
@ -1185,6 +1201,12 @@
"seedPhraseReq": {
"message": "Seed phrases contain 12, 15, 18, 21, or 24 words"
},
"selectingAllWillAllow": {
"message": "Selecting all will allow this site to view all of your current accounts. Make sure you trust this site."
},
"selectAll": {
"message": "Select all"
},
"selectCurrency": {
"message": "Select Currency"
},
@ -1422,10 +1444,6 @@
"toWithColon": {
"message": "To:"
},
"toConnectWith": {
"message": "To connect with $1",
"description": "$1 is the name or domain of a site/dapp that asking to connect with MetaMask"
},
"toETHviaShapeShift": {
"message": "$1 to ETH via ShapeShift",
"description": "system will fill in deposit type in start of message"

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Rechazar"
},
"likeToConnect": {
"message": "$1 quisiera conectar con tu cuenta"
},
"about": {
"message": "Acerca"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Rechazar"
},
"likeToConnect": {
"message": "$1 desea conectarse a tu cuenta"
},
"about": {
"message": "Acerca de"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Lükka tagasi"
},
"likeToConnect": {
"message": "$1 soovib teie kontoga ühenduse luua"
},
"about": {
"message": "Teave"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "عدم پذیرش"
},
"likeToConnect": {
"message": "1$1 میخواهید تا با حساب تان وصل شوید"
},
"about": {
"message": "درباره"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Hylkää"
},
"likeToConnect": {
"message": "$1 haluaisi yhdistää tiliisi"
},
"about": {
"message": "Tietoja asetuksista"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Tanggihan"
},
"likeToConnect": {
"message": "Gusto ng $1 na kumonekta sa iyong account"
},
"about": {
"message": "Tungkol sa"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Rejeter"
},
"likeToConnect": {
"message": "$1 voudrait se connecter à votre compte"
},
"about": {
"message": "À propos"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "דחה"
},
"likeToConnect": {
"message": "$1 מבקש להתחבר לחשבון שלך"
},
"about": {
"message": "מידע כללי"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "अस्‍वीकार करें"
},
"likeToConnect": {
"message": "$1 आपके खाते से कनेक्ट होता चाहता हैं"
},
"about": {
"message": "इसके बारे में"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Odbaci"
},
"likeToConnect": {
"message": "Korisnik $1 želi se povezati na vaš račun"
},
"about": {
"message": "O opcijama"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Elutasítás"
},
"likeToConnect": {
"message": "$1 szeretne kapcsolódni az ön fiókjához"
},
"about": {
"message": "Névjegy"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Tolak"
},
"likeToConnect": {
"message": "$1 ingin menghubungkan ke akun Anda"
},
"about": {
"message": "Tentang"
},

View File

@ -26,8 +26,9 @@
"connectingWithMetaMask": {
"message": "Connettendo con MetaMask..."
},
"chooseAnAcount": {
"message": "Scegli un account"
"connectTo": {
"message": "Collegati a $1",
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
},
"contractInteraction": {
"message": "Interazione Contratto"
@ -35,9 +36,6 @@
"reject": {
"message": "Annulla"
},
"redirectingBackToDapp": {
"message": "Ritornando alla dapp..."
},
"about": {
"message": "Informazioni"
},
@ -773,9 +771,6 @@
"learnMore": {
"message": "Scopri di più"
},
"learnAboutRisks": {
"message": "Scopri di piu sui rischi qua."
},
"ledgerAccountRestriction": {
"message": "E' necessario utilizzare l'ultimo account prima di poterne aggiungere uno nuovo."
},
@ -785,10 +780,6 @@
"likeToAddTokens": {
"message": "Vorresti aggiungere questi token?"
},
"likeToConnect": {
"message": "$1 vorrebbe connettersi al tuo account",
"description": "$1 is the name/url of a site/dapp asking to connect to MetaMask"
},
"links": {
"message": "Collegamenti"
},
@ -1401,10 +1392,6 @@
"toWithColon": {
"message": "To:"
},
"toConnectWith": {
"message": "Di connettersi con $1",
"description": "$1 is the name or domain of a site/dapp that asking to connect with MetaMask"
},
"toETHviaShapeShift": {
"message": "$1 a ETH con ShapeShift",
"description": "system will fill in deposit type in start of message"

View File

@ -8,9 +8,6 @@
"reject": {
"message": "拒否"
},
"likeToConnect": {
"message": "$1 はあなたのアカウントにアクセスしようとしています。"
},
"aboutSettingsDescription": {
"message": "バージョンやサポート、問合せ先など"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "ತಿರಸ್ಕರಿಸಿ"
},
"likeToConnect": {
"message": "$1 ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಪರ್ಕಿಸಲು ಬಯಸುತ್ತಿದೆ"
},
"about": {
"message": "ಕುರಿತು"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "거부"
},
"likeToConnect": {
"message": "$1이 당신의 계정에 연결하길 원합니다."
},
"about": {
"message": "정보"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Atmesti"
},
"likeToConnect": {
"message": "$1 norėtų prisijungti prie jūsų paskyros"
},
"about": {
"message": "Apie"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Noraidīt"
},
"likeToConnect": {
"message": "$1 vēlas izveidot savienojumu ar jūsu kontu"
},
"about": {
"message": "Par"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Tolak"
},
"likeToConnect": {
"message": "$1 ingin menyambung kepada akaun anda"
},
"about": {
"message": "Mengenai"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Avslå"
},
"likeToConnect": {
"message": "$1 ønsker å forbindes med kontoen din "
},
"about": {
"message": "Info"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Odrzuć"
},
"likeToConnect": {
"message": "$1 chce połączyć się z Twoim kontem"
},
"about": {
"message": "Informacje"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Rejeitar"
},
"likeToConnect": {
"message": "$1 gostaria de se conectar à sua conta"
},
"about": {
"message": "Sobre"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Respingeți"
},
"likeToConnect": {
"message": "$1 ar dori să se conecteze la contul dvs."
},
"about": {
"message": "Despre"
},

View File

@ -527,9 +527,6 @@
"contractInteraction": {
"message": "Взаимодействие с контрактом"
},
"likeToConnect": {
"message": "$1 запрашивает доступ к вашему аккаунту"
},
"about": {
"message": "О нас"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Odmítnout"
},
"likeToConnect": {
"message": "$1 sa chce pripojiť k vášmu účtu"
},
"about": {
"message": "Informácie"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Zavrni"
},
"likeToConnect": {
"message": "$1 se želi povezati z vašim računom."
},
"about": {
"message": "O možnostih"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Одбиј"
},
"likeToConnect": {
"message": "$1 bi hteo da se poveže sa vašim nalogom"
},
"about": {
"message": "Основни подаци"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Avvisa"
},
"likeToConnect": {
"message": "$1 vill ansluta till ditt konto"
},
"about": {
"message": "Om"
},

View File

@ -12,9 +12,6 @@
"reject": {
"message": "Kataa"
},
"likeToConnect": {
"message": "$1 ingependa kuunganishwa kwenye akaunti yako"
},
"about": {
"message": "Kuhusu"
},

View File

@ -2,9 +2,6 @@
"reject": {
"message": "ปฏิเสธ"
},
"likeToConnect": {
"message": "$1 ต้องการเชื่อมต่อกับบัญชีของคุณ"
},
"about": {
"message": "เกี่ยวกับ"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "Відхилити"
},
"likeToConnect": {
"message": "$1 бажає підключитися до вашого облікового запису"
},
"about": {
"message": "Про Google Chrome"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "拒绝"
},
"likeToConnect": {
"message": "$1 希望关联您的账户"
},
"about": {
"message": "关于"
},

View File

@ -8,9 +8,6 @@
"reject": {
"message": "拒絕"
},
"likeToConnect": {
"message": "$1 請求訪問帳戶權限"
},
"about": {
"message": "關於"
},

View File

@ -1,3 +1,3 @@
<svg width="131" height="2" viewBox="0 0 131 2" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 1H134" stroke="#CDD1E4" stroke-linejoin="round" stroke-dasharray="8 0"/>
<path d="M0 1H134" stroke="#CDD1E4" stroke-linejoin="round" stroke-dasharray="8 7"/>
</svg>

Before

Width:  |  Height:  |  Size: 188 B

After

Width:  |  Height:  |  Size: 188 B

View File

@ -127,6 +127,7 @@ describe('MetaMask', function () {
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`))
await driver.waitUntilXWindowHandles(2)

View File

@ -415,6 +415,7 @@ describe('MetaMask', function () {
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`))
await driver.waitUntilXWindowHandles(2)

View File

@ -125,6 +125,7 @@ describe('MetaMask', function () {
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`))
await driver.waitUntilXWindowHandles(2)

View File

@ -86,6 +86,7 @@ describe('MetaMask', function () {
await driver.clickElement(By.css('.permissions-connect-choose-account__account'))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Next')]`))
await driver.clickElement(By.xpath(`//button[contains(text(), 'Submit')]`))
await driver.waitUntilXWindowHandles(2)

View File

@ -95,3 +95,7 @@
@import './connected-status-indicator/index';
@import './dropdowns/account-details-dropdown/index';
@import '../ui/check-box/index';
@import 'permissions-connect-header/index';

View File

@ -15,7 +15,7 @@ export default class NewAccountModal extends Component {
}
state = {
alias: '',
alias: this.context.t('newAccountNumberName', [this.props.newAccountNumber]),
}
onChange = (e) => {
@ -53,7 +53,6 @@ export default class NewAccountModal extends Component {
onChange={this.onChange}
onKeyPress={this.onKeyPress}
value={this.state.alias}
placeholder={ t('account', [this.props.newAccountNumber]) }
autoFocus
/>
</div>

View File

@ -18,8 +18,7 @@
@extend %header--18;
line-height: 25px;
text-align: center;
position: fixed;
left: 0;
margin-top: 32px;
width: 100%;
}
@ -31,214 +30,38 @@
color: #7C808E;
&--redirect {
margin-top: 60px;
}
h1, h2 {
color: #4A4A4A;
margin-top: 50px;
width: 100%;
display: flex;
justify-content: center;
text-align: center;
}
h2 {
font-size: 16px;
line-height: 18px;
padding: 20px;
}
h1 {
font-size: 22px;
line-height: 26px;
padding: 20px;
}
p {
padding: 0 40px;
text-align: center;
font-size: 12px;
line-height: 18px;
align-items: center;
padding-top: 8px;
}
a, a:hover {
color: $dodger-blue;
}
section {
h1 {
padding: 30px 0px 0px 0px;
}
h2 {
padding: 0px 0px 20px 0px;
}
}
&__requested {
text-align: left;
}
&__revoke-note {
margin-top: 24px;
}
&__checkbox {
margin-right: 10px;
margin-top: 60px;
}
&__permission {
display: flex;
margin-top: 18px;
i {
color: #6A737D;
font-size: 1.4rem;
color: $Grey-200;
}
label {
margin-left: 6px;
color: #24292E;
color: $Black-100;
}
}
.permission-approval-visual {
display: flex;
flex-direction: row;
justify-content: space-evenly;
position: relative;
margin: 0 32px;
margin-top: 40px;
section {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
h1 {
font-size: 14px;
line-height: 18px;
padding: 8px 0 0;
}
h2 {
font-size: 12px;
line-height: 17px;
color: #6A737D;
padding: 0;
}
&__check {
width: 40px;
height: 40px;
background: white url("/images/permissions-check.svg") no-repeat;
margin-top: 24px;
z-index: 1;
}
&__reject {
background: white;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
i {
color: #D73A49;
transform: scale(3);
}
}
&__broken-line {
z-index: 0;
position: absolute;
top: 43px;
}
&__identicon, .icon-with-fallback__identicon {
width: 32px;
height: 32px;
z-index: 1;
&--default {
background-color: #777A87;
color: white;
width: 64px;
height: 64px;
border-radius: 32px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
z-index: 1;
}
}
&__identicon-container, .icon-with-fallback__identicon-container {
padding: 1rem;
flex: 1;
position: relative;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
&__identicon-border, .icon-with-fallback__identicon-border {
height: 64px;
width: 64px;
border-radius: 50%;
border: 1px solid white;
background: #FFFFFF;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
}
&__identicon-border {
display: flex;
justify-content: center;
align-items: center;
}
.icon-with-fallback__identicon-border {
position: absolute;
}
&:before {
border-top: 2px dashed #CDD1E4;
content: "";
margin: 0 auto;
position: absolute;
top: 32px;
left: 0;
bottom: 0;
right: 0;
width: 65%;
z-index: -1;
}
&__account-info {
display: flex;
flex-direction: column;
align-items: center;
&__label {
@extend %content-text;
line-height: 20px;
color: #000000;
}
&__address {
@extend %font;
font-size: 12px;
line-height: 17px;
color: #6A737D;
}
}
}
.secure-badge {
display: flex;
justify-content: center;
padding: 25px;
}
}
&__permissions-header {
@ -266,10 +89,6 @@
}
}
&__permissions-header-redirect {
text-align: center;
}
@media screen and (max-width: 575px) {
width: 100%;
margin-top: 25px;
@ -288,3 +107,106 @@
}
}
}
.permission-result {
@extend %header--24;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
text-align: center;
color: $Black-100;
height: 114px;
&__icons {
display: flex;
}
&__center-icon {
display: flex;
position: relative;
justify-content: center;
align-items: center;
font-size: 12px;
}
h1 {
font-size: 14px;
line-height: 18px;
padding: 8px 0 0;
}
h2 {
font-size: 12px;
line-height: 17px;
color: #6A737D;
padding: 0;
}
&__check {
width: 40px;
height: 40px;
background: white url("/images/permissions-check.svg") no-repeat;
position: absolute;
}
&__reject {
position: absolute;
background: white;
display: flex;
justify-content: center;
align-items: center;
i {
color: #D73A49;
transform: scale(3);
}
}
&__identicon, .icon-with-fallback__identicon {
width: 32px;
height: 32px;
&--default {
background-color: #777A87;
color: white;
width: 64px;
height: 64px;
border-radius: 32px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
}
&__identicon-container, .icon-with-fallback__identicon-container {
height: auto;
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 64px;
width: 64px;
}
&__identicon-border, .icon-with-fallback__identicon-border {
height: 64px;
width: 64px;
border-radius: 50%;
border: 1px solid white;
background: #FFFFFF;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
}
&__identicon-border {
display: flex;
justify-content: center;
align-items: center;
}
.icon-with-fallback__identicon-border {
position: absolute;
}
}

View File

@ -2,17 +2,17 @@ import PropTypes from 'prop-types'
import React, { PureComponent } from 'react'
import Identicon from '../../../ui/identicon'
import IconWithFallBack from '../../../ui/icon-with-fallback'
import PermissionsConnectHeader from '../../permissions-connect-header'
import classnames from 'classnames'
export default class PermissionPageContainerContent extends PureComponent {
static propTypes = {
requestMetadata: PropTypes.object.isRequired,
domainMetadata: PropTypes.object.isRequired,
selectedPermissions: PropTypes.object.isRequired,
permissionsDescriptions: PropTypes.object.isRequired,
onPermissionToggle: PropTypes.func.isRequired,
selectedAccount: PropTypes.object,
selectedIdentities: PropTypes.array,
redirect: PropTypes.bool,
permissionRejected: PropTypes.bool,
}
@ -20,55 +20,38 @@ export default class PermissionPageContainerContent extends PureComponent {
static defaultProps = {
redirect: null,
permissionRejected: null,
selectedAccount: {},
selectedIdentities: [],
}
static contextTypes = {
t: PropTypes.func,
}
renderAccountInfo = (account) => {
renderRedirect () {
const { t } = this.context
const { permissionRejected, selectedIdentities, domainMetadata } = this.props
return (
<div className="permission-approval-visual__account-info">
<div className="permission-approval-visual__account-info__label">
{ account.label }
</div>
<div className="permission-approval-visual__account-info__address">
{ account.truncatedAddress }
</div>
</div>
)
}
renderPermissionApprovalVisual = () => {
const {
requestMetadata, domainMetadata, selectedAccount, redirect, permissionRejected,
} = this.props
return (
<div className="permission-approval-visual">
<section>
<div className="permission-result">
{ permissionRejected ? t('cancelling') : t('connecting') }
<div className="permission-result__icons">
<IconWithFallBack icon={domainMetadata.icon} name={domainMetadata.name} />
{ redirect ? null : <h1>{domainMetadata.name}</h1> }
{ redirect ? null : <h2>{requestMetadata.origin}</h2> }
</section>
{ permissionRejected
? <span className="permission-approval-visual__reject" ><i className="fa fa-times-circle" /></span>
: <span className="permission-approval-visual__check" />
}
<img className="permission-approval-visual__broken-line" src="/images/broken-line.svg" />
<section>
<div className="permission-approval-visual__identicon-container">
<div className="permission-approval-visual__identicon-border">
<div className="permission-result__center-icon">
{ permissionRejected
? <span className="permission-result__reject" ><i className="fa fa-times-circle" /></span>
: <span className="permission-result__check" />
}
<img className="permission-result__broken-line" src="/images/broken-line.svg" />
</div>
<div className="permission-result__identicon-container">
<div className="permission-result__identicon-border">
<Identicon
className="permission-approval-visual__identicon"
address={selectedAccount.address}
className="permission-result__identicon"
address={selectedIdentities[0].address}
diameter={54}
/>
</div>
</div>
{ redirect ? null : this.renderAccountInfo(selectedAccount) }
</section>
</div>
</div>
)
}
@ -100,8 +83,8 @@ export default class PermissionPageContainerContent extends PureComponent {
}}
>
{ selectedPermissions[methodName]
? <i className="fa fa-check-circle fa-sm" />
: <i className="fa fa-circle fa-sm" />
? <i title={t('permissionCheckedIconDescription')} className="fa fa-check-square" />
: <i title={t('permissionUncheckedIconDescription')} className="fa fa-square" />
}
<label>{description}</label>
</div>
@ -117,7 +100,7 @@ export default class PermissionPageContainerContent extends PureComponent {
}
render () {
const { domainMetadata, redirect, permissionRejected } = this.props
const { domainMetadata, redirect, permissionRejected, selectedIdentities } = this.props
const { t } = this.context
let titleArgs
@ -127,8 +110,14 @@ export default class PermissionPageContainerContent extends PureComponent {
titleArgs = [ 'connectingWithMetaMask' ]
} else if (domainMetadata.extensionId) {
titleArgs = [ 'externalExtension', [domainMetadata.extensionId] ]
} else if (selectedIdentities.length > 1) {
titleArgs = ['connectToMultiple', [ selectedIdentities.length ] ]
} else {
titleArgs = [ 'likeToConnect', [domainMetadata.name] ]
titleArgs = [
'connectTo', [
`${selectedIdentities[0].label} (...${selectedIdentities[0].address.slice(selectedIdentities[0].address.length - 4)})`,
],
]
}
return (
@ -137,27 +126,24 @@ export default class PermissionPageContainerContent extends PureComponent {
'permission-approval-container__content--redirect': redirect,
})}
>
<div className="permission-approval-container__title">
{ t(...titleArgs) }
</div>
{this.renderPermissionApprovalVisual()}
{ !redirect
? (
<section className="permission-approval-container__permissions-container">
<div className="permission-approval-container__permissions-header">
{ domainMetadata.extensionId
<div>
<PermissionsConnectHeader
icon={domainMetadata.icon}
iconName={domainMetadata.origin}
headerTitle={t(...titleArgs)}
headerText={ domainMetadata.extensionId
? t('thisWillAllowExternalExtension', [domainMetadata.extensionId])
: t('thisWillAllow', [domainMetadata.name])
: t('thisWillAllow', [domainMetadata.origin])
}
</div>
{ this.renderRequestedPermissions() }
</section>
)
: (
<div className="permission-approval-container__permissions-header-redirect">
{ t('redirectingBackToDapp') }
/>
<section className="permission-approval-container__permissions-container">
{ this.renderRequestedPermissions() }
</section>
</div>
)
: this.renderRedirect()
}
</div>
)

View File

@ -9,7 +9,7 @@ export default class PermissionPageContainer extends Component {
static propTypes = {
approvePermissionsRequest: PropTypes.func.isRequired,
rejectPermissionsRequest: PropTypes.func.isRequired,
selectedIdentity: PropTypes.object,
selectedIdentities: PropTypes.array,
permissionsDescriptions: PropTypes.object.isRequired,
request: PropTypes.object,
redirect: PropTypes.bool,
@ -23,7 +23,7 @@ export default class PermissionPageContainer extends Component {
permissionRejected: null,
request: {},
requestMetadata: {},
selectedIdentity: {},
selectedIdentities: [],
}
static contextTypes = {
@ -88,7 +88,7 @@ export default class PermissionPageContainer extends Component {
onSubmit = () => {
const {
request: _request, approvePermissionsRequest, rejectPermissionsRequest, selectedIdentity,
request: _request, approvePermissionsRequest, rejectPermissionsRequest, selectedIdentities,
} = this.props
const request = {
@ -103,7 +103,7 @@ export default class PermissionPageContainer extends Component {
})
if (Object.keys(request.permissions).length > 0) {
approvePermissionsRequest(request, [selectedIdentity.address])
approvePermissionsRequest(request, selectedIdentities.map((selectedIdentity) => selectedIdentity.address))
} else {
rejectPermissionsRequest(request.metadata.id)
}
@ -114,7 +114,7 @@ export default class PermissionPageContainer extends Component {
requestMetadata,
targetDomainMetadata,
permissionsDescriptions,
selectedIdentity,
selectedIdentities,
redirect,
permissionRejected,
} = this.props
@ -127,7 +127,7 @@ export default class PermissionPageContainer extends Component {
selectedPermissions={this.state.selectedPermissions}
permissionsDescriptions={permissionsDescriptions}
onPermissionToggle={this.onPermissionToggle}
selectedAccount={selectedIdentity}
selectedIdentities={selectedIdentities}
redirect={redirect}
permissionRejected={permissionRejected}
/>

View File

@ -2,20 +2,15 @@ import { connect } from 'react-redux'
import PermissionPageContainer from './permission-page-container.component'
import {
getPermissionsDescriptions,
getDomainMetadata,
getTargetDomainMetadata,
} from '../../../selectors/selectors'
const mapStateToProps = (state, ownProps) => {
const { request, cachedOrigin } = ownProps
const { metadata: requestMetadata = {} } = request || {}
const domainMetadata = getDomainMetadata(state)
const origin = requestMetadata.origin || cachedOrigin
const targetDomainMetadata = (domainMetadata[origin] || { name: origin, icon: null })
const targetDomainMetadata = getTargetDomainMetadata(state, request, cachedOrigin)
return {
permissionsDescriptions: getPermissionsDescriptions(state),
requestMetadata,
targetDomainMetadata,
}
}

View File

@ -0,0 +1,39 @@
.permissions-connect-header {
display: flex;
flex-direction: column;
justify-content: center;
&__icon {
display: flex;
flex-direction: column;
align-items: center;
.icon-with-fallback__identicon-container,
.icon-with-fallback__identicon-border {
height: 64px;
width: 64px;
}
.icon-with-fallback__identicon-border {
border: 1px solid $Grey-100;
}
.icon-with-fallback__identicon-container {
margin-bottom: 8px;
}
}
&__title {
@extend %header--24;
text-align: center;
color: $Black-100;
margin-top: 16px;
}
&__text {
@extend %content-text;
text-align: center;
margin-top: 4px;
color: $Grey-500;
}
}

View File

@ -0,0 +1,44 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import IconWithFallBack from '../../ui/icon-with-fallback'
export default class PermissionsConnectHeader extends Component {
static propTypes = {
icon: PropTypes.string,
iconName: PropTypes.string.isRequired,
headerTitle: PropTypes.node,
headerText: PropTypes.string,
}
static defaultProps = {
icon: null,
headerTitle: '',
headerText: '',
}
renderHeaderIcon () {
const { icon, iconName } = this.props
return (
<div className="permissions-connect-header__icon">
<IconWithFallBack icon={ icon } name={ iconName } />
<div className="permissions-connect-header__text">{iconName }</div>
</div>
)
}
render () {
const { headerTitle, headerText } = this.props
return (
<div className="permissions-connect-header">
{ this.renderHeaderIcon() }
<div className="permissions-connect-header__title">
{ headerTitle }
</div>
<div className="permissions-connect-header__text">
{ headerText }
</div>
</div>
)
}
}

View File

@ -0,0 +1,36 @@
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
export default class CheckBox extends PureComponent {
static propTypes = {
className: PropTypes.string,
checked: PropTypes.bool,
onClick: PropTypes.func.isRequired,
}
static defaultProps = {
className: '',
checked: false,
}
render () {
const { className, checked, onClick } = this.props
return (
<div
onClick={ () => onClick() }
className={classnames('check-box', className, {
'check-box--checked': checked,
'check-box--un-checked': !checked,
})}
>
{
checked
? <i className="fa fa-check" />
: null
}
</div>
)
}
}

View File

@ -0,0 +1 @@
export { default } from './check-box.component'

View File

@ -0,0 +1,26 @@
.check-box {
cursor: pointer;
&--checked {
background: $curious-blue;
border: 2px solid $curious-blue;
border-radius: 2px;
width: 18px;
height: 18px;
display: flex;
justify-content: center;
align-items: center;
i {
color: $white;
}
}
&--un-checked {
background: $white;
border: 2px solid $Grey-100;
border-radius: 2px;
width: 18px;
height: 18px;
}
}

View File

@ -176,6 +176,8 @@ $Orange-300: #faa66c;
$Orange-600: #c65507;
$Orange-500: #F66A0A;
$Black-100: #24292E;
// Font Sizes
%h3 {
font-size: 1.5rem;
@ -265,7 +267,7 @@ $xxlarge-spacing: 64px;
%header--24 {
@extend %font;
font-size: 18px;
font-size: 24px;
}
%content-text {

View File

@ -1,8 +1,13 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import classnames from 'classnames'
import Identicon from '../../../components/ui/identicon'
import Button from '../../../components/ui/button'
import CheckBox from '../../../components/ui/check-box'
import Tooltip from '../../../components/ui/tooltip-v2'
import { PRIMARY } from '../../../helpers/constants/common'
import UserPreferencedCurrencyDisplay from '../../../components/app/user-preferenced-currency-display'
import PermissionsConnectHeader from '../../../components/app/permissions-connect-header'
export default class ChooseAccount extends Component {
static propTypes = {
@ -12,13 +17,18 @@ export default class ChooseAccount extends Component {
lastConnectedDate: PropTypes.string,
balance: PropTypes.string,
})).isRequired,
originName: PropTypes.string.isRequired,
selectAccount: PropTypes.func.isRequired,
selectAccounts: PropTypes.func.isRequired,
selectNewAccountViaModal: PropTypes.func.isRequired,
nativeCurrency: PropTypes.string.isRequired,
addressLastConnectedMap: PropTypes.object,
cancelPermissionsRequest: PropTypes.func.isRequired,
permissionsRequestId: PropTypes.string.isRequired,
selectedAccountAddresses: PropTypes.object.isRequired,
targetDomainMetadata: PropTypes.object,
}
state = {
selectedAccounts: this.props.selectedAccountAddresses,
}
static defaultProps = {
@ -29,8 +39,42 @@ export default class ChooseAccount extends Component {
t: PropTypes.func,
}
handleAccountClick (address) {
const { selectedAccounts } = this.state
const newSelectedAccounts = new Set(selectedAccounts)
if (newSelectedAccounts.has(address)) {
newSelectedAccounts.delete(address)
} else {
newSelectedAccounts.add(address)
}
this.setState({ selectedAccounts: newSelectedAccounts })
}
selectAll () {
const { accounts } = this.props
const newSelectedAccounts = new Set(accounts.map((account) => account.address))
this.setState({ selectedAccounts: newSelectedAccounts })
}
deselectAll () {
this.setState({ selectedAccounts: new Set() })
}
allAreSelected () {
const { accounts } = this.props
const { selectedAccounts } = this.state
return accounts.every(({ address }) => selectedAccounts.has(address))
}
renderAccountsList = () => {
const { accounts, selectAccount, nativeCurrency, addressLastConnectedMap } = this.props
const { accounts, nativeCurrency, addressLastConnectedMap } = this.props
const { selectedAccounts } = this.state
return (
<div className="permissions-connect-choose-account__accounts-list">
{
@ -39,10 +83,14 @@ export default class ChooseAccount extends Component {
return (
<div
key={`permissions-connect-choose-account-${index}`}
onClick={ () => selectAccount(address) }
onClick={ () => this.handleAccountClick(address) }
className="permissions-connect-choose-account__account"
>
<div className="permissions-connect-choose-account__account-info-wrapper">
<CheckBox
className="permissions-connect-choose-account__list-check-box"
checked={ selectedAccounts.has(address) }
/>
<Identicon
diameter={34}
address={address}
@ -76,31 +124,86 @@ export default class ChooseAccount extends Component {
)
}
renderAccountsListHeader () {
const { t } = this.context
const { selectNewAccountViaModal, accounts } = this.props
return (
<div
className={classnames({
'permissions-connect-choose-account__accounts-list-header--one-item': accounts.length === 1,
'permissions-connect-choose-account__accounts-list-header--two-items': accounts.length > 1,
})}
>
{ accounts.length > 1
? (
<div className="permissions-connect-choose-account__select-all">
<CheckBox
className="permissions-connect-choose-account__header-check-box"
checked={this.allAreSelected()}
onClick={() => (this.allAreSelected() ? this.deselectAll() : this.selectAll())}
/>
<div className="permissions-connect-choose-account__text-grey">{ this.context.t('selectAll') }</div>
<Tooltip
position="bottom"
html={(
<div style={{ width: 200, padding: 4 }}>
{t('selectingAllWillAllow')}
</div>
)}
>
<i className="fa fa-info-circle" />
</Tooltip>
</div>
)
: null
}
<div
className="permissions-connect-choose-account__text-blue"
onClick={() => selectNewAccountViaModal(this.handleAccountClick.bind(this))}
>
{ this.context.t('newAccount') }
</div>
</div>
)
}
render () {
const { originName, selectNewAccountViaModal, permissionsRequestId, cancelPermissionsRequest } = this.props
const {
selectAccounts,
permissionsRequestId,
cancelPermissionsRequest,
targetDomainMetadata,
accounts,
} = this.props
const { selectedAccounts } = this.state
const { t } = this.context
return (
<div className="permissions-connect-choose-account">
<div className="permissions-connect-choose-account__title">
{ t('chooseAnAcount') }
</div>
<div className="permissions-connect-choose-account__text">
{ t('toConnectWith', [originName]) }
</div>
<PermissionsConnectHeader
icon={targetDomainMetadata.icon}
iconName={targetDomainMetadata.origin}
headerTitle={t('connectWithMetaMask')}
headerText={accounts.length > 0
? t('chooseAccountsToUse')
: t('connectAccountOrCreate')
}
/>
{ this.renderAccountsListHeader() }
{ this.renderAccountsList() }
<div className="permissions-connect-choose-account__bottom-buttons">
<div
<Button
onClick={ () => cancelPermissionsRequest(permissionsRequestId) }
className="permissions-connect-choose-account__cancel"
type="default"
>
{ t('cancel') }
</div>
<div
onClick={ () => selectNewAccountViaModal() }
className="permissions-connect-choose-account__new-account"
</Button>
<Button
onClick={ () => selectAccounts(selectedAccounts) }
type="primary"
disabled={ selectedAccounts.size === 0 }
>
{ t('newAccount') }
</div>
{ t('next') }
</Button>
</div>
</div>
)

View File

@ -1,34 +1,93 @@
.permissions-connect-choose-account {
display: flex;
flex-direction: column;
margin-top: 40px;
width: 100%;
align-items: center;
margin-top: 40px;
width: 428px;
margin-left: auto;
margin-right: auto;
&__title {
@extend %header--18;
}
&__text {
&__text, &__text--blue, &__text--grey {
@extend %content-text;
line-height: 25px;
}
&__text-blue {
color: $curious-blue;
cursor: pointer;
}
&__text-grey {
color: $Grey-500;
}
&__accounts-list {
width: 393px;
width: 100%;
border: 1px solid #D0D5DA;
box-sizing: border-box;
border-radius: 8px;
margin-top: 36px;
margin-top: 8px;
max-height: 338px;
overflow-y: auto;
@media screen and (max-width: 575px) {
width: 100%;
}
}
&__accounts-list-header--one-item,
&__accounts-list-header--two-items {
display: flex;
margin-top: 36px;
width: 100%;
padding-right: 2px;
}
&__accounts-list-header--one-item {
justify-content: flex-end;
}
&__accounts-list-header--two-items {
justify-content: space-between;
}
&__account-info-wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
}
&__list-check-box {
margin-right: 24px;
}
&__header-check-box {
margin-right: 16px;
}
&__select-all {
display: flex;
margin-left: 16px;
align-items: center;
.fa-info-circle, .fa-info-circle:hover {
color: $silver;
cursor: pointer;
margin-left: 8px;
font-size: 0.9rem;
}
.fa-info-circle {
cursor: pointer;
}
.fa-info-circle:hover {
color: $mid-gray;
}
}
&__account {
@ -76,22 +135,23 @@
}
}
&__new-account, &__cancel {
@extend %content-text;
line-height: 20px;
color: #037DD6;
margin-top: 24px;
cursor: pointer;
}
&__cancel {
color: $Red-400;
}
&__bottom-buttons {
display: flex;
justify-content: space-around;
width: 393px;
justify-content: space-between;
width: 100%;
margin-top: 16px;
button {
width: 124px;
}
.btn-default {
background: white;
}
}
}

View File

@ -1,5 +1,3 @@
@import 'permissions-connect-header/index';
@import 'permissions-connect-footer/index';
@import 'choose-account/index';
@ -8,4 +6,20 @@
width: 100%;
position: relative;
background: white;
&__page-count-wrapper {
margin-top: 26px;
margin-left: 20px;
display: flex;
justify-content: flex-end;
align-items: flex-end;
&__page-count {
@extend %content-text;
margin-right: 30px;
font-size: 12px;
line-height: 17px;
color: #6A737D;
}
}
}

View File

@ -10,7 +10,6 @@ export default class PermissionsConnectFooter extends Component {
const { t } = this.context
return (
<div className="permissions-connect-footer">
<img src="/images/mm-secure.svg" />
<div className="permissions-connect-footer__text">
<div>{ t('onlyConnectTrust') }</div>
<div
@ -18,7 +17,7 @@ export default class PermissionsConnectFooter extends Component {
onClick={() => {
global.platform.openWindow({ url: 'https://medium.com/metamask/privacy-mode-is-now-enabled-by-default-1c1c957f4d57' })
}}
>{ t('learnAboutRisks') }
>{ t('learnMore') }
</div>
</div>
</div>

View File

@ -1,15 +0,0 @@
.permissions-connect-header {
margin-top: 26px;
margin-left: 20px;
display: flex;
justify-content: space-between;
align-items: flex-end;
&__page-count {
@extend %content-text;
margin-right: 30px;
font-size: 12px;
line-height: 17px;
color: #6A737D;
}
}

View File

@ -1,23 +0,0 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import MetaFoxLogo from '../../../components/ui/metafox-logo'
export default class PermissionsConnectHeader extends Component {
static propTypes = {
page: PropTypes.number.isRequired,
}
render () {
const { page } = this.props
return (
<div className="permissions-connect-header">
<MetaFoxLogo
unsetIconHeight
/>
<div className="permissions-connect-header__page-count">
{ `${page}/2` }
</div>
</div>
)
}
}

View File

@ -1,7 +1,6 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom'
import PermissionsConnectHeader from './permissions-connect-header'
import PermissionsConnectFooter from './permissions-connect-footer'
import ChooseAccount from './choose-account'
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
@ -37,6 +36,7 @@ export default class PermissionConnect extends Component {
confirmPermissionPath: PropTypes.string.isRequired,
page: PropTypes.string.isRequired,
redirecting: PropTypes.bool,
targetDomainMetadata: PropTypes.object,
}
static defaultProps = {
@ -56,7 +56,7 @@ export default class PermissionConnect extends Component {
state = {
redirecting: false,
selectedAccountAddress: '',
selectedAccountAddresses: new Set(),
permissionAccepted: null,
originName: this.props.originName,
}
@ -94,9 +94,9 @@ export default class PermissionConnect extends Component {
}
}
selectAccount = (address) => {
selectAccounts = (addresses) => {
this.setState({
selectedAccountAddress: address,
selectedAccountAddresses: addresses,
}, () => this.props.history.push(this.props.confirmPermissionPath))
}
@ -161,13 +161,25 @@ export default class PermissionConnect extends Component {
connectPath,
confirmPermissionPath,
page,
targetDomainMetadata,
} = this.props
const { selectedAccountAddress, permissionAccepted, originName, redirecting } = this.state
const {
selectedAccountAddresses,
permissionAccepted,
originName,
redirecting,
} = this.state
return (
<div className="permissions-connect">
{ !redirecting
? <PermissionsConnectHeader page={page} />
? (
<div className="permissions-connect__page-count-wrapper">
<div className="permissions-connect-header__page-count">
{ `${page}/2` }
</div>
</div>
)
: null
}
<Switch>
@ -175,26 +187,31 @@ export default class PermissionConnect extends Component {
path={connectPath}
exact
render={() => (
<ChooseAccount
accounts={accounts}
originName={originName}
nativeCurrency={nativeCurrency}
selectAccount={(address) => this.selectAccount(address)}
selectNewAccountViaModal={() => {
showNewAccountModal({
onCreateNewAccount: this.selectAccount,
newAccountNumber,
})
}}
addressLastConnectedMap={addressLastConnectedMap}
cancelPermissionsRequest={(requestId) => {
if (requestId) {
rejectPermissionsRequest(requestId)
this.redirectFlow(false)
}
}}
permissionsRequestId={permissionsRequestId}
/>
<div>
<ChooseAccount
accounts={accounts}
originName={originName}
nativeCurrency={nativeCurrency}
selectAccounts={(addresses) => this.selectAccounts(addresses)}
selectNewAccountViaModal={(handleAccountClick) => {
showNewAccountModal({
onCreateNewAccount: (address) => handleAccountClick(address),
newAccountNumber,
})
}}
addressLastConnectedMap={addressLastConnectedMap}
cancelPermissionsRequest={(requestId) => {
if (requestId) {
rejectPermissionsRequest(requestId)
this.redirectFlow(false)
}
}}
permissionsRequestId={permissionsRequestId}
selectedAccountAddresses={selectedAccountAddresses}
targetDomainMetadata={targetDomainMetadata}
/>
{ !redirecting ? <PermissionsConnectFooter /> : null }
</div>
)}
/>
<Route
@ -212,11 +229,12 @@ export default class PermissionConnect extends Component {
rejectPermissionsRequest(requestId)
this.redirectFlow(false)
}}
selectedIdentity={accounts.find((account) => account.address === selectedAccountAddress)}
selectedIdentities={accounts.filter((account) => selectedAccountAddresses.has(account.address))}
redirect={redirecting}
permissionRejected={ permissionAccepted === false }
cachedOrigin={originName}
/>
<PermissionsConnectFooter />
{ !redirecting ? <PermissionsConnectFooter /> : null }
</div>
)}
/>

View File

@ -7,6 +7,7 @@ import {
getAccountsWithLabels,
getLastConnectedInfo,
getPermissionsDomains,
getTargetDomainMetadata,
} from '../../selectors/selectors'
import { formatDate } from '../../helpers/utils/util'
import { approvePermissionsRequest, rejectPermissionsRequest, showModal, getCurrentWindowTab, getRequestAccountTabIds } from '../../store/actions'
@ -52,6 +53,8 @@ const mapStateToProps = (state, ownProps) => {
throw new Error('Incorrect path for permissions-connect component')
}
const targetDomainMetadata = getTargetDomainMetadata(state, permissionsRequest, origin)
return {
permissionsRequest,
permissionsRequestId,
@ -65,6 +68,7 @@ const mapStateToProps = (state, ownProps) => {
connectPath,
confirmPermissionPath,
page,
targetDomainMetadata,
}
}

View File

@ -376,6 +376,17 @@ export function getDomainMetadata (state) {
return state.metamask.domainMetadata
}
export function getTargetDomainMetadata (state, request, defaultOrigin) {
const domainMetadata = getDomainMetadata(state)
const { metadata: requestMetadata = {} } = request || {}
const origin = requestMetadata.origin || defaultOrigin
const targetDomainMetadata = (domainMetadata[origin] || { name: origin, icon: null })
targetDomainMetadata.origin = origin
return targetDomainMetadata
}
export function getActiveTab (state) {
return state.activeTab
}