Merge commit 'c15c8c7aa8' into kb_migration

This commit is contained in:
KMY 2023-06-01 17:30:18 +09:00
commit 093cfdbb7b
208 changed files with 2976 additions and 5888 deletions

View file

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { FormattedMessage, FormattedHTMLMessage } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
@ -77,7 +77,7 @@ class Follows extends PureComponent {
{loadedContent}
</div>
<p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' /></p>
<p className='onboarding__lead'><FormattedMessage id='onboarding.tips.accounts_from_other_servers' defaultMessage='<strong>Did you know?</strong> Since Mastodon is decentralized, some profiles you come across will be hosted on servers other than yours. And yet you can interact with them seamlessly! Their server is in the second half of their username!' values={{ strong: chunks => <strong>{chunks}</strong> }} /></p>
<div className='onboarding__footer'>
<button className='link-button' onClick={onBack}><FormattedMessage id='onboarding.actions.back' defaultMessage='Take me back' /></button>

View file

@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage, FormattedHTMLMessage } from 'react-intl';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { Link } from 'react-router-dom';
@ -168,9 +168,9 @@ class Share extends PureComponent {
<CopyPasteText value={intl.formatMessage(messages.shareableMessage, { username: `@${account.get('username')}@${domain}`, url })} />
<TipCarousel>
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.verification' defaultMessage='<strong>Did you know?</strong> You can verify your account by putting a link to your Mastodon profile on your own website and adding the website to your profile. No fees or documents necessary!' /></p></div>
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.migration' defaultMessage='<strong>Did you know?</strong> If you feel like {domain} is not a great server choice for you in the future, you can move to another Mastodon server without losing your followers. You can even host your own server!' values={{ domain }} /></p></div>
<div><p className='onboarding__lead'><FormattedHTMLMessage id='onboarding.tips.2fa' defaultMessage='<strong>Did you know?</strong> You can secure your account by setting up two-factor authentication in your account settings. It works with any TOTP app of your choice, no phone number necessary!' /></p></div>
<div><p className='onboarding__lead'><FormattedMessage id='onboarding.tips.verification' defaultMessage='<strong>Did you know?</strong> You can verify your account by putting a link to your Mastodon profile on your own website and adding the website to your profile. No fees or documents necessary!' values={{ strong: chunks => <strong>{chunks}</strong> }} /></p></div>
<div><p className='onboarding__lead'><FormattedMessage id='onboarding.tips.migration' defaultMessage='<strong>Did you know?</strong> If you feel like {domain} is not a great server choice for you in the future, you can move to another Mastodon server without losing your followers. You can even host your own server!' values={{ domain, strong: chunks => <strong>{chunks}</strong> }} /></p></div>
<div><p className='onboarding__lead'><FormattedMessage id='onboarding.tips.2fa' defaultMessage='<strong>Did you know?</strong> You can secure your account by setting up two-factor authentication in your account settings. It works with any TOTP app of your choice, no phone number necessary!' values={{ strong: chunks => <strong>{chunks}</strong> }} /></p></div>
</TipCarousel>
<p className='onboarding__lead'><FormattedMessage id='onboarding.share.next_steps' defaultMessage='Possible next steps:' /></p>

View file

@ -143,17 +143,20 @@ class DetailedStatus extends ImmutablePureComponent {
outerStyle.height = `${this.state.height}px`;
}
const language = status.getIn(['translation', 'language']) || status.get('language');
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]);
const description = attachment.getIn(['translation', 'description']) || attachment.get('description');
media = (
<Audio
src={attachment.get('url')}
alt={attachment.get('description')}
lang={status.get('language')}
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'])}
@ -168,6 +171,7 @@ class DetailedStatus extends ImmutablePureComponent {
);
} 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
@ -175,8 +179,8 @@ class DetailedStatus extends ImmutablePureComponent {
frameRate={attachment.getIn(['meta', 'original', 'frame_rate'])}
blurhash={attachment.get('blurhash')}
src={attachment.get('url')}
alt={attachment.get('description')}
lang={status.get('language')}
alt={description}
lang={language}
width={300}
height={150}
inline
@ -192,7 +196,7 @@ class DetailedStatus extends ImmutablePureComponent {
standalone
sensitive={status.get('sensitive')}
media={status.get('media_attachments')}
lang={status.get('language')}
lang={language}
height={300}
onOpenMedia={this.props.onOpenMedia}
visible={this.props.showMedia}

View file

@ -456,7 +456,7 @@ class Status extends ImmutablePureComponent {
const { dispatch } = this.props;
if (status.get('translation')) {
dispatch(undoStatusTranslation(status.get('id')));
dispatch(undoStatusTranslation(status.get('id'), status.get('poll')));
} else {
dispatch(translateStatus(status.get('id')));
}

View file

@ -8,7 +8,7 @@ import Audio from 'mastodon/features/audio';
import Footer from 'mastodon/features/picture_in_picture/components/footer';
const mapStateToProps = (state, { statusId }) => ({
language: state.getIn(['statuses', statusId, 'language']),
status: state.getIn(['statuses', statusId]),
accountStaticAvatar: state.getIn(['accounts', state.getIn(['statuses', statusId, 'account']), 'avatar_static']),
});
@ -17,7 +17,7 @@ class AudioModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,
statusId: PropTypes.string.isRequired,
language: PropTypes.string,
status: ImmutablePropTypes.map.isRequired,
accountStaticAvatar: PropTypes.string.isRequired,
options: PropTypes.shape({
autoPlay: PropTypes.bool,
@ -27,15 +27,17 @@ class AudioModal extends ImmutablePureComponent {
};
render () {
const { media, language, accountStaticAvatar, statusId, onClose } = this.props;
const { media, status, accountStaticAvatar, onClose } = this.props;
const options = this.props.options || {};
const language = status.getIn(['translation', 'language']) || status.get('language');
const description = media.getIn(['translation', 'description']) || media.get('description');
return (
<div className='modal-root__modal audio-modal'>
<div className='audio-modal__container'>
<Audio
src={media.get('url')}
alt={media.get('description')}
alt={description}
lang={language}
duration={media.getIn(['meta', 'original', 'duration'], 0)}
height={150}
@ -48,7 +50,7 @@ class AudioModal extends ImmutablePureComponent {
</div>
<div className='media-modal__overlay'>
{statusId && <Footer statusId={statusId} withOpenButton onClose={onClose} />}
{status && <Footer statusId={status.get('id')} withOpenButton onClose={onClose} />}
</div>
</div>
);

View file

@ -145,6 +145,7 @@ class MediaModal extends ImmutablePureComponent {
const content = media.map((image) => {
const width = image.getIn(['meta', 'original', 'width']) || null;
const height = image.getIn(['meta', 'original', 'height']) || null;
const description = image.getIn(['translation', 'description']) || image.get('description');
if (image.get('type') === 'image') {
return (
@ -153,7 +154,7 @@ class MediaModal extends ImmutablePureComponent {
src={image.get('url')}
width={width}
height={height}
alt={image.get('description')}
alt={description}
lang={lang}
key={image.get('url')}
onClick={this.toggleNavigation}
@ -176,7 +177,7 @@ class MediaModal extends ImmutablePureComponent {
volume={volume || 1}
onCloseVideo={onClose}
detailed
alt={image.get('description')}
alt={description}
lang={lang}
key={image.get('url')}
/>
@ -188,7 +189,7 @@ class MediaModal extends ImmutablePureComponent {
width={width}
height={height}
key={image.get('url')}
alt={image.get('description')}
alt={description}
lang={lang}
onClick={this.toggleNavigation}
/>

View file

@ -9,7 +9,7 @@ import Footer from 'mastodon/features/picture_in_picture/components/footer';
import Video from 'mastodon/features/video';
const mapStateToProps = (state, { statusId }) => ({
language: state.getIn(['statuses', statusId, 'language']),
status: state.getIn(['statuses', statusId]),
});
class VideoModal extends ImmutablePureComponent {
@ -17,7 +17,7 @@ class VideoModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.map.isRequired,
statusId: PropTypes.string,
language: PropTypes.string,
status: ImmutablePropTypes.map,
options: PropTypes.shape({
startTime: PropTypes.number,
autoPlay: PropTypes.bool,
@ -38,8 +38,10 @@ class VideoModal extends ImmutablePureComponent {
}
render () {
const { media, statusId, language, onClose } = this.props;
const { media, status, onClose } = this.props;
const options = this.props.options || {};
const language = status.getIn(['translation', 'language']) || status.get('language');
const description = media.getIn(['translation', 'description']) || media.get('description');
return (
<div className='modal-root__modal video-modal'>
@ -55,13 +57,13 @@ class VideoModal extends ImmutablePureComponent {
onCloseVideo={onClose}
autoFocus
detailed
alt={media.get('description')}
alt={description}
lang={language}
/>
</div>
<div className='media-modal__overlay'>
{statusId && <Footer statusId={statusId} withOpenButton onClose={onClose} />}
{status && <Footer statusId={status.get('id')} withOpenButton onClose={onClose} />}
</div>
</div>
);