diff --git a/react/src/actions/actions/addCoin.js b/react/src/actions/actions/addCoin.js
index ab2e2181d..642631db7 100644
--- a/react/src/actions/actions/addCoin.js
+++ b/react/src/actions/actions/addCoin.js
@@ -243,7 +243,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
console.warn(acData);
dispatch(
triggerToaster(
- `Error starting ${coin} daemon. Port ${acData.rpc} is already taken!`, // translate
+ translate('TOASTR.ERROR_STARTING_DAEMON', coin) + ' ' + translate('TOASTR.PORT_IS_TAKEN', acData.rpc),
translate('TOASTR.SERVICE_NOTIFICATION'),
'error',
false
diff --git a/react/src/actions/actions/coinList.js b/react/src/actions/actions/coinList.js
index c078fb0ba..7a69e197e 100644
--- a/react/src/actions/actions/coinList.js
+++ b/react/src/actions/actions/coinList.js
@@ -1,6 +1,54 @@
import { triggerToaster } from '../actionCreators';
import Config from '../../config';
+export function shepherdElectrumLock() {
+ return new Promise((resolve, reject) => {
+ fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/lock`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: '',
+ })
+ .catch((error) => {
+ console.log(error);
+ dispatch(
+ triggerToaster(
+ 'shepherdElectrumLock',
+ 'Error',
+ 'error'
+ )
+ );
+ })
+ .then(response => response.json())
+ .then(json => resolve(json))
+ });
+}
+
+export function shepherdElectrumLogout() {
+ return new Promise((resolve, reject) => {
+ fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/logout`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: '',
+ })
+ .catch((error) => {
+ console.log(error);
+ dispatch(
+ triggerToaster(
+ 'shepherdElectrumLogout',
+ 'Error',
+ 'error'
+ )
+ );
+ })
+ .then(response => response.json())
+ .then(json => resolve(json))
+ });
+}
+
export function shepherdStopCoind(coin) {
return new Promise((resolve, reject) => {
fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/coind/stop`, {
@@ -25,14 +73,19 @@ export function shepherdStopCoind(coin) {
});
}
-export function shepherdRemoveCoin(coin) {
+export function shepherdRemoveCoin(coin, mode) {
return new Promise((resolve, reject) => {
fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/coins/remove`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
- body: coin === 'KMD' ? '' : JSON.stringify({ chain: coin }),
+ body: JSON.stringify(coin === 'KMD' && mode === 'native' ? {
+ mode,
+ } : {
+ mode,
+ chain: coin,
+ }),
})
.catch((error) => {
console.log(error);
diff --git a/react/src/components/addcoin/addcoin.js b/react/src/components/addcoin/addcoin.js
index 56e9f57d3..43237f64c 100644
--- a/react/src/components/addcoin/addcoin.js
+++ b/react/src/components/addcoin/addcoin.js
@@ -128,7 +128,7 @@ class AddCoin extends React.Component {
addCoinProps.display !== this.state.display) {
this.setState(Object.assign({}, this.state, {
display: addCoinProps.display,
- modalClassName: addCoinProps.display ? 'show fade' : 'show fade',
+ modalClassName: 'show fade',
}));
setTimeout(() => {
diff --git a/react/src/components/dashboard/claimInterestModal/claimInterestModal.js b/react/src/components/dashboard/claimInterestModal/claimInterestModal.js
index 13cff7858..8fe21d3ea 100755
--- a/react/src/components/dashboard/claimInterestModal/claimInterestModal.js
+++ b/react/src/components/dashboard/claimInterestModal/claimInterestModal.js
@@ -35,7 +35,9 @@ class ClaimInterestModal extends React.Component {
}
componentWillMount() {
- this.loadListUnspent();
+ if (this.props.ActiveCoin.mode === 'native') {
+ this.loadListUnspent();
+ }
}
loadListUnspent() {
diff --git a/react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js b/react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js
index 1d02e9731..a423385b9 100644
--- a/react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js
+++ b/react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js
@@ -15,7 +15,7 @@ export const _ClaimInterestTableRender = function() {
className="btn btn-default btn-xs clipboard-edexaddr copy-string-btn"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this.copyTxId(_transactionsList[i].txid) }>
- { translate('INDEX.COPY') }
+ { translate('INDEX.COPY') + ' TXID' }
{ _transactionsList[i].address } |
diff --git a/react/src/components/dashboard/coinTile/coinTileItem.js b/react/src/components/dashboard/coinTile/coinTileItem.js
index e3d3e4493..cbd3c6419 100644
--- a/react/src/components/dashboard/coinTile/coinTileItem.js
+++ b/react/src/components/dashboard/coinTile/coinTileItem.js
@@ -30,7 +30,7 @@ import Config from '../../../config';
import CoinTileItemRender from './coinTileItem.render';
-const SPV_DASHBOARD_UPDATE_TIMEOUT = 60000;
+const SPV_DASHBOARD_UPDATE_TIMEOUT = 10000;
const ACTIVE_HANDLE_TIMEOUT_COIND_NATIVE = 15000;
const COIND_DOWN_MODAL_FETCH_FAILURES_THRESHOLD = window.require('electron').remote.getCurrentWindow().appConfig.failedRPCAttemptsThreshold || 10;
@@ -43,6 +43,28 @@ class CoinTileItem extends React.Component {
this.autoSetActiveCoin = this.autoSetActiveCoin.bind(this);
}
+ renderStopCoinButton() {
+ if (this.props.Main &&
+ this.props.Main.coins &&
+ this.props.Main.coins.native &&
+ this.props.Main.coins.native.length) {
+ return true;
+ }
+ }
+
+ renderRemoveCoinButton() {
+ if (this.props.Main &&
+ this.props.Main.coins &&
+ ((this.props.Main.coins.native &&
+ this.props.Main.coins.native.length &&
+ this.state.appConfig &&
+ !this.state.appConfig.stopNativeDaemonsOnQuit) ||
+ (this.props.Main.coins.spv &&
+ this.props.Main.coins.spv.length))) {
+ return true;
+ }
+ }
+
autoSetActiveCoin() {
const modes = [
'native',
@@ -97,8 +119,8 @@ class CoinTileItem extends React.Component {
});
}
- removeCoin(coin) {
- shepherdRemoveCoin(coin)
+ removeCoin(coin, mode) {
+ shepherdRemoveCoin(coin, mode)
.then((res) => {
Store.dispatch(
triggerToaster(
@@ -189,9 +211,7 @@ class CoinTileItem extends React.Component {
)
);
}
- }
-
- if (mode === 'spv') {
+ } else if (mode === 'spv') {
Store.dispatch(shepherdElectrumBalance(coin, this.props.Dashboard.electrumCoins[coin].pub));
Store.dispatch(shepherdElectrumTransactions(coin, this.props.Dashboard.electrumCoins[coin].pub));
}
diff --git a/react/src/components/dashboard/coinTile/coinTileItem.render.js b/react/src/components/dashboard/coinTile/coinTileItem.render.js
index f7b111708..08578f0e6 100644
--- a/react/src/components/dashboard/coinTile/coinTileItem.render.js
+++ b/react/src/components/dashboard/coinTile/coinTileItem.render.js
@@ -24,29 +24,17 @@ const CoinTileItemRender = function() {
- { item.mode === 'native' &&
- this.props.Main &&
- this.props.Main.coins &&
- this.props.Main.coins.native &&
- this.props.Main.coins.native.length &&
- this.props.Main.coins.native.length > 1 &&
+ { this.renderStopCoinButton() &&
this.stopCoind(item.coin) }
+ onClick={ () => this.stopCoind(item.coin, item.mode) }
title="Stop"
className="icon fa-stop-circle coind-stop-icon">
}
- { item.mode === 'native' &&
- this.props.Main &&
- this.props.Main.coins &&
- this.props.Main.coins.native &&
- this.props.Main.coins.native.length &&
- this.props.Main.coins.native.length > 1 &&
- this.state.appConfig &&
- !this.state.appConfig.stopNativeDaemonsOnQuit &&
+ { this.renderRemoveCoinButton() &&
this.removeCoin(item.coin) }
+ onClick={ () => this.removeCoin(item.coin, item.mode) }
title="Remove"
- className="icon fa-plus-circle coind-remove-icon">
+ className={ 'icon fa-plus-circle ' + (item.mode === 'spv' ? 'coind-remove-icon coind-remove-icon-spv' : 'coind-remove-icon') }>
}
{ this.props.Dashboard &&
this.props.Dashboard.electrumCoins &&
diff --git a/react/src/components/dashboard/importKeyModal/importKeyModal.js b/react/src/components/dashboard/importKeyModal/importKeyModal.js
index 5e130ce18..9e92e0519 100755
--- a/react/src/components/dashboard/importKeyModal/importKeyModal.js
+++ b/react/src/components/dashboard/importKeyModal/importKeyModal.js
@@ -77,11 +77,11 @@ class ImportKeyModal extends React.Component {
this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
- [e.target.name]: newValue,
+ [e.target.name === 'wifkeysPassphraseTextarea' ? 'wifkeysPassphrase' : e.target.name]: newValue,
});
} else {
this.setState({
- [e.target.name]: e.target.value,
+ [e.target.name === 'wifkeysPassphraseTextarea' ? 'wifkeysPassphrase' : e.target.name]: e.target.value,
});
}
}
@@ -174,7 +174,7 @@ class ImportKeyModal extends React.Component {
rescan ? translate('INDEX.WALLET_RESCAN_FINISHED') : translate('INDEX.ADDRESS_IMPORTED'),
translate('TOASTR.WALLET_NOTIFICATION'),
'success',
- false
+ rescan ? false : true,
)
);
} else {
@@ -187,6 +187,19 @@ class ImportKeyModal extends React.Component {
);
}
});
+
+ this.state({
+ passphraseWif: null,
+ passphraseAddress: null,
+ wifkeysPassphrase: null,
+ wifkeysPassphraseTextarea: null,
+ importWithRescan: this.state.importWithRescan ? false : this.state.importWithRescan,
+ });
+
+ // reset input vals
+ this.refs.wif
+ this.refs.wifkeysPassphrase.value = '';
+ this.refs.wifkeysPassphraseTextarea.value = '';
}
generateKeysFromPassphrase() {
diff --git a/react/src/components/dashboard/importKeyModal/importKeyModal.render.js b/react/src/components/dashboard/importKeyModal/importKeyModal.render.js
index 053d9ce56..a13065781 100644
--- a/react/src/components/dashboard/importKeyModal/importKeyModal.render.js
+++ b/react/src/components/dashboard/importKeyModal/importKeyModal.render.js
@@ -26,23 +26,25 @@ export const ImportKeyModalRender = function() {
{ translate('IMPORT_KEY.NOTICE') }: { translate('IMPORT_KEY.NOTICE_DESC') }.
{ translate('IMPORT_KEY.KMD_RESCAN_WARNING_TIME') }.
-
+
{ this.state.passphraseAddress &&
this.state.passphraseWif &&
@@ -118,6 +120,7 @@ export const ImportKeyModalRender = function() {
type="text"
className="form-control"
name="wif"
+ ref="wif"
onChange={ this.updateInput }
value={ this.state.wif } />
diff --git a/react/src/components/dashboard/navbar/navbar.js b/react/src/components/dashboard/navbar/navbar.js
index a5e9042ea..ec62a38bb 100755
--- a/react/src/components/dashboard/navbar/navbar.js
+++ b/react/src/components/dashboard/navbar/navbar.js
@@ -6,6 +6,10 @@ import {
stopInterval,
startInterval,
displayImportKeyModal,
+ shepherdElectrumLock,
+ shepherdElectrumLogout,
+ getDexCoins,
+ activeHandle,
} from '../../../actions/actionCreators';
import Store from '../../../store';
import Config from '../../../config';
@@ -23,6 +27,24 @@ class Navbar extends React.Component {
this.openDropMenu = this.openDropMenu.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this._checkAC = this._checkAC.bind(this);
+ this.spvLock = this.spvLock.bind(this);
+ this.spvLogout = this.spvLogout.bind(this);
+ }
+
+ spvLock() {
+ shepherdElectrumLock()
+ .then((res) => {
+ Store.dispatch(getDexCoins());
+ Store.dispatch(activeHandle());
+ });
+ }
+
+ spvLogout() {
+ shepherdElectrumLogout()
+ .then((res) => {
+ Store.dispatch(getDexCoins());
+ Store.dispatch(activeHandle());
+ });
}
componentWillMount() {
@@ -106,6 +128,9 @@ const mapStateToProps = (state) => {
Interval: {
interval: state.Interval.interval,
},
+ Main: {
+ isLoggedIn: state.Main.isLoggedIn,
+ },
};
};
diff --git a/react/src/components/dashboard/navbar/navbar.render.js b/react/src/components/dashboard/navbar/navbar.render.js
index fca2a46fa..14a7f7054 100644
--- a/react/src/components/dashboard/navbar/navbar.render.js
+++ b/react/src/components/dashboard/navbar/navbar.render.js
@@ -109,6 +109,26 @@ const NavbarRender = function() {
{ translate('ABOUT.ABOUT_AGAMA') }
+ { this.props.Main &&
+ this.props.Main.isLoggedIn &&
+ this.props.Main.spv &&
+ this.props.Main.spv.length &&
+
+
+ Lock
+
+
+ }
+ { this.props.Main &&
+ this.props.Main.isLoggedIn &&
+ this.props.Main.spv &&
+ this.props.Main.spv.length &&
+
+
+ Logout
+
+
+ }
diff --git a/react/src/components/dashboard/settings/settings.exportKeysPanel.js b/react/src/components/dashboard/settings/settings.exportKeysPanel.js
index e3c50be84..6fcada6a4 100644
--- a/react/src/components/dashboard/settings/settings.exportKeysPanel.js
+++ b/react/src/components/dashboard/settings/settings.exportKeysPanel.js
@@ -28,7 +28,12 @@ class ExportKeysPanel extends React.Component {
props.Dashboard.activeSection !== 'settings') {
this.setState(Object.assign({}, this.state, {
keys: null,
+ wifkeysPassphrase: '',
}));
+
+ // reset input vals
+ this.refs.wifkeysPassphrase.value = '';
+ this.refs.wifkeysPassphraseTextarea.value = '';
}
}
@@ -46,8 +51,12 @@ class ExportKeysPanel extends React.Component {
} else {
this.setState(Object.assign({}, this.state, {
keys: keys.result,
+ wifkeysPassphrase: '',
}));
- console.warn(keys);
+
+ // reset input vals
+ this.refs.wifkeysPassphrase.value = '';
+ this.refs.wifkeysPassphraseTextarea.value = '';
}
})
}
@@ -116,11 +125,11 @@ class ExportKeysPanel extends React.Component {
this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
- [e.target.name]: newValue,
+ [e.target.name === 'wifkeysPassphraseTextarea' ? 'wifkeysPassphrase' : e.target.name]: newValue,
});
} else {
this.setState({
- [e.target.name]: e.target.value,
+ [e.target.name === 'wifkeysPassphraseTextarea' ? 'wifkeysPassphrase' : e.target.name]: e.target.value,
});
}
}
@@ -162,23 +171,25 @@ class ExportKeysPanel extends React.Component {
-
+
{ this.state.keys &&
-
-
- |
- { translate('SETTINGS.ADDRESS_LIST') }
- |
-
- { translate('SETTINGS.WIF_KEY_LIST') }
- |
-
- { this.renderWifKeys() }
+
+
+
+ |
+ { translate('SETTINGS.ADDRESS_LIST') }
+ |
+
+ { translate('SETTINGS.WIF_KEY_LIST') }
+ |
+
+ { this.renderWifKeys() }
+
diff --git a/react/src/components/dashboard/walletsMain/walletsMain.render.js b/react/src/components/dashboard/walletsMain/walletsMain.render.js
index b14303a32..3e4a1a526 100644
--- a/react/src/components/dashboard/walletsMain/walletsMain.render.js
+++ b/react/src/components/dashboard/walletsMain/walletsMain.render.js
@@ -5,6 +5,7 @@ import SendCoin from '../sendCoin/sendCoin';
import WalletsProgress from '../walletsProgress/walletsProgress';
import WalletsData from '../walletsData/walletsData';
import ReceiveCoin from '../receiveCoin/receiveCoin';
+import { getCoinTitle } from '../../../util/coinHelper';
const WalletsMainRender = function() {
return (
@@ -22,7 +23,7 @@ const WalletsMainRender = function() {
- { this.props.ActiveCoin.coin }
+ { getCoinTitle(this.props.ActiveCoin.coin).name }
diff --git a/react/src/components/login/login.js b/react/src/components/login/login.js
index 55fc37ab5..8b655f8d9 100644
--- a/react/src/components/login/login.js
+++ b/react/src/components/login/login.js
@@ -8,7 +8,9 @@ import {
startInterval,
getDexCoins,
triggerToaster,
- toggleLoginSettingsModal
+ toggleLoginSettingsModal,
+ stopInterval,
+ dashboardChangeActiveCoin,
} from '../../actions/actionCreators';
import Config from '../../config';
import Store from '../../store';
@@ -197,16 +199,19 @@ class Login extends React.Component {
if (props.Login.pinList === 'no pins') {
props.Login.pinList = [];
}
+
if (props &&
props.Main &&
props.Main.isLoggedIn) {
if (props.Main.total === 0) {
this.setState({
activeLoginSection: 'activateCoin',
+ loginPassphrase: '',
display: true,
});
} else {
this.setState({
+ loginPassphrase: '',
display: false,
});
}
@@ -215,21 +220,51 @@ class Login extends React.Component {
if (props &&
props.Main &&
!props.Main.isLoggedIn) {
+ document.body.className = 'page-login layout-full page-dark';
+
+ if (props.Interval &&
+ props.Interval.interval &&
+ props.Interval.interval.sync) {
+ Store.dispatch(dashboardChangeActiveCoin());
+ Store.dispatch(
+ stopInterval(
+ 'sync',
+ props.Interval.interval
+ )
+ );
+ }
+
this.setState({
display: true,
activeLoginSection: this.state.activeLoginSection !== 'signup' ? 'login' : 'signup',
});
+ }
+ if (props.Main &&
+ props.Main.total === 0) {
document.body.className = 'page-login layout-full page-dark';
+
+ if (props.Interval &&
+ props.Interval.interval &&
+ props.Interval.interval.sync) {
+ Store.dispatch(dashboardChangeActiveCoin());
+ Store.dispatch(
+ stopInterval(
+ 'sync',
+ props.Interval.interval
+ )
+ );
+ }
}
if (this.state.activeLoginSection !== 'signup' &&
props &&
props.Main &&
props.Main.isLoggedIn) {
- this.setState({
- activeLoginSection: 'activateCoin',
- });
+ this.setState({
+ loginPassphrase: '',
+ activeLoginSection: 'activateCoin',
+ });
}
}
@@ -264,7 +299,7 @@ class Login extends React.Component {
this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
- [e.target.name]: newValue,
+ [e.target.name === 'loginPassphraseTextarea' ? 'loginPassphrase' : e.target.name]: newValue,
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue),
});
}
@@ -288,10 +323,14 @@ class Login extends React.Component {
loginSeed() {
// reset the login pass phrase values so that when the user logs out, the values are clear
this.setState({
- loginPassphrase: null,
+ loginPassphrase: '',
loginPassPhraseSeedType: null,
});
+ // reset login input vals
+ this.refs.loginPassphrase.value = '';
+ this.refs.loginPassphraseTextarea.value = '';
+
if (this.state.shouldEncryptSeed) {
Store.dispatch(encryptPassphrase(this.state.loginPassphrase, this.state.encryptKey, this.state.pubKey));
}
@@ -362,13 +401,6 @@ class Login extends React.Component {
}
execWalletCreate() {
- /*Store.dispatch(
- createNewWallet(
- this.state.randomSeedConfirm,
- this.props.Dashboard.activeHandle
- )
- );*/
-
Store.dispatch(
shepherdElectrumAuth(this.state.randomSeedConfirm)
);
diff --git a/react/src/components/login/login.render.js b/react/src/components/login/login.render.js
index c3f97f250..3442a9e80 100644
--- a/react/src/components/login/login.render.js
+++ b/react/src/components/login/login.render.js
@@ -55,13 +55,17 @@ const LoginRender = function () {
type="password"
className={ !this.state.seedInputVisibility ? 'form-control' : 'hide' }
name="loginPassphrase"
+ ref="loginPassphrase"
onChange={ this.updateLoginPassPhraseInput }
onKeyDown={ (event) => this.handleKeydown(event) }
+ autoComplete="off"
value={ this.state.loginPassphrase || '' } />
diff --git a/react/src/components/overrides.scss b/react/src/components/overrides.scss
index 8253a30cf..99a3facb8 100644
--- a/react/src/components/overrides.scss
+++ b/react/src/components/overrides.scss
@@ -375,6 +375,7 @@ select{
.header-easydex-section {
img {
width: 60px;
+ max-height: 60px;
}
}
}
@@ -511,4 +512,14 @@ select{
.coind-remove-icon {
transform: rotate(45deg);
top: 45px;
+}
+
+.coind-remove-icon-spv {
+ top: 19px;
+}
+
+.no-borders {
+ tbody > tr > td {
+ border: none;
+ }
}
\ No newline at end of file