[build] upgrade eslint to 9.37.0 (#88)

Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/88
Co-authored-by: Zoë Bijl <moiety@noreply.codeberg.org>
Co-committed-by: Zoë Bijl <moiety@noreply.codeberg.org>
This commit is contained in:
Zoë Bijl
2025-10-12 13:42:02 +02:00
committed by tobi
parent 75d7a62693
commit 1ff70886a1
975 changed files with 22196 additions and 21964 deletions
@@ -1,55 +1,55 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { defineMessages, injectIntl } from 'react-intl';
import { defineMessages, injectIntl } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import ImmutablePropTypes from "react-immutable-proptypes";
import { connect } from "react-redux";
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from "mastodon/permissions";
import { IconButton } from '../../../components/icon_button';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
import { me } from '../../../initial_state';
import { IconButton } from "../../../components/icon_button";
import DropdownMenuContainer from "../../../containers/dropdown_menu_container";
import { me } from "../../../initial_state";
const messages = defineMessages({
delete: { id: 'status.delete', defaultMessage: 'Delete' },
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
edit: { id: 'status.edit', defaultMessage: 'Edit' },
direct: { id: 'status.direct', defaultMessage: 'Privately mention @{name}' },
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
reply: { id: 'status.reply', defaultMessage: 'Reply' },
reblog: { id: 'status.reblog', defaultMessage: 'Boost' },
reblog_private: { id: 'status.reblog_private', defaultMessage: 'Boost with original visibility' },
cancel_reblog_private: { id: 'status.cancel_reblog_private', defaultMessage: 'Unboost' },
cannot_reblog: { id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted' },
favourite: { id: 'status.favourite', defaultMessage: 'Favorite' },
bookmark: { id: 'status.bookmark', defaultMessage: 'Bookmark' },
more: { id: 'status.more', defaultMessage: 'More' },
mute: { id: 'status.mute', defaultMessage: 'Mute @{name}' },
muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' },
unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' },
block: { id: 'status.block', defaultMessage: 'Block @{name}' },
report: { id: 'status.report', defaultMessage: 'Report @{name}' },
share: { id: 'status.share', defaultMessage: 'Share' },
pin: { id: 'status.pin', defaultMessage: 'Pin on profile' },
unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' },
embed: { id: 'status.embed', defaultMessage: 'Embed' },
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
admin_status: { id: 'status.admin_status', defaultMessage: 'Open this post in the moderation interface' },
admin_domain: { id: 'status.admin_domain', defaultMessage: 'Open moderation interface for {domain}' },
copy: { id: 'status.copy', defaultMessage: 'Copy link to post' },
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
openOriginalPage: { id: 'account.open_original_page', defaultMessage: 'Open original page' },
delete: { id: "status.delete", defaultMessage: "Delete" },
redraft: { id: "status.redraft", defaultMessage: "Delete & re-draft" },
edit: { id: "status.edit", defaultMessage: "Edit" },
direct: { id: "status.direct", defaultMessage: "Privately mention @{name}" },
mention: { id: "status.mention", defaultMessage: "Mention @{name}" },
reply: { id: "status.reply", defaultMessage: "Reply" },
reblog: { id: "status.reblog", defaultMessage: "Boost" },
reblog_private: { id: "status.reblog_private", defaultMessage: "Boost with original visibility" },
cancel_reblog_private: { id: "status.cancel_reblog_private", defaultMessage: "Unboost" },
cannot_reblog: { id: "status.cannot_reblog", defaultMessage: "This post cannot be boosted" },
favourite: { id: "status.favourite", defaultMessage: "Favorite" },
bookmark: { id: "status.bookmark", defaultMessage: "Bookmark" },
more: { id: "status.more", defaultMessage: "More" },
mute: { id: "status.mute", defaultMessage: "Mute @{name}" },
muteConversation: { id: "status.mute_conversation", defaultMessage: "Mute conversation" },
unmuteConversation: { id: "status.unmute_conversation", defaultMessage: "Unmute conversation" },
block: { id: "status.block", defaultMessage: "Block @{name}" },
report: { id: "status.report", defaultMessage: "Report @{name}" },
share: { id: "status.share", defaultMessage: "Share" },
pin: { id: "status.pin", defaultMessage: "Pin on profile" },
unpin: { id: "status.unpin", defaultMessage: "Unpin from profile" },
embed: { id: "status.embed", defaultMessage: "Embed" },
admin_account: { id: "status.admin_account", defaultMessage: "Open moderation interface for @{name}" },
admin_status: { id: "status.admin_status", defaultMessage: "Open this post in the moderation interface" },
admin_domain: { id: "status.admin_domain", defaultMessage: "Open moderation interface for {domain}" },
copy: { id: "status.copy", defaultMessage: "Copy link to post" },
blockDomain: { id: "account.block_domain", defaultMessage: "Block domain {domain}" },
unblockDomain: { id: "account.unblock_domain", defaultMessage: "Unblock domain {domain}" },
unmute: { id: "account.unmute", defaultMessage: "Unmute @{name}" },
unblock: { id: "account.unblock", defaultMessage: "Unblock @{name}" },
openOriginalPage: { id: "account.open_original_page", defaultMessage: "Open original page" },
});
const mapStateToProps = (state, { status }) => ({
relationship: state.getIn(['relationships', status.getIn(['account', 'id'])]),
relationship: state.getIn(["relationships", status.getIn(["account", "id"])]),
});
class ActionBar extends PureComponent {
@@ -112,18 +112,18 @@ class ActionBar extends PureComponent {
};
handleDirectClick = () => {
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
this.props.onDirect(this.props.status.get("account"), this.context.router.history);
};
handleMentionClick = () => {
this.props.onMention(this.props.status.get('account'), this.context.router.history);
this.props.onMention(this.props.status.get("account"), this.context.router.history);
};
handleMuteClick = () => {
const { status, relationship, onMute, onUnmute } = this.props;
const account = status.get('account');
const account = status.get("account");
if (relationship && relationship.get('muting')) {
if (relationship && relationship.get("muting")) {
onUnmute(account);
} else {
onMute(account);
@@ -132,9 +132,9 @@ class ActionBar extends PureComponent {
handleBlockClick = () => {
const { status, relationship, onBlock, onUnblock } = this.props;
const account = status.get('account');
const account = status.get("account");
if (relationship && relationship.get('blocking')) {
if (relationship && relationship.get("blocking")) {
onUnblock(account);
} else {
onBlock(status);
@@ -143,16 +143,16 @@ class ActionBar extends PureComponent {
handleBlockDomain = () => {
const { status, onBlockDomain } = this.props;
const account = status.get('account');
const account = status.get("account");
onBlockDomain(account.get('acct').split('@')[1]);
onBlockDomain(account.get("acct").split("@")[1]);
};
handleUnblockDomain = () => {
const { status, onUnblockDomain } = this.props;
const account = status.get('account');
const account = status.get("account");
onUnblockDomain(account.get('acct').split('@')[1]);
onUnblockDomain(account.get("acct").split("@")[1]);
};
handleConversationMuteClick = () => {
@@ -169,7 +169,7 @@ class ActionBar extends PureComponent {
handleShare = () => {
navigator.share({
url: this.props.status.get('url'),
url: this.props.status.get("url"),
});
};
@@ -178,7 +178,7 @@ class ActionBar extends PureComponent {
};
handleCopy = () => {
const url = this.props.status.get('url');
const url = this.props.status.get("url");
navigator.clipboard.writeText(url);
};
@@ -186,22 +186,22 @@ class ActionBar extends PureComponent {
const { status, relationship, intl } = this.props;
const { signedIn, permissions } = this.context.identity;
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'));
const pinnableStatus = ['public', 'unlisted', 'private'].includes(status.get('visibility'));
const mutingConversation = status.get('muted');
const account = status.get('account');
const writtenByMe = status.getIn(['account', 'id']) === me;
const isRemote = status.getIn(['account', 'username']) !== status.getIn(['account', 'acct']);
const publicStatus = ["public", "unlisted"].includes(status.get("visibility"));
const pinnableStatus = ["public", "unlisted", "private"].includes(status.get("visibility"));
const mutingConversation = status.get("muted");
const account = status.get("account");
const writtenByMe = status.getIn(["account", "id"]) === me;
const isRemote = status.getIn(["account", "username"]) !== status.getIn(["account", "acct"]);
let menu = [];
if (publicStatus && isRemote) {
menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: status.get('url') });
menu.push({ text: intl.formatMessage(messages.openOriginalPage), href: status.get("url") });
}
menu.push({ text: intl.formatMessage(messages.copy), action: this.handleCopy });
if (publicStatus && 'share' in navigator) {
if (publicStatus && "share" in navigator) {
menu.push({ text: intl.formatMessage(messages.share), action: this.handleShare });
}
@@ -214,7 +214,7 @@ class ActionBar extends PureComponent {
if (writtenByMe) {
if (pinnableStatus) {
menu.push({ text: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick });
menu.push({ text: intl.formatMessage(status.get("pinned") ? messages.unpin : messages.pin), action: this.handlePinClick });
menu.push(null);
}
@@ -224,29 +224,29 @@ class ActionBar extends PureComponent {
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick, dangerous: true });
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick, dangerous: true });
} else {
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(["account", "username"]) }), action: this.handleMentionClick });
menu.push(null);
if (relationship && relationship.get('muting')) {
menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.handleMuteClick });
if (relationship && relationship.get("muting")) {
menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get("username") }), action: this.handleMuteClick });
} else {
menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.handleMuteClick, dangerous: true });
menu.push({ text: intl.formatMessage(messages.mute, { name: account.get("username") }), action: this.handleMuteClick, dangerous: true });
}
if (relationship && relationship.get('blocking')) {
menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.handleBlockClick });
if (relationship && relationship.get("blocking")) {
menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get("username") }), action: this.handleBlockClick });
} else {
menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.handleBlockClick, dangerous: true });
menu.push({ text: intl.formatMessage(messages.block, { name: account.get("username") }), action: this.handleBlockClick, dangerous: true });
}
menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport, dangerous: true });
menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(["account", "username"]) }), action: this.handleReport, dangerous: true });
if (account.get('acct') !== account.get('username')) {
const domain = account.get('acct').split('@')[1];
if (account.get("acct") !== account.get("username")) {
const domain = account.get("acct").split("@")[1];
menu.push(null);
if (relationship && relationship.get('domain_blocking')) {
if (relationship && relationship.get("domain_blocking")) {
menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain }), action: this.handleUnblockDomain });
} else {
menu.push({ text: intl.formatMessage(messages.blockDomain, { domain }), action: this.handleBlockDomain, dangerous: true });
@@ -256,11 +256,11 @@ class ActionBar extends PureComponent {
if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS || (isRemote && (permissions & PERMISSION_MANAGE_FEDERATION) === PERMISSION_MANAGE_FEDERATION)) {
menu.push(null);
if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(["account", "username"]) }), href: `/admin/accounts/${status.getIn(["account", "id"])}` });
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(["account", "id"])}/statuses/${status.get("id")}` });
}
if (isRemote && (permissions & PERMISSION_MANAGE_FEDERATION) === PERMISSION_MANAGE_FEDERATION) {
const domain = account.get('acct').split('@')[1];
const domain = account.get("acct").split("@")[1];
menu.push({ text: intl.formatMessage(messages.admin_domain, { domain: domain }), href: `/admin/instances/${domain}` });
}
}
@@ -268,16 +268,16 @@ class ActionBar extends PureComponent {
}
let replyIcon;
if (status.get('in_reply_to_id', null) === null) {
replyIcon = 'reply';
if (status.get("in_reply_to_id", null) === null) {
replyIcon = "reply";
} else {
replyIcon = 'reply-all';
replyIcon = "reply-all";
}
const reblogPrivate = status.getIn(['account', 'id']) === me && status.get('visibility') === 'private';
const reblogPrivate = status.getIn(["account", "id"]) === me && status.get("visibility") === "private";
let reblogTitle;
if (status.get('reblogged')) {
if (status.get("reblogged")) {
reblogTitle = intl.formatMessage(messages.cancel_reblog_private);
} else if (publicStatus) {
reblogTitle = intl.formatMessage(messages.reblog);
@@ -289,10 +289,10 @@ class ActionBar extends PureComponent {
return (
<div className='detailed-status__action-bar'>
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon} onClick={this.handleReplyClick} /></div>
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get('reblogged')} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div>
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get('favourited')} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /></div>
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get('bookmarked')} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} /></div>
<div className='detailed-status__button'><IconButton title={intl.formatMessage(messages.reply)} icon={status.get("in_reply_to_account_id") === status.getIn(["account", "id"]) ? "reply" : replyIcon} onClick={this.handleReplyClick} /></div>
<div className='detailed-status__button'><IconButton className={classNames({ reblogPrivate })} disabled={!publicStatus && !reblogPrivate} active={status.get("reblogged")} title={reblogTitle} icon='retweet' onClick={this.handleReblogClick} /></div>
<div className='detailed-status__button'><IconButton className='star-icon' animate active={status.get("favourited")} title={intl.formatMessage(messages.favourite)} icon='star' onClick={this.handleFavouriteClick} /></div>
<div className='detailed-status__button'><IconButton className='bookmark-icon' disabled={!signedIn} active={status.get("bookmarked")} title={intl.formatMessage(messages.bookmark)} icon='bookmark' onClick={this.handleBookmarkClick} /></div>
<div className='detailed-status__action-bar-dropdown'>
<DropdownMenuContainer size={18} icon='ellipsis-h' status={status} items={menu} direction='left' title={intl.formatMessage(messages.more)} />
@@ -1,31 +1,31 @@
import punycode from 'punycode';
import punycode from "punycode";
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Immutable from "immutable";
import ImmutablePropTypes from "react-immutable-proptypes";
import { Blurhash } from 'mastodon/components/blurhash';
import { Icon } from 'mastodon/components/icon';
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
import { useBlurhash } from 'mastodon/initial_state';
import { Blurhash } from "mastodon/components/blurhash";
import { Icon } from "mastodon/components/icon";
import { RelativeTimestamp } from "mastodon/components/relative_timestamp";
import { useBlurhash } from "mastodon/initial_state";
const IDNA_PREFIX = 'xn--';
const IDNA_PREFIX = "xn--";
const decodeIDNA = domain => {
return domain
.split('.')
.split(".")
.map(part => part.indexOf(IDNA_PREFIX) === 0 ? punycode.decode(part.slice(IDNA_PREFIX.length)) : part)
.join('.');
.join(".");
};
const getHostname = url => {
const parser = document.createElement('a');
const parser = document.createElement("a");
parser.href = url;
return parser.hostname;
};
@@ -33,21 +33,21 @@ const getHostname = url => {
const domParser = new DOMParser();
const addAutoPlay = html => {
const document = domParser.parseFromString(html, 'text/html').documentElement;
const iframe = document.querySelector('iframe');
const document = domParser.parseFromString(html, "text/html").documentElement;
const iframe = document.querySelector("iframe");
if (iframe) {
if (iframe.src.indexOf('?') !== -1) {
iframe.src += '&';
if (iframe.src.indexOf("?") !== -1) {
iframe.src += "&";
} else {
iframe.src += '?';
iframe.src += "?";
}
iframe.src += 'autoplay=1&auto_play=1';
iframe.src += "autoplay=1&auto_play=1";
// DOM parser creates html/body elements around original HTML fragment,
// so we need to get innerHTML out of the body and not the entire document
return document.querySelector('body').innerHTML;
return document.querySelector("body").innerHTML;
}
return html;
@@ -78,11 +78,11 @@ export default class Card extends PureComponent {
}
componentDidMount () {
window.addEventListener('resize', this.handleResize, { passive: true });
window.addEventListener("resize", this.handleResize, { passive: true });
}
componentWillUnmount () {
window.removeEventListener('resize', this.handleResize);
window.removeEventListener("resize", this.handleResize);
}
handleEmbedClick = () => {
@@ -105,14 +105,14 @@ export default class Card extends PureComponent {
renderVideo () {
const { card } = this.props;
const content = { __html: addAutoPlay(card.get('html')) };
const content = { __html: addAutoPlay(card.get("html")) };
return (
<div
ref={this.setRef}
className='status-card__image status-card-video'
dangerouslySetInnerHTML={content}
style={{ aspectRatio: '16 / 9' }}
style={{ aspectRatio: "16 / 9" }}
/>
);
}
@@ -125,32 +125,32 @@ export default class Card extends PureComponent {
return null;
}
const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name');
const interactive = card.get('type') === 'video';
const language = card.get('language') || '';
const largeImage = (card.get('image')?.length > 0 && card.get('width') > card.get('height')) || interactive;
const provider = card.get("provider_name").length === 0 ? decodeIDNA(getHostname(card.get("url"))) : card.get("provider_name");
const interactive = card.get("type") === "video";
const language = card.get("language") || "";
const largeImage = (card.get("image")?.length > 0 && card.get("width") > card.get("height")) || interactive;
const description = (
<div className='status-card__content'>
<span className='status-card__host'>
<span lang={language}>{provider}</span>
{card.get('published_at') && <> · <RelativeTimestamp timestamp={card.get('published_at')} /></>}
{card.get("published_at") && <> · <RelativeTimestamp timestamp={card.get("published_at")} /></>}
</span>
<strong className='status-card__title' title={card.get('title')} lang={language}>{card.get('title')}</strong>
<strong className='status-card__title' title={card.get("title")} lang={language}>{card.get("title")}</strong>
{card.get('author_name').length > 0 ? <span className='status-card__author'><FormattedMessage id='link_preview.author' defaultMessage='By {name}' values={{ name: <strong>{card.get('author_name')}</strong> }} /></span> : <span className='status-card__description'>{card.get('description')}</span>}
{card.get("author_name").length > 0 ? <span className='status-card__author'><FormattedMessage id='link_preview.author' defaultMessage='By {name}' values={{ name: <strong>{card.get("author_name")}</strong> }} /></span> : <span className='status-card__description'>{card.get("description")}</span>}
</div>
);
const thumbnailStyle = {
visibility: revealed ? null : 'hidden',
visibility: revealed ? null : "hidden",
};
if (largeImage && card.get('type') === 'video') {
thumbnailStyle.aspectRatio = `16 / 9`;
if (largeImage && card.get("type") === "video") {
thumbnailStyle.aspectRatio = "16 / 9";
} else if (largeImage) {
thumbnailStyle.aspectRatio = '1.91 / 1';
thumbnailStyle.aspectRatio = "1.91 / 1";
} else {
thumbnailStyle.aspectRatio = 1;
}
@@ -159,16 +159,16 @@ export default class Card extends PureComponent {
let canvas = (
<Blurhash
className={classNames('status-card__image-preview', {
'status-card__image-preview--hidden': revealed && this.state.previewLoaded,
className={classNames("status-card__image-preview", {
"status-card__image-preview--hidden": revealed && this.state.previewLoaded,
})}
hash={card.get('blurhash')}
hash={card.get("blurhash")}
dummy={!useBlurhash}
/>
);
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 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' />;
let spoilerButton = (
<button type='button' onClick={this.handleReveal} className='spoiler-button__overlay'>
@@ -180,7 +180,7 @@ export default class Card extends PureComponent {
);
spoilerButton = (
<div className={classNames('spoiler-button', { 'spoiler-button--minified': revealed })}>
<div className={classNames("spoiler-button", { "spoiler-button--minified": revealed })}>
{spoilerButton}
</div>
);
@@ -198,7 +198,7 @@ export default class Card extends PureComponent {
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
<div>
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' /></button>
<a href={card.get('url')} target='_blank' rel='noopener noreferrer'><Icon id='external-link' /></a>
<a href={card.get("url")} target='_blank' rel='noopener noreferrer'><Icon id='external-link' /></a>
</div>
</div>
) : spoilerButton}
@@ -207,12 +207,12 @@ export default class Card extends PureComponent {
}
return (
<div className={classNames('status-card', { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? 'button' : null}>
<div className={classNames("status-card", { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? "button" : null}>
{embed}
<a href={card.get('url')} target='_blank' rel='noopener noreferrer'>{description}</a>
<a href={card.get("url")} target='_blank' rel='noopener noreferrer'>{description}</a>
</div>
);
} else if (card.get('image')) {
} else if (card.get("image")) {
embed = (
<div className='status-card__image'>
{canvas}
@@ -228,7 +228,7 @@ export default class Card extends PureComponent {
}
return (
<a href={card.get('url')} className={classNames('status-card', { expanded: largeImage })} target='_blank' rel='noopener noreferrer' ref={this.setRef}>
<a href={card.get("url")} className={classNames("status-card", { expanded: largeImage })} target='_blank' rel='noopener noreferrer' ref={this.setRef}>
{embed}
{description}
</a>
@@ -1,34 +1,34 @@
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import { injectIntl, defineMessages, FormattedDate, FormattedMessage } from 'react-intl';
import { injectIntl, defineMessages, FormattedDate, FormattedMessage } from "react-intl";
import classNames from 'classnames';
import { Link } from 'react-router-dom';
import classNames from "classnames";
import { Link } from "react-router-dom";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from "react-immutable-proptypes";
import ImmutablePureComponent from "react-immutable-pure-component";
import { AnimatedNumber } from 'mastodon/components/animated_number';
import EditedTimestamp from 'mastodon/components/edited_timestamp';
import { getHashtagBarForStatus } from 'mastodon/components/hashtag_bar';
import { Icon } from 'mastodon/components/icon';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
import { AnimatedNumber } from "mastodon/components/animated_number";
import EditedTimestamp from "mastodon/components/edited_timestamp";
import { getHashtagBarForStatus } from "mastodon/components/hashtag_bar";
import { Icon } from "mastodon/components/icon";
import PictureInPicturePlaceholder from "mastodon/components/picture_in_picture_placeholder";
import { Avatar } from '../../../components/avatar';
import { DisplayName } from '../../../components/display_name';
import MediaGallery from '../../../components/media_gallery';
import StatusContent from '../../../components/status_content';
import Audio from '../../audio';
import scheduleIdleTask from '../../ui/util/schedule_idle_task';
import Video from '../../video';
import { Avatar } from "../../../components/avatar";
import { DisplayName } from "../../../components/display_name";
import MediaGallery from "../../../components/media_gallery";
import StatusContent from "../../../components/status_content";
import Audio from "../../audio";
import scheduleIdleTask from "../../ui/util/schedule_idle_task";
import Video from "../../video";
import Card from './card';
import Card from "./card";
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
unlisted_short: { id: 'privacy.unlisted.short', defaultMessage: 'Unlisted' },
private_short: { id: 'privacy.private.short', defaultMessage: 'Followers only' },
direct_short: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' },
public_short: { id: "privacy.public.short", defaultMessage: "Public" },
unlisted_short: { id: "privacy.unlisted.short", defaultMessage: "Unlisted" },
private_short: { id: "privacy.private.short", defaultMessage: "Followers only" },
direct_short: { id: "privacy.direct.short", defaultMessage: "Mentioned people only" },
});
class DetailedStatus extends ImmutablePureComponent {
@@ -62,14 +62,14 @@ class DetailedStatus extends ImmutablePureComponent {
handleAccountClick = (e) => {
if (e.button === 0 && !(e.ctrlKey || e.metaKey) && this.context.router) {
e.preventDefault();
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
this.context.router.history.push(`/@${this.props.status.getIn(["account", "acct"])}`);
}
e.stopPropagation();
};
handleOpenVideo = (options) => {
this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), options);
this.props.onOpenVideo(this.props.status.getIn(["media_attachments", 0]), options);
};
handleExpandedToggle = () => {
@@ -100,13 +100,13 @@ class DetailedStatus extends ImmutablePureComponent {
let href;
if (e.target.nodeName !== 'A') {
if (e.target.nodeName !== "A") {
href = e.target.parentNode.href;
} else {
href = e.target.href;
}
window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
window.open(href, "mastodon-intent", "width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes");
};
handleTranslate = () => {
@@ -117,88 +117,88 @@ class DetailedStatus extends ImmutablePureComponent {
_properStatus () {
const { status } = this.props;
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
return status.get('reblog');
if (status.get("reblog", null) !== null && typeof status.get("reblog") === "object") {
return status.get("reblog");
} else {
return status;
}
}
getAttachmentAspectRatio () {
const attachments = this._properStatus().get('media_attachments');
const attachments = this._properStatus().get("media_attachments");
if (attachments.getIn([0, 'type']) === 'video') {
return `${attachments.getIn([0, 'meta', 'original', 'width'])} / ${attachments.getIn([0, 'meta', 'original', 'height'])}`;
} else if (attachments.getIn([0, 'type']) === 'audio') {
return '16 / 9';
if (attachments.getIn([0, "type"]) === "video") {
return `${attachments.getIn([0, "meta", "original", "width"])} / ${attachments.getIn([0, "meta", "original", "height"])}`;
} else if (attachments.getIn([0, "type"]) === "audio") {
return "16 / 9";
} else {
return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2';
return (attachments.size === 1 && attachments.getIn([0, "meta", "small", "aspect"])) ? attachments.getIn([0, "meta", "small", "aspect"]) : "3 / 2";
}
}
render () {
const status = this._properStatus();
const outerStyle = { boxSizing: 'border-box' };
const outerStyle = { boxSizing: "border-box" };
const { intl, compact, pictureInPicture } = this.props;
if (!status) {
return null;
}
let media = '';
let applicationLink = '';
let reblogLink = '';
let reblogIcon = 'retweet';
let favouriteLink = '';
let edited = '';
let media = "";
let applicationLink = "";
let reblogLink;
let reblogIcon = "retweet";
let favouriteLink;
let edited = "";
if (this.props.measureHeight) {
outerStyle.height = `${this.state.height}px`;
}
const language = status.getIn(['translation', 'language']) || status.get('language');
const language = status.getIn(["translation", "language"]) || status.get("language");
if (pictureInPicture.get('inUse')) {
if (pictureInPicture.get("inUse")) {
media = <PictureInPicturePlaceholder aspectRatio={this.getAttachmentAspectRatio()} />;
} else if (status.get('media_attachments').size > 0) {
if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
const attachment = status.getIn(['media_attachments', 0]);
const description = attachment.getIn(['translation', 'description']) || attachment.get('description');
} else if (status.get("media_attachments").size > 0) {
if (status.getIn(["media_attachments", 0, "type"]) === "audio") {
const attachment = status.getIn(["media_attachments", 0]);
const description = attachment.getIn(["translation", "description"]) || attachment.get("description");
media = (
<Audio
src={attachment.get('url')}
src={attachment.get("url")}
alt={description}
lang={language}
duration={attachment.getIn(['meta', 'original', 'duration'], 0)}
poster={attachment.get('preview_url') || status.getIn(['account', 'avatar_static'])}
backgroundColor={attachment.getIn(['meta', 'colors', 'background'])}
foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])}
accentColor={attachment.getIn(['meta', 'colors', 'accent'])}
sensitive={status.get('sensitive')}
duration={attachment.getIn(["meta", "original", "duration"], 0)}
poster={attachment.get("preview_url") || status.getIn(["account", "avatar_static"])}
backgroundColor={attachment.getIn(["meta", "colors", "background"])}
foregroundColor={attachment.getIn(["meta", "colors", "foreground"])}
accentColor={attachment.getIn(["meta", "colors", "accent"])}
sensitive={status.get("sensitive")}
visible={this.props.showMedia}
blurhash={attachment.get('blurhash')}
blurhash={attachment.get("blurhash")}
height={150}
onToggleVisibility={this.props.onToggleMediaVisibility}
/>
);
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
const attachment = status.getIn(['media_attachments', 0]);
const description = attachment.getIn(['translation', 'description']) || attachment.get('description');
} else if (status.getIn(["media_attachments", 0, "type"]) === "video") {
const attachment = status.getIn(["media_attachments", 0]);
const description = attachment.getIn(["translation", "description"]) || attachment.get("description");
media = (
<Video
preview={attachment.get('preview_url')}
frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])}
aspectRatio={`${attachment.getIn(['meta', 'original', 'width'])} / ${attachment.getIn(['meta', 'original', 'height'])}`}
blurhash={attachment.get('blurhash')}
src={attachment.get('url')}
preview={attachment.get("preview_url")}
frameRate={attachment.getIn(["meta", "original", "frame_rate"])}
aspectRatio={`${attachment.getIn(["meta", "original", "width"])} / ${attachment.getIn(["meta", "original", "height"])}`}
blurhash={attachment.get("blurhash")}
src={attachment.get("url")}
alt={description}
lang={language}
width={300}
height={150}
onOpenVideo={this.handleOpenVideo}
sensitive={status.get('sensitive')}
sensitive={status.get("sensitive")}
visible={this.props.showMedia}
onToggleVisibility={this.props.onToggleMediaVisibility}
/>
@@ -207,8 +207,8 @@ class DetailedStatus extends ImmutablePureComponent {
media = (
<MediaGallery
standalone
sensitive={status.get('sensitive')}
media={status.get('media_attachments')}
sensitive={status.get("sensitive")}
media={status.get("media_attachments")}
lang={language}
height={300}
onOpenMedia={this.props.onOpenMedia}
@@ -217,34 +217,34 @@ class DetailedStatus extends ImmutablePureComponent {
/>
);
}
} else if (status.get('spoiler_text').length === 0) {
media = <Card sensitive={status.get('sensitive')} onOpenMedia={this.props.onOpenMedia} card={status.get('card', null)} />;
} else if (status.get("spoiler_text").length === 0) {
media = <Card sensitive={status.get("sensitive")} onOpenMedia={this.props.onOpenMedia} card={status.get("card", null)} />;
}
if (status.get('application')) {
applicationLink = <> · <a className='detailed-status__application' href={status.getIn(['application', 'website'])} target='_blank' rel='noopener noreferrer'>{status.getIn(['application', 'name'])}</a></>;
if (status.get("application")) {
applicationLink = <> · <a className='detailed-status__application' href={status.getIn(["application", "website"])} target='_blank' rel='noopener noreferrer'>{status.getIn(["application", "name"])}</a></>;
}
const visibilityIconInfo = {
'public': { icon: 'globe', text: intl.formatMessage(messages.public_short) },
'unlisted': { icon: 'unlock', text: intl.formatMessage(messages.unlisted_short) },
'private': { icon: 'lock', text: intl.formatMessage(messages.private_short) },
'direct': { icon: 'at', text: intl.formatMessage(messages.direct_short) },
"public": { icon: "globe", text: intl.formatMessage(messages.public_short) },
"unlisted": { icon: "unlock", text: intl.formatMessage(messages.unlisted_short) },
"private": { icon: "lock", text: intl.formatMessage(messages.private_short) },
"direct": { icon: "at", text: intl.formatMessage(messages.direct_short) },
};
const visibilityIcon = visibilityIconInfo[status.get('visibility')];
const visibilityIcon = visibilityIconInfo[status.get("visibility")];
const visibilityLink = <> · <Icon id={visibilityIcon.icon} title={visibilityIcon.text} /></>;
if (['private', 'direct'].includes(status.get('visibility'))) {
reblogLink = '';
if (["private", "direct"].includes(status.get("visibility"))) {
reblogLink = "";
} else if (this.context.router) {
reblogLink = (
<>
{' · '}
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/reblogs`} className='detailed-status__link'>
{" · "}
<Link to={`/@${status.getIn(["account", "acct"])}/${status.get("id")}/reblogs`} className='detailed-status__link'>
<Icon id={reblogIcon} />
<span className='detailed-status__reblogs'>
<AnimatedNumber value={status.get('reblogs_count')} />
<AnimatedNumber value={status.get("reblogs_count")} />
</span>
</Link>
</>
@@ -252,11 +252,11 @@ class DetailedStatus extends ImmutablePureComponent {
} else {
reblogLink = (
<>
{' · '}
<a href={`/interact/${status.get('id')}?type=reblog`} className='detailed-status__link' onClick={this.handleModalLink}>
{" · "}
<a href={`/interact/${status.get("id")}?type=reblog`} className='detailed-status__link' onClick={this.handleModalLink}>
<Icon id={reblogIcon} />
<span className='detailed-status__reblogs'>
<AnimatedNumber value={status.get('reblogs_count')} />
<AnimatedNumber value={status.get("reblogs_count")} />
</span>
</a>
</>
@@ -265,53 +265,53 @@ class DetailedStatus extends ImmutablePureComponent {
if (this.context.router) {
favouriteLink = (
<Link to={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}/favourites`} className='detailed-status__link'>
<Link to={`/@${status.getIn(["account", "acct"])}/${status.get("id")}/favourites`} className='detailed-status__link'>
<Icon id='star' />
<span className='detailed-status__favorites'>
<AnimatedNumber value={status.get('favourites_count')} />
<AnimatedNumber value={status.get("favourites_count")} />
</span>
</Link>
);
} else {
favouriteLink = (
<a href={`/interact/${status.get('id')}?type=favourite`} className='detailed-status__link' onClick={this.handleModalLink}>
<a href={`/interact/${status.get("id")}?type=favourite`} className='detailed-status__link' onClick={this.handleModalLink}>
<Icon id='star' />
<span className='detailed-status__favorites'>
<AnimatedNumber value={status.get('favourites_count')} />
<AnimatedNumber value={status.get("favourites_count")} />
</span>
</a>
);
}
if (status.get('edited_at')) {
if (status.get("edited_at")) {
edited = (
<>
{' · '}
<EditedTimestamp statusId={status.get('id')} timestamp={status.get('edited_at')} />
{" · "}
<EditedTimestamp statusId={status.get("id")} timestamp={status.get("edited_at")} />
</>
);
}
const {statusContentProps, hashtagBar} = getHashtagBarForStatus(status);
const expanded = !status.get('hidden') || status.get('spoiler_text').length === 0;
const expanded = !status.get("hidden") || status.get("spoiler_text").length === 0;
return (
<div style={outerStyle}>
<div ref={this.setRef} className={classNames('detailed-status', { compact })}>
{status.get('visibility') === 'direct' && (
<div ref={this.setRef} className={classNames("detailed-status", { compact })}>
{status.get("visibility") === "direct" && (
<div className='status__prepend'>
<div className='status__prepend-icon-wrapper'><Icon id='at' className='status__prepend-icon' fixedWidth /></div>
<FormattedMessage id='status.direct_indicator' defaultMessage='Private mention' />
</div>
)}
<a href={`/@${status.getIn(['account', 'acct'])}`} onClick={this.handleAccountClick} className='detailed-status__display-name'>
<div className='detailed-status__display-avatar'><Avatar account={status.get('account')} size={46} /></div>
<DisplayName account={status.get('account')} localDomain={this.props.domain} />
<a href={`/@${status.getIn(["account", "acct"])}`} onClick={this.handleAccountClick} className='detailed-status__display-name'>
<div className='detailed-status__display-avatar'><Avatar account={status.get("account")} size={46} /></div>
<DisplayName account={status.get("account")} localDomain={this.props.domain} />
</a>
<StatusContent
status={status}
expanded={!status.get('hidden')}
expanded={!status.get("hidden")}
onExpandedToggle={this.handleExpandedToggle}
onTranslate={this.handleTranslate}
{...statusContentProps}
@@ -322,8 +322,8 @@ class DetailedStatus extends ImmutablePureComponent {
{expanded && hashtagBar}
<div className='detailed-status__meta'>
<a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`} target='_blank' rel='noopener noreferrer'>
<FormattedDate value={new Date(status.get('created_at'))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
<a className='detailed-status__datetime' href={`/@${status.getIn(["account", "acct"])}/${status.get("id")}`} target='_blank' rel='noopener noreferrer'>
<FormattedDate value={new Date(status.get("created_at"))} hour12={false} year='numeric' month='short' day='2-digit' hour='2-digit' minute='2-digit' />
</a>{edited}{visibilityLink}{applicationLink}{reblogLink} · {favouriteLink}
</div>
</div>