Merge tag 'v3.3.0' into instance_only_statuses

This commit is contained in:
Renato "Lond" Cerqueira
2020-12-27 11:00:43 +01:00
877 changed files with 35407 additions and 11128 deletions

View File

@ -15,7 +15,7 @@ const messages = defineMessages({
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 to original audience' },
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' },

View File

@ -15,6 +15,7 @@ import scheduleIdleTask from '../../ui/util/schedule_idle_task';
import classNames from 'classnames';
import Icon from 'mastodon/components/icon';
import AnimatedNumber from 'mastodon/components/animated_number';
import PictureInPicturePlaceholder from 'mastodon/components/picture_in_picture_placeholder';
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
@ -41,6 +42,10 @@ class DetailedStatus extends ImmutablePureComponent {
domain: PropTypes.string.isRequired,
compact: PropTypes.bool,
showMedia: PropTypes.bool,
pictureInPicture: ImmutablePropTypes.contains({
inUse: PropTypes.bool,
available: PropTypes.bool,
}),
onToggleMediaVisibility: PropTypes.func,
};
@ -57,8 +62,8 @@ class DetailedStatus extends ImmutablePureComponent {
e.stopPropagation();
}
handleOpenVideo = (media, options) => {
this.props.onOpenVideo(media, options);
handleOpenVideo = (options) => {
this.props.onOpenVideo(this.props.status.getIn(['media_attachments', 0]), options);
}
handleExpandedToggle = () => {
@ -101,7 +106,7 @@ class DetailedStatus extends ImmutablePureComponent {
render () {
const status = (this.props.status && this.props.status.get('reblog')) ? this.props.status.get('reblog') : this.props.status;
const outerStyle = { boxSizing: 'border-box' };
const { intl, compact } = this.props;
const { intl, compact, pictureInPicture } = this.props;
if (!status) {
return null;
@ -118,7 +123,9 @@ class DetailedStatus extends ImmutablePureComponent {
outerStyle.height = `${this.state.height}px`;
}
if (status.get('media_attachments').size > 0) {
if (pictureInPicture.get('inUse')) {
media = <PictureInPicturePlaceholder />;
} else if (status.get('media_attachments').size > 0) {
if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
const attachment = status.getIn(['media_attachments', 0]);
@ -140,6 +147,7 @@ class DetailedStatus extends ImmutablePureComponent {
media = (
<Video
preview={attachment.get('preview_url')}
frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])}
blurhash={attachment.get('blurhash')}
src={attachment.get('url')}
alt={attachment.get('description')}

View File

@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import DetailedStatus from '../components/detailed_status';
import { makeGetStatus } from '../../../selectors';
import { makeGetStatus, makeGetPictureInPicture } from '../../../selectors';
import {
replyCompose,
mentionCompose,
@ -40,10 +40,12 @@ const messages = defineMessages({
const makeMapStateToProps = () => {
const getStatus = makeGetStatus();
const getPictureInPicture = makeGetPictureInPicture();
const mapStateToProps = (state, props) => ({
status: getStatus(state, props),
domain: state.getIn(['meta', 'domain']),
pictureInPicture: getPictureInPicture(state, props),
});
return mapStateToProps;

View File

@ -43,7 +43,7 @@ import {
import { initMuteModal } from '../../actions/mutes';
import { initBlockModal } from '../../actions/blocks';
import { initReport } from '../../actions/reports';
import { makeGetStatus } from '../../selectors';
import { makeGetStatus, makeGetPictureInPicture } from '../../selectors';
import { ScrollContainer } from 'react-router-scroll-4';
import ColumnBackButton from '../../components/column_back_button';
import ColumnHeader from '../../components/column_header';
@ -72,6 +72,7 @@ const messages = defineMessages({
const makeMapStateToProps = () => {
const getStatus = makeGetStatus();
const getPictureInPicture = makeGetPictureInPicture();
const getAncestorsIds = createSelector([
(_, { id }) => id,
@ -129,11 +130,12 @@ const makeMapStateToProps = () => {
const mapStateToProps = (state, props) => {
const status = getStatus(state, { id: props.params.statusId });
let ancestorsIds = Immutable.List();
let ancestorsIds = Immutable.List();
let descendantsIds = Immutable.List();
if (status) {
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
ancestorsIds = getAncestorsIds(state, { id: status.get('in_reply_to_id') });
descendantsIds = getDescendantsIds(state, { id: status.get('id') });
}
@ -143,6 +145,7 @@ const makeMapStateToProps = () => {
descendantsIds,
askReplyConfirmation: state.getIn(['compose', 'text']).trim().length !== 0,
domain: state.getIn(['meta', 'domain']),
pictureInPicture: getPictureInPicture(state, { id: props.params.statusId }),
};
};
@ -167,6 +170,10 @@ class Status extends ImmutablePureComponent {
askReplyConfirmation: PropTypes.bool,
multiColumn: PropTypes.bool,
domain: PropTypes.string.isRequired,
pictureInPicture: ImmutablePropTypes.contains({
inUse: PropTypes.bool,
available: PropTypes.bool,
}),
};
state = {
@ -274,22 +281,20 @@ class Status extends ImmutablePureComponent {
}
handleOpenMedia = (media, index) => {
this.props.dispatch(openModal('MEDIA', { media, index }));
this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index }));
}
handleOpenVideo = (media, options) => {
this.props.dispatch(openModal('VIDEO', { media, options }));
this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, options }));
}
handleHotkeyOpenMedia = e => {
const status = this._properStatus();
const { status } = this.props;
e.preventDefault();
if (status.get('media_attachments').size > 0) {
if (status.getIn(['media_attachments', 0, 'type']) === 'audio') {
// TODO: toggle play/paused?
} else if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
if (status.getIn(['media_attachments', 0, 'type']) === 'video') {
this.handleOpenVideo(status.getIn(['media_attachments', 0]), { startTime: 0 });
} else {
this.handleOpenMedia(status.get('media_attachments'), 0);
@ -492,7 +497,7 @@ class Status extends ImmutablePureComponent {
render () {
let ancestors, descendants;
const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl, domain, multiColumn } = this.props;
const { shouldUpdateScroll, status, ancestorsIds, descendantsIds, intl, domain, multiColumn, pictureInPicture } = this.props;
const { fullscreen } = this.state;
if (status === null) {
@ -550,6 +555,7 @@ class Status extends ImmutablePureComponent {
domain={domain}
showMedia={this.state.showMedia}
onToggleMediaVisibility={this.handleToggleMediaVisibility}
pictureInPicture={pictureInPicture}
/>
<ActionBar