Add edit history to web UI (#17390)

* Add edit history to web UI

* Change history reducer to store items per status

* Fix missing loading prop
This commit is contained in:
Eugen Rochko
2022-02-09 01:17:07 +01:00
committed by GitHub
parent 2adcad04ff
commit fd3a45e348
18 changed files with 615 additions and 127 deletions

View File

@ -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, FormattedMessage } from 'react-intl';
import { injectIntl, defineMessages, FormattedDate } from 'react-intl';
import Card from './card';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Video from '../../video';
@ -16,6 +16,7 @@ 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';
import EditedTimestamp from 'mastodon/components/edited_timestamp';
const messages = defineMessages({
public_short: { id: 'privacy.public.short', defaultMessage: 'Public' },
@ -242,7 +243,7 @@ class DetailedStatus extends ImmutablePureComponent {
edited = (
<React.Fragment>
<React.Fragment> · </React.Fragment>
<FormattedMessage id='status.edited' defaultMessage='Edited {date}' values={{ date: intl.formatDate(status.get('edited_at'), { hour12: false, month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) }} />
<EditedTimestamp statusId={status.get('id')} timestamp={status.get('edited_at')} />
</React.Fragment>
);
}

View File

@ -0,0 +1,79 @@
import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { closeModal } from 'mastodon/actions/modal';
import emojify from 'mastodon/features/emoji/emoji';
import escapeTextContentForBrowser from 'escape-html';
import InlineAccount from 'mastodon/components/inline_account';
import IconButton from 'mastodon/components/icon_button';
import RelativeTimestamp from 'mastodon/components/relative_timestamp';
const mapStateToProps = (state, { statusId }) => ({
versions: state.getIn(['history', statusId, 'items']),
});
const mapDispatchToProps = dispatch => ({
onClose() {
dispatch(closeModal());
},
});
export default @connect(mapStateToProps, mapDispatchToProps)
class CompareHistoryModal extends React.PureComponent {
static propTypes = {
onClose: PropTypes.func.isRequired,
index: PropTypes.number.isRequired,
statusId: PropTypes.string.isRequired,
versions: ImmutablePropTypes.list.isRequired,
};
render () {
const { index, versions, onClose } = this.props;
const currentVersion = versions.get(index);
const emojiMap = currentVersion.get('emojis').reduce((obj, emoji) => {
obj[`:${emoji.get('shortcode')}:`] = emoji.toJS();
return obj;
}, {});
const content = { __html: emojify(currentVersion.get('content'), emojiMap) };
const spoilerContent = { __html: emojify(escapeTextContentForBrowser(currentVersion.get('spoiler_text')), emojiMap) };
const formattedDate = <RelativeTimestamp timestamp={currentVersion.get('created_at')} short={false} />;
const formattedName = <InlineAccount accountId={currentVersion.get('account')} />;
const label = currentVersion.get('original') ? (
<FormattedMessage id='status.history.created' defaultMessage='{name} created {date}' values={{ name: formattedName, date: formattedDate }} />
) : (
<FormattedMessage id='status.history.edited' defaultMessage='{name} edited {date}' values={{ name: formattedName, date: formattedDate }} />
);
return (
<div className='modal-root__modal compare-history-modal'>
<div className='report-modal__target'>
<IconButton className='report-modal__close' icon='times' onClick={onClose} size={20} />
{label}
</div>
<div className='compare-history-modal__container'>
<div className='status__content'>
{currentVersion.get('spoiler_text').length > 0 && (
<React.Fragment>
<div className='translate' dangerouslySetInnerHTML={spoilerContent} />
<hr />
</React.Fragment>
)}
<div className='status__content__text status__content__text--visible translate' dangerouslySetInnerHTML={content} />
</div>
</div>
</div>
);
}
}

View File

@ -19,7 +19,8 @@ import {
EmbedModal,
ListEditor,
ListAdder,
} from '../../../features/ui/util/async-components';
CompareHistoryModal,
} from 'mastodon/features/ui/util/async-components';
const MODAL_COMPONENTS = {
'MEDIA': () => Promise.resolve({ default: MediaModal }),
@ -34,7 +35,8 @@ const MODAL_COMPONENTS = {
'EMBED': EmbedModal,
'LIST_EDITOR': ListEditor,
'FOCAL_POINT': () => Promise.resolve({ default: FocalPointModal }),
'LIST_ADDER':ListAdder,
'LIST_ADDER': ListAdder,
'COMPARE_HISTORY': CompareHistoryModal,
};
export default class ModalRoot extends React.PureComponent {

View File

@ -157,3 +157,7 @@ export function Directory () {
export function FollowRecommendations () {
return import(/* webpackChunkName: "features/follow_recommendations" */'../../follow_recommendations');
}
export function CompareHistoryModal () {
return import(/*webpackChunkName: "modals/compare_history_modal" */'../components/compare_history_modal');
}