Change labels on thread indicators in web UI (#31806)

pull/31829/head
Eugen Rochko 2024-09-09 17:28:54 +02:00 committed by GitHub
parent 2caa3f365d
commit a021dee642
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 76 additions and 15 deletions

View File

@ -12,7 +12,6 @@ import { HotKeys } from 'react-hotkeys';
import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react'; import AlternateEmailIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import PushPinIcon from '@/material-icons/400-24px/push_pin.svg?react'; import PushPinIcon from '@/material-icons/400-24px/push_pin.svg?react';
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react'; import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import { ContentWarning } from 'mastodon/components/content_warning'; import { ContentWarning } from 'mastodon/components/content_warning';
import { FilterWarning } from 'mastodon/components/filter_warning'; import { FilterWarning } from 'mastodon/components/filter_warning';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
@ -34,6 +33,7 @@ import { getHashtagBarForStatus } from './hashtag_bar';
import { RelativeTimestamp } from './relative_timestamp'; import { RelativeTimestamp } from './relative_timestamp';
import StatusActionBar from './status_action_bar'; import StatusActionBar from './status_action_bar';
import StatusContent from './status_content'; import StatusContent from './status_content';
import { StatusThreadLabel } from './status_thread_label';
import { VisibilityIcon } from './visibility_icon'; import { VisibilityIcon } from './visibility_icon';
const domParser = new DOMParser(); const domParser = new DOMParser();
@ -413,7 +413,7 @@ class Status extends ImmutablePureComponent {
if (featured) { if (featured) {
prepend = ( prepend = (
<div className='status__prepend'> <div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='thumb-tack' icon={PushPinIcon} className='status__prepend-icon' /></div> <div className='status__prepend__icon'><Icon id='thumb-tack' icon={PushPinIcon} /></div>
<FormattedMessage id='status.pinned' defaultMessage='Pinned post' /> <FormattedMessage id='status.pinned' defaultMessage='Pinned post' />
</div> </div>
); );
@ -422,7 +422,7 @@ class Status extends ImmutablePureComponent {
prepend = ( prepend = (
<div className='status__prepend'> <div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='retweet' icon={RepeatIcon} className='status__prepend-icon' /></div> <div className='status__prepend__icon'><Icon id='retweet' icon={RepeatIcon} /></div>
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handlePrependAccountClick} data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} href={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></a> }} /> <FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <a onClick={this.handlePrependAccountClick} data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} href={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></a> }} />
</div> </div>
); );
@ -434,18 +434,13 @@ class Status extends ImmutablePureComponent {
} else if (status.get('visibility') === 'direct') { } else if (status.get('visibility') === 'direct') {
prepend = ( prepend = (
<div className='status__prepend'> <div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='at' icon={AlternateEmailIcon} className='status__prepend-icon' /></div> <div className='status__prepend__icon'><Icon id='at' icon={AlternateEmailIcon} /></div>
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' /> <FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
</div> </div>
); );
} else if (showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id'])) { } else if (showThread && status.get('in_reply_to_id')) {
const display_name_html = { __html: status.getIn(['account', 'display_name_html']) };
prepend = ( prepend = (
<div className='status__prepend'> <StatusThreadLabel accountId={status.getIn(['account', 'id'])} inReplyToAccountId={status.get('in_reply_to_account_id')} />
<div className='status__prepend-icon-wrapper'><Icon id='reply' icon={ReplyIcon} className='status__prepend-icon' /></div>
<FormattedMessage id='status.replied_to' defaultMessage='Replied to {name}' values={{ name: <a onClick={this.handlePrependAccountClick} data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} href={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></a> }} />
</div>
); );
} }

View File

@ -0,0 +1,50 @@
import { FormattedMessage } from 'react-intl';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import { Icon } from 'mastodon/components/icon';
import { DisplayedName } from 'mastodon/features/notifications_v2/components/displayed_name';
import { useAppSelector } from 'mastodon/store';
export const StatusThreadLabel: React.FC<{
accountId: string;
inReplyToAccountId: string;
}> = ({ accountId, inReplyToAccountId }) => {
const inReplyToAccount = useAppSelector((state) =>
state.accounts.get(inReplyToAccountId),
);
let label;
if (accountId === inReplyToAccountId) {
label = (
<FormattedMessage
id='status.continued_thread'
defaultMessage='Continued thread'
/>
);
} else if (inReplyToAccount) {
label = (
<FormattedMessage
id='status.replied_to'
defaultMessage='Replied to {name}'
values={{ name: <DisplayedName accountIds={[inReplyToAccountId]} /> }}
/>
);
} else {
label = (
<FormattedMessage
id='status.replied_in_thread'
defaultMessage='Replied in thread'
/>
);
}
return (
<div className='status__prepend'>
<div className='status__prepend__icon'>
<Icon id='reply' icon={ReplyIcon} />
</div>
{label}
</div>
);
};

View File

@ -780,6 +780,7 @@
"status.bookmark": "Bookmark", "status.bookmark": "Bookmark",
"status.cancel_reblog_private": "Unboost", "status.cancel_reblog_private": "Unboost",
"status.cannot_reblog": "This post cannot be boosted", "status.cannot_reblog": "This post cannot be boosted",
"status.continued_thread": "Continued thread",
"status.copy": "Copy link to post", "status.copy": "Copy link to post",
"status.delete": "Delete", "status.delete": "Delete",
"status.detailed_status": "Detailed conversation view", "status.detailed_status": "Detailed conversation view",
@ -813,6 +814,7 @@
"status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.", "status.reblogs.empty": "No one has boosted this post yet. When someone does, they will show up here.",
"status.redraft": "Delete & re-draft", "status.redraft": "Delete & re-draft",
"status.remove_bookmark": "Remove bookmark", "status.remove_bookmark": "Remove bookmark",
"status.replied_in_thread": "Replied in thread",
"status.replied_to": "Replied to {name}", "status.replied_to": "Replied to {name}",
"status.reply": "Reply", "status.reply": "Reply",
"status.replyAll": "Reply to thread", "status.replyAll": "Reply to thread",

View File

@ -1607,15 +1607,29 @@ body > [data-popper-placement] {
.status__prepend { .status__prepend {
padding: 16px; padding: 16px;
padding-bottom: 0; padding-bottom: 0;
display: inline-flex; display: flex;
gap: 10px; align-items: center;
gap: 8px;
font-size: 15px; font-size: 15px;
line-height: 22px; line-height: 22px;
font-weight: 500; font-weight: 500;
color: $dark-text-color; color: $dark-text-color;
.status__display-name strong { &__icon {
color: $dark-text-color; display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
.icon {
width: 16px;
height: 16px;
}
}
a {
color: inherit;
text-decoration: none;
} }
> span { > span {