diff options
Diffstat (limited to 'app/javascript/flavours/glitch/features')
9 files changed, 106 insertions, 45 deletions
diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index 68c6bae8e..45aba53f7 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -82,6 +82,7 @@ class Header extends ImmutablePureComponent { onEditAccountNote: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; openEditProfile = () => { @@ -115,7 +116,7 @@ class Header extends ImmutablePureComponent { } render () { - const { account, intl, domain, identity_proofs } = this.props; + const { account, hidden, intl, domain } = this.props; if (!account) { return null; @@ -270,23 +271,29 @@ class Header extends ImmutablePureComponent { {info} </div> - <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' /> + {!(suspended || hidden) && <img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' className='parallax' />} </div> <div className='account__header__bar'> <div className='account__header__tabs'> <a className='avatar' href={account.get('url')} rel='noopener noreferrer' target='_blank'> - <Avatar account={account} size={90} /> + <Avatar account={suspended || hidden ? undefined : account} size={90} /> </a> <div className='spacer' /> - <div className='account__header__tabs__buttons'> - {actionBtn} - {bellBtn} + {!suspended && ( + <div className='account__header__tabs__buttons'> + {!hidden && ( + <React.Fragment> + {actionBtn} + {bellBtn} + </React.Fragment> + )} - <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> - </div> + <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' /> + </div> + )} </div> <div className='account__header__tabs__name'> @@ -298,23 +305,11 @@ class Header extends ImmutablePureComponent { <AccountNoteContainer account={account} /> - {!suspended && ( + {!(suspended || hidden) && ( <div className='account__header__extra'> <div className='account__header__bio'> - { (fields.size > 0 || identity_proofs.size > 0) && ( + { fields.size > 0 && ( <div className='account__header__fields'> - {identity_proofs.map((proof, i) => ( - <dl key={i}> - <dt dangerouslySetInnerHTML={{ __html: proof.get('provider') }} className='translate' /> - - <dd className='verified'> - <a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'><span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}> - <Icon id='check' className='verified__mark' /> - </span></a> - <a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'><span dangerouslySetInnerHTML={{ __html: ' '+proof.get('provider_username') }} className='translate' /></a> - </dd> - </dl> - ))} {fields.map((pair, i) => ( <dl key={i}> <dt dangerouslySetInnerHTML={{ __html: pair.get('name_emojified') }} title={pair.get('name')} /> diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/header.js b/app/javascript/flavours/glitch/features/account_timeline/components/header.js index d6e607a37..645ff29ea 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/components/header.js +++ b/app/javascript/flavours/glitch/features/account_timeline/components/header.js @@ -12,7 +12,6 @@ export default class Header extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, - identity_proofs: ImmutablePropTypes.list, onFollow: PropTypes.func.isRequired, onBlock: PropTypes.func.isRequired, onMention: PropTypes.func.isRequired, @@ -26,6 +25,7 @@ export default class Header extends ImmutablePureComponent { onAddToList: PropTypes.func.isRequired, hideTabs: PropTypes.bool, domain: PropTypes.string.isRequired, + hidden: PropTypes.bool, }; static contextTypes = { @@ -93,7 +93,7 @@ export default class Header extends ImmutablePureComponent { } render () { - const { account, hideTabs, identity_proofs } = this.props; + const { account, hidden, hideTabs } = this.props; if (account === null) { return null; @@ -101,11 +101,10 @@ export default class Header extends ImmutablePureComponent { return ( <div className='account-timeline__header'> - {account.get('moved') && <MovedNote from={account} to={account.get('moved')} />} + {(!hidden && account.get('moved')) && <MovedNote from={account} to={account.get('moved')} />} <InnerHeader account={account} - identity_proofs={identity_proofs} onFollow={this.handleFollow} onBlock={this.handleBlock} onMention={this.handleMention} @@ -120,13 +119,14 @@ export default class Header extends ImmutablePureComponent { onAddToList={this.handleAddToList} onEditAccountNote={this.handleEditAccountNote} domain={this.props.domain} + hidden={hidden} /> <ActionBar account={account} /> - {!hideTabs && ( + {!(hideTabs || hidden) && ( <div className='account__section-headline'> <NavLink exact to={`/@${account.get('acct')}`}><FormattedMessage id='account.posts' defaultMessage='Posts' /></NavLink> <NavLink exact to={`/@${account.get('acct')}/with_replies`}><FormattedMessage id='account.posts_with_replies' defaultMessage='Posts with replies' /></NavLink> diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js b/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js new file mode 100644 index 000000000..e465c83b4 --- /dev/null +++ b/app/javascript/flavours/glitch/features/account_timeline/components/limited_account_hint.js @@ -0,0 +1,35 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { revealAccount } from 'flavours/glitch/actions/accounts'; +import { FormattedMessage } from 'react-intl'; +import Button from 'flavours/glitch/components/button'; + +const mapDispatchToProps = (dispatch, { accountId }) => ({ + + reveal () { + dispatch(revealAccount(accountId)); + }, + +}); + +export default @connect(() => {}, mapDispatchToProps) +class LimitedAccountHint extends React.PureComponent { + + static propTypes = { + accountId: PropTypes.string.isRequired, + reveal: PropTypes.func, + } + + render () { + const { reveal } = this.props; + + return ( + <div className='limited-account-hint'> + <p><FormattedMessage id='limited_account_hint.title' defaultMessage='This profile has been hidden by the moderators of your server.' /></p> + <Button onClick={reveal}><FormattedMessage id='limited_account_hint.action' defaultMessage='Show profile anyway' /></Button> + </div> + ); + } + +} diff --git a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js index 90e746679..3fa7c1448 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js +++ b/app/javascript/flavours/glitch/features/account_timeline/containers/header_container.js @@ -1,6 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; -import { makeGetAccount } from 'flavours/glitch/selectors'; +import { makeGetAccount, getAccountHidden } from 'flavours/glitch/selectors'; import Header from '../components/header'; import { followAccount, @@ -22,7 +22,6 @@ import { blockDomain, unblockDomain } from 'flavours/glitch/actions/domain_block import { initEditAccountNote } from 'flavours/glitch/actions/account_notes'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { unfollowModal } from 'flavours/glitch/util/initial_state'; -import { List as ImmutableList } from 'immutable'; const messages = defineMessages({ unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' }, @@ -35,7 +34,7 @@ const makeMapStateToProps = () => { const mapStateToProps = (state, { accountId }) => ({ account: getAccount(state, accountId), domain: state.getIn(['meta', 'domain']), - identity_proofs: state.getIn(['identity_proofs', accountId], ImmutableList()), + hidden: getAccountHidden(state, accountId), }); return mapStateToProps; diff --git a/app/javascript/flavours/glitch/features/account_timeline/index.js b/app/javascript/flavours/glitch/features/account_timeline/index.js index 6d2df5c6f..68d558e66 100644 --- a/app/javascript/flavours/glitch/features/account_timeline/index.js +++ b/app/javascript/flavours/glitch/features/account_timeline/index.js @@ -13,9 +13,10 @@ import ColumnBackButton from 'flavours/glitch/components/column_back_button'; import { List as ImmutableList } from 'immutable'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -import { fetchAccountIdentityProofs } from '../../actions/identity_proofs'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from './components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const emptyList = ImmutableList(); @@ -40,6 +41,7 @@ const mapStateToProps = (state, { params: { acct, id }, withReplies = false }) = isLoading: state.getIn(['timelines', `account:${path}`, 'isLoading']), hasMore: state.getIn(['timelines', `account:${path}`, 'hasMore']), suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -68,6 +70,7 @@ class AccountTimeline extends ImmutablePureComponent { withReplies: PropTypes.bool, isAccount: PropTypes.bool, suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -77,7 +80,7 @@ class AccountTimeline extends ImmutablePureComponent { const { accountId, withReplies, dispatch } = this.props; dispatch(fetchAccount(accountId)); - dispatch(fetchAccountIdentityProofs(accountId)); + if (!withReplies) { dispatch(expandAccountFeaturedTimeline(accountId)); } @@ -109,10 +112,11 @@ class AccountTimeline extends ImmutablePureComponent { if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) { dispatch(fetchAccount(nextProps.params.accountId)); - dispatch(fetchAccountIdentityProofs(nextProps.params.accountId)); + if (!nextProps.withReplies) { dispatch(expandAccountFeaturedTimeline(nextProps.params.accountId)); } + dispatch(expandAccountTimeline(nextProps.params.accountId, { withReplies: nextProps.params.withReplies })); } } @@ -130,7 +134,7 @@ class AccountTimeline extends ImmutablePureComponent { } render () { - const { statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, multiColumn, remote, remoteUrl } = this.props; + const { accountId, statusIds, featuredStatusIds, isLoading, hasMore, suspended, isAccount, hidden, multiColumn, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -151,8 +155,12 @@ class AccountTimeline extends ImmutablePureComponent { let emptyMessage; + const forceEmptyState = suspended || hidden; + if (suspended) { emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; } else if (remote && statusIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { @@ -166,14 +174,14 @@ class AccountTimeline extends ImmutablePureComponent { <ProfileColumnHeader onClick={this.handleHeaderClick} multiColumn={multiColumn} /> <StatusList - prepend={<HeaderContainer accountId={this.props.accountId} />} + prepend={<HeaderContainer accountId={this.props.accountId} hideTabs={forceEmptyState} />} alwaysPrepend append={remoteMessage} scrollKey='account_timeline' - statusIds={suspended ? emptyList : statusIds} + statusIds={forceEmptyState ? emptyList : statusIds} featuredStatusIds={featuredStatusIds} isLoading={isLoading} - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} onLoadMore={this.handleLoadMore} emptyMessage={emptyMessage} bindToDocument={!multiColumn} diff --git a/app/javascript/flavours/glitch/features/blocks/index.js b/app/javascript/flavours/glitch/features/blocks/index.js index 4d0f58239..4461bd14d 100644 --- a/app/javascript/flavours/glitch/features/blocks/index.js +++ b/app/javascript/flavours/glitch/features/blocks/index.js @@ -69,7 +69,7 @@ class Blocks extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='block' />, )} </ScrollableList> </Column> diff --git a/app/javascript/flavours/glitch/features/followers/index.js b/app/javascript/flavours/glitch/features/followers/index.js index 978436dcc..27a63b3fd 100644 --- a/app/javascript/flavours/glitch/features/followers/index.js +++ b/app/javascript/flavours/glitch/features/followers/index.js @@ -19,6 +19,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import ScrollableList from 'flavours/glitch/components/scrollable_list'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']), isLoading: state.getIn(['user_lists', 'followers', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -62,6 +66,8 @@ class Followers extends ImmutablePureComponent { hasMore: PropTypes.bool, isLoading: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -107,7 +113,7 @@ class Followers extends ImmutablePureComponent { } render () { - const { accountIds, hasMore, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -127,7 +133,13 @@ class Followers extends ImmutablePureComponent { let emptyMessage; - if (remote && accountIds.isEmpty()) { + const forceEmptyState = suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { emptyMessage = <FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />; @@ -141,7 +153,7 @@ class Followers extends ImmutablePureComponent { <ScrollableList scrollKey='followers' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} diff --git a/app/javascript/flavours/glitch/features/following/index.js b/app/javascript/flavours/glitch/features/following/index.js index 446a19894..aa187bf95 100644 --- a/app/javascript/flavours/glitch/features/following/index.js +++ b/app/javascript/flavours/glitch/features/following/index.js @@ -19,6 +19,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import MissingIndicator from 'flavours/glitch/components/missing_indicator'; import ScrollableList from 'flavours/glitch/components/scrollable_list'; import TimelineHint from 'flavours/glitch/components/timeline_hint'; +import LimitedAccountHint from '../account_timeline/components/limited_account_hint'; +import { getAccountHidden } from 'flavours/glitch/selectors'; const mapStateToProps = (state, { params: { acct, id } }) => { const accountId = id || state.getIn(['accounts_map', acct]); @@ -37,6 +39,8 @@ const mapStateToProps = (state, { params: { acct, id } }) => { accountIds: state.getIn(['user_lists', 'following', accountId, 'items']), hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']), isLoading: state.getIn(['user_lists', 'following', accountId, 'isLoading'], true), + suspended: state.getIn(['accounts', accountId, 'suspended'], false), + hidden: getAccountHidden(state, accountId), }; }; @@ -62,6 +66,8 @@ class Following extends ImmutablePureComponent { hasMore: PropTypes.bool, isLoading: PropTypes.bool, isAccount: PropTypes.bool, + suspended: PropTypes.bool, + hidden: PropTypes.bool, remote: PropTypes.bool, remoteUrl: PropTypes.string, multiColumn: PropTypes.bool, @@ -107,7 +113,7 @@ class Following extends ImmutablePureComponent { } render () { - const { accountIds, hasMore, isAccount, multiColumn, isLoading, remote, remoteUrl } = this.props; + const { accountId, accountIds, hasMore, isAccount, multiColumn, isLoading, suspended, hidden, remote, remoteUrl } = this.props; if (!isAccount) { return ( @@ -127,7 +133,13 @@ class Following extends ImmutablePureComponent { let emptyMessage; - if (remote && accountIds.isEmpty()) { + const forceEmptyState = suspended || hidden; + + if (suspended) { + emptyMessage = <FormattedMessage id='empty_column.account_suspended' defaultMessage='Account suspended' />; + } else if (hidden) { + emptyMessage = <LimitedAccountHint accountId={accountId} />; + } else if (remote && accountIds.isEmpty()) { emptyMessage = <RemoteHint url={remoteUrl} />; } else { emptyMessage = <FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />; @@ -141,7 +153,7 @@ class Following extends ImmutablePureComponent { <ScrollableList scrollKey='following' - hasMore={hasMore} + hasMore={!forceEmptyState && hasMore} isLoading={isLoading} onLoadMore={this.handleLoadMore} prepend={<HeaderContainer accountId={this.props.accountId} hideTabs />} diff --git a/app/javascript/flavours/glitch/features/mutes/index.js b/app/javascript/flavours/glitch/features/mutes/index.js index 9f0d5a43e..764cbef1a 100644 --- a/app/javascript/flavours/glitch/features/mutes/index.js +++ b/app/javascript/flavours/glitch/features/mutes/index.js @@ -69,7 +69,7 @@ class Mutes extends ImmutablePureComponent { bindToDocument={!multiColumn} > {accountIds.map(id => - <AccountContainer key={id} id={id} />, + <AccountContainer key={id} id={id} defaultAction='mute' />, )} </ScrollableList> </Column> |