diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 835151619c..5ebeca8802 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -289,6 +289,7 @@ RSpec/LetSetup: - 'spec/controllers/oauth/tokens_controller_spec.rb' - 'spec/controllers/settings/imports_controller_spec.rb' - 'spec/lib/activitypub/activity/delete_spec.rb' + - 'spec/lib/vacuum/applications_vacuum_spec.rb' - 'spec/lib/vacuum/preview_cards_vacuum_spec.rb' - 'spec/models/account_spec.rb' - 'spec/models/account_statuses_cleanup_policy_spec.rb' diff --git a/CHANGELOG.md b/CHANGELOG.md index 5383d426b6..c49b192735 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ All notable changes to this project will be documented in this file. +## [4.1.5] - 2023-07-21 + +### Added + +- Add check preventing Sidekiq workers from running with Makara configured ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25850)) + +### Changed + +- Change request timeout handling to use a longer deadline ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26055)) + +### Fixed + +- Fix moderation interface for remote instances with a .zip TLD ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25885)) +- Fix remote accounts being possibly persisted to database with incomplete protocol values ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/25886)) +- Fix trending publishers table not rendering correctly on narrow screens ([vmstan](https://github.com/mastodon/mastodon/pull/25945)) + +### Security + +- Fix CSP headers being unintentionally wide ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/26105)) + ## [4.1.4] - 2023-07-07 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index 63a9388ee2..d308192e8b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,7 +103,7 @@ GEM attr_required (1.0.1) awrence (1.2.1) aws-eventstream (1.2.0) - aws-partitions (1.786.0) + aws-partitions (1.791.0) aws-sdk-core (3.178.0) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.651.0) @@ -112,7 +112,7 @@ GEM aws-sdk-kms (1.71.0) aws-sdk-core (~> 3, >= 3.177.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.130.0) + aws-sdk-s3 (1.131.0) aws-sdk-core (~> 3, >= 3.177.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.6) @@ -144,7 +144,7 @@ GEM blurhash (0.1.7) bootsnap (1.16.0) msgpack (~> 1.2) - brakeman (6.0.0) + brakeman (6.0.1) browser (5.3.1) brpoplpush-redis_script (0.1.3) concurrent-ruby (~> 1.0, >= 1.0.5) @@ -307,7 +307,7 @@ GEM activesupport (>= 5.1) haml (>= 4.0.6) railties (>= 5.1) - haml_lint (0.48.0) + haml_lint (0.49.1) haml (>= 4.0, < 6.2) parallel (~> 1.10) rainbow @@ -569,7 +569,7 @@ GEM rake (13.0.6) rdf (3.2.11) link_header (~> 0.0, >= 0.0.8) - rdf-normalize (0.6.0) + rdf-normalize (0.6.1) rdf (~> 3.2) redcarpet (3.6.0) redis (4.8.1) diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index 1380e6f283..06a3deee2b 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -108,7 +108,7 @@ class Auth::SessionsController < Devise::SessionsController end def home_paths(resource) - paths = [about_path] + paths = [about_path, '/explore'] paths << short_account_path(username: resource.account) if single_user_mode? && resource.is_a?(User) diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx index 0416df5d45..fd66310e85 100644 --- a/app/javascript/mastodon/components/dropdown_menu.jsx +++ b/app/javascript/mastodon/components/dropdown_menu.jsx @@ -297,7 +297,7 @@ export default class Dropdown extends PureComponent { onKeyPress: this.handleKeyPress, }) : ( {children && cloneElement(children, { hidden: true })} @@ -122,7 +122,7 @@ export default class IntersectionObserverArticle extends Component { } return ( -
+
{children && cloneElement(children, { hidden: false })}
); diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx index d4d472334a..be2f457c76 100644 --- a/app/javascript/mastodon/components/media_gallery.jsx +++ b/app/javascript/mastodon/components/media_gallery.jsx @@ -12,7 +12,7 @@ import { debounce } from 'lodash'; import { Blurhash } from 'mastodon/components/blurhash'; -import { autoPlayGif, cropImages, displayMedia, displayMediaExpand, useBlurhash } from '../initial_state'; +import { autoPlayGif, displayMedia, displayMediaExpand, useBlurhash } from '../initial_state'; import { IconButton } from './icon_button'; @@ -225,7 +225,6 @@ class MediaGallery extends PureComponent { static propTypes = { sensitive: PropTypes.bool, - standalone: PropTypes.bool, media: ImmutablePropTypes.list.isRequired, lang: PropTypes.string, size: PropTypes.object, @@ -239,10 +238,6 @@ class MediaGallery extends PureComponent { onToggleVisibility: PropTypes.func, }; - static defaultProps = { - standalone: false, - }; - state = { visible: this.props.visible !== undefined ? this.props.visible : (displayMedia !== 'hide_all' && !this.props.sensitive || displayMedia === 'show_all'), width: this.props.defaultWidth, @@ -311,7 +306,7 @@ class MediaGallery extends PureComponent { } render () { - const { media, lang, intl, sensitive, defaultWidth, standalone, autoplay } = this.props; + const { media, lang, intl, sensitive, defaultWidth, autoplay } = this.props; const { visible } = this.state; const width = this.state.width || defaultWidth; @@ -319,10 +314,10 @@ class MediaGallery extends PureComponent { const style = {}; - if (this.isFullSizeEligible() && (standalone || !cropImages)) { + if (this.isFullSizeEligible()) { style.aspectRatio = `${this.props.media.getIn([0, 'meta', 'small', 'aspect'])}`; } else { - style.aspectRatio = '16 / 9'; + style.aspectRatio = '3 / 2'; } const maxSize = displayMediaExpand ? 16 : 4; @@ -330,7 +325,7 @@ class MediaGallery extends PureComponent { const size = media.take(maxSize).size; const uncached = media.every(attachment => attachment.get('type') === 'unknown'); - if (standalone && this.isFullSizeEligible()) { + if (this.isFullSizeEligible()) { children = ; } else { children = media.take(maxSize).map((attachment, i) => ); diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx index 756a977224..c65bd494f3 100644 --- a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx +++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx @@ -12,6 +12,7 @@ class PictureInPicturePlaceholder extends PureComponent { static propTypes = { dispatch: PropTypes.func.isRequired, + aspectRatio: PropTypes.string, }; handleClick = () => { @@ -20,8 +21,10 @@ class PictureInPicturePlaceholder extends PureComponent { }; render () { + const { aspectRatio } = this.props; + return ( -
+
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx index a74866ecce..6a195201d5 100644 --- a/app/javascript/mastodon/components/status.jsx +++ b/app/javascript/mastodon/components/status.jsx @@ -19,7 +19,6 @@ import Bundle from '../features/ui/components/bundle'; import { MediaGallery, Video, Audio } from '../features/ui/util/async-components'; import { displayMedia } from '../initial_state'; -import AttachmentList from './attachment_list'; import { Avatar } from './avatar'; import { AvatarOverlay } from './avatar_overlay'; import { DisplayName } from './display_name'; @@ -198,17 +197,35 @@ class Status extends ImmutablePureComponent { this.props.onTranslate(this._properStatus()); }; - renderLoadingMediaGallery () { - return
; + getAttachmentAspectRatio () { + 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'; + } else { + return (attachments.size === 1 && attachments.getIn([0, 'meta', 'small', 'aspect'])) ? attachments.getIn([0, 'meta', 'small', 'aspect']) : '3 / 2' + } } - renderLoadingVideoPlayer () { - return
; - } + renderLoadingMediaGallery = () => { + return ( +
+ ); + }; - renderLoadingAudioPlayer () { - return
; - } + renderLoadingVideoPlayer = () => { + return ( +
+ ); + }; + + renderLoadingAudioPlayer = () => { + return ( +
+ ); + }; handleOpenVideo = (options) => { const status = this._properStatus(); @@ -445,18 +462,11 @@ class Status extends ImmutablePureComponent { } if (pictureInPicture.get('inUse')) { - media = ; + media = ; } else if (status.get('media_attachments').size > 0) { const language = status.getIn(['translation', 'language']) || status.get('language'); - if (this.props.muted) { - media = ( - - ); - } else if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { + if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); const description = attachment.getIn(['translation', 'description']) || attachment.get('description'); @@ -494,11 +504,11 @@ class Status extends ImmutablePureComponent { ); } - } else if (status.get('spoiler_text').length === 0 && status.get('card') && !this.props.muted) { + } else if (status.get('spoiler_text').length === 0 && status.get('card')) { media = ( ; } else { @@ -515,7 +516,10 @@ class Audio extends PureComponent {
diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx index 936dee12e3..b0c90a4302 100644 --- a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx +++ b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx @@ -86,7 +86,6 @@ class Bookmarks extends ImmutablePureComponent { onClick={this.handleHeaderClick} pinned={pinned} multiColumn={multiColumn} - showBackButton /> - - {this.props.account.get('acct')} + + {username}
- - @{this.props.account.get('acct')} - + + + @{username} + + - + + +
-
diff --git a/app/javascript/mastodon/features/explore/components/story.jsx b/app/javascript/mastodon/features/explore/components/story.jsx index 73ec99c14b..92eb41cff8 100644 --- a/app/javascript/mastodon/features/explore/components/story.jsx +++ b/app/javascript/mastodon/features/explore/components/story.jsx @@ -1,10 +1,13 @@ import PropTypes from 'prop-types'; import { PureComponent } from 'react'; +import { FormattedMessage } from 'react-intl'; + import classNames from 'classnames'; import { Blurhash } from 'mastodon/components/blurhash'; import { accountsCountRenderer } from 'mastodon/components/hashtag'; +import { RelativeTimestamp } from 'mastodon/components/relative_timestamp'; import { ShortNumber } from 'mastodon/components/short_number'; import { Skeleton } from 'mastodon/components/skeleton'; @@ -13,10 +16,14 @@ export default class Story extends PureComponent { static propTypes = { url: PropTypes.string, title: PropTypes.string, + lang: PropTypes.string, publisher: PropTypes.string, + publishedAt: PropTypes.string, + author: PropTypes.string, sharedTimes: PropTypes.number, thumbnail: PropTypes.string, blurhash: PropTypes.string, + expanded: PropTypes.bool, }; state = { @@ -26,16 +33,16 @@ export default class Story extends PureComponent { handleImageLoad = () => this.setState({ thumbnailLoaded: true }); render () { - const { url, title, publisher, sharedTimes, thumbnail, blurhash } = this.props; + const { expanded, url, title, lang, publisher, author, publishedAt, sharedTimes, thumbnail, blurhash } = this.props; const { thumbnailLoaded } = this.state; return ( - +
-
{publisher ? publisher : }
-
{title ? title : }
-
{typeof sharedTimes === 'number' ? : }
+
{publisher ? {publisher} : }{publishedAt && <> · }
+
{title ? title : }
+
{author && <>{author} }} /> · }{typeof sharedTimes === 'number' ? : }
diff --git a/app/javascript/mastodon/features/explore/links.jsx b/app/javascript/mastodon/features/explore/links.jsx index 8b199bf47c..489ab6dd61 100644 --- a/app/javascript/mastodon/features/explore/links.jsx +++ b/app/javascript/mastodon/features/explore/links.jsx @@ -55,12 +55,16 @@ class Links extends PureComponent {
{banner} - {isLoading ? () : links.map(link => ( + {isLoading ? () : links.map((link, i) => ( - + ({ @@ -74,7 +74,7 @@ class Favourites extends ImmutablePureComponent { const { intl, statusIds, columnId, multiColumn, hasMore, isLoading } = this.props; const pinned = !!columnId; - const emptyMessage = ; + const emptyMessage = ; return ( @@ -86,7 +86,6 @@ class Favourites extends ImmutablePureComponent { onClick={this.handleHeaderClick} pinned={pinned} multiColumn={multiColumn} - showBackButton /> ; + const emptyMessage = ; return ( diff --git a/app/javascript/mastodon/features/getting_started/index.jsx b/app/javascript/mastodon/features/getting_started/index.jsx index 85fd6f1209..f0cd70d7a1 100644 --- a/app/javascript/mastodon/features/getting_started/index.jsx +++ b/app/javascript/mastodon/features/getting_started/index.jsx @@ -32,7 +32,7 @@ const messages = defineMessages({ bookmarks: { id: 'navigation_bar.bookmarks', defaultMessage: 'Bookmarks' }, preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, - favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favourites' }, + favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Favorites' }, blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Blocked domains' }, mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx index 59522eb8fd..b728760ceb 100644 --- a/app/javascript/mastodon/features/interaction_modal/index.jsx +++ b/app/javascript/mastodon/features/interaction_modal/index.jsx @@ -116,8 +116,8 @@ class InteractionModal extends PureComponent { break; case 'favourite': icon = ; - title = ; - actionDescription = ; + title = ; + actionDescription = ; break; case 'emoji_reaction': icon = ; @@ -163,7 +163,7 @@ class InteractionModal extends PureComponent {

-

+

diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx index ec117e5841..cf3a27b11a 100644 --- a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx +++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx @@ -54,7 +54,7 @@ class KeyboardShortcuts extends ImmutablePureComponent { f - + b @@ -138,7 +138,7 @@ class KeyboardShortcuts extends ImmutablePureComponent { g+f - + g+e diff --git a/app/javascript/mastodon/features/lists/index.jsx b/app/javascript/mastodon/features/lists/index.jsx index ecec4b68df..e947a40b83 100644 --- a/app/javascript/mastodon/features/lists/index.jsx +++ b/app/javascript/mastodon/features/lists/index.jsx @@ -65,7 +65,7 @@ class Lists extends ImmutablePureComponent { return ( - + diff --git a/app/javascript/mastodon/features/notifications/components/column_settings.jsx b/app/javascript/mastodon/features/notifications/components/column_settings.jsx index e141039c96..3a8bd6943f 100644 --- a/app/javascript/mastodon/features/notifications/components/column_settings.jsx +++ b/app/javascript/mastodon/features/notifications/components/column_settings.jsx @@ -109,7 +109,7 @@ export default class ColumnSettings extends PureComponent {
- +
diff --git a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx index 2c0431d3fd..aaea6819b8 100644 --- a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx +++ b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx @@ -7,7 +7,7 @@ import { Icon } from 'mastodon/components/icon'; const tooltips = defineMessages({ mentions: { id: 'notifications.filter.mentions', defaultMessage: 'Mentions' }, - favourites: { id: 'notifications.filter.favourites', defaultMessage: 'Favourites' }, + favourites: { id: 'notifications.filter.favourites', defaultMessage: 'Favorites' }, emojiReactions: { id: 'notifications.filter.emoji_reactions', defaultMessage: 'Stamps' }, boosts: { id: 'notifications.filter.boosts', defaultMessage: 'Boosts' }, status_references: { id: 'notifications.filter.status_references', defaultMessage: 'Status references' }, diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx index 69471e268e..cb3f92b71c 100644 --- a/app/javascript/mastodon/features/notifications/components/notification.jsx +++ b/app/javascript/mastodon/features/notifications/components/notification.jsx @@ -21,7 +21,7 @@ import FollowRequestContainer from '../containers/follow_request_container'; import Report from './report'; const messages = defineMessages({ - favourite: { id: 'notification.favourite', defaultMessage: '{name} favourited your status' }, + favourite: { id: 'notification.favourite', defaultMessage: '{name} favorited your status' }, emojiReaction: { id: 'notification.emoji_reaction', defaultMessage: '{name} reacted your status with emoji' }, follow: { id: 'notification.follow', defaultMessage: '{name} followed you' }, ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' }, @@ -201,7 +201,7 @@ class Notification extends ImmutablePureComponent {
- +
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx index d0a962056e..a5a48749fc 100644 --- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx +++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx @@ -23,7 +23,7 @@ const messages = defineMessages({ 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: 'Favourite' }, + favourite: { id: 'status.favourite', defaultMessage: 'Favorite' }, replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' }, replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' }, open: { id: 'status.open', defaultMessage: 'Expand this status' }, diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx index 5fe4650b6d..6c50344916 100644 --- a/app/javascript/mastodon/features/status/components/action_bar.jsx +++ b/app/javascript/mastodon/features/status/components/action_bar.jsx @@ -26,7 +26,7 @@ const messages = defineMessages({ 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: 'Favourite' }, + 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}' }, diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx index d23bbf16a7..29a12c87bf 100644 --- a/app/javascript/mastodon/features/status/components/card.jsx +++ b/app/javascript/mastodon/features/status/components/card.jsx @@ -12,6 +12,7 @@ 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'; const IDNA_PREFIX = 'xn--'; @@ -57,14 +58,9 @@ export default class Card extends PureComponent { static propTypes = { card: ImmutablePropTypes.map, onOpenMedia: PropTypes.func.isRequired, - compact: PropTypes.bool, sensitive: PropTypes.bool, }; - static defaultProps = { - compact: false, - }; - state = { previewLoaded: false, embedded: false, @@ -148,7 +144,7 @@ export default class Card extends PureComponent { } render () { - const { card, compact } = this.props; + const { card } = this.props; const { embedded, revealed } = this.state; if (card === null) { @@ -156,29 +152,27 @@ export default class Card extends PureComponent { } const provider = card.get('provider_name').length === 0 ? decodeIDNA(getHostname(card.get('url'))) : card.get('provider_name'); - const horizontal = (!compact && card.get('width') > card.get('height')) || card.get('type') !== 'link' || embedded; const interactive = card.get('type') !== 'link'; - const className = classnames('status-card', { horizontal, compact, interactive }); - const title = interactive ?
{card.get('title')} : {card.get('title')}; const language = card.get('language') || ''; const description = ( -
- {title} - {!(horizontal || compact) &&

{card.get('description')}

} - {provider} +
+ + {provider} + {card.get('published_at') && <> · } + + {card.get('title')} + {card.get('author_name').length > 0 && {card.get('author_name')} }} />}
); const thumbnailStyle = { - visibility: revealed? null : 'hidden', + visibility: revealed ? null : 'hidden', + aspectRatio: `${card.get('width')} / ${card.get('height')}` }; - if (horizontal) { - thumbnailStyle.aspectRatio = (compact && !embedded) ? '16 / 9' : `${card.get('width')} / ${card.get('height')}`; - } + let embed; - let embed = ''; let canvas = ( ); + let thumbnail = ; + let spoilerButton = ( ); + spoilerButton = (
{spoilerButton} @@ -219,19 +219,20 @@ export default class Card extends PureComponent {
- {horizontal && } +
)} + {!revealed && spoilerButton}
); } return ( -
+
{embed} - {!compact && description} + {description}
); } else if (card.get('image')) { @@ -243,14 +244,14 @@ export default class Card extends PureComponent { ); } else { embed = ( -
+
); } return ( - + {embed} {description} diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx index 6bd016332b..f4fb303c17 100644 --- a/app/javascript/mastodon/features/status/components/detailed_status.jsx +++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx @@ -122,8 +122,30 @@ class DetailedStatus extends ImmutablePureComponent { onTranslate(status); }; + _properStatus () { + const { status } = this.props; + + 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'); + + 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' + } + } + render () { - const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status; + const status = this._properStatus(); const outerStyle = { boxSizing: 'border-box' }; const { intl, compact, pictureInPicture } = this.props; @@ -147,7 +169,7 @@ class DetailedStatus extends ImmutablePureComponent { const language = status.getIn(['translation', 'language']) || status.get('language'); if (pictureInPicture.get('inUse')) { - media = ; + media = ; } else if (status.get('media_attachments').size > 0) { if (status.getIn(['media_attachments', 0, 'type']) === 'audio') { const attachment = status.getIn(['media_attachments', 0]); @@ -178,13 +200,13 @@ class DetailedStatus extends ImmutablePureComponent {