Browse Source

Merge pull request #96 from LN-Zap/fix/peers-channel-loading-ux

Fix/peers channel loading ux
renovate/lint-staged-8.x
JimmyMow 7 years ago
committed by GitHub
parent
commit
87db25b0ca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      app/app.global.scss
  2. 4
      app/components/Channels/Channel.scss
  3. 25
      app/components/Channels/OpenPendingChannel.js
  4. 13
      app/components/Channels/OpenPendingChannel.scss
  5. 55
      app/components/Peers/PeerModal.js
  6. 42
      app/components/Peers/PeerModal.scss
  7. 54
      app/components/Wallet/ReceiveModal.js
  8. 79
      app/components/Wallet/ReceiveModal.scss
  9. 21
      app/components/Wallet/Wallet.js
  10. 4
      app/components/Wallet/Wallet.scss
  11. 9
      app/lnd/methods/paymentsController.js
  12. 2
      app/lnd/subscribe/transactions.js
  13. 1
      app/main.dev.js
  14. 15
      app/reducers/channels.js
  15. 5
      app/reducers/info.js
  16. 1
      app/routes/activity/components/components/Modal/Invoice/Invoice.js

3
app/app.global.scss

@ -86,7 +86,8 @@ body {
padding-bottom: 15px;
border-radius: 2px;
text-align: center;
font-size: 18px;
font-size: 16px;
letter-spacing: 1.5px;
transition: none;
position: relative;
color: white;

4
app/components/Channels/Channel.scss

@ -2,15 +2,17 @@
.channel {
position: relative;
background: $lightgrey;
background: $white;
margin: 5px 0;
padding: 10px;
border-top: 1px solid $white;
cursor: pointer;
transition: all 0.25s;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
&:hover {
opacity: 0.75;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}
&:first-child {

25
app/components/Channels/OpenPendingChannel.js

@ -4,17 +4,20 @@ import PropTypes from 'prop-types'
import { btc } from 'utils'
import styles from './OpenPendingChannel.scss'
const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explorerLinkBase }) => (
<li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel_point.split(':')[0]}`)}>
<h1 className={styles.pending}>Opening Channel...</h1>
const OpenPendingChannel = ({ ticker, channel, currentTicker, explorerLinkBase }) => (
<li className={styles.channel} onClick={() => shell.openExternal(`${explorerLinkBase}/tx/${channel.channel.channel_point.split(':')[0]}`)}>
<div className={styles.pending}>
<h1>Opening Channel...</h1>
<span>Blocks till open: {channel.blocks_till_open}</span>
</div>
<div className={styles.left}>
<section className={styles.remotePubkey}>
<span>Remote Pubkey</span>
<h4>{channel.remote_node_pub}</h4>
<h4>{channel.channel.remote_node_pub}</h4>
</section>
<section className={styles.channelPoint}>
<span>Channel Point</span>
<h4>{channel.channel_point}</h4>
<h4>{channel.channel.channel_point}</h4>
</section>
</div>
<div className={styles.right}>
@ -23,9 +26,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h2>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.capacity)
btc.satoshisToBtc(channel.channel.capacity)
:
btc.satoshisToUsd(channel.capacity, currentTicker.price_usd)
btc.satoshisToUsd(channel.channel.capacity, currentTicker.price_usd)
}
</h2>
</section>
@ -34,9 +37,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h4>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.local_balance)
btc.satoshisToBtc(channel.channel.local_balance)
:
btc.satoshisToUsd(channel.local_balance, currentTicker.price_usd)
btc.satoshisToUsd(channel.channel.local_balance, currentTicker.price_usd)
}
</h4>
<span>Local</span>
@ -45,9 +48,9 @@ const OpenPendingChannel = ({ ticker, channel: { channel }, currentTicker, explo
<h4>
{
ticker.currency === 'btc' ?
btc.satoshisToBtc(channel.remote_balance)
btc.satoshisToBtc(channel.channel.remote_balance)
:
btc.satoshisToUsd(channel.remote_balance, currentTicker.price_usd)
btc.satoshisToUsd(channel.channel.remote_balance, currentTicker.price_usd)
}
</h4>
<span>Remote</span>

13
app/components/Channels/OpenPendingChannel.scss

@ -13,14 +13,21 @@
opacity: 0.5;
.pending {
color: $main;
position: absolute;
top: 0;
left: 10px;
padding: 10px;
text-transform: uppercase;
font-weight: bold;
font-size: 10px;
h1 {
color: $main;
font-size: 10px;
}
span {
font-size: 8px;
}
}
&:first-child {
@ -30,7 +37,7 @@
.left, .right {
padding: 0 10px;
margin-bottom: 5;
margin-top: 25px;
margin-top: 40px;
section {
margin-bottom: 20px;

55
app/components/Peers/PeerModal.js

@ -1,6 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import ReactModal from 'react-modal'
import { MdClose } from 'react-icons/lib/md'
import styles from './PeerModal.scss'
const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
@ -16,7 +19,8 @@ const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
bottom: 'auto',
width: '40%',
margin: '50px auto',
padding: '40px'
borderRadius: 'none',
padding: '0'
}
}
@ -30,32 +34,35 @@ const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
parentSelector={() => document.body}
style={customStyles}
>
<div className={styles.closeContainer}>
<span onClick={() => resetPeer(null)}>
<MdClose />
</span>
</div>
{
peer ?
<div className={styles.peer}>
<header className={styles.header}>
<h1 data-hint='Peer address' className='hint--top-left'>{peer.address}</h1>
<h2 data-hint='Peer public key' className='hint--top-left'>{peer.pub_key}</h2>
</header>
peer &&
<div className={styles.peer}>
<header className={styles.header}>
<h1 data-hint='Peer address' className='hint--top-left'>{peer.address}</h1>
<h2 data-hint='Peer public key' className='hint--top-left'>{peer.pub_key}</h2>
</header>
<div className={styles.details}>
<dl>
<dt>Satoshis Received</dt>
<dd>{peer.sat_recv}</dd>
<dt>Satoshis Sent</dt>
<dd>{peer.sat_sent}</dd>
<dt>Bytes Received</dt>
<dd>{peer.bytes_recv}</dd>
<dt>Bytes Sent</dt>
<dd>{peer.bytes_sent}</dd>
</dl>
</div>
<div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}>
<div>Disconnect peer</div>
</div>
<div className={styles.details}>
<dl>
<dt>Satoshis Received</dt>
<dd>{peer.sat_recv}</dd>
<dt>Satoshis Sent</dt>
<dd>{peer.sat_sent}</dd>
<dt>Bytes Received</dt>
<dd>{peer.bytes_recv}</dd>
<dt>Bytes Sent</dt>
<dd>{peer.bytes_sent}</dd>
</dl>
</div>
<div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}>
<div>Disconnect peer</div>
</div>
:
null
</div>
}
</ReactModal>
)

42
app/components/Peers/PeerModal.scss

@ -1,29 +1,39 @@
@import '../../variables.scss';
.peer {
padding: 40px;
.closeContainer {
background: $lightgrey;
text-align: right;
padding: 10px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
}
}
.header {
margin-bottom: 50px;
background: $lightgrey;
padding: 20px;
h1 {
color: $black;
text-align: center;
margin-bottom: 5px;
margin-bottom: 20px;
font-weight: bold;
}
h2 {
color: $darkestgrey;
font-size: 14px;
font-size: 12px;
text-align: center;
}
}
.details {
width: 75%;
margin: 20px auto;
dl {
padding: 40px 40px 40px 40px;
}
dt {
text-align: left;
@ -38,36 +48,28 @@
dd {
text-align: right;
font-weight: 400;
padding: 19px 0;
padding: 30px 0 10px 0;
margin-left: 0;
border-top: 1px solid $darkgrey;
border-bottom: 1px solid $darkgrey;
}
}
.close {
text-align: center;
padding-bottom: 40px;
div {
width: 35%;
margin: 0 auto;
cursor: pointer;
height: 55px;
min-height: 55px;
text-transform: none;
font-size: 18px;
transition: opacity .2s ease-out;
background: $red;
color: $white;
color: $red;
border: none;
font-weight: 500;
padding: 0;
text-align: center;
line-height: 55px;
transition: all 0.25s;
border-radius: 5px;
&:hover {
background: darken($red, 10%);
color: lighten($red, 10%);
}
}
}

54
app/components/Wallet/ReceiveModal.js

@ -4,9 +4,11 @@ import ReactModal from 'react-modal'
import copy from 'copy-to-clipboard'
import QRCode from 'qrcode.react'
import { showNotification } from 'notifications'
import { MdClose } from 'react-icons/lib/md'
import { FaCopy } from 'react-icons/lib/fa'
import styles from './ReceiveModal.scss'
const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }) => {
const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress, qrCodeType, changeQrCode }) => {
const customStyles = {
overlay: {
cursor: 'pointer'
@ -16,8 +18,10 @@ const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }
left: '20%',
right: '0',
bottom: 'auto',
width: '60%',
margin: '50px auto'
width: '40%',
margin: '50px auto',
borderRadius: 'none',
padding: '0'
}
}
@ -36,22 +40,48 @@ const ReceiveModal = ({ isOpen, hideActivityModal, pubkey, address, newAddress }
parentSelector={() => document.body}
style={customStyles}
>
<div className={styles.closeContainer}>
<span onClick={() => hideActivityModal()}>
<MdClose />
</span>
</div>
<div className={styles.container}>
<section>
<h4>Node Public Key (<span onClick={() => copyOnClick(pubkey)}>Copy</span>)</h4>
<p>{pubkey}</p>
</section>
<header>
<div className={styles.qrcodes}>
<QRCode value={qrCodeType === 1 ? address : pubkey} />
</div>
<ul className={styles.tabs}>
<li className={qrCodeType === 1 && styles.active} onClick={changeQrCode}>
Wallet address
</li>
<li className={qrCodeType === 2 && styles.active} onClick={changeQrCode}>
Node pubkey
</li>
</ul>
</header>
<section>
<div className={styles.addressHeader}>
<h4>Deposit Address (<span onClick={() => copyOnClick(address)}>Copy</span>)</h4>
<h4>Deposit Address</h4>
<span className={styles.newAddress} onClick={() => newAddress('p2pkh')}>New Address</span>
</div>
<p>{address}</p>
<p>
<span>{address}</span>
<span onClick={() => copyOnClick(address)} className='hint--left' data-hint='Copy address'>
<FaCopy />
</span>
</p>
</section>
<div className={styles.qrcode}>
<QRCode value={address} />
</div>
<section>
<h4>Node Public Key</h4>
<p>
<span>{pubkey}</span>
<span onClick={() => copyOnClick(pubkey)} className='hint--left' data-hint='Copy pubkey'>
<FaCopy />
</span>
</p>
</section>
</div>
</ReactModal>

79
app/components/Wallet/ReceiveModal.scss

@ -1,15 +1,59 @@
@import '../../variables.scss';
.closeContainer {
background: $lightgrey;
text-align: right;
padding: 10px;
span {
color: $darkestgrey;
font-size: 20px;
cursor: pointer;
}
}
.container {
header {
background: $lightgrey;
padding: 10px 40px 40px;
text-align: center;
.qrcodes {
text-align: center;
margin-top: 20px;
}
.tabs {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-top: 20px;
li {
margin: 0 20px;
color: $darkestgrey;
transition: all 0.25s;
&:hover {
color: $black;
}
&.active {
color: $black;
font-weight: bold;
}
}
}
}
section {
margin: 25px 0;
padding: 25px;
border-bottom: 1px solid $darkestgrey;
h4 {
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 1.5px;
margin-bottom: 10px;
@ -19,20 +63,33 @@
}
}
.qrcode {
text-align: center;
margin-top: 20px;
}
p {
display: flex;
flex-direction: row;
font-family: 'Roboto';
text-align: center;
font-size: 14px;
font-weight: 200;
border-radius: 7px;
background: $lightgrey;
border: 1px solid $main;
padding: 10px;
span {
padding: 15px;
}
span:nth-child(1) {
flex: 9;
overflow-x: scroll;
}
span:nth-child(2) {
background: $darkgrey;
color: $black;
cursor: pointer;
transition: all 0.25s;
&:hover {
background: $darkestgrey;
}
}
}
}
}

21
app/components/Wallet/Wallet.js

@ -13,7 +13,8 @@ class Wallet extends Component {
super(props)
this.state = {
modalOpen: false
modalOpen: false,
qrCodeType: 1
}
}
@ -25,19 +26,29 @@ class Wallet extends Component {
newAddress
} = this.props
const { modalOpen } = this.state
const { modalOpen, qrCodeType } = this.state
const changeQrCode = () => {
const qrCodeType = this.state.qrCodeType === 1 ? 2 : 1
this.setState({ qrCodeType })
}
return (
<div className={styles.wallet}>
{
(modalOpen &&
(
modalOpen &&
<ReceiveModal
isOpen={modalOpen}
hideActivityModal={() => this.setState({ modalOpen: false })}
pubkey={info.data.identity_pubkey}
address={address}
newAddress={newAddress}
/>)
qrCodeType={qrCodeType}
changeQrCode={changeQrCode}
/>
)
}
<div className={styles.content}>
<div className={styles.left}>
@ -52,7 +63,7 @@ class Wallet extends Component {
</div>
<div className={styles.right}>
<div className={styles.rightContent}>
<div onClick={() => this.setState({ modalOpen: true })}>
<div className={'buttonPrimary'} onClick={() => this.setState({ modalOpen: true })}>
<FaQrcode />
Address
</div>

4
app/components/Wallet/Wallet.scss

@ -58,10 +58,10 @@
height: calc(100% - 50px);
div {
font-size: 20px;
padding: 10px 25px;
padding: 7px 20px;
background: $main;
transition: background 0.25s;
color: $black;
&:hover {
background: darken($main, 10%);

9
app/lnd/methods/paymentsController.js

@ -6,10 +6,13 @@
*/
export function sendPaymentSync(lnd, { paymentRequest }) {
return new Promise((resolve, reject) => {
lnd.sendPaymentSync({ payment_request: paymentRequest }, (err, data) => {
if (err) { reject(err) }
lnd.sendPaymentSync({ payment_request: paymentRequest }, (error, data) => {
if (error) {
reject({ error })
return
}
if (!data.payment_route) { reject({ error: data.payment_error }) }
if (!data || !data.payment_route) { reject({ error: data.payment_error }) }
resolve(data)
})

2
app/lnd/subscribe/transactions.js

@ -9,5 +9,5 @@ export default function subscribeToTransactions(mainWindow, lnd) {
})
call.on('end', () => console.log('end'))
call.on('error', error => console.log('error: ', error))
call.on('status', status => console.log('status: ', status))
call.on('status', status => console.log('TRANSACTION STATUS: ', status))
}

1
app/main.dev.js

@ -165,6 +165,7 @@ export const startLnd = () => {
'--bitcoin.active',
'--bitcoin.testnet',
'--neutrino.active',
'--neutrino.connect=btcd0.lightning.computer:18333',
'--neutrino.connect=faucet.lightning.community:18333',
'--autopilot.active',
'--debuglevel=debug',

15
app/reducers/channels.js

@ -165,27 +165,32 @@ export const closeChannel = ({ channel_point }) => (dispatch) => {
// TODO: Decide how to handle streamed updates for closing channels
// Receive IPC event for closeChannel
export const closeChannelSuccessful = () => (dispatch) => {
export const closeChannelSuccessful = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL SUCCESSFUL: ', data)
dispatch(fetchChannels())
}
// Receive IPC event for updated closing channel
export const pushclosechannelupdated = () => (dispatch) => {
export const pushclosechannelupdated = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL UPDATED: ', data)
dispatch(fetchChannels())
}
// Receive IPC event for closing channel end
export const pushclosechannelend = () => (dispatch) => {
export const pushclosechannelend = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL END: ', data)
dispatch(fetchChannels())
}
// Receive IPC event for closing channel error
export const pushclosechannelerror = () => (dispatch) => {
export const pushclosechannelerror = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL END: ', data)
dispatch(fetchChannels())
}
// Receive IPC event for closing channel status
export const pushclosechannelstatus = () => (dispatch) => {
export const pushclosechannelstatus = (event, data) => (dispatch) => {
console.log('PUSH CLOSE CHANNEL STATUS: ', data)
dispatch(fetchChannels())
}

5
app/reducers/info.js

@ -1,7 +1,6 @@
import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import { fetchBalance } from './balance'
import { newAddress } from './address'
// ------------------------------------
// Constants
// ------------------------------------
@ -25,8 +24,6 @@ export const fetchInfo = () => async (dispatch) => {
// Receive IPC event for info
export const receiveInfo = (event, data) => (dispatch) => {
dispatch(fetchBalance())
dispatch(newAddress('p2pkh'))
dispatch({ type: RECEIVE_INFO, data })
}

1
app/routes/activity/components/components/Modal/Invoice/Invoice.js

@ -6,7 +6,6 @@ import 'moment-timezone'
import QRCode from 'qrcode.react'
import { MdCheck } from 'react-icons/lib/md'
import { FaCircle } from 'react-icons/lib/fa'
import CurrencyIcon from 'components/CurrencyIcon'

Loading…
Cancel
Save