Browse Source

feature(contacts): loading state while adding a contact

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
bd2f1e7b0d
  1. 2
      app/components/Contacts/ClosingContact.js
  2. 49
      app/components/Contacts/Contact.scss
  3. 12
      app/components/Contacts/ContactsForm.js
  4. 43
      app/components/Contacts/ContactsForm.scss
  5. 28
      app/components/Contacts/LoadingContact.js
  6. 9
      app/lnd/methods/channelController.js
  7. 33
      app/reducers/channels.js
  8. 14
      app/routes/contacts/components/Contacts.js
  9. 1
      app/routes/contacts/containers/ContactsContainer.js

2
app/components/Contacts/ClosingContact.js

@ -6,7 +6,7 @@ import { btc } from 'utils'
import styles from './Contact.scss'
const ClosingContact = ({ channel }) => (
<li className={styles.friend} key={index}>
<li className={styles.friend}>
<section className={styles.info}>
<p className={styles.closing}>
<FaCircle style={{ verticalAlign: 'top' }} />

49
app/components/Contacts/Contact.scss

@ -7,6 +7,12 @@
padding: 30px 0;
border-bottom: 1px solid $traditionalgrey;
&.loading {
.info {
opacity: 0.2;
}
}
.limits {
display: flex;
flex-direction: row;
@ -100,3 +106,46 @@
}
}
}
@-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);
}
}
.spinner {
border: 1px solid rgba(0, 0, 0, 0.1);
border-left-color: rgba(0, 0, 0, 0.4);
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
border-radius: 999px;
}
.spinner {
margin: 0 auto;
height: 50px;
width: 50px;
-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;
}

12
app/components/Contacts/ContactsForm.js

@ -27,12 +27,24 @@ class ContactsForm extends React.Component {
nonActiveChannelPubkeys,
pendingOpenChannelPubkeys,
filteredNetworkNodes,
loadingChannelPubkeys,
showManualForm
} = this.props
const { editing, manualFormInput } = this.state
const renderRightSide = (node) => {
if (loadingChannelPubkeys.includes(node.pub_key)) {
return (
<span className={styles.inactive}>
<div className={styles.loading}>
<div className={styles.spinner} />
</div>
</span>
)
}
if (activeChannelPubkeys.includes(node.pub_key)) {
return (
<span className={`${styles.online} ${styles.inactive}`}>

43
app/components/Contacts/ContactsForm.scss

@ -188,3 +188,46 @@
}
}
}
@-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);
}
}
.spinner {
border: 1px solid rgba(0, 0, 0, 0.1);
border-left-color: rgba(0, 0, 0, 0.4);
-webkit-border-radius: 999px;
-moz-border-radius: 999px;
border-radius: 999px;
}
.spinner {
margin: 0 auto;
height: 20px;
width: 20px;
-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;
}

28
app/components/Contacts/LoadingContact.js

@ -0,0 +1,28 @@
import React from 'react'
import PropTypes from 'prop-types'
import { FaCircle } from 'react-icons/lib/fa'
import { btc } from 'utils'
import styles from './Contact.scss'
const LoadingContact = ({ pubkey }) => (
<li className={`${styles.friend} ${styles.loading}`}>
<section className={styles.info}>
<p>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>Loading</span>
</p>
<h2>{pubkey}</h2>
</section>
<section className={styles.limits}>
<div className={styles.loading}>
<div className={styles.spinner} />
</div>
</section>
</li>
)
LoadingContact.propTypes = {
}
export default LoadingContact

9
app/lnd/methods/channelController.js

@ -30,7 +30,11 @@ export function connectAndOpen(lnd, meta, event, payload) {
const peer = find(peers, { pub_key: pubkey })
if (peer) {
console.log('we can open the channel')
console.log('already have the peer. can open the channel now')
const call = lnd.openChannel(channelPayload, meta)
call.on('data', data => event.sender.send('pushchannelupdated', { pubkey, data }))
call.on('error', error => event.sender.send('pushchannelerror', { pubkey, error: error.toString() }))
} else {
console.log('connect to the peer first')
connectPeer(lnd, meta, { pubkey, host })
@ -41,9 +45,6 @@ export function connectAndOpen(lnd, meta, event, payload) {
call.on('data', data => event.sender.send('pushchannelupdated', { data }))
call.on('error', error => event.sender.send('pushchannelerror', { error: error.toString() }))
call.on('end', () => event.sender.send('pushchannelend'))
call.on('status', status => event.sender.send('pushchannelstatus', { status }))
})
.catch(err => {
console.log('connectPeer err: ', err)

33
app/reducers/channels.js

@ -29,6 +29,9 @@ export const SET_VIEW_TYPE = 'SET_VIEW_TYPE'
export const TOGGLE_CHANNEL_PULLDOWN = 'TOGGLE_CHANNEL_PULLDOWN'
export const CHANGE_CHANNEL_FILTER = 'CHANGE_CHANNEL_FILTER'
export const ADD_LOADING_PUBKEY = 'ADD_LOADING_PUBKEY'
export const REMOVE_LOADING_PUBKEY = 'REMOVE_LOADING_PUBKEY'
// ------------------------------------
// Actions
// ------------------------------------
@ -91,6 +94,20 @@ export function setViewType(viewType) {
}
}
export function addLoadingPubkey(pubkey) {
return {
type: ADD_LOADING_PUBKEY,
pubkey
}
}
export function removeLoadingPubkey(pubkey) {
return {
type: REMOVE_LOADING_PUBKEY,
pubkey
}
}
// Send IPC event for peers
export const fetchChannels = () => async (dispatch) => {
dispatch(getChannels())
@ -105,6 +122,7 @@ export const openChannel = ({ pubkey, host, local_amt, push_amt }) => (dispatch)
const localamt = btc.btcToSatoshis(local_amt)
dispatch(openingChannel())
dispatch(addLoadingPubkey(pubkey))
ipcRenderer.send('lnd', { msg: 'connectAndOpen', data: { pubkey, host, localamt } })
}
@ -118,9 +136,10 @@ export const channelSuccessful = () => (dispatch) => {
}
// Receive IPC event for updated channel
export const pushchannelupdated = (event, data) => (dispatch) => {
export const pushchannelupdated = (event, { pubkey, data }) => (dispatch) => {
console.log('PUSH CHANNEL UPDATED: ', data)
dispatch(fetchChannels())
dispatch(removeLoadingPubkey(pubkey))
}
// Receive IPC event for channel end
@ -130,10 +149,11 @@ export const pushchannelend = event => (dispatch) => { // eslint-disable-line
}
// Receive IPC event for channel error
export const pushchannelerror = (event, { error }) => (dispatch) => {
export const pushchannelerror = (event, { pubkey, error }) => (dispatch) => {
console.log('PUSH CHANNEL ERROR: ', error)
dispatch(openingFailure())
dispatch(setError(error))
dispatch(removeLoadingPubkey(pubkey))
}
// Receive IPC event for channel status
@ -269,7 +289,10 @@ const ACTION_HANDLERS = {
[SET_VIEW_TYPE]: (state, { viewType }) => ({ ...state, viewType }),
[TOGGLE_CHANNEL_PULLDOWN]: state => ({ ...state, filterPulldown: !state.filterPulldown }),
[CHANGE_CHANNEL_FILTER]: (state, { filter }) => ({ ...state, filterPulldown: false, filter })
[CHANGE_CHANNEL_FILTER]: (state, { filter }) => ({ ...state, filterPulldown: false, filter }),
[ADD_LOADING_PUBKEY]: (state, { pubkey }) => ({ ...state, loadingChannelPubkeys: [pubkey, ...state.loadingChannelPubkeys] }),
[REMOVE_LOADING_PUBKEY]: (state, { pubkey }) => ({ ...state, loadingChannelPubkeys: state.loadingChannelPubkeys.filter(loadingPubkey => loadingPubkey !== pubkey) })
}
const channelsSelectors = {}
@ -427,7 +450,9 @@ const initialState = {
{ key: 'NON_ACTIVE_CHANNELS', name: 'Offline Contacts' },
{ key: 'OPEN_PENDING_CHANNELS', name: 'Pending Contacts' },
{ key: 'CLOSING_PENDING_CHANNELS', name: 'Closing Contacts' }
]
],
loadingChannelPubkeys: []
}
export default function channelsReducer(state = initialState, action) {

14
app/routes/contacts/components/Contacts.js

@ -12,6 +12,7 @@ import OnlineContact from 'components/Contacts/OnlineContact'
import PendingContact from 'components/Contacts/PendingContact'
import ClosingContact from 'components/Contacts/ClosingContact'
import OfflineContact from 'components/Contacts/OfflineContact'
import LoadingContact from 'components/Contacts/LoadingContact'
import plus from 'icons/plus.svg'
@ -40,7 +41,8 @@ class Contacts extends Component {
searchQuery,
filterPulldown,
filter,
viewType
viewType,
loadingChannelPubkeys
},
currentChannels,
activeChannels,
@ -148,6 +150,16 @@ class Contacts extends Component {
</div>
<ul className={`${styles.friends} ${filterPulldown && styles.fade}`}>
{
loadingChannelPubkeys.map(pubkey => {
console.log('pubkey: ', pubkey)
return (
<LoadingContact pubkey={pubkey} />
)
})
}
{
currentChannels.length > 0 && currentChannels.map((channel, index) => {
if (Object.prototype.hasOwnProperty.call(channel, 'blocks_till_open')) {

1
app/routes/contacts/containers/ContactsContainer.js

@ -71,6 +71,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
contactsform: stateProps.contactsform,
filteredNetworkNodes: stateProps.filteredNetworkNodes,
loadingChannelPubkeys: stateProps.channels.loadingChannelPubkeys,
showManualForm: stateProps.showManualForm,
activeChannelPubkeys: stateProps.activeChannelPubkeys,

Loading…
Cancel
Save