Add emoji reaction detail status
This commit is contained in:
parent
de951a0ef9
commit
a1485f242d
22 changed files with 393 additions and 16 deletions
107
app/javascript/mastodon/features/emoji_reactions/index.jsx
Normal file
107
app/javascript/mastodon/features/emoji_reactions/index.jsx
Normal file
|
@ -0,0 +1,107 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import { connect } from 'react-redux';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
import Icon from 'mastodon/components/icon';
|
||||
import { fetchEmojiReactions, fetchFavourites } from 'mastodon/actions/interactions';
|
||||
import LoadingIndicator from 'mastodon/components/loading_indicator';
|
||||
import ScrollableList from 'mastodon/components/scrollable_list';
|
||||
import AccountContainer from 'mastodon/containers/account_container';
|
||||
import Column from 'mastodon/features/ui/components/column';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import EmojiView from '../../components/emoji_view';
|
||||
|
||||
const messages = defineMessages({
|
||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => { return {
|
||||
accountIds: state.getIn(['user_lists', 'emoji_reactioned_by', props.params.statusId]),
|
||||
} };
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class EmojiReactions extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
multiColumn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchEmojiReactions(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchEmojiReactions(nextProps.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
handleRefresh = () => {
|
||||
this.props.dispatch(fetchEmojiReactions(this.props.params.statusId));
|
||||
};
|
||||
|
||||
render () {
|
||||
const { intl, accountIds, multiColumn } = this.props;
|
||||
console.dir(accountIds);
|
||||
|
||||
if (!accountIds) {
|
||||
return (
|
||||
<Column>
|
||||
<LoadingIndicator />
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
let groups = {};
|
||||
for (const emoji_reaction of accountIds) {
|
||||
const key = emoji_reaction.account.id;
|
||||
const value = emoji_reaction;
|
||||
if (!groups[key]) groups[key] = [value];
|
||||
else groups[key].push(value);
|
||||
}
|
||||
console.dir(groups)
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.emoji_reactions' defaultMessage='No one has reacted with emoji this post yet. When someone does, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<Column bindToDocument={!multiColumn}>
|
||||
<ColumnHeader
|
||||
showBackButton
|
||||
multiColumn={multiColumn}
|
||||
extraButton={(
|
||||
<button type='button' className='column-header__button' title={intl.formatMessage(messages.refresh)} aria-label={intl.formatMessage(messages.refresh)} onClick={this.handleRefresh}><Icon id='refresh' /></button>
|
||||
)}
|
||||
/>
|
||||
|
||||
<ScrollableList
|
||||
scrollKey='emoji_reactions'
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{Object.keys(groups).map((key, index) =>(
|
||||
<AccountContainer key={index} id={key} withNote={false}>
|
||||
<div style={ { 'max-width': '100px' } }>
|
||||
{groups[key].map((value) => <EmojiView name={value.name} url={value.url} staticUrl={value.static_url} />)}
|
||||
</div>
|
||||
</AccountContainer>
|
||||
))}
|
||||
</ScrollableList>
|
||||
|
||||
<Helmet>
|
||||
<meta name='robots' content='noindex' />
|
||||
</Helmet>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -49,6 +49,8 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
available: PropTypes.bool,
|
||||
}),
|
||||
onToggleMediaVisibility: PropTypes.func,
|
||||
onEmojiReact: PropTypes.func,
|
||||
onUnEmojiReact: PropTypes.func,
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -191,7 +193,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
let emojiReactionsBar = null;
|
||||
if (status.get('emoji_reactions')) {
|
||||
const emojiReactions = status.get('emoji_reactions');
|
||||
emojiReactionsBar = <StatusEmojiReactionsBar emojiReactions={emojiReactions} status={status} onEmojiReaction={this.props.onEmojiReaction} OnUnEmojiReaction={this.props.OnUnEmojiReaction} />;
|
||||
emojiReactionsBar = <StatusEmojiReactionsBar emojiReactions={emojiReactions} status={status} onEmojiReact={this.props.onEmojiReact} onUnEmojiReact={this.props.onUnEmojiReact} />;
|
||||
}
|
||||
|
||||
if (status.get('application')) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
pin,
|
||||
unpin,
|
||||
emojiReact,
|
||||
unEmojiReact,
|
||||
} from '../../../actions/interactions';
|
||||
import {
|
||||
muteStatus,
|
||||
|
@ -98,6 +99,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
dispatch(emojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onUnEmojiReact (status, emoji) {
|
||||
dispatch(unEmojiReact(status, emoji));
|
||||
},
|
||||
|
||||
onPin (status) {
|
||||
if (status.get('pinned')) {
|
||||
dispatch(unpin(status));
|
||||
|
|
|
@ -24,6 +24,8 @@ import Column from '../ui/components/column';
|
|||
import {
|
||||
favourite,
|
||||
unfavourite,
|
||||
emojiReact,
|
||||
unEmojiReact,
|
||||
bookmark,
|
||||
unbookmark,
|
||||
reblog,
|
||||
|
@ -254,6 +256,16 @@ class Status extends ImmutablePureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleEmojiReact = (status, emoji) => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(emojiReact(status, emoji));
|
||||
};
|
||||
|
||||
handleUnEmojiReact = (status, emoji) => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(unEmojiReact(status, emoji));
|
||||
};
|
||||
|
||||
handlePin = (status) => {
|
||||
if (status.get('pinned')) {
|
||||
this.props.dispatch(unpin(status));
|
||||
|
@ -644,6 +656,8 @@ class Status extends ImmutablePureComponent {
|
|||
showMedia={this.state.showMedia}
|
||||
onToggleMediaVisibility={this.handleToggleMediaVisibility}
|
||||
pictureInPicture={pictureInPicture}
|
||||
onEmojiReact={this.handleEmojiReact}
|
||||
onUnEmojiReact={this.handleUnEmojiReact}
|
||||
/>
|
||||
|
||||
<ActionBar
|
||||
|
@ -651,6 +665,7 @@ class Status extends ImmutablePureComponent {
|
|||
status={status}
|
||||
onReply={this.handleReplyClick}
|
||||
onFavourite={this.handleFavouriteClick}
|
||||
onEmojiReact={this.handleEmojiReact}
|
||||
onReblog={this.handleReblogClick}
|
||||
onBookmark={this.handleBookmarkClick}
|
||||
onDelete={this.handleDeleteClick}
|
||||
|
|
|
@ -36,6 +36,7 @@ import {
|
|||
Following,
|
||||
Reblogs,
|
||||
Favourites,
|
||||
EmojiReactions,
|
||||
DirectTimeline,
|
||||
HashtagTimeline,
|
||||
Notifications,
|
||||
|
@ -206,6 +207,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/@:acct/:statusId' exact component={Status} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/reblogs' component={Reblogs} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/favourites' component={Favourites} content={children} />
|
||||
<WrappedRoute path='/@:acct/:statusId/emoji_reactions' component={EmojiReactions} content={children} />
|
||||
|
||||
{/* Legacy routes, cannot be easily factored with other routes because they share a param name */}
|
||||
<WrappedRoute path='/timelines/tag/:id' component={HashtagTimeline} content={children} />
|
||||
|
@ -213,6 +215,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/statuses/:statusId' exact component={Status} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/reblogs' component={Reblogs} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/favourites' component={Favourites} content={children} />
|
||||
<WrappedRoute path='/statuses/:statusId/emoji_reactions' component={EmojiReactions} content={children} />
|
||||
|
||||
<WrappedRoute path='/follow_requests' component={FollowRequests} content={children} />
|
||||
<WrappedRoute path='/blocks' component={Blocks} content={children} />
|
||||
|
|
|
@ -78,6 +78,10 @@ export function Favourites () {
|
|||
return import(/* webpackChunkName: "features/favourites" */'../../favourites');
|
||||
}
|
||||
|
||||
export function EmojiReactions () {
|
||||
return import(/* webpackChunkName: "features/favourites" */'../../emoji_reactions');
|
||||
}
|
||||
|
||||
export function FollowRequests () {
|
||||
return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests');
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue