Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Extension installation overlay (#4423)
Browse files Browse the repository at this point in the history
* Extension installation overlay

* Pr gumbles

* Spelling

* Update Chrome URL
  • Loading branch information
jacogr committed Feb 3, 2017
1 parent 532567d commit fa9204d
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 0 deletions.
1 change: 1 addition & 0 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
"scryptsy": "2.0.0",
"solc": "ngotchac/solc-js",
"store": "1.3.20",
"useragent.js": "0.5.6",
"utf8": "2.1.2",
"valid-url": "1.0.9",
"validator": "6.2.0",
Expand Down
52 changes: 52 additions & 0 deletions js/src/views/Application/Extension/extension.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Copyright 2015-2017 Parity Technologies (UK) Ltd.
/* This file is part of Parity.
/*
/* Parity is free software: you can redistribute it and/or modify
/* it under the terms of the GNU General Public License as published by
/* the Free Software Foundation, either version 3 of the License, or
/* (at your option) any later version.
/*
/* Parity is distributed in the hope that it will be useful,
/* but WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/* GNU General Public License for more details.
/*
/* You should have received a copy of the GNU General Public License
/* along with Parity. If not, see <http://www.gnu.org/licenses/>.
*/

.body {
background: #f80;
color: white;
opacity: 1;
max-width: 500px;
padding: 1em 4em 1em 2em;
position: fixed;
right: 1.5em;
top: 1.5em;
z-index: 1000;

.button {
background: rgba(0, 0, 0, 0.5);
color: white !important;

svg {
fill: white !important;
}
}

.buttonrow {
text-align: right;
}

p {
color: white;
}

.close {
cursor: pointer;
position: absolute;
right: 1em;
top: 1em;
}
}
74 changes: 74 additions & 0 deletions js/src/views/Application/Extension/extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import { observer } from 'mobx-react';
import React, { Component } from 'react';
import { FormattedMessage } from 'react-intl';

import { Button } from '~/ui';
import { CloseIcon, CheckIcon } from '~/ui/Icons';

import Store from './store';
import styles from './extension.css';

@observer
export default class Extension extends Component {
store = new Store();

render () {
const { showWarning } = this.store;

if (!showWarning) {
return null;
}

return (
<div className={ styles.body }>
<CloseIcon
className={ styles.close }
onClick={ this.onClose }
/>
<p>
<FormattedMessage
id='extension.intro'
defaultMessage='Parity now has an extension available for Chrome that allows safe browsing of Ethereum-enabled distributed applications. It is highly recommended that you install this extension to further enhance your Parity experience.'
/>
</p>
<p className={ styles.buttonrow }>
<Button
className={ styles.button }
icon={ <CheckIcon /> }
label={
<FormattedMessage
id='extension.install'
defaultMessage='Install the extension now'
/>
}
onClick={ this.onInstallClick }
/>
</p>
</div>
);
}

onClose = () => {
this.store.snoozeWarning();
}

onInstallClick = () => {
this.store.installExtension();
}
}
17 changes: 17 additions & 0 deletions js/src/views/Application/Extension/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

export default from './extension';
89 changes: 89 additions & 0 deletions js/src/views/Application/Extension/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

/* global chrome */

import { action, computed, observable } from 'mobx';

import store from 'store';
import browser from 'useragent.js/lib/browser';

const A_DAY = 24 * 60 * 60 * 1000;
const NEXT_DISPLAY = '_parity::extensionWarning::nextDisplay';

// 'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig';
const EXTENSION_PAGE = 'https://chrome.google.com/webstore/detail/himekenlppkgeaoeddcliojfddemadig';

export default class Store {
@observable isInstalling = false;
@observable nextDisplay = 0;
@observable shouldInstall = false;

constructor () {
this.nextDisplay = store.get(NEXT_DISPLAY) || 0;
this.testInstall();
}

@computed get showWarning () {
return !this.isInstalling && this.shouldInstall && (Date.now() > this.nextDisplay);
}

@action setInstalling = (isInstalling) => {
this.isInstalling = isInstalling;
}

@action snoozeWarning = (sleep = A_DAY) => {
this.nextDisplay = Date.now() + sleep;
store.set(NEXT_DISPLAY, this.nextDisplay);
}

@action testInstall = () => {
this.shouldInstall = this.readStatus();
}

readStatus = () => {
const hasExtension = Symbol.for('parity.extension') in window;
const ua = browser.analyze(navigator.userAgent || '');

if (hasExtension) {
return false;
}

return (ua || {}).name.toLowerCase() === 'chrome';
}

installExtension = () => {
this.setInstalling(true);

return new Promise((resolve, reject) => {
const link = document.createElement('link');

link.setAttribute('rel', 'chrome-webstore-item');
link.setAttribute('href', EXTENSION_PAGE);
document.querySelector('head').appendChild(link);

if (chrome && chrome.webstore && chrome.webstore.install) {
chrome.webstore.install(EXTENSION_PAGE, resolve, reject);
} else {
reject(new Error('Direct installation failed.'));
}
})
.catch((error) => {
console.warn('Unable to perform direct install', error);
window.open(EXTENSION_PAGE, '_blank');
});
}
}
2 changes: 2 additions & 0 deletions js/src/views/Application/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ParityBar from '../ParityBar';
import Snackbar from './Snackbar';
import Container from './Container';
import DappContainer from './DappContainer';
import Extension from './Extension';
import FrameError from './FrameError';
import Status from './Status';
import Store from './store';
Expand Down Expand Up @@ -104,6 +105,7 @@ class Application extends Component {
? <Status upgradeStore={ this.upgradeStore } />
: null
}
<Extension />
<Snackbar />
</Container>
);
Expand Down

0 comments on commit fa9204d

Please sign in to comment.