From a0f9027180c31eb8aa312944d04d4caebd82939c Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 28 Mar 2018 14:25:22 -0500 Subject: [PATCH 01/12] feature(contactsform): tie up new contacts form to reducer --- app/components/Contacts/AddChannel.js | 154 ++++++++++++++++++ app/components/Contacts/AddChannel.scss | 141 ++++++++++++++++ app/components/Contacts/Network.js | 5 +- app/components/Contacts/Network.scss | 12 +- app/components/Contacts/SubmitChannelForm.js | 89 ++++++++++ .../Contacts/SubmitChannelForm.scss | 154 ++++++++++++++++++ app/components/Form/Form.js | 2 +- app/main.dev.js | 2 +- app/reducers/contactsform.js | 89 +++++++++- app/routes/app/components/App.js | 13 +- app/routes/app/components/App.scss | 2 +- app/routes/app/containers/AppContainer.js | 45 ++++- 12 files changed, 696 insertions(+), 12 deletions(-) create mode 100644 app/components/Contacts/AddChannel.js create mode 100644 app/components/Contacts/AddChannel.scss create mode 100644 app/components/Contacts/SubmitChannelForm.js create mode 100644 app/components/Contacts/SubmitChannelForm.scss diff --git a/app/components/Contacts/AddChannel.js b/app/components/Contacts/AddChannel.js new file mode 100644 index 00000000..92a23799 --- /dev/null +++ b/app/components/Contacts/AddChannel.js @@ -0,0 +1,154 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Isvg from 'react-inlinesvg' +import { FaCircle, FaQuestionCircle } from 'react-icons/lib/fa' + +import x from 'icons/x.svg' + +import styles from './AddChannel.scss' + +const AddChannel = ({ + contactsform, + contactsform: { showErrors }, + closeContactsForm, + openSubmitChannelForm, + updateContactFormSearchQuery, + updateManualFormSearchQuery, + updateContactCapacity, + setPubkey, + openChannel, + updateManualFormErrors, + activeChannelPubkeys, + nonActiveChannelPubkeys, + pendingOpenChannelPubkeys, + filteredNetworkNodes, + loadingChannelPubkeys, + showManualForm, + manualFormIsValid +}) => { + + const renderRightSide = (node) => { + if (loadingChannelPubkeys.includes(node.pub_key)) { + return ( + +
+
+
+ + ) + } + + if (activeChannelPubkeys.includes(node.pub_key)) { + return ( + + Online + + ) + } + + if (nonActiveChannelPubkeys.includes(node.pub_key)) { + return ( + + Offline + + ) + } + + if (pendingOpenChannelPubkeys.includes(node.pub_key)) { + return ( + + Pending + + ) + } + + if (!node.addresses.length) { + return ( + + Private + + ) + } + + return ( + { + // set the node public key for the submit form + setPubkey(node.pub_key) + // open the submit form + openSubmitChannelForm() + }} + > + Connect + + ) + } + + const searchUpdated = (search) => { + updateContactFormSearchQuery(search) + + if (search.includes('@') && search.split('@')[0].length === 66) { + updateManualFormSearchQuery(search) + } + } + + return ( +
+
+ searchUpdated(event.target.value)} + ref={input => input && input.focus()} + /> + + + +
+ +
+
    + { + filteredNetworkNodes.map(node => ( +
  • +
    + { + node.alias.length > 0 ? +

    + {node.alias.trim()} + ({node.pub_key.substr(0, 10)}...{node.pub_key.substr(node.pub_key.length - 10)}) +

    + : +

    + {node.pub_key} +

    + } +
    +
    + {renderRightSide(node)} +
    +
  • + )) + } +
+
+ + { + showManualForm && +
+

Hm, looks like we can't see that node from here, wanna try to manually connect?

+
Connect Manually
+
+ } +
+ ) +} + +AddChannel.propTypes = { + +} + +export default AddChannel diff --git a/app/components/Contacts/AddChannel.scss b/app/components/Contacts/AddChannel.scss new file mode 100644 index 00000000..eda5f64a --- /dev/null +++ b/app/components/Contacts/AddChannel.scss @@ -0,0 +1,141 @@ +@import '../../variables.scss'; + +.container { + position: relative; + width: 30%; + display: inline-block; + vertical-align: top; + height: 100vh; + background: #31343f; +} + +.header { + display: flex; + flex-direction: row; + justify-content: space-between; + background: linear-gradient(270deg, #868B9F 0%, #333C5E 100%); + padding: 15px 10px; + color: $white; + + input { + background: transparent; + outline: 0; + border: 0; + color: $white; + font-size: 14px; + width: 90%; + } + + .closeIcon { + cursor: pointer; + transition: all 0.25s; + + &:hover { + opacity: 0.5; + } + + svg { + height: 14px; + width: 14px; + } + } +} + +.nodes { + background: #31343F; + + .networkResults { + overflow-y: auto; + margin-top: 30px; + padding: 0 10px; + color: $white; + + li { + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 10px 0; + + h2 { + font-size: 10px; + font-weight: bold; + letter-spacing: 1.3px; + + span { + display: inline-block; + vertical-align: middle; + + &:nth-child(1) { + font-size: 10px; + font-weight: bold; + letter-spacing: 1.3px; + } + + &:nth-child(2) { + display: block; + color: $darkestgrey; + font-size: 8px; + margin-top: 5px; + } + } + } + + .connect { + cursor: pointer; + color: $darkestgrey; + transition: all 0.25s; + font-size: 10px; + + &:hover { + color: darken($darkestgrey, 10%); + } + } + + .inactive { + font-size: 10px; + + display: inline-block; + vertical-align: top; + + &.online { + color: $green; + } + + &.offline { + color: $darkestgrey; + } + + &.pending { + color: $orange; + } + + &.private { + color: darken($darkestgrey, 50%); + } + } + } + } +} + +.manualForm { + color: $white; + text-align: center; + margin: 0 25px; + + p { + font-size: 14px; + margin: 20px 0; + } + + div { + background: #383B47; + font-size: 16px; + padding: 10px; + cursor: pointer; + transition: all 0.25s; + + &:hover { + background: lighten(#383B47, 10%); + } + } +} \ No newline at end of file diff --git a/app/components/Contacts/Network.js b/app/components/Contacts/Network.js index 13a3c61f..8bba7417 100644 --- a/app/components/Contacts/Network.js +++ b/app/components/Contacts/Network.js @@ -6,6 +6,7 @@ import { FaAngleDown, FaCircle, FaRepeat } from 'react-icons/lib/fa' import { btc } from 'utils' import plus from 'icons/plus.svg' import search from 'icons/search.svg' + import styles from './Network.scss' class Network extends Component { @@ -100,7 +101,9 @@ class Network extends Component {
- + + +
diff --git a/app/components/Contacts/Network.scss b/app/components/Contacts/Network.scss index 7f9332e8..0eb56a29 100644 --- a/app/components/Contacts/Network.scss +++ b/app/components/Contacts/Network.scss @@ -2,7 +2,7 @@ .network { position: relative; - width: 20%; + width: 30%; display: inline-block; vertical-align: top; height: 100vh; @@ -33,8 +33,16 @@ cursor: pointer; transition: all 0.25s; + svg { + border-radius: 5px; + } + &:hover { - color: $darkestgrey; + opacity: 0.5; + + svg { + background: #272931; + } } } } diff --git a/app/components/Contacts/SubmitChannelForm.js b/app/components/Contacts/SubmitChannelForm.js new file mode 100644 index 00000000..e67f822b --- /dev/null +++ b/app/components/Contacts/SubmitChannelForm.js @@ -0,0 +1,89 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { FaAngleDown } from 'react-icons/lib/fa' +import Isvg from 'react-inlinesvg' +import x from 'icons/x.svg' + +import styles from './SubmitChannelForm.scss' + +class SubmitChannelForm extends React.Component { + render() { + const { + submitChannelFormOpen, + closeSubmitChannelForm, + + pubkey, + contactCapacity, + updateContactCapacity, + + toggleCurrencyProps: { + setContactsCurrencyFilters, + setCurrencyFilters, + showCurrencyFilters, + currencyName, + currentCurrencyFilters, + onCurrencyFilterClick, + contactFormUsdAmount + } + } = this.props + + if (!submitChannelFormOpen) { return null } + + return ( +
+
+ + + +
+ +
+
+

Add Funds to Network

+

Adding a connection will help you send and receive money on the Lightning Network. You aren't spening any money, rather moving the money you plan to use onto the network.

+
+ +
+

{pubkey}

+
+ +
+
+ { this.amountInput = input }} + size='' + placeholder='0.00000000' + value={contactCapacity || ''} + onChange={event => updateContactCapacity(event.target.value)} + // onBlur={onPayAmountBlur} + id='amount' + /> +
+
setContactsCurrencyFilters(!showCurrencyFilters)}> + {currencyName} +
+
    + { + currentCurrencyFilters.map(filter => +
  • onCurrencyFilterClick(filter.key)}>{filter.name}
  • ) + } +
+
+
+ +
+ {`≈ ${contactFormUsdAmount || 0} USD`} +
+
+
+
+ ) + } +} + +SubmitChannelForm.propTypes = {} + +export default SubmitChannelForm diff --git a/app/components/Contacts/SubmitChannelForm.scss b/app/components/Contacts/SubmitChannelForm.scss new file mode 100644 index 00000000..114bcbb0 --- /dev/null +++ b/app/components/Contacts/SubmitChannelForm.scss @@ -0,0 +1,154 @@ +@import '../../variables.scss'; + +.container { + position: absolute; + top: 0; + z-index: 10; + height: 100vh; + width: 100%; + background: #31343F; +} + +.closeContainer { + text-align: right; + padding: 20px 40px 0px; + + span { + cursor: pointer; + opacity: 1.0; + transition: 0.25s all; + + &:hover { + opacity: 0.5; + } + } + + svg { + color: $white; + } +} + + +.content { + padding: 0 40px; + font-family: Roboto; + color: $white; + + .header { + padding: 20px 100px; + + h1 { + margin-bottom: 15px; + font-size: 20px; + } + + p { + text-align: left; + line-height: 1.3; + font-size: 12px; + } + } +} + +.header { + text-align: center; + padding-bottom: 20px; + border-bottom: 1px solid $spaceborder; + + h1 { + font-size: 22px; + font-weight: 100; + margin-top: 10px; + letter-spacing: 1.5px; + } +} + +.title { + margin: 50px 0; + + h2 { + font-size: 14px; + background: $spaceblue; + padding: 10px; + border-radius: 17.5px; + display: inline; + } +} + +.input { + display: flex; + flex-direction: row; + align-items: center; + + input { + font-size: 40px; + max-width: 230px; + } +} + +.input input { + background: transparent; + outline: none; + border: 0; + color: $gold; + -webkit-text-fill-color: $white; + width: 100%; + font-weight: 200; +} + +.input input::-webkit-input-placeholder, ::-webkit-input-placeholder { + text-shadow: none; + -webkit-text-fill-color: initial; +} + +.currency { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + + .currentCurrency { + cursor: pointer; + transition: 0.25s all; + + &:hover { + opacity: 0.5; + } + + span { + font-size: 14px; + + &:nth-child(1) { + font-weight: bold; + } + } + + } + + ul { + visibility: hidden; + position: absolute; + top: 30px; + + &.active { + visibility: visible; + } + + li { + padding: 8px 15px; + background: #191919; + cursor: pointer; + transition: 0.25s hover; + border-bottom: 1px solid #0f0f0f; + + &:hover { + background: #0f0f0f; + } + } + } +} + +.usdAmount { + margin-top: 20px; + opacity: 0.5; +} diff --git a/app/components/Form/Form.js b/app/components/Form/Form.js index 9346fbd5..5a5c6892 100644 --- a/app/components/Form/Form.js +++ b/app/components/Form/Form.js @@ -19,7 +19,7 @@ const Form = ({ formType, formProps, closeForm }) => { const FormComponent = FORM_TYPES[formType] return ( -
+
diff --git a/app/main.dev.js b/app/main.dev.js index e3b54bba..4e5dfcf3 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -200,7 +200,7 @@ const startLnd = (alias, autopilot) => { }, 1000) } - if (line.includes('The wallet has been unlocked')) { + if (line.includes('LightningWallet opened')) { console.log('WALLET OPENED, STARTING LIGHTNING GRPC CONNECTION') sendLndSyncing() startGrpc() diff --git a/app/reducers/contactsform.js b/app/reducers/contactsform.js index f09144b2..47648a45 100644 --- a/app/reducers/contactsform.js +++ b/app/reducers/contactsform.js @@ -2,15 +2,24 @@ import { createSelector } from 'reselect' import filter from 'lodash/filter' import isEmpty from 'lodash/isEmpty' +import { tickerSelectors } from './ticker' +import { btc } from '../utils' + // Initial State const initialState = { isOpen: false, searchQuery: '', manualSearchQuery: '', contactCapacity: 0.1, + pubkey: '', showErrors: { manualInput: false - } + }, + + manualFormOpen: false, + submitChannelFormOpen: false, + + showCurrencyFilters: false } // Constants @@ -18,6 +27,14 @@ const initialState = { export const OPEN_CONTACTS_FORM = 'OPEN_CONTACTS_FORM' export const CLOSE_CONTACTS_FORM = 'CLOSE_CONTACTS_FORM' +export const OPEN_MANUAL_FORM = 'OPEN_MANUAL_FORM' +export const CLOSE_MANUAL_FORM = 'CLOSE_MANUAL_FORM' + +export const OPEN_SUBMIT_CHANNEL_FORM = 'OPEN_SUBMIT_CHANNEL_FORM' +export const CLOSE_SUBMIT_CHANNEL_FORM = 'CLOSE_SUBMIT_CHANNEL_FORM' + +export const SET_PUBKEY = 'SET_PUBKEY' + export const UPDATE_CONTACT_FORM_SEARCH_QUERY = 'UPDATE_CONTACT_FORM_SEARCH_QUERY' export const UPDATE_CONTACT_CAPACITY = 'UPDATE_CONTACT_CAPACITY' @@ -26,6 +43,8 @@ export const UPDATE_MANUAL_FORM_ERRORS = 'UPDATE_MANUAL_FORM_ERRORS' export const UPDATE_MANUAL_FORM_SEARCH_QUERY = 'UPDATE_MANUAL_FORM_SEARCH_QUERY' +export const SET_CONTACTS_CURRENCY_FILTERS = 'SET_CONTACTS_CURRENCY_FILTERS' + // ------------------------------------ // Actions // ------------------------------------ @@ -41,6 +60,30 @@ export function closeContactsForm() { } } +export function openManualForm() { + return { + type: OPEN_MANUAL_FORM + } +} + +export function closeManualForm() { + return { + type: CLOSE_MANUAL_FORM + } +} + +export function openSubmitChannelForm() { + return { + type: OPEN_SUBMIT_CHANNEL_FORM + } +} + +export function closeSubmitChannelForm() { + return { + type: CLOSE_SUBMIT_CHANNEL_FORM + } +} + export function updateContactFormSearchQuery(searchQuery) { return { type: UPDATE_CONTACT_FORM_SEARCH_QUERY, @@ -62,6 +105,13 @@ export function updateContactCapacity(contactCapacity) { } } +export function setPubkey(pubkey) { + return { + type: SET_PUBKEY, + pubkey + } +} + export function updateManualFormErrors(errorsObject) { return { type: UPDATE_MANUAL_FORM_ERRORS, @@ -69,6 +119,13 @@ export function updateManualFormErrors(errorsObject) { } } +export function setContactsCurrencyFilters(showCurrencyFilters) { + return { + type: SET_CONTACTS_CURRENCY_FILTERS, + showCurrencyFilters + } +} + // ------------------------------------ // Action Handlers // ------------------------------------ @@ -76,15 +133,25 @@ const ACTION_HANDLERS = { [OPEN_CONTACTS_FORM]: state => ({ ...state, isOpen: true }), [CLOSE_CONTACTS_FORM]: state => ({ ...state, isOpen: false }), + [OPEN_MANUAL_FORM]: state => ({ ...state, manualFormOpen: true }), + [CLOSE_MANUAL_FORM]: state => ({ ...state, manualFormOpen: false }), + + [OPEN_SUBMIT_CHANNEL_FORM]: state => ({ ...state, submitChannelFormOpen: true }), + [CLOSE_SUBMIT_CHANNEL_FORM]: state => ({ ...state, submitChannelFormOpen: false }), + [UPDATE_CONTACT_FORM_SEARCH_QUERY]: (state, { searchQuery }) => ({ ...state, searchQuery }), [UPDATE_MANUAL_FORM_SEARCH_QUERY]: (state, { searchQuery }) => ({ ...state, searchQuery }), [UPDATE_CONTACT_CAPACITY]: (state, { contactCapacity }) => ({ ...state, contactCapacity }), + + [SET_PUBKEY]: (state, { pubkey }) => ({ ...state, pubkey }), [UPDATE_MANUAL_FORM_ERRORS]: (state, { errorsObject }) => ({ ...state, showErrors: Object.assign(state.showErrors, errorsObject) }), - [UPDATE_MANUAL_FORM_SEARCH_QUERY]: (state, { manualSearchQuery }) => ({ ...state, manualSearchQuery }) + [UPDATE_MANUAL_FORM_SEARCH_QUERY]: (state, { manualSearchQuery }) => ({ ...state, manualSearchQuery }), + + [SET_CONTACTS_CURRENCY_FILTERS]: (state, { showCurrencyFilters }) => ({ ...state, showCurrencyFilters }) } // ------------------------------------ @@ -94,6 +161,8 @@ const contactFormSelectors = {} const networkNodesSelector = state => state.network.nodes const searchQuerySelector = state => state.contactsform.searchQuery const manualSearchQuerySelector = state => state.contactsform.manualSearchQuery +const contactCapacitySelector = state => state.contactsform.contactCapacity +const currencySelector = state => state.ticker.currency const contactable = node => ( node.addresses.length > 0 @@ -115,7 +184,10 @@ contactFormSelectors.filteredNetworkNodes = createSelector( (nodes, searchQuery) => { // If there is no search query default to showing the first 20 nodes from the nodes array // (performance hit to render the entire thing by default) - if (!searchQuery.length) { return nodes.sort(contactableFirst).slice(0, 20) } + // if (!searchQuery.length) { return nodes.sort(contactableFirst).slice(0, 20) } + + // return an empty array if there is no search query + if (!searchQuery.length) { return [] } // if there is an '@' in the search query we are assuming they are using the format pubkey@host // we can ignore the '@' and the host and just grab the pubkey for our search @@ -153,6 +225,17 @@ contactFormSelectors.manualFormIsValid = createSelector( } ) +contactFormSelectors.contactFormUsdAmount = createSelector( + contactCapacitySelector, + currencySelector, + tickerSelectors.currentTicker, + (amount, currency, ticker) => { + if (!ticker || !ticker.price_usd) { return false } + + return btc.convert(currency, 'usd', amount, ticker.price_usd) + } +) + export { contactFormSelectors } diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index f80e44b2..420961c0 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -8,9 +8,12 @@ import Form from 'components/Form' import ModalRoot from 'components/ModalRoot' import Network from 'components/Contacts/Network' +import AddChannel from 'components/Contacts/AddChannel' import ContactModal from 'components/Contacts/ContactModal' import ContactsForm from 'components/Contacts/ContactsForm' +import SubmitChannelForm from 'components/Contacts/SubmitChannelForm' + import ReceiveModal from 'components/Wallet/ReceiveModal' import ActivityModal from 'components/Activity/ActivityModal' @@ -60,6 +63,7 @@ class App extends Component { networkTabProps, receiveModalProps, activityModalProps, + submitChannelFormProps, children } = this.props @@ -79,9 +83,9 @@ class App extends Component { /> -
+ @@ -90,7 +94,12 @@ class App extends Component { {children}
- + { + contactsFormProps.contactsform.isOpen ? + + : + + }
) } diff --git a/app/routes/app/components/App.scss b/app/routes/app/components/App.scss index d12cf532..f7472067 100644 --- a/app/routes/app/components/App.scss +++ b/app/routes/app/components/App.scss @@ -2,7 +2,7 @@ .content { position: relative; - width: 80%; + width: 70%; display: inline-block; vertical-align: top; overflow-y: auto; diff --git a/app/routes/app/containers/AppContainer.js b/app/routes/app/containers/AppContainer.js index cc7459c8..435e7d93 100644 --- a/app/routes/app/containers/AppContainer.js +++ b/app/routes/app/containers/AppContainer.js @@ -1,6 +1,8 @@ import { withRouter } from 'react-router' import { connect } from 'react-redux' +import { btc } from 'utils' + import { fetchTicker, setCurrency, tickerSelectors } from 'reducers/ticker' import { newAddress, closeWalletModal } from 'reducers/address' @@ -39,11 +41,19 @@ import { import { openContactsForm, closeContactsForm, + + openSubmitChannelForm, + closeSubmitChannelForm, + updateContactFormSearchQuery, updateManualFormSearchQuery, updateContactCapacity, + setPubkey, + contactFormSelectors, - updateManualFormErrors + updateManualFormErrors, + + setContactsCurrencyFilters } from 'reducers/contactsform' import { fetchBalance } from 'reducers/balance' @@ -100,11 +110,15 @@ const mapDispatchToProps = { openContactsForm, closeContactsForm, + openSubmitChannelForm, + closeSubmitChannelForm, updateContactFormSearchQuery, updateManualFormSearchQuery, updateContactCapacity, + setPubkey, contactFormSelectors, updateManualFormErrors, + setContactsCurrencyFilters, fetchDescribeNetwork, @@ -155,6 +169,7 @@ const mapStateToProps = state => ({ filteredNetworkNodes: contactFormSelectors.filteredNetworkNodes(state), showManualForm: contactFormSelectors.showManualForm(state), manualFormIsValid: contactFormSelectors.manualFormIsValid(state), + contactFormUsdAmount: contactFormSelectors.contactFormUsdAmount(state), currentChannels: currentChannels(state), activeChannelPubkeys: channelsSelectors.activeChannelPubkeys(state), @@ -292,9 +307,11 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { const contactsFormProps = { closeContactsForm: dispatchProps.closeContactsForm, + openSubmitChannelForm: dispatchProps.openSubmitChannelForm, updateContactFormSearchQuery: dispatchProps.updateContactFormSearchQuery, updateManualFormSearchQuery: dispatchProps.updateManualFormSearchQuery, updateContactCapacity: dispatchProps.updateContactCapacity, + setPubkey: dispatchProps.setPubkey, openChannel: dispatchProps.openChannel, updateManualFormErrors: dispatchProps.updateManualFormErrors, @@ -348,6 +365,30 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { closeReceiveModal: dispatchProps.closeWalletModal } + const submitChannelFormProps = { + submitChannelFormOpen: stateProps.contactsform.submitChannelFormOpen, + pubkey: stateProps.contactsform.pubkey, + contactCapacity: stateProps.contactsform.contactCapacity, + + closeSubmitChannelForm: dispatchProps.closeSubmitChannelForm, + updateContactCapacity: dispatchProps.updateContactCapacity, + + toggleCurrencyProps: { + currentCurrencyFilters: stateProps.currentCurrencyFilters, + currencyName: stateProps.currencyName, + showCurrencyFilters: stateProps.contactsform.showCurrencyFilters, + contactFormUsdAmount: stateProps.contactFormUsdAmount, + + setContactsCurrencyFilters: dispatchProps.setContactsCurrencyFilters, + setCurrencyFilters: dispatchProps.setCurrencyFilters, + onCurrencyFilterClick: (currency) => { + dispatchProps.updateContactCapacity(btc.convert(stateProps.ticker.currency, currency, stateProps.contactsform.contactCapacity)) + dispatchProps.setCurrency(currency) + dispatchProps.setContactsCurrencyFilters(false) + } + } + } + return { ...stateProps, ...dispatchProps, @@ -363,6 +404,8 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { receiveModalProps, // props for the activity modals activityModalProps, + // props for the for to open a channel + submitChannelFormProps, // Props to pass to the pay form formProps: formProps(stateProps.form.formType), // action to close form From 3eb2263ff4defbf28628b0303efe2efa3a968f47 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Tue, 3 Apr 2018 19:55:21 -0500 Subject: [PATCH 02/12] feature(SubmitChannel): wire up backend to new submit channel form + loading pubkeys UI --- app/components/Contacts/AddChannel.js | 11 +- app/components/Contacts/ChannelForm.js | 42 +++++++ app/components/Contacts/ChannelForm.scss | 29 +++++ app/components/Contacts/ConnectManually.js | 46 +++++++ app/components/Contacts/ConnectManually.scss | 102 +++++++++++++++ app/components/Contacts/Network.js | 30 ++++- app/components/Contacts/Network.scss | 39 ++++++ app/components/Contacts/SubmitChannelForm.js | 118 ++++++++++-------- .../Contacts/SubmitChannelForm.scss | 54 ++++---- app/components/Form/Form.scss | 7 +- app/reducers/channels.js | 4 +- app/reducers/contactsform.js | 51 ++++++++ app/routes/app/components/App.js | 8 +- app/routes/app/containers/AppContainer.js | 54 ++++++-- 14 files changed, 499 insertions(+), 96 deletions(-) create mode 100644 app/components/Contacts/ChannelForm.js create mode 100644 app/components/Contacts/ChannelForm.scss create mode 100644 app/components/Contacts/ConnectManually.js create mode 100644 app/components/Contacts/ConnectManually.scss diff --git a/app/components/Contacts/AddChannel.js b/app/components/Contacts/AddChannel.js index 92a23799..bd61986b 100644 --- a/app/components/Contacts/AddChannel.js +++ b/app/components/Contacts/AddChannel.js @@ -15,7 +15,7 @@ const AddChannel = ({ updateContactFormSearchQuery, updateManualFormSearchQuery, updateContactCapacity, - setPubkey, + setNode, openChannel, updateManualFormErrors, activeChannelPubkeys, @@ -24,7 +24,8 @@ const AddChannel = ({ filteredNetworkNodes, loadingChannelPubkeys, showManualForm, - manualFormIsValid + manualFormIsValid, + openManualForm }) => { const renderRightSide = (node) => { @@ -75,7 +76,7 @@ const AddChannel = ({ className={styles.connect} onClick={() => { // set the node public key for the submit form - setPubkey(node.pub_key) + setNode(node) // open the submit form openSubmitChannelForm() }} @@ -102,7 +103,7 @@ const AddChannel = ({ className={styles.searchInput} value={contactsform.searchQuery} onChange={event => searchUpdated(event.target.value)} - ref={input => input && input.focus()} + // ref={input => input && input.focus()} /> @@ -140,7 +141,7 @@ const AddChannel = ({ showManualForm &&

Hm, looks like we can't see that node from here, wanna try to manually connect?

-
Connect Manually
+
Connect Manually
}
diff --git a/app/components/Contacts/ChannelForm.js b/app/components/Contacts/ChannelForm.js new file mode 100644 index 00000000..4a0b9b89 --- /dev/null +++ b/app/components/Contacts/ChannelForm.js @@ -0,0 +1,42 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import Isvg from 'react-inlinesvg' +import x from 'icons/x.svg' + +import ConnectManually from './ConnectManually' +import SubmitChannelForm from './SubmitChannelForm' + +import styles from './ChannelForm.scss' + +const FORM_TYPES = { + MANUAL_FORM: ConnectManually, + SUBMIT_CHANNEL_FORM: SubmitChannelForm +} + +const ChannelForm = ({ formType, formProps, closeForm }) => { + console.log('formType: ', formType) + if (!formType) { return null } + + const FormComponent = FORM_TYPES[formType] + console.log('FormComponent: ', FormComponent) + return ( +
+
+ + + +
+ +
+ ) +} + + +ChannelForm.propTypes = { + formType: PropTypes.string, + formProps: PropTypes.object.isRequired, + closeForm: PropTypes.func.isRequired +} + +export default ChannelForm diff --git a/app/components/Contacts/ChannelForm.scss b/app/components/Contacts/ChannelForm.scss new file mode 100644 index 00000000..7f3d3a21 --- /dev/null +++ b/app/components/Contacts/ChannelForm.scss @@ -0,0 +1,29 @@ +@import '../../variables.scss'; + +.container { + position: absolute; + top: 0; + z-index: 10; + height: 100vh; + width: 100%; + background: #31343F; +} + +.closeContainer { + text-align: right; + padding: 20px 40px 0px; + + span { + cursor: pointer; + opacity: 1.0; + transition: 0.25s all; + + &:hover { + opacity: 0.5; + } + } + + svg { + color: $white; + } +} \ No newline at end of file diff --git a/app/components/Contacts/ConnectManually.js b/app/components/Contacts/ConnectManually.js new file mode 100644 index 00000000..b32c6640 --- /dev/null +++ b/app/components/Contacts/ConnectManually.js @@ -0,0 +1,46 @@ +import React from 'react' +import PropTypes from 'prop-types' + +import { FaAngleDown } from 'react-icons/lib/fa' +import Isvg from 'react-inlinesvg' +import x from 'icons/x.svg' + +import styles from './ConnectManually.scss' + +class ConnectManually extends React.Component { + render() { + const { + manualFormOpen, + manualSearchQuery, + + closeManualForm, + updateManualFormSearchQuery + } = this.props + + console.log('props: ', this.props) + + return ( +
+
+

Connect Manually

+

Please enter the peer's pubkey@host

+
+ +
+
+ updateManualFormSearchQuery(event.target.value)} + /> +
+
+
+ ) + } +} + +ConnectManually.propTypes = {} + +export default ConnectManually diff --git a/app/components/Contacts/ConnectManually.scss b/app/components/Contacts/ConnectManually.scss new file mode 100644 index 00000000..b831dfed --- /dev/null +++ b/app/components/Contacts/ConnectManually.scss @@ -0,0 +1,102 @@ +@import '../../variables.scss'; + +.container { + position: absolute; + top: 0; + z-index: 10; + height: 100vh; + width: 100%; + background: #31343F; +} + +.closeContainer { + text-align: right; + padding: 20px 40px 0px; + + span { + cursor: pointer; + opacity: 1.0; + transition: 0.25s all; + + &:hover { + opacity: 0.5; + } + } + + svg { + color: $white; + } +} + + +.content { + padding: 0 40px; + font-family: Roboto; + color: $white; + + .header { + padding: 20px 100px; + + h1 { + margin-bottom: 15px; + font-size: 20px; + } + + p { + text-align: center; + line-height: 1.3; + font-size: 14px; + } + } +} + +.header { + text-align: center; + padding-bottom: 20px; + border-bottom: 1px solid $spaceborder; + + h1 { + font-size: 22px; + font-weight: 100; + margin-top: 10px; + letter-spacing: 1.5px; + } +} + +.title { + margin: 50px 0; + + h2 { + font-size: 14px; + background: $spaceblue; + padding: 10px; + border-radius: 17.5px; + display: inline; + } +} + +.input { + display: flex; + flex-direction: row; + align-items: center; + margin-top: 50px; + + input { + font-size: 25px; + } +} + +.input input { + background: transparent; + outline: none; + border: 0; + color: $gold; + -webkit-text-fill-color: $white; + width: 100%; + font-weight: 200; +} + +.input input::-webkit-input-placeholder, ::-webkit-input-placeholder { + text-shadow: none; + -webkit-text-fill-color: initial; +} diff --git a/app/components/Contacts/Network.js b/app/components/Contacts/Network.js index 8bba7417..36ae819b 100644 --- a/app/components/Contacts/Network.js +++ b/app/components/Contacts/Network.js @@ -23,8 +23,8 @@ class Network extends Component { channels: { searchQuery, filterPulldown, - filter - // loadingChannelPubkeys, + filter, + loadingChannelPubkeys, // closingChannelIds }, currentChannels, @@ -82,10 +82,16 @@ class Network extends Component { } const channelStatus = (channel) => { + // if the channel has a confirmation_height property that means it's pending if (Object.prototype.hasOwnProperty.call(channel, 'confirmation_height')) { return 'pending' } + + // if the channel has a closing tx that means it's closing if (Object.prototype.hasOwnProperty.call(channel, 'closing_txid')) { return 'closing' } + + // if the channel isn't active that means the remote peer isn't online if (!channel.active) { return 'offline' } + // if all of the above conditionals fail we can assume the node is online :) return 'online' } @@ -137,6 +143,26 @@ class Network extends Component {
    + { + loadingChannelPubkeys.map(loadingPubkey => { + // TODO(jimmymow): refactor this out. same logic is in displayNodeName above + const node = find(nodes, n => loadingPubkey === n.pub_key) + const nodeDisplay = () => { + if (node && node.alias.length) { return node.alias } + + return loadingPubkey.substring(0, 10) + } + + return ( +
  • + {nodeDisplay()} + + + +
  • + ) + }) + } { currentChannels.length > 0 && currentChannels.map((channelObj, index) => { const channel = Object.prototype.hasOwnProperty.call(channelObj, 'channel') ? channelObj.channel : channelObj diff --git a/app/components/Contacts/Network.scss b/app/components/Contacts/Network.scss index 0eb56a29..49e92860 100644 --- a/app/components/Contacts/Network.scss +++ b/app/components/Contacts/Network.scss @@ -195,3 +195,42 @@ color: $white; } } + +.spinner { + height: 10px; + width: 10px; + border: 1px solid rgba(235, 184, 100, 0.1); + border-left-color: rgba(235, 184, 100, 0.4); + -webkit-border-radius: 999px; + -moz-border-radius: 999px; + border-radius: 999px; + -webkit-animation: animation-rotate 1000ms linear infinite; + -moz-animation: animation-rotate 1000ms linear infinite; + -o-animation: animation-rotate 1000ms linear infinite; + animation: animation-rotate 1000ms linear infinite; + display: inline-block; +} + +@-webkit-keyframes animation-rotate { + 100% { + -webkit-transform: rotate(360deg); + } +} + +@-moz-keyframes animation-rotate { + 100% { + -moz-transform: rotate(360deg); + } +} + +@-o-keyframes animation-rotate { + 100% { + -o-transform: rotate(360deg); + } +} + +@keyframes animation-rotate { + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/app/components/Contacts/SubmitChannelForm.js b/app/components/Contacts/SubmitChannelForm.js index e67f822b..a6084a26 100644 --- a/app/components/Contacts/SubmitChannelForm.js +++ b/app/components/Contacts/SubmitChannelForm.js @@ -11,11 +11,13 @@ class SubmitChannelForm extends React.Component { render() { const { submitChannelFormOpen, - closeSubmitChannelForm, + closeChannelForm, + closeContactsForm, - pubkey, + node, contactCapacity, updateContactCapacity, + openChannel, toggleCurrencyProps: { setContactsCurrencyFilters, @@ -28,57 +30,75 @@ class SubmitChannelForm extends React.Component { } } = this.props - if (!submitChannelFormOpen) { return null } + const renderTitle = () => { + // if the node has an alias set we will show that with the pubkey in parens + // if not, just show the pubkey (would look ugly with rando parens) + if (node.alias && node.alias.length) { + return `${node.alias} (${node.pub_key})` + } else { + return node.addresses + } + } + + const formSubmitted = () => { + // submit the channel to LND + openChannel({ pubkey: node.pub_key, host: node.addresses[0].addr, local_amt: contactCapacity }) + + // close the ChannelForm component + closeChannelForm() + + // close the AddChannel component + closeContactsForm() + } return ( -
    -
    - - - -
    - -
    -
    -

    Add Funds to Network

    -

    Adding a connection will help you send and receive money on the Lightning Network. You aren't spening any money, rather moving the money you plan to use onto the network.

    -
    - -
    -

    {pubkey}

    -
    - -
    -
    - { this.amountInput = input }} - size='' - placeholder='0.00000000' - value={contactCapacity || ''} - onChange={event => updateContactCapacity(event.target.value)} - // onBlur={onPayAmountBlur} - id='amount' - /> -
    -
    setContactsCurrencyFilters(!showCurrencyFilters)}> - {currencyName} -
    -
      - { - currentCurrencyFilters.map(filter => -
    • onCurrencyFilterClick(filter.key)}>{filter.name}
    • ) - } -
    -
    -
    +
    +
    +

    Add Funds to Network

    +

    Adding a connection will help you send and receive money on the Lightning Network. You aren't spening any money, rather moving the money you plan to use onto the network.

    +
    + +
    +

    {renderTitle()}

    +
    -
    - {`≈ ${contactFormUsdAmount || 0} USD`} +
    +
    + updateContactCapacity(event.target.value)} + id='amount' + /> +
    +
    setContactsCurrencyFilters(!showCurrencyFilters)}> + {currencyName} +
    +
      + { + currentCurrencyFilters.map(filter => +
    • onCurrencyFilterClick(filter.key)}>{filter.name}
    • ) + } +
    -
    -
    +
    + +
    + {`≈ ${contactFormUsdAmount || 0} USD`} +
    +
    + +
    +
    0 && styles.active}`} + onClick={formSubmitted} + > + Submit +
    +
    ) } diff --git a/app/components/Contacts/SubmitChannelForm.scss b/app/components/Contacts/SubmitChannelForm.scss index 114bcbb0..d580f763 100644 --- a/app/components/Contacts/SubmitChannelForm.scss +++ b/app/components/Contacts/SubmitChannelForm.scss @@ -1,33 +1,5 @@ @import '../../variables.scss'; -.container { - position: absolute; - top: 0; - z-index: 10; - height: 100vh; - width: 100%; - background: #31343F; -} - -.closeContainer { - text-align: right; - padding: 20px 40px 0px; - - span { - cursor: pointer; - opacity: 1.0; - transition: 0.25s all; - - &:hover { - opacity: 0.5; - } - } - - svg { - color: $white; - } -} - .content { padding: 0 40px; @@ -43,7 +15,7 @@ } p { - text-align: left; + text-align: center; line-height: 1.3; font-size: 12px; } @@ -152,3 +124,27 @@ margin-top: 20px; opacity: 0.5; } + +.submit { + margin-top: 50px; + text-align: center; + + .button { + width: 235px; + margin: 0 auto; + padding: 20px 10px; + background: #31343f; + opacity: 0.5; + cursor: pointer; + transition: 0.25s all; + + &.active { + background: $gold; + opacity: 1.0; + + &:hover { + background: darken($gold, 5%); + } + } + } +} diff --git a/app/components/Form/Form.scss b/app/components/Form/Form.scss index 703c1713..f30d07f9 100644 --- a/app/components/Form/Form.scss +++ b/app/components/Form/Form.scss @@ -1,8 +1,11 @@ @import '../../variables.scss'; .container { - position: relative; + position: absolute; + top: 0; + z-index: 10; height: 100vh; + width: 100%; background: $spaceblue; } @@ -23,4 +26,4 @@ svg { color: $white; } -} +} \ No newline at end of file diff --git a/app/reducers/channels.js b/app/reducers/channels.js index 6c255519..69291459 100644 --- a/app/reducers/channels.js +++ b/app/reducers/channels.js @@ -521,7 +521,9 @@ const initialState = { { key: 'CLOSING_PENDING_CHANNELS', name: 'Closing' } ], - loadingChannelPubkeys: [], + loadingChannelPubkeys: [ + '039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3' + ], closingChannelIds: [], contactModal: { diff --git a/app/reducers/contactsform.js b/app/reducers/contactsform.js index 47648a45..604b4211 100644 --- a/app/reducers/contactsform.js +++ b/app/reducers/contactsform.js @@ -7,11 +7,18 @@ import { btc } from '../utils' // Initial State const initialState = { + // this determines whether or not the network side bar is in search state for a peer or not isOpen: false, + // this determines what form (manual or submit) the user currently has open + // if this is not null the ChannelForm component will be open + formType: null, + searchQuery: '', manualSearchQuery: '', contactCapacity: 0.1, pubkey: '', + host: '', + node: {}, showErrors: { manualInput: false }, @@ -27,6 +34,11 @@ const initialState = { export const OPEN_CONTACTS_FORM = 'OPEN_CONTACTS_FORM' export const CLOSE_CONTACTS_FORM = 'CLOSE_CONTACTS_FORM' +export const OPEN_CHANNEL_FORM_FORM = 'OPEN_CHANNEL_FORM_FORM' +export const CLOSE_CHANNEL_FORM_FORM = 'CLOSE_CHANNEL_FORM_FORM' + +export const SET_CHANNEL_FORM_TYPE = 'SET_CHANNEL_FORM_TYPE' + export const OPEN_MANUAL_FORM = 'OPEN_MANUAL_FORM' export const CLOSE_MANUAL_FORM = 'CLOSE_MANUAL_FORM' @@ -34,6 +46,8 @@ export const OPEN_SUBMIT_CHANNEL_FORM = 'OPEN_SUBMIT_CHANNEL_FORM' export const CLOSE_SUBMIT_CHANNEL_FORM = 'CLOSE_SUBMIT_CHANNEL_FORM' export const SET_PUBKEY = 'SET_PUBKEY' +export const SET_HOST = 'SET_HOST' +export const SET_NODE = 'SET_NODE' export const UPDATE_CONTACT_FORM_SEARCH_QUERY = 'UPDATE_CONTACT_FORM_SEARCH_QUERY' @@ -60,6 +74,25 @@ export function closeContactsForm() { } } +export function openChannelForm() { + return { + type: OPEN_CONTACTS_FORM + } +} + +export function closeChannelForm() { + return { + type: CLOSE_CONTACTS_FORM + } +} + +export function setChannelFormType(formType) { + return { + type: SET_CHANNEL_FORM_TYPE, + formType + } +} + export function openManualForm() { return { type: OPEN_MANUAL_FORM @@ -112,6 +145,20 @@ export function setPubkey(pubkey) { } } +export function setHost(host) { + return { + type: SET_HOST, + host + } +} + +export function setNode(node) { + return { + type: SET_NODE, + node + } +} + export function updateManualFormErrors(errorsObject) { return { type: UPDATE_MANUAL_FORM_ERRORS, @@ -132,6 +179,8 @@ export function setContactsCurrencyFilters(showCurrencyFilters) { const ACTION_HANDLERS = { [OPEN_CONTACTS_FORM]: state => ({ ...state, isOpen: true }), [CLOSE_CONTACTS_FORM]: state => ({ ...state, isOpen: false }), + + [SET_CHANNEL_FORM_TYPE]: (state, { formType }) => ({ ...state, formType }), [OPEN_MANUAL_FORM]: state => ({ ...state, manualFormOpen: true }), [CLOSE_MANUAL_FORM]: state => ({ ...state, manualFormOpen: false }), @@ -146,6 +195,8 @@ const ACTION_HANDLERS = { [UPDATE_CONTACT_CAPACITY]: (state, { contactCapacity }) => ({ ...state, contactCapacity }), [SET_PUBKEY]: (state, { pubkey }) => ({ ...state, pubkey }), + [SET_HOST]: (state, { host }) => ({ ...state, host }), + [SET_NODE]: (state, { node }) => ({ ...state, node }), [UPDATE_MANUAL_FORM_ERRORS]: (state, { errorsObject }) => ({ ...state, showErrors: Object.assign(state.showErrors, errorsObject) }), diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index 420961c0..809e8ba8 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -5,6 +5,7 @@ import GlobalError from 'components/GlobalError' import LoadingBolt from 'components/LoadingBolt' import Form from 'components/Form' +import ChannelForm from 'components/Contacts/ChannelForm' import ModalRoot from 'components/ModalRoot' import Network from 'components/Contacts/Network' @@ -13,6 +14,7 @@ import ContactModal from 'components/Contacts/ContactModal' import ContactsForm from 'components/Contacts/ContactsForm' import SubmitChannelForm from 'components/Contacts/SubmitChannelForm' +import ConnectManually from 'components/Contacts/ConnectManually' import ReceiveModal from 'components/Wallet/ReceiveModal' import ActivityModal from 'components/Activity/ActivityModal' @@ -64,6 +66,10 @@ class App extends Component { receiveModalProps, activityModalProps, submitChannelFormProps, + connectManuallyProps, + channelFormProps, + + contactsform, children } = this.props @@ -85,7 +91,7 @@ class App extends Component { - + diff --git a/app/routes/app/containers/AppContainer.js b/app/routes/app/containers/AppContainer.js index 435e7d93..6d9ec2b4 100644 --- a/app/routes/app/containers/AppContainer.js +++ b/app/routes/app/containers/AppContainer.js @@ -42,13 +42,18 @@ import { openContactsForm, closeContactsForm, + setChannelFormType, + + openManualForm, + closeManualForm, + openSubmitChannelForm, closeSubmitChannelForm, updateContactFormSearchQuery, updateManualFormSearchQuery, updateContactCapacity, - setPubkey, + setNode, contactFormSelectors, updateManualFormErrors, @@ -112,13 +117,16 @@ const mapDispatchToProps = { closeContactsForm, openSubmitChannelForm, closeSubmitChannelForm, + openManualForm, + closeManualForm, updateContactFormSearchQuery, updateManualFormSearchQuery, updateContactCapacity, - setPubkey, + setNode, contactFormSelectors, updateManualFormErrors, setContactsCurrencyFilters, + setChannelFormType, fetchDescribeNetwork, @@ -307,13 +315,14 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { const contactsFormProps = { closeContactsForm: dispatchProps.closeContactsForm, - openSubmitChannelForm: dispatchProps.openSubmitChannelForm, + openSubmitChannelForm: () => dispatchProps.setChannelFormType('SUBMIT_CHANNEL_FORM'), updateContactFormSearchQuery: dispatchProps.updateContactFormSearchQuery, updateManualFormSearchQuery: dispatchProps.updateManualFormSearchQuery, updateContactCapacity: dispatchProps.updateContactCapacity, - setPubkey: dispatchProps.setPubkey, + setNode: dispatchProps.setNode, openChannel: dispatchProps.openChannel, updateManualFormErrors: dispatchProps.updateManualFormErrors, + openManualForm: () => dispatchProps.setChannelFormType('MANUAL_FORM'), contactsform: stateProps.contactsform, filteredNetworkNodes: stateProps.filteredNetworkNodes, @@ -367,11 +376,15 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { const submitChannelFormProps = { submitChannelFormOpen: stateProps.contactsform.submitChannelFormOpen, - pubkey: stateProps.contactsform.pubkey, + node: stateProps.contactsform.node, contactCapacity: stateProps.contactsform.contactCapacity, - closeSubmitChannelForm: dispatchProps.closeSubmitChannelForm, updateContactCapacity: dispatchProps.updateContactCapacity, + + closeChannelForm: () => dispatchProps.setChannelFormType(null), + closeContactsForm: dispatchProps.closeContactsForm, + + openChannel: dispatchProps.openChannel, toggleCurrencyProps: { currentCurrencyFilters: stateProps.currentCurrencyFilters, @@ -389,6 +402,29 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { } } + const connectManuallyProps = { + closeManualForm: dispatchProps.closeManualForm, + updateManualFormSearchQuery: dispatchProps.updateManualFormSearchQuery, + closeChannelForm: () => dispatchProps.setChannelFormType(null), + + manualFormOpen: stateProps.contactsform.manualFormOpen, + manualSearchQuery: stateProps.contactsform.manualSearchQuery + } + + const calcChannelFormProps = (formType) => { + if (formType === 'MANUAL_FORM') { return connectManuallyProps } + if (formType === 'SUBMIT_CHANNEL_FORM') { return submitChannelFormProps } + + return {} + } + + const channelFormProps = { + formType: stateProps.contactsform.formType, + formProps: calcChannelFormProps(stateProps.contactsform.formType), + closeForm: () => dispatchProps.setChannelFormType(null) + } + + return { ...stateProps, ...dispatchProps, @@ -404,8 +440,12 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { receiveModalProps, // props for the activity modals activityModalProps, - // props for the for to open a channel + // props for the form to open a channel submitChannelFormProps, + // props for the form to connect manually to a peer + connectManuallyProps, + // props for the channel form wrapper + channelFormProps, // Props to pass to the pay form formProps: formProps(stateProps.form.formType), // action to close form From de9dffb28cd1141566af39acdb623cd80e349cca Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Tue, 3 Apr 2018 21:33:29 -0500 Subject: [PATCH 03/12] feature(ConnectManually): wire up ConnectManually component --- app/components/Contacts/ConnectManually.js | 53 ++++++++++++++++++-- app/components/Contacts/ConnectManually.scss | 39 +++++++++++++- app/components/Contacts/SubmitChannelForm.js | 2 +- app/routes/app/containers/AppContainer.js | 8 ++- 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/app/components/Contacts/ConnectManually.js b/app/components/Contacts/ConnectManually.js index b32c6640..afda00e2 100644 --- a/app/components/Contacts/ConnectManually.js +++ b/app/components/Contacts/ConnectManually.js @@ -13,11 +13,43 @@ class ConnectManually extends React.Component { manualFormOpen, manualSearchQuery, - closeManualForm, - updateManualFormSearchQuery + manualFormIsValid, + updateManualFormErrors, + + openSubmitChannelForm, + updateManualFormSearchQuery, + + setNode, + + showErrors } = this.props - console.log('props: ', this.props) + const formSubmitted = () => { + if (!manualFormIsValid.isValid) { + updateManualFormErrors(manualFormIsValid.errors) + + return + } + // clear any existing errors + updateManualFormErrors({ manualInput: null }) + + const [pub_key, addr] = manualSearchQuery && manualSearchQuery.split('@') + + // the SubmitChannel component is expecting a node object that looks like the following + // { + // pub_key: 'some_string', + // addresses: [ + // { + // addr: 'some_host_address' + // } + // ] + // } + // knowing this we will set the node object with the known format and plug in the pubkey + host accordingly + setNode({ pub_key, addresses: [{ addr }] }) + + // now we close the ConnectManually form and open the SubmitChannel form by chaning the channelFormType + openSubmitChannelForm() + } return (
    @@ -36,6 +68,21 @@ class ConnectManually extends React.Component { />
    + +
    + {showErrors.manualInput && + {manualFormIsValid && manualFormIsValid.errors.manualInput} + } +
    + +
    +
    + Submit +
    +
    ) } diff --git a/app/components/Contacts/ConnectManually.scss b/app/components/Contacts/ConnectManually.scss index b831dfed..5dac74ab 100644 --- a/app/components/Contacts/ConnectManually.scss +++ b/app/components/Contacts/ConnectManually.scss @@ -82,7 +82,7 @@ margin-top: 50px; input { - font-size: 25px; + font-size: 20px; } } @@ -100,3 +100,40 @@ text-shadow: none; -webkit-text-fill-color: initial; } + +.errorMessage { + margin-top: 20px; + font-size: 12px; + color: $red; + min-height: 12px; + visibility: hidden; + + &.active { + visibility: visible; + } +} + +.submit { + margin-top: 50px; + text-align: center; + + .button { + width: 235px; + margin: 0 auto; + padding: 20px 10px; + background: #31343f; + opacity: 0.5; + cursor: pointer; + transition: 0.25s all; + + &.active { + background: $gold; + opacity: 1.0; + + &:hover { + background: darken($gold, 5%); + } + } + } +} + diff --git a/app/components/Contacts/SubmitChannelForm.js b/app/components/Contacts/SubmitChannelForm.js index a6084a26..fabdce52 100644 --- a/app/components/Contacts/SubmitChannelForm.js +++ b/app/components/Contacts/SubmitChannelForm.js @@ -36,7 +36,7 @@ class SubmitChannelForm extends React.Component { if (node.alias && node.alias.length) { return `${node.alias} (${node.pub_key})` } else { - return node.addresses + return node.pub_key } } diff --git a/app/routes/app/containers/AppContainer.js b/app/routes/app/containers/AppContainer.js index 6d9ec2b4..a37a7f26 100644 --- a/app/routes/app/containers/AppContainer.js +++ b/app/routes/app/containers/AppContainer.js @@ -405,10 +405,14 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { const connectManuallyProps = { closeManualForm: dispatchProps.closeManualForm, updateManualFormSearchQuery: dispatchProps.updateManualFormSearchQuery, - closeChannelForm: () => dispatchProps.setChannelFormType(null), + updateManualFormErrors: dispatchProps.updateManualFormErrors, + setNode: dispatchProps.setNode, + openSubmitChannelForm: () => dispatchProps.setChannelFormType('SUBMIT_CHANNEL_FORM'), manualFormOpen: stateProps.contactsform.manualFormOpen, - manualSearchQuery: stateProps.contactsform.manualSearchQuery + manualSearchQuery: stateProps.contactsform.manualSearchQuery, + manualFormIsValid: stateProps.manualFormIsValid, + showErrors: stateProps.contactsform.showErrors } const calcChannelFormProps = (formType) => { From 813585a2ec625febaca21343556b85efa86caf41 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 09:47:33 -0500 Subject: [PATCH 04/12] fix(cleanup): remove hard-coded initialState data and set PropTypes on ConnectManually --- app/components/Contacts/ConnectManually.js | 15 ++++++++++++++- app/reducers/channels.js | 4 +--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/components/Contacts/ConnectManually.js b/app/components/Contacts/ConnectManually.js index afda00e2..fc6a2bc1 100644 --- a/app/components/Contacts/ConnectManually.js +++ b/app/components/Contacts/ConnectManually.js @@ -88,6 +88,19 @@ class ConnectManually extends React.Component { } } -ConnectManually.propTypes = {} +ConnectManually.propTypes = { + manualFormOpen: PropTypes.bool.isRequired, + manualSearchQuery: PropTypes.string.isRequired, + + manualFormIsValid: PropTypes.object.isRequired, + updateManualFormErrors: PropTypes.func.isRequired, + + openSubmitChannelForm: PropTypes.func.isRequired, + updateManualFormSearchQuery: PropTypes.func.isRequired, + + setNode: PropTypes.func.isRequired, + + showErrors: PropTypes.bool.isRequired +} export default ConnectManually diff --git a/app/reducers/channels.js b/app/reducers/channels.js index 69291459..6c255519 100644 --- a/app/reducers/channels.js +++ b/app/reducers/channels.js @@ -521,9 +521,7 @@ const initialState = { { key: 'CLOSING_PENDING_CHANNELS', name: 'Closing' } ], - loadingChannelPubkeys: [ - '039cc950286a8fa99218283d1adc2456e0d5e81be558da77dd6e85ba9a1fff5ad3' - ], + loadingChannelPubkeys: [], closingChannelIds: [], contactModal: { From 4b35c5f1aae44a06c90012c32ac2feb5ab91dcae Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 10:05:48 -0500 Subject: [PATCH 05/12] fix(channelform): remove old unused reducer --- app/main.dev.js | 2 +- app/reducers/channelform.js | 130 --------------------------------- app/reducers/channels.js | 1 - app/reducers/index.js | 2 - test/reducers/channels.spec.js | 4 - 5 files changed, 1 insertion(+), 138 deletions(-) delete mode 100644 app/reducers/channelform.js diff --git a/app/main.dev.js b/app/main.dev.js index 4e5dfcf3..265933a0 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -164,7 +164,7 @@ const startLnd = (alias, autopilot) => { '--bitcoin.active', '--bitcoin.testnet', '--bitcoin.node=neutrino', - '--neutrino.connect=btcd.jackmallers.com:18333', + '--neutrino.connect=btcd0.lightning.computer:18333', '--neutrino.addpeer=btcd.jackmallers.com:18333', '--neutrino.addpeer=159.65.48.139:18333', '--neutrino.connect=127.0.0.1:18333', diff --git a/app/reducers/channelform.js b/app/reducers/channelform.js deleted file mode 100644 index 50a92848..00000000 --- a/app/reducers/channelform.js +++ /dev/null @@ -1,130 +0,0 @@ -import { createSelector } from 'reselect' - -// Initial State -const initialState = { - isOpen: false, - node_key: '', - local_amt: 0, - push_amt: 0, - - step: 1 -} - -// Constants -// ------------------------------------ -export const OPEN_CHANNEL_FORM = 'OPEN_CHANNEL_FORM' -export const CLOSE_CHANNEL_FORM = 'CLOSE_CHANNEL_FORM' - -export const SET_NODE_KEY = 'SET_NODE_KEY' -export const SET_LOCAL_AMOUNT = 'SET_LOCAL_AMOUNT' -export const SET_PUSH_AMOUNT = 'SET_PUSH_AMOUNT' - -export const CHANGE_STEP = 'CHANGE_STEP' - -export const RESET_CHANNEL_FORM = 'RESET_CHANNEL_FORM' - -// ------------------------------------ -// Actions -// ------------------------------------ -export function openChannelForm() { - return { - type: OPEN_CHANNEL_FORM - } -} - -export function closeChannelForm() { - return { - type: CLOSE_CHANNEL_FORM - } -} - -export function setNodeKey(node_key) { - return { - type: SET_NODE_KEY, - node_key - } -} - -export function setLocalAmount(local_amt) { - return { - type: SET_LOCAL_AMOUNT, - local_amt - } -} - -export function setPushAmount(push_amt) { - return { - type: SET_PUSH_AMOUNT, - push_amt - } -} - -export function changeStep(step) { - return { - type: CHANGE_STEP, - step - } -} - -export function resetChannelForm() { - return { - type: RESET_CHANNEL_FORM - } -} - -// ------------------------------------ -// Action Handlers -// ------------------------------------ -const ACTION_HANDLERS = { - [OPEN_CHANNEL_FORM]: state => ({ ...state, isOpen: true }), - [CLOSE_CHANNEL_FORM]: state => ({ ...state, isOpen: false }), - - [SET_NODE_KEY]: (state, { node_key }) => ({ ...state, node_key }), - [SET_LOCAL_AMOUNT]: (state, { local_amt }) => ({ ...state, local_amt }), - [SET_PUSH_AMOUNT]: (state, { push_amt }) => ({ ...state, push_amt }), - - [CHANGE_STEP]: (state, { step }) => ({ ...state, step }), - - [RESET_CHANNEL_FORM]: () => (initialState) -} - -const channelFormSelectors = {} -const channelFormStepSelector = state => state.channelform.step -const channelFormLocalAmountSelector = state => state.channelform.local_amt - -channelFormSelectors.channelFormHeader = createSelector( - channelFormStepSelector, - (step) => { - switch (step) { - case 1: - return 'Step 1: Select a peer' - case 2: - return 'Step 2: Set your local amount' - case 3: - return 'Step 3: Set your push amount' - default: - return 'Step 4: Create your channel' - } - } -) - -channelFormSelectors.channelFormProgress = createSelector( - channelFormStepSelector, - step => ((step - 1) / 3) * 100 -) - -channelFormSelectors.stepTwoIsValid = createSelector( - channelFormLocalAmountSelector, - local_amt => local_amt > 0 -) - -export { channelFormSelectors } - -// ------------------------------------ -// Reducer -// ------------------------------------ -export default function channelFormReducer(state = initialState, action) { - const handler = ACTION_HANDLERS[action.type] - - return handler ? handler(state, action) : state -} diff --git a/app/reducers/channels.js b/app/reducers/channels.js index 6c255519..fc96de0f 100644 --- a/app/reducers/channels.js +++ b/app/reducers/channels.js @@ -3,7 +3,6 @@ import { ipcRenderer } from 'electron' import filter from 'lodash/filter' import { btc } from 'utils' import { showNotification } from 'notifications' -import { closeChannelForm, resetChannelForm } from './channelform' import { setError } from './error' // ------------------------------------ // Constants diff --git a/app/reducers/index.js b/app/reducers/index.js index ea131b2e..0bb57dc8 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -8,7 +8,6 @@ import balance from './balance' import payment from './payment' import peers from './peers' import channels from './channels' -import channelform from './channelform' import contactsform from './contactsform' @@ -34,7 +33,6 @@ const rootReducer = combineReducers({ payment, peers, channels, - channelform, contactsform, form, diff --git a/test/reducers/channels.spec.js b/test/reducers/channels.spec.js index 757c63c1..26120e99 100644 --- a/test/reducers/channels.spec.js +++ b/test/reducers/channels.spec.js @@ -46,10 +46,6 @@ describe('reducers', () => { expect(channelsReducer(undefined, { type: SET_CHANNEL, channel: 'channel' })).toMatchSnapshot() }) - it('should correctly setChannelForm', () => { - expect(channelsReducer(undefined, { type: SET_CHANNEL_FORM, form: { isOpen: true } })).toMatchSnapshot() - }) - it('should correctly getChannels', () => { expect(channelsReducer(undefined, { type: GET_CHANNELS })).toMatchSnapshot() }) From 7cff397a4c25727979a52c0d6e8e38b2105399cf Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 10:38:28 -0500 Subject: [PATCH 06/12] fix(lint + grpc): fix lint errors and a bug where gRPC connection starts too early --- app/components/Contacts/AddChannel.js | 23 +++++---- app/components/Contacts/ChannelForm.js | 2 - app/components/Contacts/ConnectManually.js | 51 +++++++++----------- app/components/Contacts/Network.js | 4 +- app/components/Contacts/SubmitChannelForm.js | 28 ++++++++--- app/main.dev.js | 2 +- app/reducers/channels.js | 4 -- app/reducers/contactsform.js | 24 +-------- app/routes/app/components/App.js | 9 +--- app/routes/app/containers/AppContainer.js | 4 +- 10 files changed, 64 insertions(+), 87 deletions(-) diff --git a/app/components/Contacts/AddChannel.js b/app/components/Contacts/AddChannel.js index bd61986b..b1047fb5 100644 --- a/app/components/Contacts/AddChannel.js +++ b/app/components/Contacts/AddChannel.js @@ -1,7 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' import Isvg from 'react-inlinesvg' -import { FaCircle, FaQuestionCircle } from 'react-icons/lib/fa' import x from 'icons/x.svg' @@ -9,25 +8,19 @@ import styles from './AddChannel.scss' const AddChannel = ({ contactsform, - contactsform: { showErrors }, closeContactsForm, openSubmitChannelForm, updateContactFormSearchQuery, updateManualFormSearchQuery, - updateContactCapacity, setNode, - openChannel, - updateManualFormErrors, activeChannelPubkeys, nonActiveChannelPubkeys, pendingOpenChannelPubkeys, filteredNetworkNodes, loadingChannelPubkeys, showManualForm, - manualFormIsValid, openManualForm }) => { - const renderRightSide = (node) => { if (loadingChannelPubkeys.includes(node.pub_key)) { return ( @@ -140,7 +133,7 @@ const AddChannel = ({ { showManualForm &&
    -

    Hm, looks like we can't see that node from here, wanna try to manually connect?

    +

    Hm, looks like we can't see that node from here, wanna try to manually connect?

    Connect Manually
    } @@ -149,7 +142,19 @@ const AddChannel = ({ } AddChannel.propTypes = { - + contactsform: PropTypes.object.isRequired, + closeContactsForm: PropTypes.func.isRequired, + openSubmitChannelForm: PropTypes.func.isRequired, + updateContactFormSearchQuery: PropTypes.func.isRequired, + updateManualFormSearchQuery: PropTypes.func.isRequired, + setNode: PropTypes.func.isRequired, + activeChannelPubkeys: PropTypes.array.isRequired, + nonActiveChannelPubkeys: PropTypes.array.isRequired, + pendingOpenChannelPubkeys: PropTypes.array.isRequired, + filteredNetworkNodes: PropTypes.array.isRequired, + loadingChannelPubkeys: PropTypes.array.isRequired, + showManualForm: PropTypes.bool.isRequired, + openManualForm: PropTypes.func.isRequired } export default AddChannel diff --git a/app/components/Contacts/ChannelForm.js b/app/components/Contacts/ChannelForm.js index 4a0b9b89..c796865a 100644 --- a/app/components/Contacts/ChannelForm.js +++ b/app/components/Contacts/ChannelForm.js @@ -15,11 +15,9 @@ const FORM_TYPES = { } const ChannelForm = ({ formType, formProps, closeForm }) => { - console.log('formType: ', formType) if (!formType) { return null } const FormComponent = FORM_TYPES[formType] - console.log('FormComponent: ', FormComponent) return (
    diff --git a/app/components/Contacts/ConnectManually.js b/app/components/Contacts/ConnectManually.js index fc6a2bc1..8779fa46 100644 --- a/app/components/Contacts/ConnectManually.js +++ b/app/components/Contacts/ConnectManually.js @@ -1,16 +1,10 @@ import React from 'react' import PropTypes from 'prop-types' - -import { FaAngleDown } from 'react-icons/lib/fa' -import Isvg from 'react-inlinesvg' -import x from 'icons/x.svg' - import styles from './ConnectManually.scss' class ConnectManually extends React.Component { render() { const { - manualFormOpen, manualSearchQuery, manualFormIsValid, @@ -27,35 +21,35 @@ class ConnectManually extends React.Component { const formSubmitted = () => { if (!manualFormIsValid.isValid) { updateManualFormErrors(manualFormIsValid.errors) - + return } - // clear any existing errors - updateManualFormErrors({ manualInput: null }) - - const [pub_key, addr] = manualSearchQuery && manualSearchQuery.split('@') - - // the SubmitChannel component is expecting a node object that looks like the following - // { - // pub_key: 'some_string', - // addresses: [ - // { - // addr: 'some_host_address' - // } - // ] - // } - // knowing this we will set the node object with the known format and plug in the pubkey + host accordingly - setNode({ pub_key, addresses: [{ addr }] }) - - // now we close the ConnectManually form and open the SubmitChannel form by chaning the channelFormType - openSubmitChannelForm() + // clear any existing errors + updateManualFormErrors({ manualInput: null }) + + const [pub_key, addr] = manualSearchQuery && manualSearchQuery.split('@') + + // the SubmitChannel component is expecting a node object that looks like the following + // { + // pub_key: 'some_string', + // addresses: [ + // { + // addr: 'some_host_address' + // } + // ] + // } + // knowing this we will set the node object with the known format and plug in the pubkey + host accordingly + setNode({ pub_key, addresses: [{ addr }] }) + + // now we close the ConnectManually form and open the SubmitChannel form by chaning the channelFormType + openSubmitChannelForm() } return (

    Connect Manually

    -

    Please enter the peer's pubkey@host

    +

    Please enter the peer's pubkey@host

    @@ -89,7 +83,6 @@ class ConnectManually extends React.Component { } ConnectManually.propTypes = { - manualFormOpen: PropTypes.bool.isRequired, manualSearchQuery: PropTypes.string.isRequired, manualFormIsValid: PropTypes.object.isRequired, @@ -100,7 +93,7 @@ ConnectManually.propTypes = { setNode: PropTypes.func.isRequired, - showErrors: PropTypes.bool.isRequired + showErrors: PropTypes.object.isRequired } export default ConnectManually diff --git a/app/components/Contacts/Network.js b/app/components/Contacts/Network.js index 36ae819b..8a77b7d6 100644 --- a/app/components/Contacts/Network.js +++ b/app/components/Contacts/Network.js @@ -24,7 +24,7 @@ class Network extends Component { searchQuery, filterPulldown, filter, - loadingChannelPubkeys, + loadingChannelPubkeys // closingChannelIds }, currentChannels, @@ -144,7 +144,7 @@ class Network extends Component {
      { - loadingChannelPubkeys.map(loadingPubkey => { + loadingChannelPubkeys.map((loadingPubkey) => { // TODO(jimmymow): refactor this out. same logic is in displayNodeName above const node = find(nodes, n => loadingPubkey === n.pub_key) const nodeDisplay = () => { diff --git a/app/components/Contacts/SubmitChannelForm.js b/app/components/Contacts/SubmitChannelForm.js index fabdce52..5a656c88 100644 --- a/app/components/Contacts/SubmitChannelForm.js +++ b/app/components/Contacts/SubmitChannelForm.js @@ -2,15 +2,12 @@ import React from 'react' import PropTypes from 'prop-types' import { FaAngleDown } from 'react-icons/lib/fa' -import Isvg from 'react-inlinesvg' -import x from 'icons/x.svg' import styles from './SubmitChannelForm.scss' class SubmitChannelForm extends React.Component { render() { const { - submitChannelFormOpen, closeChannelForm, closeContactsForm, @@ -21,7 +18,6 @@ class SubmitChannelForm extends React.Component { toggleCurrencyProps: { setContactsCurrencyFilters, - setCurrencyFilters, showCurrencyFilters, currencyName, currentCurrencyFilters, @@ -35,9 +31,9 @@ class SubmitChannelForm extends React.Component { // if not, just show the pubkey (would look ugly with rando parens) if (node.alias && node.alias.length) { return `${node.alias} (${node.pub_key})` - } else { - return node.pub_key } + + return node.pub_key } const formSubmitted = () => { @@ -55,7 +51,10 @@ class SubmitChannelForm extends React.Component {

      Add Funds to Network

      -

      Adding a connection will help you send and receive money on the Lightning Network. You aren't spening any money, rather moving the money you plan to use onto the network.

      +

      + Adding a connection will help you send and receive money on the Lightning Network. + You aren't spening any money, rather moving the money you plan to use onto the network. +

      @@ -104,6 +103,19 @@ class SubmitChannelForm extends React.Component { } } -SubmitChannelForm.propTypes = {} +SubmitChannelForm.propTypes = { + closeChannelForm: PropTypes.func.isRequired, + closeContactsForm: PropTypes.func.isRequired, + + node: PropTypes.object.isRequired, + contactCapacity: PropTypes.PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string + ]), + updateContactCapacity: PropTypes.func.isRequired, + openChannel: PropTypes.func.isRequired, + + toggleCurrencyProps: PropTypes.object.isRequired +} export default SubmitChannelForm diff --git a/app/main.dev.js b/app/main.dev.js index 265933a0..4a0dd49b 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -200,7 +200,7 @@ const startLnd = (alias, autopilot) => { }, 1000) } - if (line.includes('LightningWallet opened')) { + if (line.includes('gRPC proxy started') && !line.includes('password')) { console.log('WALLET OPENED, STARTING LIGHTNING GRPC CONNECTION') sendLndSyncing() startGrpc() diff --git a/app/reducers/channels.js b/app/reducers/channels.js index fc96de0f..5b315ee6 100644 --- a/app/reducers/channels.js +++ b/app/reducers/channels.js @@ -166,8 +166,6 @@ export const openChannel = ({ // Receive IPC event for openChannel export const channelSuccessful = () => (dispatch) => { dispatch(fetchChannels()) - dispatch(closeChannelForm()) - dispatch(resetChannelForm()) } // Receive IPC event for updated channel @@ -198,8 +196,6 @@ export const closeChannel = ({ channel_point, chan_id, force }) => (dispatch) => dispatch(closingChannel()) dispatch(addClosingChanId(chan_id)) - console.log('force: ', force) - const [funding_txid, output_index] = channel_point.split(':') ipcRenderer.send( 'lnd', diff --git a/app/reducers/contactsform.js b/app/reducers/contactsform.js index 604b4211..5e55451a 100644 --- a/app/reducers/contactsform.js +++ b/app/reducers/contactsform.js @@ -16,8 +16,6 @@ const initialState = { searchQuery: '', manualSearchQuery: '', contactCapacity: 0.1, - pubkey: '', - host: '', node: {}, showErrors: { manualInput: false @@ -45,8 +43,6 @@ export const CLOSE_MANUAL_FORM = 'CLOSE_MANUAL_FORM' export const OPEN_SUBMIT_CHANNEL_FORM = 'OPEN_SUBMIT_CHANNEL_FORM' export const CLOSE_SUBMIT_CHANNEL_FORM = 'CLOSE_SUBMIT_CHANNEL_FORM' -export const SET_PUBKEY = 'SET_PUBKEY' -export const SET_HOST = 'SET_HOST' export const SET_NODE = 'SET_NODE' export const UPDATE_CONTACT_FORM_SEARCH_QUERY = 'UPDATE_CONTACT_FORM_SEARCH_QUERY' @@ -138,20 +134,6 @@ export function updateContactCapacity(contactCapacity) { } } -export function setPubkey(pubkey) { - return { - type: SET_PUBKEY, - pubkey - } -} - -export function setHost(host) { - return { - type: SET_HOST, - host - } -} - export function setNode(node) { return { type: SET_NODE, @@ -179,7 +161,7 @@ export function setContactsCurrencyFilters(showCurrencyFilters) { const ACTION_HANDLERS = { [OPEN_CONTACTS_FORM]: state => ({ ...state, isOpen: true }), [CLOSE_CONTACTS_FORM]: state => ({ ...state, isOpen: false }), - + [SET_CHANNEL_FORM_TYPE]: (state, { formType }) => ({ ...state, formType }), [OPEN_MANUAL_FORM]: state => ({ ...state, manualFormOpen: true }), @@ -193,9 +175,7 @@ const ACTION_HANDLERS = { [UPDATE_MANUAL_FORM_SEARCH_QUERY]: (state, { searchQuery }) => ({ ...state, searchQuery }), [UPDATE_CONTACT_CAPACITY]: (state, { contactCapacity }) => ({ ...state, contactCapacity }), - - [SET_PUBKEY]: (state, { pubkey }) => ({ ...state, pubkey }), - [SET_HOST]: (state, { host }) => ({ ...state, host }), + [SET_NODE]: (state, { node }) => ({ ...state, node }), [UPDATE_MANUAL_FORM_ERRORS]: (state, { errorsObject }) => ({ ...state, showErrors: Object.assign(state.showErrors, errorsObject) }), diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index 809e8ba8..870ee71c 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -11,10 +11,6 @@ import ModalRoot from 'components/ModalRoot' import Network from 'components/Contacts/Network' import AddChannel from 'components/Contacts/AddChannel' import ContactModal from 'components/Contacts/ContactModal' -import ContactsForm from 'components/Contacts/ContactsForm' - -import SubmitChannelForm from 'components/Contacts/SubmitChannelForm' -import ConnectManually from 'components/Contacts/ConnectManually' import ReceiveModal from 'components/Wallet/ReceiveModal' import ActivityModal from 'components/Activity/ActivityModal' @@ -65,12 +61,8 @@ class App extends Component { networkTabProps, receiveModalProps, activityModalProps, - submitChannelFormProps, - connectManuallyProps, channelFormProps, - contactsform, - children } = this.props @@ -124,6 +116,7 @@ App.propTypes = { networkTabProps: PropTypes.object, activityModalProps: PropTypes.object, receiveModalProps: PropTypes.object, + channelFormProps: PropTypes.object, newAddress: PropTypes.func.isRequired, fetchInfo: PropTypes.func.isRequired, diff --git a/app/routes/app/containers/AppContainer.js b/app/routes/app/containers/AppContainer.js index a37a7f26..5937e056 100644 --- a/app/routes/app/containers/AppContainer.js +++ b/app/routes/app/containers/AppContainer.js @@ -380,7 +380,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { contactCapacity: stateProps.contactsform.contactCapacity, updateContactCapacity: dispatchProps.updateContactCapacity, - + closeChannelForm: () => dispatchProps.setChannelFormType(null), closeContactsForm: dispatchProps.closeContactsForm, @@ -408,7 +408,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { updateManualFormErrors: dispatchProps.updateManualFormErrors, setNode: dispatchProps.setNode, openSubmitChannelForm: () => dispatchProps.setChannelFormType('SUBMIT_CHANNEL_FORM'), - + manualFormOpen: stateProps.contactsform.manualFormOpen, manualSearchQuery: stateProps.contactsform.manualSearchQuery, manualFormIsValid: stateProps.manualFormIsValid, From 08d263ca9480d9e180c02f656edefb0ad5010e70 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 10:43:50 -0500 Subject: [PATCH 07/12] fix(contactsform): fix performance hit when searching the network for nodes. limit the amount thats returned so we arent rendering thousands of nodes ever. --- app/reducers/contactsform.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/reducers/contactsform.js b/app/reducers/contactsform.js index 5e55451a..6c9f6f8c 100644 --- a/app/reducers/contactsform.js +++ b/app/reducers/contactsform.js @@ -224,7 +224,12 @@ contactFormSelectors.filteredNetworkNodes = createSelector( // we can ignore the '@' and the host and just grab the pubkey for our search const query = searchQuery.includes('@') ? searchQuery.split('@')[0] : searchQuery - return filter(nodes, node => node.alias.includes(query) || node.pub_key.includes(query)).sort(contactableFirst) + // list of the nodes + const list = filter(nodes, node => node.alias.includes(query) || node.pub_key.includes(query)).sort(contactableFirst) + + // if we don't limit the nodes returned then we take a huge performance hit + // rendering thousands of nodes potentially, so we just render 20 for the time being + return list.slice(0, 20) } ) From ff4673c6eea81ec44cfeff6071a844a9ad42923f Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 10:47:37 -0500 Subject: [PATCH 08/12] fix(snapshots): create new snapshots so tests pass --- .../__snapshots__/channels.spec.js.snap | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/test/reducers/__snapshots__/channels.spec.js.snap b/test/reducers/__snapshots__/channels.spec.js.snap index f5613681..6f8dcd6a 100644 --- a/test/reducers/__snapshots__/channels.spec.js.snap +++ b/test/reducers/__snapshots__/channels.spec.js.snap @@ -229,63 +229,6 @@ Object { } `; -exports[`reducers channelsReducer should correctly setChannelForm 1`] = ` -Object { - "channel": null, - "channelForm": Object { - "isOpen": true, - "local_amt": "", - "node_key": "", - "push_amt": "", - }, - "channels": Array [], - "channelsLoading": false, - "closingChannel": false, - "closingChannelIds": Array [], - "contactModal": Object { - "channel": null, - "isOpen": false, - }, - "filter": Object { - "key": "ALL_CHANNELS", - "name": "All", - }, - "filterPulldown": false, - "filters": Array [ - Object { - "key": "ALL_CHANNELS", - "name": "All", - }, - Object { - "key": "ACTIVE_CHANNELS", - "name": "Online", - }, - Object { - "key": "NON_ACTIVE_CHANNELS", - "name": "Offline", - }, - Object { - "key": "OPEN_PENDING_CHANNELS", - "name": "Pending", - }, - Object { - "key": "CLOSING_PENDING_CHANNELS", - "name": "Closing", - }, - ], - "loadingChannelPubkeys": Array [], - "openingChannel": false, - "pendingChannels": Object { - "pending_closing_channels": Array [], - "pending_force_closing_channels": Array [], - "pending_open_channels": Array [], - "total_limbo_balance": "", - }, - "searchQuery": "", - "viewType": 0, -} -`; - exports[`reducers channelsReducer should handle initial state 1`] = ` Object { "channel": null, From 41dfede1914adfcb4856208743e8ff7cc8f242d0 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 11:51:20 -0500 Subject: [PATCH 09/12] fix(flowconfig): fix flowconfig so travis doesnt throw any Required module not found errors --- .flowconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.flowconfig b/.flowconfig index 491120be..ad1c3908 100644 --- a/.flowconfig +++ b/.flowconfig @@ -13,6 +13,25 @@ [include] [libs] +declare module 'react-redux' { + declare var exports: 'react-redux'; +} + +declare module 'react-router-redux' { + declare var exports: 'react-router-redux'; +} + +declare module 'prop-types' { + declare var exports: 'prop-types'; +} + +declare module 'electron' { + declare var exports: 'electron'; +} + +declare module 'chalk' { + declare var exports: 'chalk'; +} [options] esproposal.class_static_fields=enable From ebd697db249cb77b4c6f74f8a8825745d8d36813 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 13:05:37 -0500 Subject: [PATCH 10/12] fix(flow type): attempting to fix flow type errors --- .flowconfig | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/.flowconfig b/.flowconfig index ad1c3908..2082d04b 100644 --- a/.flowconfig +++ b/.flowconfig @@ -13,25 +13,7 @@ [include] [libs] -declare module 'react-redux' { - declare var exports: 'react-redux'; -} - -declare module 'react-router-redux' { - declare var exports: 'react-router-redux'; -} - -declare module 'prop-types' { - declare var exports: 'prop-types'; -} - -declare module 'electron' { - declare var exports: 'electron'; -} - -declare module 'chalk' { - declare var exports: 'chalk'; -} +flow-typed [options] esproposal.class_static_fields=enable From 1f7ac98fbb45eabd0c5d35b62b599209bea2cabf Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 13:40:26 -0500 Subject: [PATCH 11/12] fix(flow) --- flow-typed/react-redux_v5.x.x.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 flow-typed/react-redux_v5.x.x.js diff --git a/flow-typed/react-redux_v5.x.x.js b/flow-typed/react-redux_v5.x.x.js new file mode 100644 index 00000000..6961ad40 --- /dev/null +++ b/flow-typed/react-redux_v5.x.x.js @@ -0,0 +1,3 @@ +declare module 'react-redux' { + declare module.exports: any; +} From e1c674d374488c063961466339b7f3b98b1cf617 Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Wed, 4 Apr 2018 13:54:16 -0500 Subject: [PATCH 12/12] fix(flow): remove custom flow file --- flow-typed/react-redux_v5.x.x.js | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 flow-typed/react-redux_v5.x.x.js diff --git a/flow-typed/react-redux_v5.x.x.js b/flow-typed/react-redux_v5.x.x.js deleted file mode 100644 index 6961ad40..00000000 --- a/flow-typed/react-redux_v5.x.x.js +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'react-redux' { - declare module.exports: any; -}