diff --git a/js/src/embed.js b/js/src/embed.js
new file mode 100644
index 000000000..f228d264e
--- /dev/null
+++ b/js/src/embed.js
@@ -0,0 +1,120 @@
+// Copyright 2015, 2016 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 .
+
+import 'babel-polyfill';
+import 'whatwg-fetch';
+
+import es6Promise from 'es6-promise';
+es6Promise.polyfill();
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { AppContainer } from 'react-hot-loader';
+
+import injectTapEventPlugin from 'react-tap-event-plugin';
+
+import SecureApi from '~/secureApi';
+import ContractInstances from '~/contracts';
+
+import { initStore } from '~/redux';
+import ContextProvider from '~/ui/ContextProvider';
+import muiTheme from '~/ui/Theme';
+
+import { patchApi } from '~/util/tx';
+import { setApi } from '~/redux/providers/apiActions';
+
+import '~/environment';
+
+import '../assets/fonts/Roboto/font.css';
+import '../assets/fonts/RobotoMono/font.css';
+
+injectTapEventPlugin();
+
+import ParityBar from '~/views/ParityBar';
+
+// Test transport (std transport should be provided as global object)
+class FakeTransport {
+ constructor () {
+ console.warn('Secure Transport not provided. Falling back to FakeTransport');
+ }
+
+ execute (method, ...params) {
+ console.log('Calling', method, params);
+ return Promise.reject('not connected');
+ }
+
+ on () {
+ }
+}
+
+class FrameSecureApi extends SecureApi {
+ constructor (transport) {
+ super('', null, () => {
+ return transport;
+ });
+ }
+
+ connect () {
+ // Do nothing - this API does not need connecting
+ this.emit('connecting');
+ // Fire connected event with some delay.
+ setTimeout(() => {
+ this.emit('connected');
+ });
+ }
+
+ needsToken () {
+ return false;
+ }
+
+ isConnecting () {
+ return false;
+ }
+
+ isConnected () {
+ return true;
+ }
+}
+
+const api = new FrameSecureApi(window.secureTransport || new FakeTransport());
+
+patchApi(api);
+ContractInstances.create(api);
+
+const store = initStore(api, null, true);
+
+store.dispatch({ type: 'initAll', api });
+store.dispatch(setApi(api));
+
+window.secureApi = api;
+
+const app = (
+
+);
+const container = document.querySelector('#container');
+
+ReactDOM.render(
+
+
+ { app }
+
+ ,
+ container
+);
diff --git a/js/src/index.ejs b/js/src/index.ejs
index 48cd5c0c0..590070e8b 100644
--- a/js/src/index.ejs
+++ b/js/src/index.ejs
@@ -27,7 +27,7 @@
-
Loading
+
Loading
diff --git a/js/src/redux/middleware.js b/js/src/redux/middleware.js
index bffeddc98..baaef358e 100644
--- a/js/src/redux/middleware.js
+++ b/js/src/redux/middleware.js
@@ -25,24 +25,27 @@ import CertificationsMiddleware from './providers/certifications/middleware';
import ChainMiddleware from './providers/chainMiddleware';
import RegistryMiddleware from './providers/registry/middleware';
-export default function (api, browserHistory) {
+export default function (api, browserHistory, forEmbed = false) {
const errors = new ErrorsMiddleware();
const signer = new SignerMiddleware(api);
const settings = new SettingsMiddleware();
- const status = statusMiddleware();
- const certifications = new CertificationsMiddleware();
- const routeMiddleware = routerMiddleware(browserHistory);
const chain = new ChainMiddleware();
- const registry = new RegistryMiddleware(api);
-
const middleware = [
settings.toMiddleware(),
signer.toMiddleware(),
errors.toMiddleware(),
- certifications.toMiddleware(),
- chain.toMiddleware(),
- registry
+ chain.toMiddleware()
];
+ if (!forEmbed) {
+ const certifications = new CertificationsMiddleware().toMiddleware();
+ const registry = new RegistryMiddleware(api);
+
+ middleware.push(certifications, registry);
+ }
+
+ const status = statusMiddleware();
+ const routeMiddleware = browserHistory ? routerMiddleware(browserHistory) : [];
+
return middleware.concat(status, routeMiddleware, thunk);
}
diff --git a/js/src/redux/store.js b/js/src/redux/store.js
index 132375784..dff56bd20 100644
--- a/js/src/redux/store.js
+++ b/js/src/redux/store.js
@@ -33,9 +33,9 @@ const storeCreation = window.devToolsExtension
? window.devToolsExtension()(createStore)
: createStore;
-export default function (api, browserHistory) {
+export default function (api, browserHistory, forEmbed = false) {
const reducers = initReducers();
- const middleware = initMiddleware(api, browserHistory);
+ const middleware = initMiddleware(api, browserHistory, forEmbed);
const store = applyMiddleware(...middleware)(storeCreation)(reducers);
BalancesProvider.instantiate(store, api);
diff --git a/js/src/secureApi.js b/js/src/secureApi.js
index b39ecaf3b..8ee0d5196 100644
--- a/js/src/secureApi.js
+++ b/js/src/secureApi.js
@@ -15,12 +15,12 @@
// along with Parity. If not, see .
import { uniq } from 'lodash';
+import store from 'store';
import Api from './api';
import { LOG_KEYS, getLogger } from '~/config';
const log = getLogger(LOG_KEYS.Signer);
-const sysuiToken = window.localStorage.getItem('sysuiToken');
export default class SecureApi extends Api {
_isConnecting = false;
@@ -31,13 +31,18 @@ export default class SecureApi extends Api {
_dappsPort = 8080;
_signerPort = 8180;
- constructor (url, nextToken) {
- const transport = new Api.Transport.Ws(url, sysuiToken, false);
+ static getTransport (url, sysuiToken) {
+ return new Api.Transport.Ws(url, sysuiToken, false);
+ }
+
+ constructor (url, nextToken, getTransport = SecureApi.getTransport) {
+ const sysuiToken = store.get('sysuiToken');
+ const transport = getTransport(url, sysuiToken);
+
super(transport);
this._url = url;
-
- // Try tokens from localstorage, from hash and 'initial'
+ // Try tokens from localStorage, from hash and 'initial'
this._tokens = uniq([sysuiToken, nextToken, 'initial'])
.filter((token) => token)
.map((token) => ({ value: token, tried: false }));
@@ -308,7 +313,7 @@ export default class SecureApi extends Api {
}
_saveToken (token) {
- window.localStorage.setItem('sysuiToken', token);
+ store.set('sysuiToken', token);
}
/**
diff --git a/js/src/ui/Tooltips/reducers.js b/js/src/ui/Tooltips/reducers.js
index cc0ebf926..1d05de954 100644
--- a/js/src/ui/Tooltips/reducers.js
+++ b/js/src/ui/Tooltips/reducers.js
@@ -14,13 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see .
+import store from 'store';
+
const LS_KEY = 'tooltips';
let currentId = -1;
let maxId = 0;
function closeTooltips (state, action) {
- window.localStorage.setItem(LS_KEY, '{"state":"off"}');
+ store.set(LS_KEY, '{"state":"off"}');
currentId = -1;
@@ -41,7 +43,7 @@ function newTooltip (state, action) {
}
function nextTooltip (state, action) {
- const hideTips = window.localStorage.getItem(LS_KEY);
+ const hideTips = store.get(LS_KEY);
currentId = hideTips
? -1
diff --git a/js/src/views/Application/store.js b/js/src/views/Application/store.js
index 535d0942b..cc1968f37 100644
--- a/js/src/views/Application/store.js
+++ b/js/src/views/Application/store.js
@@ -15,17 +15,14 @@
// along with Parity. If not, see .
import { action, observable } from 'mobx';
+import store from 'store';
export default class Store {
@observable firstrunVisible = false;
constructor (api) {
this._api = api;
-
- const value = window.localStorage.getItem('showFirstRun');
- if (value) {
- this.firstrunVisible = JSON.parse(value);
- }
+ this.firstrunVisible = store.get('showFirstRun');
this._checkAccounts();
}
@@ -36,7 +33,7 @@ export default class Store {
@action toggleFirstrun = (visible = false) => {
this.firstrunVisible = visible;
- window.localStorage.setItem('showFirstRun', JSON.stringify(!!visible));
+ store.set('showFirstRun', !!visible);
}
_checkAccounts () {
diff --git a/js/src/views/ParityBar/parityBar.js b/js/src/views/ParityBar/parityBar.js
index d75890a90..1c7fdaeb3 100644
--- a/js/src/views/ParityBar/parityBar.js
+++ b/js/src/views/ParityBar/parityBar.js
@@ -26,7 +26,7 @@ import { Badge, Button, ContainerTitle, ParityBackground } from '~/ui';
import { Embedded as Signer } from '../Signer';
import DappsStore from '~/views/Dapps/dappsStore';
-import imagesEthcoreBlock from '../../../assets/images/parity-logo-white-no-text.svg';
+import imagesEthcoreBlock from '!url-loader!../../../assets/images/parity-logo-white-no-text.svg';
import styles from './parityBar.css';
const LS_STORE_KEY = '_parity::parityBar';
@@ -43,6 +43,7 @@ class ParityBar extends Component {
static propTypes = {
dapp: PropTypes.bool,
+ externalLink: PropTypes.string,
pending: PropTypes.array
};
@@ -82,12 +83,32 @@ class ParityBar extends Component {
}
if (count < newCount) {
- this.setState({ opened: true });
+ this.setOpened(true);
} else if (newCount === 0 && count === 1) {
- this.setState({ opened: false });
+ this.setOpened(false);
}
}
+ setOpened (opened) {
+ this.setState({ opened });
+
+ if (!this.bar) {
+ return;
+ }
+
+ // Fire up custom even to support having parity bar iframed.
+ const event = new CustomEvent('parity.bar.visibility', {
+ bubbles: true,
+ detail: { opened }
+ });
+
+ this.bar.dispatchEvent(event);
+ }
+
+ onRef = (element) => {
+ this.bar = element;
+ }
+
render () {
const { moving, opened, position } = this.state;
@@ -168,21 +189,20 @@ class ParityBar extends Component {
/>
);
- const dragButtonClasses = [ styles.dragButton ];
-
- if (this.state.moving) {
- dragButtonClasses.push(styles.moving);
- }
+ const parityButton = (
+
+ );
return (
-