[Glitch] Add limited attribute to accounts in REST API and a warning in web UI

Port b4d373a3df to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Eugen Rochko
2022-05-10 09:44:35 +02:00
committed by Claire
parent bb1a3e902d
commit 6fb837aa1d
12 changed files with 143 additions and 37 deletions

View File

@@ -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 } = 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,7 +305,7 @@ class Header extends ImmutablePureComponent {
<AccountNoteContainer account={account} />
{!suspended && (
{!(suspended || hidden) && (
<div className='account__header__extra'>
<div className='account__header__bio'>
{ fields.size > 0 && (

View File

@@ -25,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 = {
@@ -92,7 +93,7 @@ export default class Header extends ImmutablePureComponent {
}
render () {
const { account, hideTabs } = this.props;
const { account, hidden, hideTabs } = this.props;
if (account === null) {
return null;
@@ -100,7 +101,7 @@ 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}
@@ -118,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>

View File

@@ -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>
);
}
}

View File

@@ -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,
@@ -34,6 +34,7 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, { accountId }) => ({
account: getAccount(state, accountId),
domain: state.getIn(['meta', 'domain']),
hidden: getAccountHidden(state, accountId),
});
return mapStateToProps;

View File

@@ -15,6 +15,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { FormattedMessage } from 'react-intl';
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();
@@ -39,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),
};
};
@@ -67,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,
@@ -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}

View File

@@ -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 />}

View File

@@ -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 />}