Browse Source

feature(friends): create friends route and start implementing friends list

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
bcb158b417
  1. 10
      app/components/Nav/Nav.js
  2. 16
      app/components/Nav/Nav.scss
  3. 1
      app/icons/plus.svg
  4. 2
      app/main.dev.js
  5. 10
      app/reducers/channels.js
  6. 2
      app/routes.js
  7. 138
      app/routes/friends/components/Friends.js
  8. 147
      app/routes/friends/components/Friends.scss
  9. 24
      app/routes/friends/containers/FriendsContainer.js
  10. 3
      app/routes/friends/index.js

10
app/components/Nav/Nav.js

@ -18,28 +18,30 @@ const Nav = ({ openPayForm, openRequestForm }) => (
</header>
<ul className={styles.links}>
<NavLink exact to='/' activeClassName={styles.active} className={styles.link}>
<span className={styles.activeBorder} />
<li>
<Isvg styles={{ verticalAlign: 'middle' }} src={walletIcon} />
<span>Wallet</span>
</li>
</NavLink>
<NavLink exact to='/friends' activeClassName={styles.active} className={styles.link}>
<li>
<Isvg styles={{ verticalAlign: 'middle' }} src={peersIcon} />
<span>Friends</span>
</li>
</NavLink>
<NavLink exact to='/peers' activeClassName={styles.active} className={styles.link}>
<span className={styles.activeBorder} />
<li>
<Isvg styles={{ verticalAlign: 'middle' }} src={peersIcon} />
<span>Peers</span>
</li>
</NavLink>
<NavLink exact to='/channels' activeClassName={styles.active} className={styles.link}>
<span className={styles.activeBorder} />
<li>
<Isvg styles={{ verticalAlign: 'middle' }} src={channelsIcon} />
<span>Channels</span>
</li>
</NavLink>
<NavLink exact to='/network' activeClassName={styles.active} className={styles.link}>
<span className={styles.activeBorder} />
<li>
<Isvg styles={{ verticalAlign: 'middle' }} src={networkIcon} />
<span>Network</span>

16
app/components/Nav/Nav.scss

@ -136,27 +136,17 @@
border-left: 20px solid transparent;
transition: all 0.25s;
.activeBorder {
position: absolute;
left: -30px;
width: 10px;
height: 100%;
margin: 0;
background: $main;
transition: all 0.25s;
}
li {
margin: 12.5px 0;
min-width: 200px;
}
&.active {
color: $white;
color: $main;
opacity: 1.0;
.activeBorder {
left: -10px;
svg g {
stroke: $main;
}
}

1
app/icons/plus.svg

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>

After

Width:  |  Height:  |  Size: 304 B

2
app/main.dev.js

@ -169,7 +169,7 @@ export const startLnd = () => {
'--bitcoin.active',
'--bitcoin.testnet',
'--neutrino.active',
'--neutrino.connect=btcd.jackmallers.com:18333',
'--neutrino.connect=btcd0.lightning.computer:18333',
'--autopilot.active',
'--debuglevel=debug',
'--noencryptwallet'

10
app/reducers/channels.js

@ -293,6 +293,16 @@ channelsSelectors.activeChannels = createSelector(
openChannels => openChannels.filter(channel => channel.active)
)
channelsSelectors.nonActiveChannels = createSelector(
channelsSelector,
openChannels => openChannels.filter(channel => !channel.active)
)
channelsSelectors.pendingOpenChannels = createSelector(
pendingOpenChannelsSelector,
pendingOpenChannels => pendingOpenChannels
)
const closingPendingChannels = createSelector(
pendingClosedChannelsSelector,
pendingForceClosedChannelsSelector,

2
app/routes.js

@ -3,6 +3,7 @@ import React from 'react'
import { Switch, Route } from 'react-router'
import App from './routes/app'
import Activity from './routes/activity'
import Friends from './routes/friends'
import Peers from './routes/peers'
import Channels from './routes/channels'
import Network from './routes/network'
@ -12,6 +13,7 @@ export default () => (
<Switch>
<Route path='/peers' component={Peers} />
<Route path='/channels' component={Channels} />
<Route path='/friends' component={Friends} />
<Route path='/network' component={Network} />
<Route path='/' component={Activity} />
</Switch>

138
app/routes/friends/components/Friends.js

@ -0,0 +1,138 @@
import { shell } from 'electron'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Isvg from 'react-inlinesvg'
import { MdSearch } from 'react-icons/lib/md'
import { FaCircle } from 'react-icons/lib/fa'
import plus from 'icons/plus.svg'
import styles from './Friends.scss'
class Friends extends Component {
constructor(props) {
super(props)
}
componentWillMount() {
const { fetchChannels, fetchPeers } = this.props
fetchChannels()
fetchPeers()
}
render() {
const {
channels,
activeChannels,
nonActiveChannels,
pendingOpenChannels,
peers
} = this.props
console.log('pendingOpenChannels: ', pendingOpenChannels)
return (
<div className={styles.friendsContainer}>
<header className={styles.header}>
<div className={styles.titleContainer}>
<div className={styles.left}>
<h1>Friends ({activeChannels.length} online)</h1>
</div>
</div>
<div className={styles.newFriendContainer}>
<div className={`buttonPrimary ${styles.newFriendButton}`} onClick={() => (console.log('yo'))}>
<Isvg src={plus} />
<span>Add</span>
</div>
</div>
</header>
<div className={styles.search}>
<label className={`${styles.label} ${styles.input}`} htmlFor='channelSearch'>
<MdSearch />
</label>
<input
value={''}
onChange={event => console.log('event: ', event)}
className={`${styles.text} ${styles.input}`}
placeholder='Search your friends list...'
type='text'
id='channelSearch'
/>
</div>
<ul className={styles.friends}>
{
activeChannels.length > 0 && activeChannels.map(activeChannel => {
console.log('activeChannel: ', activeChannel)
return (
<li className={styles.friend} key={activeChannel.chan_id}>
<section className={styles.info}>
<p className={styles.online}>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>Online</span>
</p>
<h2>{activeChannel.remote_pubkey}</h2>
</section>
<section>
</section>
</li>
)
})
}
{
pendingOpenChannels.length > 0 && pendingOpenChannels.map(pendingOpenChannel => {
console.log('pendingOpenChannel: ', pendingOpenChannel)
return (
<li className={styles.friend} key={pendingOpenChannel.chan_id}>
<section className={styles.info}>
<p className={styles.pending}>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>
Pending
<i onClick={() => shell.openExternal(`${'https://testnet.smartbit.com.au'}/tx/${pendingOpenChannel.channel.channel_point.split(':')[0]}`)}>
(~{pendingOpenChannel.blocks_till_open * 10} minutes)
</i>
</span>
</p>
<h2>{pendingOpenChannel.channel.remote_node_pub}</h2>
</section>
<section>
</section>
</li>
)
})
}
{
nonActiveChannels.length > 0 && nonActiveChannels.map(nonActiveChannel => {
console.log('nonActiveChannel: ', nonActiveChannel)
return (
<li className={styles.friend} key={nonActiveChannel.chan_id}>
<section className={styles.info}>
<p>
<FaCircle style={{ verticalAlign: 'top' }} />
<span>Offline</span>
</p>
<h2>{nonActiveChannel.remote_pubkey}</h2>
</section>
<section>
</section>
</li>
)
})
}
</ul>
</div>
)
}
}
Friends.propTypes = {}
export default Friends

147
app/routes/friends/components/Friends.scss

@ -0,0 +1,147 @@
@import '../../../variables.scss';
.header {
display: flex;
flex-direction: row;
justify-content: space-between;
background: $lightgrey;
.titleContainer {
padding: 20px 40px;
.left {
padding: 10px 0;
h1 {
text-transform: uppercase;
font-size: 26px;
margin-right: 5px;
}
}
}
.newFriendContainer {
padding: 20px 40px;
.newFriendButton {
box-shadow: none;
transition: all 0.25s;
&:hover {
background: darken($main, 10%);
}
span {
display: inline-block;
vertical-align: top;
&:nth-child(1) svg {
width: 16px;
height: 16px;
margin-right: 5px;
}
}
}
}
}
.search {
height: 55px;
padding: 2px 25px;
border-top: 1px solid $darkgrey;
border-bottom: 1px solid $darkgrey;
background: $white;
.input {
display: inline-block;
vertical-align: top;
height: 100%;
}
.label {
width: 5%;
line-height: 50px;
font-size: 20px;
text-align: center;
cursor: pointer;
}
.text {
width: 95%;
outline: 0;
padding: 0;
border: 0;
border-radius: 0;
height: 50px;
font-size: 16px;
}
}
.friends {
padding: 10px 60px 60px 60px;
}
.friend {
padding: 30px 0;
border-bottom: 1px solid $traditionalgrey;
.info {
p {
margin-bottom: 20px;
&.online {
color: $green;
svg {
color: $green;
}
}
&.pending {
color: #FF8A65;
svg {
color: #FF8A65;
}
i {
margin-left: 5px;
color: $darkestgrey;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
}
svg, span {
display: inline-block;
vertical-align: top;
}
svg {
margin-right: 5px;
width: 12px;
height: 12px;
color: $darkestgrey;
}
span {
font-size: 12px;
}
}
h2 {
color: $black;
font-size: 14px;
font-weight: bold;
letter-spacing: 1.3px;
span {
color: $darkestgrey;
margin-left: 5px;
}
}
}
}

24
app/routes/friends/containers/FriendsContainer.js

@ -0,0 +1,24 @@
import { withRouter } from 'react-router'
import { connect } from 'react-redux'
import { fetchChannels, channelsSelectors } from 'reducers/channels'
import { fetchPeers } from 'reducers/peers'
import Friends from '../components/Friends'
const mapDispatchToProps = {
fetchChannels,
fetchPeers
}
const mapStateToProps = state => ({
channels: state.channels,
peers: state.peers,
activeChannels: channelsSelectors.activeChannels(state),
nonActiveChannels: channelsSelectors.nonActiveChannels(state),
pendingOpenChannels: channelsSelectors.pendingOpenChannels(state)
})
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Friends))

3
app/routes/friends/index.js

@ -0,0 +1,3 @@
import FriendsContainer from './containers/FriendsContainer'
export default FriendsContainer
Loading…
Cancel
Save