diff options
Diffstat (limited to 'app/javascript/mastodon/features/status')
-rw-r--r-- | app/javascript/mastodon/features/status/components/action_bar.jsx (renamed from app/javascript/mastodon/features/status/components/action_bar.js) | 44 | ||||
-rw-r--r-- | app/javascript/mastodon/features/status/components/card.jsx (renamed from app/javascript/mastodon/features/status/components/card.js) | 11 | ||||
-rw-r--r-- | app/javascript/mastodon/features/status/components/detailed_status.jsx (renamed from app/javascript/mastodon/features/status/components/detailed_status.js) | 30 | ||||
-rw-r--r-- | app/javascript/mastodon/features/status/index.jsx (renamed from app/javascript/mastodon/features/status/index.js) | 106 |
4 files changed, 101 insertions, 90 deletions
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.jsx index 46ee9f6c1..0c74c4cc4 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.js +++ b/app/javascript/mastodon/features/status/components/action_bar.jsx @@ -13,7 +13,7 @@ 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: 'Direct message @{name}' }, + 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' }, @@ -47,8 +47,6 @@ const mapStateToProps = (state, { status }) => ({ relationship: state.getIn(['relationships', status.getIn(['account', 'id'])]), }); -export default @connect(mapStateToProps) -@injectIntl class ActionBar extends React.PureComponent { static contextTypes = { @@ -82,39 +80,39 @@ class ActionBar extends React.PureComponent { handleReplyClick = () => { this.props.onReply(this.props.status); - } + }; handleReblogClick = (e) => { this.props.onReblog(this.props.status, e); - } + }; handleFavouriteClick = () => { this.props.onFavourite(this.props.status); - } + }; handleBookmarkClick = (e) => { this.props.onBookmark(this.props.status, e); - } + }; handleDeleteClick = () => { this.props.onDelete(this.props.status, this.context.router.history); - } + }; handleRedraftClick = () => { this.props.onDelete(this.props.status, this.context.router.history, true); - } + }; handleEditClick = () => { this.props.onEdit(this.props.status, this.context.router.history); - } + }; handleDirectClick = () => { 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); - } + }; handleMuteClick = () => { const { status, relationship, onMute, onUnmute } = this.props; @@ -125,7 +123,7 @@ class ActionBar extends React.PureComponent { } else { onMute(account); } - } + }; handleBlockClick = () => { const { status, relationship, onBlock, onUnblock } = this.props; @@ -136,49 +134,49 @@ class ActionBar extends React.PureComponent { } else { onBlock(status); } - } + }; handleBlockDomain = () => { const { status, onBlockDomain } = this.props; const account = status.get('account'); onBlockDomain(account.get('acct').split('@')[1]); - } + }; handleUnblockDomain = () => { const { status, onUnblockDomain } = this.props; const account = status.get('account'); onUnblockDomain(account.get('acct').split('@')[1]); - } + }; handleConversationMuteClick = () => { this.props.onMuteConversation(this.props.status); - } + }; handleReport = () => { this.props.onReport(this.props.status); - } + }; handlePinClick = () => { this.props.onPin(this.props.status); - } + }; handleShare = () => { navigator.share({ text: this.props.status.get('search_index'), url: this.props.status.get('url'), }); - } + }; handleEmbed = () => { this.props.onEmbed(this.props.status); - } + }; handleCopy = () => { const url = this.props.status.get('url'); navigator.clipboard.writeText(url); - } + }; render () { const { status, relationship, intl } = this.props; @@ -298,3 +296,5 @@ class ActionBar extends React.PureComponent { } } + +export default connect(mapStateToProps)(injectIntl(ActionBar)); diff --git a/app/javascript/mastodon/features/status/components/card.js b/app/javascript/mastodon/features/status/components/card.jsx index 82537dd5d..b588c83e4 100644 --- a/app/javascript/mastodon/features/status/components/card.js +++ b/app/javascript/mastodon/features/status/components/card.jsx @@ -146,7 +146,7 @@ export default class Card extends React.PureComponent { } else { this.setState({ embedded: true }); } - } + }; setRef = c => { this.node = c; @@ -154,17 +154,17 @@ export default class Card extends React.PureComponent { if (this.node) { this._setDimensions(); } - } + }; handleImageLoad = () => { this.setState({ previewLoaded: true }); - } + }; handleReveal = e => { e.preventDefault(); e.stopPropagation(); this.setState({ revealed: true }); - } + }; renderVideo () { const { card } = this.props; @@ -196,11 +196,12 @@ export default class Card extends React.PureComponent { const interactive = card.get('type') !== 'link'; const className = classnames('status-card', { horizontal, compact, interactive }); const title = interactive ? <a className='status-card__title' href={card.get('url')} title={card.get('title')} rel='noopener noreferrer' target='_blank'><strong>{card.get('title')}</strong></a> : <strong className='status-card__title' title={card.get('title')}>{card.get('title')}</strong>; + const language = card.get('language') || ''; const ratio = card.get('width') / card.get('height'); const height = (compact && !embedded) ? (width / (16 / 9)) : (width / ratio); const description = ( - <div className='status-card__content'> + <div className='status-card__content' lang={language}> {title} {!(horizontal || compact) && <p className='status-card__description'>{trim(card.get('description') || '', maxDescription)}</p>} <span className='status-card__host'>{provider}</span> diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.jsx index c62910e0e..e4e572026 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.js +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -6,7 +6,7 @@ import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; import MediaGallery from '../../../components/media_gallery'; import { Link } from 'react-router-dom'; -import { injectIntl, defineMessages, FormattedDate } from 'react-intl'; +import { injectIntl, defineMessages, FormattedDate, FormattedMessage } from 'react-intl'; import Card from './card'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Video from '../../video'; @@ -25,7 +25,6 @@ const messages = defineMessages({ direct_short: { id: 'privacy.direct.short', defaultMessage: 'Direct' }, }); -export default @injectIntl class DetailedStatus extends ImmutablePureComponent { static contextTypes = { @@ -61,15 +60,15 @@ class DetailedStatus extends ImmutablePureComponent { } e.stopPropagation(); - } + }; handleOpenVideo = (options) => { this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), options); - } + }; handleExpandedToggle = () => { this.props.onToggleHidden(this.props.status); - } + }; _measureHeight (heightJustChanged) { if (this.props.measureHeight && this.node) { @@ -84,7 +83,7 @@ class DetailedStatus extends ImmutablePureComponent { setRef = c => { this.node = c; this._measureHeight(); - } + }; componentDidUpdate (prevProps, prevState) { this._measureHeight(prevState.height !== this.state.height); @@ -102,12 +101,12 @@ class DetailedStatus extends ImmutablePureComponent { } window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); - } + }; handleTranslate = () => { const { onTranslate, status } = this.props; onTranslate(status); - } + }; render () { const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; @@ -139,6 +138,7 @@ class DetailedStatus extends ImmutablePureComponent { <Audio src={attachment.get('url')} alt={attachment.get('description')} + lang={status.get('language')} duration={attachment.getIn(['meta', 'original', 'duration'], 0)} poster={attachment.get('preview_url') || status.getIn(['account', 'avatar_static'])} backgroundColor={attachment.getIn(['meta', 'colors', 'background'])} @@ -161,6 +161,7 @@ class DetailedStatus extends ImmutablePureComponent { blurhash={attachment.get('blurhash')} src={attachment.get('url')} alt={attachment.get('description')} + lang={status.get('language')} width={300} height={150} inline @@ -176,6 +177,7 @@ class DetailedStatus extends ImmutablePureComponent { standalone sensitive={status.get('sensitive')} media={status.get('media_attachments')} + lang={status.get('language')} height={300} onOpenMedia={this.props.onOpenMedia} visible={this.props.showMedia} @@ -260,7 +262,13 @@ class DetailedStatus extends ImmutablePureComponent { return ( <div style={outerStyle}> - <div ref={this.setRef} className={classNames('detailed-status', `detailed-status-${status.get('visibility')}`, { compact })}> + <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} /> @@ -276,7 +284,7 @@ class DetailedStatus extends ImmutablePureComponent { {media} <div className='detailed-status__meta'> - <a className='detailed-status__datetime' href={`/@${status.getIn(['account', 'acct'])}\/${status.get('id')}`} target='_blank' rel='noopener noreferrer'> + <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> @@ -286,3 +294,5 @@ class DetailedStatus extends ImmutablePureComponent { } } + +export default injectIntl(DetailedStatus); diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.jsx index 8a63cced2..2d18c6e9d 100644 --- a/app/javascript/mastodon/features/status/index.js +++ b/app/javascript/mastodon/features/status/index.jsx @@ -5,7 +5,17 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { createSelector } from 'reselect'; -import { fetchStatus } from '../../actions/statuses'; +import { + fetchStatus, + muteStatus, + unmuteStatus, + deleteStatus, + editStatus, + hideStatus, + revealStatus, + translateStatus, + undoStatusTranslation, +} from '../../actions/statuses'; import MissingIndicator from '../../components/missing_indicator'; import LoadingIndicator from 'mastodon/components/loading_indicator'; import DetailedStatus from './components/detailed_status'; @@ -27,16 +37,6 @@ import { directCompose, } from '../../actions/compose'; import { - muteStatus, - unmuteStatus, - deleteStatus, - editStatus, - hideStatus, - revealStatus, - translateStatus, - undoStatusTranslation, -} from '../../actions/statuses'; -import { unblockAccount, unmuteAccount, } from '../../actions/accounts'; @@ -176,8 +176,6 @@ const titleFromStatus = status => { return `${prefix}: "${truncate(text, 30)}"`; }; -export default @injectIntl -@connect(makeMapStateToProps) class Status extends ImmutablePureComponent { static contextTypes = { @@ -233,7 +231,7 @@ class Status extends ImmutablePureComponent { handleToggleMediaVisibility = () => { this.setState({ showMedia: !this.state.showMedia }); - } + }; handleFavouriteClick = (status) => { const { dispatch } = this.props; @@ -252,7 +250,7 @@ class Status extends ImmutablePureComponent { url: status.get('url'), })); } - } + }; handlePin = (status) => { if (status.get('pinned')) { @@ -260,7 +258,7 @@ class Status extends ImmutablePureComponent { } else { this.props.dispatch(pin(status)); } - } + }; handleReplyClick = (status) => { const { askReplyConfirmation, dispatch, intl } = this.props; @@ -283,11 +281,11 @@ class Status extends ImmutablePureComponent { url: status.get('url'), })); } - } + }; handleModalReblog = (status, privacy) => { this.props.dispatch(reblog(status, privacy)); - } + }; handleReblogClick = (status, e) => { const { dispatch } = this.props; @@ -310,7 +308,7 @@ class Status extends ImmutablePureComponent { url: status.get('url'), })); } - } + }; handleBookmarkClick = (status) => { if (status.get('bookmarked')) { @@ -318,7 +316,7 @@ class Status extends ImmutablePureComponent { } else { this.props.dispatch(bookmark(status)); } - } + }; handleDeleteClick = (status, history, withRedraft = false) => { const { dispatch, intl } = this.props; @@ -332,27 +330,27 @@ class Status extends ImmutablePureComponent { onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)), })); } - } + }; handleEditClick = (status, history) => { this.props.dispatch(editStatus(status.get('id'), history)); - } + }; handleDirectClick = (account, router) => { this.props.dispatch(directCompose(account, router)); - } + }; handleMentionClick = (account, router) => { this.props.dispatch(mentionCompose(account, router)); - } + }; handleOpenMedia = (media, index) => { this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index })); - } + }; handleOpenVideo = (media, options) => { this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, options })); - } + }; handleHotkeyOpenMedia = e => { const { status } = this.props; @@ -366,11 +364,11 @@ class Status extends ImmutablePureComponent { this.handleOpenMedia(status.get('media_attachments'), 0); } } - } + }; handleMuteClick = (account) => { this.props.dispatch(initMuteModal(account)); - } + }; handleConversationMuteClick = (status) => { if (status.get('muted')) { @@ -378,7 +376,7 @@ class Status extends ImmutablePureComponent { } else { this.props.dispatch(muteStatus(status.get('id'))); } - } + }; handleToggleHidden = (status) => { if (status.get('hidden')) { @@ -386,7 +384,7 @@ class Status extends ImmutablePureComponent { } else { this.props.dispatch(hideStatus(status.get('id'))); } - } + }; handleToggleAll = () => { const { status, ancestorsIds, descendantsIds } = this.props; @@ -397,7 +395,7 @@ class Status extends ImmutablePureComponent { } else { this.props.dispatch(hideStatus(statusIds)); } - } + }; handleTranslate = status => { const { dispatch } = this.props; @@ -407,29 +405,29 @@ class Status extends ImmutablePureComponent { } else { dispatch(translateStatus(status.get('id'))); } - } + }; handleBlockClick = (status) => { const { dispatch } = this.props; const account = status.get('account'); dispatch(initBlockModal(account)); - } + }; handleReport = (status) => { this.props.dispatch(initReport(status.get('account'), status)); - } + }; handleEmbed = (status) => { this.props.dispatch(openModal('EMBED', { url: status.get('url') })); - } + }; handleUnmuteClick = account => { this.props.dispatch(unmuteAccount(account.get('id'))); - } + }; handleUnblockClick = account => { this.props.dispatch(unblockAccount(account.get('id'))); - } + }; handleBlockDomainClick = domain => { this.props.dispatch(openModal('CONFIRM', { @@ -437,50 +435,50 @@ class Status extends ImmutablePureComponent { confirm: this.props.intl.formatMessage(messages.blockDomainConfirm), onConfirm: () => this.props.dispatch(blockDomain(domain)), })); - } + }; handleUnblockDomainClick = domain => { this.props.dispatch(unblockDomain(domain)); - } + }; handleHotkeyMoveUp = () => { this.handleMoveUp(this.props.status.get('id')); - } + }; handleHotkeyMoveDown = () => { this.handleMoveDown(this.props.status.get('id')); - } + }; handleHotkeyReply = e => { e.preventDefault(); this.handleReplyClick(this.props.status); - } + }; handleHotkeyFavourite = () => { this.handleFavouriteClick(this.props.status); - } + }; handleHotkeyBoost = () => { this.handleReblogClick(this.props.status); - } + }; handleHotkeyMention = e => { e.preventDefault(); this.handleMentionClick(this.props.status.get('account')); - } + }; handleHotkeyOpenProfile = () => { this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`); - } + }; handleHotkeyToggleHidden = () => { this.handleToggleHidden(this.props.status); - } + }; handleHotkeyToggleSensitive = () => { this.handleToggleMediaVisibility(); - } + }; handleMoveUp = id => { const { status, ancestorsIds, descendantsIds } = this.props; @@ -497,7 +495,7 @@ class Status extends ImmutablePureComponent { this._selectChild(index - 1, true); } } - } + }; handleMoveDown = id => { const { status, ancestorsIds, descendantsIds } = this.props; @@ -514,7 +512,7 @@ class Status extends ImmutablePureComponent { this._selectChild(index + 1, false); } } - } + }; _selectChild (index, align_top) { const container = this.node; @@ -544,7 +542,7 @@ class Status extends ImmutablePureComponent { setRef = c => { this.node = c; - } + }; componentDidUpdate () { if (this._scrolledIntoView) { @@ -569,7 +567,7 @@ class Status extends ImmutablePureComponent { onFullScreenChange = () => { this.setState({ fullscreen: isFullscreen() }); - } + }; render () { let ancestors, descendants; @@ -632,7 +630,7 @@ class Status extends ImmutablePureComponent { {ancestors} <HotKeys handlers={handlers}> - <div className={classNames('focusable', 'detailed-status__wrapper')} tabIndex='0' aria-label={textForScreenReader(intl, status, false)}> + <div className={classNames('focusable', 'detailed-status__wrapper', `detailed-status__wrapper-${status.get('visibility')}`)} tabIndex={0} aria-label={textForScreenReader(intl, status, false)}> <DetailedStatus key={`details-${status.get('id')}`} status={status} @@ -684,3 +682,5 @@ class Status extends ImmutablePureComponent { } } + +export default injectIntl(connect(makeMapStateToProps)(Status)); |