Merge branch 'user-verification' into 'develop'

Display user verification icon

See merge request soapbox-pub/soapbox-fe!128
This commit is contained in:
Alex Gleason 2020-08-07 23:23:11 +00:00
commit 4ee0fa8160
8 changed files with 49 additions and 10 deletions

View file

@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import VerificationBadge from './verification_badge'; import VerificationBadge from './verification_badge';
import { acctFull } from '../utils/accounts'; import { acctFull } from '../utils/accounts';
import { List as ImmutableList } from 'immutable';
export default class DisplayName extends React.PureComponent { export default class DisplayName extends React.PureComponent {
@ -16,13 +17,14 @@ export default class DisplayName extends React.PureComponent {
const { account, others, children } = this.props; const { account, others, children } = this.props;
let displayName, suffix; let displayName, suffix;
const verified = account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified');
if (others && others.size > 1) { if (others && others.size > 1) {
displayName = others.take(2).map(a => [ displayName = others.take(2).map(a => [
<bdi key={a.get('id')}> <bdi key={a.get('id')}>
<strong className='display-name__html' dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} /> <strong className='display-name__html' dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} />
</bdi>, </bdi>,
a.get('is_verified') && <VerificationBadge />, verified && <VerificationBadge />,
]).reduce((prev, cur) => [prev, ', ', cur]); ]).reduce((prev, cur) => [prev, ', ', cur]);
if (others.size - 2 > 0) { if (others.size - 2 > 0) {
@ -32,7 +34,7 @@ export default class DisplayName extends React.PureComponent {
displayName = ( displayName = (
<> <>
<bdi><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi> <bdi><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi>
{account.get('is_verified') && <VerificationBadge />} {verified && <VerificationBadge />}
</> </>
); );
suffix = <span className='display-name__account'>@{acctFull(account)}</span>; suffix = <span className='display-name__account'>@{acctFull(account)}</span>;

View file

@ -2,6 +2,8 @@ import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import { acctFull } from 'soapbox/utils/accounts'; import { acctFull } from 'soapbox/utils/accounts';
import StillImage from 'soapbox/components/still_image'; import StillImage from 'soapbox/components/still_image';
import VerificationBadge from 'soapbox/components/verification_badge';
import { List as ImmutableList } from 'immutable';
const ProfilePreview = ({ account }) => ( const ProfilePreview = ({ account }) => (
<div className='card h-card'> <div className='card h-card'>
@ -16,7 +18,10 @@ const ProfilePreview = ({ account }) => (
<div className='display-name'> <div className='display-name'>
<span style={{ display: 'none' }}>{account.get('username')}</span> <span style={{ display: 'none' }}>{account.get('username')}</span>
<bdi> <bdi>
<strong className='emojify p-name'>{account.get('display_name')}</strong> <strong className='emojify p-name'>
{account.get('display_name')}
{account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified') && <VerificationBadge />}
</strong>
</bdi> </bdi>
<span>{acctFull(account)}</span> <span>{acctFull(account)}</span>
</div> </div>

View file

@ -24,6 +24,7 @@ const messages = defineMessages({
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' }, heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
metaFieldLabel: { id: 'edit_profile.fields.meta_fields.label_placeholder', defaultMessage: 'Label' }, metaFieldLabel: { id: 'edit_profile.fields.meta_fields.label_placeholder', defaultMessage: 'Label' },
metaFieldContent: { id: 'edit_profile.fields.meta_fields.content_placeholder', defaultMessage: 'Content' }, metaFieldContent: { id: 'edit_profile.fields.meta_fields.content_placeholder', defaultMessage: 'Content' },
verified: { id: 'edit_profile.fields.verified_display_name', defaultMessage: 'Verified users may not update their display name' },
}); });
const mapStateToProps = state => { const mapStateToProps = state => {
@ -155,7 +156,8 @@ class EditProfile extends ImmutablePureComponent {
} }
render() { render() {
const { intl, maxFields } = this.props; const { intl, maxFields, account } = this.props;
const verified = account.get('pleroma').get('tags').includes('verified');
return ( return (
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim> <Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
@ -163,10 +165,13 @@ class EditProfile extends ImmutablePureComponent {
<fieldset disabled={this.state.isLoading}> <fieldset disabled={this.state.isLoading}>
<FieldsGroup> <FieldsGroup>
<TextInput <TextInput
className={verified && 'disabled'}
label={<FormattedMessage id='edit_profile.fields.display_name_label' defaultMessage='Display name' />} label={<FormattedMessage id='edit_profile.fields.display_name_label' defaultMessage='Display name' />}
name='display_name' name='display_name'
value={this.state.display_name} value={this.state.display_name}
onChange={this.handleTextChange} onChange={this.handleTextChange}
disabled={verified}
hint={verified && intl.formatMessage(messages.verified)}
/> />
<TextInput <TextInput
label={<FormattedMessage id='edit_profile.fields.bio_label' defaultMessage='Bio' />} label={<FormattedMessage id='edit_profile.fields.bio_label' defaultMessage='Bio' />}

View file

@ -59,6 +59,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
const fields = account.get('fields'); const fields = account.get('fields');
const displayNameHtml = { __html: account.get('display_name_html') }; const displayNameHtml = { __html: account.get('display_name_html') };
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' }); const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' });
const verified = account.get('pleroma').get('tags').includes('verified');
return ( return (
<div className='profile-info-panel'> <div className='profile-info-panel'>
@ -67,7 +68,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
<div className='profile-info-panel-content__name'> <div className='profile-info-panel-content__name'>
<h1> <h1>
<span dangerouslySetInnerHTML={displayNameHtml} /> <span dangerouslySetInnerHTML={displayNameHtml} />
{account.get('is_verified') && <VerificationBadge />} {verified && <VerificationBadge />}
{badge} {badge}
<small>@{acctFull(account)} {lockedIcon}</small> <small>@{acctFull(account)} {lockedIcon}</small>
</h1> </h1>

View file

@ -10,6 +10,8 @@ import Avatar from 'soapbox/components/avatar';
import { shortNumberFormat } from 'soapbox/utils/numbers'; import { shortNumberFormat } from 'soapbox/utils/numbers';
import { acctFull } from 'soapbox/utils/accounts'; import { acctFull } from 'soapbox/utils/accounts';
import StillImage from 'soapbox/components/still_image'; import StillImage from 'soapbox/components/still_image';
import VerificationBadge from 'soapbox/components/verification_badge';
import { List as ImmutableList } from 'immutable';
class UserPanel extends ImmutablePureComponent { class UserPanel extends ImmutablePureComponent {
@ -24,6 +26,7 @@ class UserPanel extends ImmutablePureComponent {
if (!account) return null; if (!account) return null;
const displayNameHtml = { __html: account.get('display_name_html') }; const displayNameHtml = { __html: account.get('display_name_html') };
const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct'); const acct = account.get('acct').indexOf('@') === -1 && domain ? `${account.get('acct')}@${domain}` : account.get('acct');
const verified = account.getIn(['pleroma', 'tags'], ImmutableList()).includes('verified');
return ( return (
<div className='user-panel'> <div className='user-panel'>
@ -45,6 +48,7 @@ class UserPanel extends ImmutablePureComponent {
<h1> <h1>
<Link to={`/@${account.get('acct')}`}> <Link to={`/@${account.get('acct')}`}>
<span className='user-panel__account__name' dangerouslySetInnerHTML={displayNameHtml} /> <span className='user-panel__account__name' dangerouslySetInnerHTML={displayNameHtml} />
{verified && <VerificationBadge />}
<small className='user-panel__account__username'>@{acctFull(account)}</small> <small className='user-panel__account__username'>@{acctFull(account)}</small>
</Link> </Link>
</h1> </h1>

View file

@ -92,6 +92,10 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
bdi, span.verified-icon {
display: inline-block;
}
} }
} }
} }

View file

@ -4,12 +4,21 @@
width: 265px; width: 265px;
flex-direction: column; flex-direction: column;
.user-panel__account__name {
display: inline;
}
.verified-icon {
opacity: 1;
}
&, &,
.user-panel__account__name, .user-panel__account__name,
.user-panel__account__username { .user-panel__account__username {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
color: var(--primary-text-color--faint);
} }
&__header { &__header {
@ -49,13 +58,13 @@
&__meta { &__meta {
display: block; display: block;
padding: 6px 20px 17px; padding: 6px 20px 17px;
opacity: 0.6; // opacity: 0.6;
} }
&__account { &__account {
a { a {
text-decoration: none; text-decoration: none;
color: var(--primary-text-color); color: var(--primary-text-color--faint);
} }
&__name { &__name {
@ -63,7 +72,7 @@
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
line-height: 24px; line-height: 24px;
color: var(--primary-text-color); color: var(--primary-text-color--faint);
} }
&:hover & { &:hover & {
@ -96,7 +105,7 @@
a { a {
text-decoration: none; text-decoration: none;
color: var(--primary-text-color); color: var(--primary-text-color--faint);
&:hover { &:hover {
opacity: 0.8; opacity: 0.8;
@ -106,7 +115,7 @@
&__value { &__value {
display: block; display: block;
width: 100%; width: 100%;
color: var(--primary-text-color); color: var(--primary-text-color--faint);
font-size: 20px; font-size: 20px;
font-weight: 800; font-weight: 800;
line-height: 24px; line-height: 24px;

View file

@ -342,6 +342,15 @@ code {
} }
} }
input[type=text][disabled],
input[type=number][disabled],
input[type=email][disabled],
input[type=password][disabled],
textarea {
color: var(--primary-text-color--faint);
border-color: var(--primary-text-color--faint);
}
.input.field_with_errors { .input.field_with_errors {
label { label {
color: lighten($error-red, 12%); color: lighten($error-red, 12%);