1
0
Fork 0
mirror of https://github.com/mastodon/mastodon.git synced 2024-08-20 21:08:15 -07:00

Compare commits

...

6 commits

Author SHA1 Message Date
Alexandre Umbelino
6b85895fdf
Merge 9511daab05 into a50c8e951f 2024-07-31 14:05:07 +00:00
Claire
a50c8e951f
Fix issue with grouped notifications UI due to recent API change (#31224) 2024-07-31 13:23:08 +00:00
Claire
2c1e75727d
Change filtered notification banner design to take up less space (#31222) 2024-07-31 12:36:08 +00:00
Alexandre Umbelino
9511daab05 fix small mistake 2024-06-29 23:34:28 +01:00
Alexandre Umbelino
770ad56494 fix of errors 2024-06-29 23:34:28 +01:00
Alexandre Umbelino
22a78e24ca Fix #29431: "Always hide media" now hides images/thumbnails from links
The images/videos that are automatically loaded by links do not blur
when the option is selected in the preferences/appearance, as is it a
different class from the ones uploaded by the devices of users.
So i used a variable called visible to check what is the option selected
for the display_media, then i modified the spoilerbutton in a way that
allows to hide, by bluring, the images/thumbnails and as a mini
spoilerButton if the person wants to hide it but it is in the option
"Always Show media"
2024-06-29 23:34:28 +01:00
7 changed files with 51 additions and 50 deletions

View file

@ -60,7 +60,7 @@ export interface BaseNotificationGroupJSON {
interface NotificationGroupWithStatusJSON extends BaseNotificationGroupJSON { interface NotificationGroupWithStatusJSON extends BaseNotificationGroupJSON {
type: NotificationWithStatusType; type: NotificationWithStatusType;
status: ApiStatusJSON; status_id: string;
} }
interface NotificationWithStatusJSON extends BaseNotificationJSON { interface NotificationWithStatusJSON extends BaseNotificationJSON {

View file

@ -49,21 +49,14 @@ export const FilteredNotificationsBanner: React.FC = () => {
<span> <span>
<FormattedMessage <FormattedMessage
id='filtered_notifications_banner.pending_requests' id='filtered_notifications_banner.pending_requests'
defaultMessage='Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know' defaultMessage='From {count, plural, =0 {no one} one {one person} other {# people}} you may know'
values={{ count: policy.summary.pending_requests_count }} values={{ count: policy.summary.pending_requests_count }}
/> />
</span> </span>
</div> </div>
<div className='filtered-notifications-banner__badge'> <div className='filtered-notifications-banner__badge'>
<div className='filtered-notifications-banner__badge__badge'> {toCappedNumber(policy.summary.pending_notifications_count)}
{toCappedNumber(policy.summary.pending_notifications_count)}
</div>
<FormattedMessage
id='filtered_notifications_banner.mentions'
defaultMessage='{count, plural, one {mention} other {mentions}}'
values={{ count: policy.summary.pending_notifications_count }}
/>
</div> </div>
</Link> </Link>
); );

View file

@ -14,11 +14,12 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react'; import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react';
import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react'; import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react';
import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react'; import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react';
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
import { Blurhash } from 'mastodon/components/blurhash'; import { Blurhash } from 'mastodon/components/blurhash';
import { Icon } from 'mastodon/components/icon'; import { Icon } from 'mastodon/components/icon';
import { MoreFromAuthor } from 'mastodon/components/more_from_author'; import { MoreFromAuthor } from 'mastodon/components/more_from_author';
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import { useBlurhash } from 'mastodon/initial_state'; import { displayMedia, useBlurhash } from 'mastodon/initial_state';
const IDNA_PREFIX = 'xn--'; const IDNA_PREFIX = 'xn--';
@ -64,12 +65,14 @@ export default class Card extends PureComponent {
card: ImmutablePropTypes.map, card: ImmutablePropTypes.map,
onOpenMedia: PropTypes.func.isRequired, onOpenMedia: PropTypes.func.isRequired,
sensitive: PropTypes.bool, sensitive: PropTypes.bool,
visible: PropTypes.bool,
}; };
state = { state = {
previewLoaded: false, previewLoaded: false,
embedded: false, embedded: false,
revealed: !this.props.sensitive, revealed: !this.props.sensitive,
visible: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'),
}; };
UNSAFE_componentWillReceiveProps (nextProps) { UNSAFE_componentWillReceiveProps (nextProps) {
@ -80,6 +83,12 @@ export default class Card extends PureComponent {
if (this.props.sensitive !== nextProps.sensitive) { if (this.props.sensitive !== nextProps.sensitive) {
this.setState({ revealed: !nextProps.sensitive }); this.setState({ revealed: !nextProps.sensitive });
} }
if (nextProps.visible === undefined) {
this.setState({ visible: displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all' });
} else if (!Immutable.is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
this.setState({ visible: nextProps.visible });
}
} }
componentDidMount () { componentDidMount () {
@ -112,6 +121,12 @@ export default class Card extends PureComponent {
this.setState({ revealed: true }); this.setState({ revealed: true });
}; };
handleOpen = (e) => {
e.preventDefault();
e.stopPropagation();
this.setState({ visible: !this.state.visible });
};
renderVideo () { renderVideo () {
const { card } = this.props; const { card } = this.props;
const content = { __html: addAutoPlay(card.get('html')) }; const content = { __html: addAutoPlay(card.get('html')) };
@ -128,7 +143,7 @@ export default class Card extends PureComponent {
render () { render () {
const { card } = this.props; const { card } = this.props;
const { embedded, revealed } = this.state; const { embedded, revealed, visible } = this.state;
if (card === null) { if (card === null) {
return null; return null;
@ -165,14 +180,14 @@ export default class Card extends PureComponent {
thumbnailStyle.aspectRatio = 1; thumbnailStyle.aspectRatio = 1;
} }
let embed; let embed, spoilerButton;
let canvas = ( let canvas = (
<Blurhash <Blurhash
className={classNames('status-card__image-preview', {
'status-card__image-preview--hidden': revealed && this.state.previewLoaded,
})}
hash={card.get('blurhash')} hash={card.get('blurhash')}
className={classNames('status-card__image-preview', {
'status-card__image-preview--hidden': visible && this.state.previewLoaded,
})}
dummy={!useBlurhash} dummy={!useBlurhash}
/> />
); );
@ -180,17 +195,24 @@ export default class Card extends PureComponent {
const thumbnailDescription = card.get('image_description'); const thumbnailDescription = card.get('image_description');
const thumbnail = <img src={card.get('image')} alt={thumbnailDescription} title={thumbnailDescription} lang={language} style={thumbnailStyle} onLoad={this.handleImageLoad} className='status-card__image-image' />; const thumbnail = <img src={card.get('image')} alt={thumbnailDescription} title={thumbnailDescription} lang={language} style={thumbnailStyle} onLoad={this.handleImageLoad} className='status-card__image-image' />;
let spoilerButton = ( if (visible) {
<button type='button' onClick={this.handleReveal} className='spoiler-button__overlay'> spoilerButton = (
<span className='spoiler-button__overlay__label'> <button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'>
<FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' /> <Icon id='eye-slash' icon={VisibilityOffIcon} />
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.show' defaultMessage='Click to show' /></span> </button>);
</span> } else {
</button> spoilerButton = (
); <button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'>
<span className='spoiler-button__overlay__label'>
{revealed ? <FormattedMessage id='status.media_hidden' defaultMessage='Media hidden' /> : <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />}
<span className='spoiler-button__overlay__action'><FormattedMessage id='status.media.show' defaultMessage='Click to show' /></span>
</span>
</button>
);
}
spoilerButton = ( spoilerButton = (
<div className={classNames('spoiler-button', { 'spoiler-button--minified': revealed })}> <div className={classNames('spoiler-button', { 'spoiler-button--minified': visible })}>
{spoilerButton} {spoilerButton}
</div> </div>
); );
@ -204,11 +226,12 @@ export default class Card extends PureComponent {
{canvas} {canvas}
{thumbnail} {thumbnail}
{revealed ? ( {visible ? (
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'> <div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
<div> <div>
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button> <button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
<a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a> <a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
<button type='button' onClick={this.handleOpen} className='spoiler-button__overlay'><Icon id='eye-slash' icon={VisibilityOffIcon} /></button>
</div> </div>
</div> </div>
) : spoilerButton} ) : spoilerButton}
@ -226,6 +249,7 @@ export default class Card extends PureComponent {
embed = ( embed = (
<div className='status-card__image'> <div className='status-card__image'>
{canvas} {canvas}
{spoilerButton}
{thumbnail} {thumbnail}
</div> </div>
); );

View file

@ -209,7 +209,7 @@ class DetailedStatus extends ImmutablePureComponent {
); );
} }
} else if (status.get('spoiler_text').length === 0) { } else if (status.get('spoiler_text').length === 0) {
media = <Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} />; media = <Card visible={this.props.showMedia} sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} />;
} }
if (status.get('application')) { if (status.get('application')) {

View file

@ -300,8 +300,7 @@
"filter_modal.select_filter.subtitle": "Use an existing category or create a new one", "filter_modal.select_filter.subtitle": "Use an existing category or create a new one",
"filter_modal.select_filter.title": "Filter this post", "filter_modal.select_filter.title": "Filter this post",
"filter_modal.title.status": "Filter a post", "filter_modal.title.status": "Filter a post",
"filtered_notifications_banner.mentions": "{count, plural, one {mention} other {mentions}}", "filtered_notifications_banner.pending_requests": "From {count, plural, =0 {no one} one {one person} other {# people}} you may know",
"filtered_notifications_banner.pending_requests": "Notifications from {count, plural, =0 {no one} one {one person} other {# people}} you may know",
"filtered_notifications_banner.title": "Filtered notifications", "filtered_notifications_banner.title": "Filtered notifications",
"firehose.all": "All", "firehose.all": "All",
"firehose.local": "This server", "firehose.local": "This server",

View file

@ -124,9 +124,9 @@ export function createNotificationGroupFromJSON(
case 'mention': case 'mention':
case 'poll': case 'poll':
case 'update': { case 'update': {
const { status, ...groupWithoutStatus } = group; const { status_id: statusId, ...groupWithoutStatus } = group;
return { return {
statusId: status.id, statusId,
sampleAccountIds, sampleAccountIds,
...groupWithoutStatus, ...groupWithoutStatus,
}; };

View file

@ -10171,25 +10171,10 @@ noscript {
} }
&__badge { &__badge {
display: flex; background: $ui-button-background-color;
align-items: center; color: $white;
border-radius: 999px; border-radius: 100px;
background: var(--background-border-color); padding: 2px 8px;
color: $darker-text-color;
padding: 4px;
padding-inline-end: 8px;
gap: 6px;
font-weight: 500;
font-size: 11px;
line-height: 16px;
word-break: keep-all;
&__badge {
background: $ui-button-background-color;
color: $white;
border-radius: 100px;
padding: 2px 8px;
}
} }
} }