diff --git a/src/renderer/component/splash/index.js b/src/renderer/component/splash/index.js index 932265392..2464b48fa 100644 --- a/src/renderer/component/splash/index.js +++ b/src/renderer/component/splash/index.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux'; import { selectDaemonVersionMatched } from 'redux/selectors/app'; import { selectNotification } from 'lbry-redux'; -import { doCheckDaemonVersion } from 'redux/actions/app'; +import { doCheckDaemonVersion, doNotifyUnlockWallet } from 'redux/actions/app'; import SplashScreen from './view'; const select = state => ({ @@ -11,6 +11,10 @@ const select = state => ({ const perform = dispatch => ({ checkDaemonVersion: () => dispatch(doCheckDaemonVersion()), + notifyUnlockWallet: () => dispatch(doNotifyUnlockWallet()), }); -export default connect(select, perform)(SplashScreen); +export default connect( + select, + perform +)(SplashScreen); diff --git a/src/renderer/component/splash/view.jsx b/src/renderer/component/splash/view.jsx index 5985503c9..79bb92ffa 100644 --- a/src/renderer/component/splash/view.jsx +++ b/src/renderer/component/splash/view.jsx @@ -1,12 +1,14 @@ import * as React from 'react'; import { Lbry, MODALS } from 'lbry-redux'; import LoadScreen from './internal/load-screen'; +import ModalWalletUnlock from 'modal/modalWalletUnlock'; import ModalIncompatibleDaemon from 'modal/modalIncompatibleDaemon'; import ModalUpgrade from 'modal/modalUpgrade'; import ModalDownloading from 'modal/modalDownloading'; type Props = { checkDaemonVersion: () => Promise, + notifyUnlockWallet: () => Promise, notification: ?{ id: string, }, @@ -17,6 +19,7 @@ type State = { message: string, isRunning: boolean, isLagging: boolean, + launchedModal: boolean, }; export class SplashScreen extends React.PureComponent { @@ -28,18 +31,23 @@ export class SplashScreen extends React.PureComponent { message: __('Connecting'), isRunning: false, isLagging: false, + launchedModal: false, }; } updateStatus() { Lbry.status().then(status => { this._updateStatusCallback(status); + window.status = status; }); } _updateStatusCallback(status) { + const { notifyUnlockWallet } = this.props; + const { launchedModal } = this.state; + const startupStatus = status.startup_status; - if (startupStatus.code == 'started') { + if (startupStatus.code === 'started') { // Wait until we are able to resolve a name before declaring // that we are done. // TODO: This is a hack, and the logic should live in the daemon @@ -61,6 +69,7 @@ export class SplashScreen extends React.PureComponent { }); return; } + if (status.blockchain_status && status.blockchain_status.blocks_behind > 0) { const format = status.blockchain_status.blocks_behind == 1 ? '%s block behind' : '%s blocks behind'; @@ -69,6 +78,17 @@ export class SplashScreen extends React.PureComponent { details: __(format, status.blockchain_status.blocks_behind), isLagging: startupStatus.is_lagging, }); + } else if (startupStatus.code === 'waiting_for_wallet_unlock') { + this.setState({ + message: __('Unlock Wallet'), + details: __('Please unlock your wallet to proceed.'), + isLagging: false, + isRunning: true, + }); + + if (launchedModal === false) { + this.setState({ launchedModal: true }, () => notifyUnlockWallet()); + } } else { this.setState({ message: __('Network Loading'), @@ -114,6 +134,7 @@ export class SplashScreen extends React.PureComponent { in the modals won't work. */} {isRunning && ( + {notificationId === MODALS.WALLET_UNLOCK && } {notificationId === MODALS.INCOMPATIBLE_DAEMON && } {notificationId === MODALS.UPGRADE && } {notificationId === MODALS.DOWNLOADING && } diff --git a/src/renderer/modal/modalRouter/view.jsx b/src/renderer/modal/modalRouter/view.jsx index 9f4cd609e..34152119f 100644 --- a/src/renderer/modal/modalRouter/view.jsx +++ b/src/renderer/modal/modalRouter/view.jsx @@ -23,6 +23,9 @@ import ModalSendTip from '../modalSendTip'; import ModalPublish from '../modalPublish'; import ModalOpenExternalLink from '../modalOpenExternalLink'; import ModalConfirmThumbnailUpload from 'modal/modalConfirmThumbnailUpload'; +import ModalWalletEncrypt from 'modal/modalWalletEncrypt'; +import ModalWalletDecrypt from 'modal/modalWalletDecrypt'; +import ModalWalletUnlock from 'modal/modalWalletUnlock'; type Props = { modal: string, @@ -165,6 +168,12 @@ class ModalRouter extends React.PureComponent { return ; case MODALS.CONFIRM_THUMBNAIL_UPLOAD: return ; + case MODALS.WALLET_ENCRYPT: + return ; + case MODALS.WALLET_DECRYPT: + return ; + case MODALS.WALLET_UNLOCK: + return ; default: return null; } diff --git a/src/renderer/modal/modalWalletDecrypt/index.js b/src/renderer/modal/modalWalletDecrypt/index.js new file mode 100644 index 000000000..5df3acdc2 --- /dev/null +++ b/src/renderer/modal/modalWalletDecrypt/index.js @@ -0,0 +1,23 @@ +import { connect } from 'react-redux'; +import { + doHideNotification, + doWalletStatus, + doWalletDecrypt, + selectWalletDecryptSucceeded, +} from 'lbry-redux'; +import ModalWalletDecrypt from './view'; + +const select = state => ({ + walletDecryptSucceded: selectWalletDecryptSucceeded(state), +}); + +const perform = dispatch => ({ + closeModal: () => dispatch(doHideNotification()), + decryptWallet: password => dispatch(doWalletDecrypt(password)), + updateWalletStatus: () => dispatch(doWalletStatus()), +}); + +export default connect( + select, + perform +)(ModalWalletDecrypt); diff --git a/src/renderer/modal/modalWalletDecrypt/view.jsx b/src/renderer/modal/modalWalletDecrypt/view.jsx new file mode 100644 index 000000000..0452d7956 --- /dev/null +++ b/src/renderer/modal/modalWalletDecrypt/view.jsx @@ -0,0 +1,61 @@ +// @flow +import React from 'react'; +import { FormRow, FormField } from 'component/common/form'; +import { Modal } from 'modal/modal'; +import Button from 'component/button'; + +type Props = { + closeModal: () => void, + unlockWallet: string => void, + walletDecryptSucceded: boolean, + updateWalletStatus: boolean, +}; + +class ModalWalletDecrypt extends React.PureComponent { + state = { + submitted: false, // Prior actions could be marked complete + }; + + submitDecryptForm() { + this.setState({ submitted: true }); + this.props.decryptWallet(); + } + + componentDidUpdate() { + const { props, state } = this; + + if (state.submitted && props.walletDecryptSucceded === true) { + props.closeModal(); + props.updateWalletStatus(); + } + } + + render() { + const { closeModal, walletDecryptSucceded } = this.props; + + return ( + this.submitDecryptForm()} + onAborted={closeModal} + > + {__( + 'Your wallet has been encrypted with a local password, performing this action will remove this password.' + )} + +