HelloWorld.jsx 4.88 KB
Newer Older
1 2
import PropTypes from 'prop-types';
import React from 'react';
3 4
import { Motion, StaggeredMotion, spring, presets } from 'react-motion';
import { FormattedMessage, FormattedNumber } from 'react-intl';
5
import ConnectPrompt from './ConnectPrompt';
6

7
export default class HelloWorld extends React.PureComponent {
8
  static propTypes = {
Eugen Rochko's avatar
Eugen Rochko committed
9 10 11
    status: PropTypes.string,
    total: PropTypes.number,
    at: PropTypes.number,
12 13 14 15 16 17
    results: PropTypes.array.isRequired,
    domains: PropTypes.array.isRequired,
    inProgress: PropTypes.bool.isRequired,
    fetchProgress: PropTypes.func.isRequired,
    fetchResults: PropTypes.func.isRequired,
    mastodonIsConnected: PropTypes.bool.isRequired,
18
    defaultDomains: PropTypes.array.isRequired,
19 20
  };

21 22 23
  componentDidMount () {
    const { fetchProgress } = this.props;
    fetchProgress();
24 25
  }

26
  render () {
27
    const { status, inProgress, at, total, results, domains, defaultDomains, mastodonIsConnected } = this.props;
28 29 30

    if (inProgress) {
      const pct   = total > 0 ? (at / total).toFixed(2) * 100 : 10;
Eugen Rochko's avatar
Eugen Rochko committed
31
      const label = total > 0 ? <span>{at || 0} / {total || 0}</span> : 'Preparing';
32 33 34 35 36 37 38 39 40 41 42

      return (
        <div>
          <div className='page-heading'>
            <h3>
              Searching for your friends...
              <small>Please wait while your Twitter friends are being fetched</small>
            </h3>
          </div>

          <div className='progress-bar'>
Eugen Rochko's avatar
Eugen Rochko committed
43
            <Motion defaultStyle={{ x: 0 }} style={{ x: spring(pct, presets.wobbly) }}>
44 45 46 47 48 49 50
              {value => <div style={{ width: `${value.x}%` }} />}
            </Motion>

            <div>{label}</div>
          </div>
        </div>
      );
51 52 53 54 55 56
    } else if (results.length === 0 && !mastodonIsConnected) {
      return (
        <div>
          <ConnectPrompt isPioneer domains={defaultDomains} />
        </div>
      );
57
    }
58 59 60

    return (
      <div>
61
        {mastodonIsConnected ? (<div className='page-heading'>
62 63 64 65
          <h3>
            Your friends
            <small>Here are your Twitter friends who are on Mastodon:</small>
          </h3>
66 67 68 69 70
        </div>) : <ConnectPrompt domains={defaultDomains} />}

        {results.length === 0 && <p className='lead'>
          Right now, there are no results to be shown here. But maybe your friends haven't used this tool yet! Or maybe you are the trendsetter!
        </p>}
71

72
        {results.length > 0 && <StaggeredMotion defaultStyles={results.map(_ => ({ scale: 0 }))} styles={prevInterpolatedStyles => prevInterpolatedStyles.map((_, i) => {
73
          return i == 0
Eugen Rochko's avatar
Eugen Rochko committed
74 75
            ? { scale: spring(1, presets.wobbly) }
            : { scale: spring(prevInterpolatedStyles[i - 1].scale, presets.wobbly) };
76 77 78 79
        })}>
          {interpolatingStyles => (
            <div className='grid'>
              {interpolatingStyles.map((style, i) => (
Eugen Rochko's avatar
Eugen Rochko committed
80
                <a target='_blank' href={results[i].mastodon_url} style={{ transformOrigin: 'center center', transform: `scale(${style.scale})` }} key={results[i].mastodon_username} className='user-card' title={`@${results[i].twitter_username} on Twitter`}>
81 82 83 84 85 86 87 88 89 90 91 92 93 94
                  <div className='avatar'><img src={results[i].avatar_url} /></div>

                  {results[i].following && <div className='following-indicator'>
                    <i className='fa fa-check' />
                  </div>}

                  <div className='name'>
                    <span className='display-name'>{results[i].display_name}</span>
                    <span className='username'>@{results[i].mastodon_username}</span>
                  </div>
                </a>
              ))}
            </div>
          )}
95
        </StaggeredMotion>}
96 97 98 99 100 101 102 103

        <div className='page-heading'>
          <h3>
            Your friends' instances
            <small>Here are the servers your friends are using:</small>
          </h3>
        </div>

104
        <div className='grid' id='domains'>
105
          {(domains.length > 0 ? domains : defaultDomains).map(domain => (
106 107 108 109 110 111 112 113 114
            <a target='_blank' className='instance-card' href={`https://${domain.uri}/about`} key={domain.uri} style={{ backgroundImage: `url(${domain.thumbnail})` }}>
              <div className='info'>
                <span className='title'>{domain.title}</span>
                <span className='uri'>{domain.uri}</span>

                {domain.stats && <span className='users'> (<FormattedMessage id='num_users' defaultMessage='{formatted_count} {count, plural, one {person} other {people}}' values={{ count: domain.stats.user_count, formatted_count: <FormattedNumber value={domain.stats.user_count} /> }} />)</span>}
              </div>
            </a>
          ))}
115 116 117 118 119 120 121

          <a target='_blank' className='instance-card' href='https://joinmastodon.org/#getting-started'>
            <div className='info'>
              <span className='title'>Find more on</span>
              <span className='uri'>joinmastodon.org</span>
            </div>
          </a>
122
        </div>
123 124 125 126
      </div>
    );
  }
}