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 (
+
+
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