/ app / js / components / UserTweets.js
UserTweets.js
  1  import { Grid, Row, Col, Thumbnail, ListGroup, ListGroupItem, PageHeader } from 'react-bootstrap';
  2  import React, { Component } from 'react';
  3  import imgAvatar from '../../img/avatar-default.png';
  4  import { formatDistance } from 'date-fns/esm'
  5  
  6  // The Player looks up the player using the number parsed from
  7  // the URL's pathname. If no player is found with the given
  8  // number, then a "player not found" message is displayed.
  9  class UserTweets extends Component {
 10    
 11    //#region Constructor
 12    constructor(props, context){
 13      super(props, context);
 14      this.state = {
 15        user: {},
 16        tweets: []
 17      };
 18      this.event = null;
 19    }
 20    //#endregion
 21  
 22    //#region Helper methods
 23    /**
 24     * Get the user details and subscribe to their tweet event
 25     */
 26    _init(){
 27      const { username } = this.props.match.params;
 28      this._getUserDetails(username);
 29  
 30      // subscribe to tweet events
 31      this._subscribeToNewTweetEvent(username);
 32    }
 33  
 34    /**
 35     * Fetches the user's details from the contract for display
 36     */
 37    _getUserDetails = async(username) => {
 38        // get user details and update state
 39        //let user = await DTwitter.methods.users(web3.utils.keccak256(username)).call();
 40  
 41        // update picture url for ipfs
 42        //user.picture = user.picture.length > 0 ? EmbarkJS.Storage.getUrl(user.picture) : imgAvatar;
 43        
 44        // format the user.creationDate for display
 45        //user.creationDate = this._formatDate(user.creationDate);
 46        
 47        this.setState({user: user});
 48    }
 49  
 50    /**
 51     * Subscribes to a tweet event from the contract.
 52     * When a tweet is received, it is appended to the list of
 53     * tweets.
 54     * 
 55     * @param {String} username 
 56     * @returns {null}
 57     */
 58    _subscribeToNewTweetEvent(username){
 59      // this.event = DTwitter.events.NewTweet({
 60      //     filter: {_from: web3.utils.keccak256(username)}, 
 61      //     fromBlock: 1
 62      //   }, (err, event) => {
 63      //     if (err){
 64      //       this.props.onError(err, 'UserTweets._subscribeToNewTweetEvent');
 65      //     }
 66      //   })
 67      //   .on('data', (event) => {
 68      //     let tweets = this.state.tweets;
 69          
 70      //     tweets.push({
 71      //       content: event.returnValues.tweet,
 72      //       time: this._formatDate(event.returnValues.time)
 73      //     });
 74  
 75      //     this.setState({tweets: tweets});
 76      //   })
 77      //   .on('error', function(error){
 78      //     this.props.onError(err, 'UserTweets._subscribeToNewTweetEvent');
 79      //   });
 80    }
 81  
 82    /**
 83     * Formats an int date into a displayable date
 84     * @param {Number} intDate - date in seconds
 85     * @returns {String} prettyfied date
 86     */
 87    _formatDate(intDate){
 88      const padZeros = 13 - intDate.length;
 89      if(padZeros > 0){
 90        intDate *= Math.pow(10, padZeros);
 91      }
 92      return formatDistance(new Date(intDate), new Date()) + ' ago';
 93    }
 94    //#endregion
 95  
 96    //#region React lifecycle events
 97    /**
 98     * Get the user details and subscribe to their tweet event
 99     */
100    componentDidMount(){
101      EmbarkJS.onReady((err) => {
102        this._init();
103      });
104    }
105  
106    /**
107     * If the username was changed (ie redirected from a new route),
108     * we need to get the new user's details and subscribe to their tweet
109     * event.
110     */
111    componentDidUpdate(prevProps){
112      if(this.props.match.params.username !== prevProps.match.params.username){
113        this._init();
114      }
115    }
116  
117    /**
118     * Unsubscribe from our tweet event so we stop
119     * receiving tweets.
120     */
121    componentWillUnmount(){
122      if(!this.event) return;
123      // TODO: check if this is the 'right' way to remove / stop the event listener
124      this.event.removeListener(this.event);
125    }
126  
127    render(){
128      const {user} = this.state;
129  
130      if (user === {}) {
131        // Render loading state ...
132        return (<Grid><Row><Col xs={12}>Loading...</Col></Row></Grid>);
133      } else if (user.username === ''){
134        return (
135        <Grid>
136          <Row>
137            <Col xs={12}>
138              <PageHeader>{ this.props.match.params.username } <small>doesn't exist!</small></PageHeader>
139            </Col>
140          </Row>
141        </Grid>);  
142      }else {
143        // Render real UI ...
144        const {username, description, picture, creationDate} = user;
145        const tweetList = this.state.tweets.map(function(tweet, index){
146                            return <ListGroupItem className='tweet' key={ index } header={ tweet.time }>{ tweet.content }</ListGroupItem>
147                          });
148        return (
149          <Grid>
150            <Row>
151              <Col xs={12}>
152                <PageHeader>{ username }'s <small>tweets</small></PageHeader>
153              </Col>
154            </Row>
155            <Row>
156              <Col xs={4}>
157                <Thumbnail src={picture} alt={username} className='profilePic'>
158                  <h3>{ username }</h3>
159                  <p>{ description }</p>
160                  <p className='created'>Created { creationDate }</p>
161                </Thumbnail>
162                
163              </Col>
164              <Col xs={8}>
165                <ListGroup className='tweets'>
166                  { tweetList }
167                </ListGroup>
168              </Col>
169            </Row>
170          </Grid>
171        )
172      }
173    }
174    //#endregion
175  }
176  export default UserTweets