diff options
Diffstat (limited to 'app/javascript/flavours/glitch/components')
3 files changed, 114 insertions, 8 deletions
diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js index 489f60736..24d3f65ef 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.js @@ -9,6 +9,7 @@ import { defineMessages, injectIntl } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { me } from 'flavours/glitch/util/initial_state'; import RelativeTimestamp from './relative_timestamp'; +import Skeleton from 'flavours/glitch/components/skeleton'; const messages = defineMessages({ follow: { id: 'account.follow', defaultMessage: 'Follow' }, @@ -26,7 +27,7 @@ export default @injectIntl class Account extends ImmutablePureComponent { static propTypes = { - account: ImmutablePropTypes.map.isRequired, + account: ImmutablePropTypes.map, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMute: PropTypes.func.isRequired, @@ -77,7 +78,16 @@ class Account extends ImmutablePureComponent { } = this.props; if (!account) { - return <div />; + return ( + <div className='account'> + <div className='account__wrapper'> + <div className='account__display-name'> + <div className='account__avatar-wrapper'><Skeleton width={36} height={36} /></div> + <DisplayName /> + </div> + </div> + </div> + ); } if (hidden) { diff --git a/app/javascript/flavours/glitch/components/display_name.js b/app/javascript/flavours/glitch/components/display_name.js index 9c7da744e..7cb0c9133 100644 --- a/app/javascript/flavours/glitch/components/display_name.js +++ b/app/javascript/flavours/glitch/components/display_name.js @@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { autoPlayGif } from 'flavours/glitch/util/initial_state'; +import Skeleton from 'flavours/glitch/components/skeleton'; export default class DisplayName extends React.PureComponent { @@ -46,14 +47,15 @@ export default class DisplayName extends React.PureComponent { const computedClass = classNames('display-name', { inline }, className); - if (!account) return null; - let displayName, suffix; + let acct; - let acct = account.get('acct'); + if (account) { + acct = account.get('acct'); - if (acct.indexOf('@') === -1 && localDomain) { - acct = `${acct}@${localDomain}`; + if (acct.indexOf('@') === -1 && localDomain) { + acct = `${acct}@${localDomain}`; + } } if (others && others.size > 0) { @@ -80,9 +82,12 @@ export default class DisplayName extends React.PureComponent { <span className='display-name__account'>@{acct}</span> </a> ); - } else { + } else if (account) { displayName = <bdi><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi>; suffix = <span className='display-name__account'>@{acct}</span>; + } else { + displayName = <bdi><strong className='display-name__html'><Skeleton width='10ch' /></strong></bdi>; + suffix = <span className='display-name__account'><Skeleton width='7ch' /></span>; } return ( diff --git a/app/javascript/flavours/glitch/components/server_banner.js b/app/javascript/flavours/glitch/components/server_banner.js new file mode 100644 index 000000000..e29876d4b --- /dev/null +++ b/app/javascript/flavours/glitch/components/server_banner.js @@ -0,0 +1,91 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { domain } from 'flavours/glitch/util/initial_state'; +import { fetchServer } from 'flavours/glitch/actions/server'; +import { connect } from 'react-redux'; +import Account from 'flavours/glitch/containers/account_container'; +import ShortNumber from 'flavours/glitch/components/short_number'; +import Skeleton from 'flavours/glitch/components/skeleton'; +import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; + +const messages = defineMessages({ + aboutActiveUsers: { id: 'server_banner.about_active_users', defaultMessage: 'People using this server during the last 30 days (Monthly Active Users)' }, +}); + +const mapStateToProps = state => ({ + server: state.get('server'), +}); + +export default @connect(mapStateToProps) +@injectIntl +class ServerBanner extends React.PureComponent { + + static propTypes = { + server: PropTypes.object, + dispatch: PropTypes.func, + intl: PropTypes.object, + }; + + componentDidMount () { + const { dispatch } = this.props; + dispatch(fetchServer()); + } + + render () { + const { server, intl } = this.props; + const isLoading = server.get('isLoading'); + + return ( + <div className='server-banner'> + <div className='server-banner__introduction'> + <FormattedMessage id='server_banner.introduction' defaultMessage='{domain} is part of the decentralized social network powered by {mastodon}.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank'>Mastodon</a> }} /> + </div> + + <img src={server.get('thumbnail')} alt={server.get('title')} className='server-banner__hero' /> + + <div className='server-banner__description'> + {isLoading ? ( + <> + <Skeleton width='100%' /> + <br /> + <Skeleton width='100%' /> + <br /> + <Skeleton width='70%' /> + </> + ) : server.get('description')} + </div> + + <div className='server-banner__meta'> + <div className='server-banner__meta__column'> + <h4><FormattedMessage id='server_banner.administered_by' defaultMessage='Administered by:' /></h4> + + <Account id={server.getIn(['contact', 'account', 'id'])} /> + </div> + + <div className='server-banner__meta__column'> + <h4><FormattedMessage id='server_banner.server_stats' defaultMessage='Server stats:' /></h4> + + {isLoading ? ( + <> + <strong className='server-banner__number'><Skeleton width='10ch' /></strong> + <br /> + <span className='server-banner__number-label'><Skeleton width='5ch' /></span> + </> + ) : ( + <> + <strong className='server-banner__number'><ShortNumber value={server.getIn(['usage', 'users', 'active_month'])} /></strong> + <br /> + <span className='server-banner__number-label' title={intl.formatMessage(messages.aboutActiveUsers)}><FormattedMessage id='server_banner.active_users' defaultMessage='active users' /></span> + </> + )} + </div> + </div> + + <hr className='spacer' /> + + <a className='button button--block button-secondary' href='/about/more' target='_blank'><FormattedMessage id='server_banner.learn_more' defaultMessage='Learn more' /></a> + </div> + ); + } + +} |