HelloWorld.jsx 6.69 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 domainShape from '../types/domainShape';
6
import ConnectPrompt from './ConnectPrompt';
7

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

  static defaultProps = {
    total: 0,
    at: 0,
23 24
  };

25 26 27
  componentDidMount () {
    const { fetchProgress } = this.props;
    fetchProgress();
28 29
  }

30
  render () {
31 32 33 34 35 36 37 38 39
    const {
      inProgress,
      at,
      total,
      results,
      domains,
      defaultDomains,
      mastodonIsConnected,
    } = this.props;
40 41 42

    if (inProgress) {
      const pct   = total > 0 ? (at / total).toFixed(2) * 100 : 10;
Eugen Rochko's avatar
Eugen Rochko committed
43
      const label = total > 0 ? <span>{at || 0} / {total || 0}</span> : 'Preparing';
44 45 46 47

      return (
        <div>
          <div className='page-heading'>
48 49 50 51 52 53 54 55
            <FormattedMessage id='friends.searching.headline' defaultMessage='Searching for your friends...'>
              {text => (
                <h3>
                  {text}
                  <FormattedMessage id='friends.searching.subheadline' defaultMessage='Please wait while your Twitter friends are being fetched' tagName='small' />
                </h3>
              )}
            </FormattedMessage>
56 57 58
          </div>

          <div className='progress-bar'>
Eugen Rochko's avatar
Eugen Rochko committed
59
            <Motion defaultStyle={{ x: 0 }} style={{ x: spring(pct, presets.wobbly) }}>
60 61 62 63 64 65 66
              {value => <div style={{ width: `${value.x}%` }} />}
            </Motion>

            <div>{label}</div>
          </div>
        </div>
      );
67 68 69 70 71 72
    } else if (results.length === 0 && !mastodonIsConnected) {
      return (
        <div>
          <ConnectPrompt isPioneer domains={defaultDomains} />
        </div>
      );
73
    }
74 75 76

    return (
      <div>
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
        {mastodonIsConnected ? (
          <div className='page-heading'>
            <FormattedMessage id='friends.headline' defaultMessage='Your friends'>
              {text => (
                <h3>
                  {text}
                  <FormattedMessage id='friends.subheadline' defaultMessage='Here are your Twitter friends who are on Mastodon:' tagName='small' />
                </h3>
              )}
            </FormattedMessage>
          </div>
        ) : <ConnectPrompt domains={defaultDomains} />}

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

        {results.length > 0 && mastodonIsConnected && (
          <div style={{ textAlign: 'center', marginTop: -10, marginBottom: 20 }}>
            <a className='candy-button' href='/friends/follow_all' data-method='post'>
              <FormattedMessage id='friends.follow_all' defaultMessage='Follow all friends on Mastodon' />
            </a>
          </div>
        )}

        {results.length > 0 && (
          <StaggeredMotion
            defaultStyles={results.map(() => ({ scale: 0 }))}
            styles={prevInterpolatedStyles => prevInterpolatedStyles.map((_, i) => ({ scale: spring(i === 0 ? 1 : prevInterpolatedStyles[i - 1].scale, presets.gentle) }))}
          >
            {interpolatingStyles => (
              <div className='grid'>
                {interpolatingStyles.map((style, i) => (
                  <a
                    rel='noopener noreferrer'
                    target='_blank'
                    href={results[i].mastodon_url}
                    style={{ pointerEvents: style.scale === 1 ? 'auto' : 'none', transformOrigin: 'center center', transform: `scale(${style.scale})` }}
                    key={results[i].mastodon_username}
                    className='user-card'
                    title={`@${results[i].twitter_username} on Twitter`}
                  >
                    <div className='avatar'><img src={results[i].avatar_url} alt='' /></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>
136
            )}
137 138
          </StaggeredMotion>
        )}
139 140

        <div className='page-heading'>
141
          <FormattedMessage id='friends.your_friends_instance.headline' defaultMessage='Your friends&quot; instances'>
142 143 144 145 146 147 148
            {text => (
              <h3>
                {text}
                <FormattedMessage id='friends.your_friends_instance.subheadline' defaultMessage='Here are the servers your friends are using:' tagName='small' />
              </h3>
            )}
          </FormattedMessage>
149 150
        </div>

151
        <div className='grid' id='domains'>
152
          {(domains.length > 0 ? domains : defaultDomains).map(domain => (
153
            <a rel='noopener noreferrer' target='_blank' className='instance-card' href={`https://${domain.uri}/about`} key={domain.uri} style={{ backgroundImage: `url(${domain.thumbnail})` }}>
154 155 156 157
              <div className='info'>
                <span className='title'>{domain.title}</span>
                <span className='uri'>{domain.uri}</span>

158
                {domain.stats && <span className='users'> (<FormattedMessage id='friends.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>}
159 160 161
              </div>
            </a>
          ))}
162

163
          <a rel='noopener noreferrer' target='_blank' className='instance-card' href='https://joinmastodon.org/#getting-started'>
164
            <div className='info'>
165 166 167
              <FormattedMessage id='friends.find_more' defaultMessage='Find more on'>
                {text => <span className='title'>{text}</span>}
              </FormattedMessage>
168 169 170
              <span className='uri'>joinmastodon.org</span>
            </div>
          </a>
171
        </div>
172 173 174 175
      </div>
    );
  }
}