Documentation and cleanup

This commit is contained in:
kibigo!
2017-07-14 11:13:02 -07:00
parent 21b04af524
commit d0aad1ac85
11 changed files with 705 additions and 189 deletions

View File

@@ -1,3 +1,21 @@
/*
`<NotificationContainer>`
=========================
This container connects `<Notification>`s to the Redux store.
*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/*
Imports:
--------
*/
// Package imports //
import { connect } from 'react-redux';
@@ -8,6 +26,20 @@ import { makeGetNotification } from '../../../mastodon/selectors';
import Notification from '.';
import { deleteNotification } from '../../../mastodon/actions/notifications';
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/*
State mapping:
--------------
The `mapStateToProps()` function maps various state properties to the
props of our component. We wrap this in `makeMapStateToProps()` so that
we only have to call `makeGetNotification()` once instead of every
time.
*/
const makeMapStateToProps = () => {
const getNotification = makeGetNotification();
@@ -19,7 +51,20 @@ const makeMapStateToProps = () => {
return mapStateToProps;
};
const mapDispatchToProps = (dispatch) => ({
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/*
Dispatch mapping:
-----------------
The `mapDispatchToProps()` function maps dispatches to our store to the
various props of our component. We only need to provide a dispatch for
deleting notifications.
*/
const mapDispatchToProps = dispatch => ({
onDeleteNotification (id) {
dispatch(deleteNotification(id));
},

View File

@@ -0,0 +1,171 @@
/*
`<NotificationFollow>`
======================
This component renders a follow notification.
__Props:__
- __`id` (`PropTypes.number.isRequired`) :__
This is the id of the notification.
- __`onDeleteNotification` (`PropTypes.func.isRequired`) :__
The function to call when a notification should be
dismissed/deleted.
- __`account` (`PropTypes.object.isRequired`) :__
The account associated with the follow notification, ie the account
which followed the user.
- __`intl` (`PropTypes.object.isRequired`) :__
Our internationalization object, inserted by `@injectIntl`.
*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/*
Imports:
--------
*/
// Package imports //
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import escapeTextContentForBrowser from 'escape-html';
import ImmutablePureComponent from 'react-immutable-pure-component';
// Mastodon imports //
import emojify from '../../../mastodon/emoji';
import Permalink from '../../../mastodon/components/permalink';
import AccountContainer from '../../../mastodon/containers/account_container';
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
/*
Inital setup:
-------------
The `messages` constant is used to define any messages that we need
from inside props.
*/
const messages = defineMessages({
deleteNotification :
{ id: 'status.dismiss_notification', defaultMessage: 'Dismiss notification' },
});
/*
Implementation:
---------------
*/
@injectIntl
export default class NotificationFollow extends ImmutablePureComponent {
static propTypes = {
id : PropTypes.number.isRequired,
onDeleteNotification : PropTypes.func.isRequired,
account : ImmutablePropTypes.map.isRequired,
intl : PropTypes.object.isRequired,
};
/*
### `handleNotificationDeleteClick()`
This function just calls our `onDeleteNotification()` prop with the
notification's `id`.
*/
handleNotificationDeleteClick = () => {
this.props.onDeleteNotification(this.props.id);
}
/*
### `render()`
This actually renders the component.
*/
render () {
const { account, intl } = this.props;
/*
`dismiss` creates the notification dismissal button. Its title is given
by `dismissTitle`.
*/
const dismissTitle = intl.formatMessage(messages.deleteNotification);
const dismiss = (
<button
aria-label={dismissTitle}
title={dismissTitle}
onClick={this.handleNotificationDeleteClick}
className='status__prepend-dismiss-button'
>
<i className='fa fa-eraser' />
</button>
);
/*
`link` is a container for the account's `displayName`, which links to
the account timeline using a `<Permalink>`.
*/
const displayName = account.get('display_name') || account.get('username');
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
const link = (
<Permalink
className='notification__display-name'
href={account.get('url')}
title={account.get('acct')}
to={`/accounts/${account.get('id')}`}
dangerouslySetInnerHTML={displayNameHTML}
/>
);
/*
We can now render our component.
*/
return (
<div className='notification notification-follow'>
<div className='notification__message'>
<div className='notification__favourite-icon-wrapper'>
<i className='fa fa-fw fa-user-plus' />
</div>
<FormattedMessage
id='notification.follow'
defaultMessage='{name} followed you'
values={{ name: link }}
/>
{dismiss}
</div>
<AccountContainer id={account.get('id')} withNote={false} />
</div>
);
}
}

View File

@@ -1,78 +0,0 @@
// Package imports //
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import escapeTextContentForBrowser from 'escape-html';
import ImmutablePureComponent from 'react-immutable-pure-component';
// Mastodon imports //
import emojify from '../../../mastodon/emoji';
import Permalink from '../../../mastodon/components/permalink';
import AccountContainer from '../../../mastodon/containers/account_container';
const messages = defineMessages({
deleteNotification: { id: 'status.dismiss_notification', defaultMessage: 'Dismiss notification' },
});
@injectIntl
export default class FollowNotification extends ImmutablePureComponent {
static contextTypes = {
router: PropTypes.object,
};
static propTypes = {
notificationId: PropTypes.number.isRequired,
onDeleteNotification: PropTypes.func.isRequired,
account: ImmutablePropTypes.map.isRequired,
intl: PropTypes.object.isRequired,
};
// Avoid checking props that are functions (and whose equality will always
// evaluate to false. See react-immutable-pure-component for usage.
updateOnProps = [
'account',
]
handleNotificationDeleteClick = () => {
this.props.onDeleteNotification(this.props.notificationId);
}
render () {
const { account, intl } = this.props;
const dismissTitle = intl.formatMessage(messages.deleteNotification);
const dismiss = (
<button
aria-label={dismissTitle}
title={dismissTitle}
onClick={this.handleNotificationDeleteClick}
className='status__prepend-dismiss-button'
>
<i className='fa fa-eraser' />
</button>
);
const displayName = account.get('display_name').length > 0 ? account.get('display_name') : account.get('username');
const displayNameHTML = { __html: emojify(escapeTextContentForBrowser(displayName)) };
const link = <Permalink className='notification__display-name' href={account.get('url')} title={account.get('acct')} to={`/accounts/${account.get('id')}`} dangerouslySetInnerHTML={displayNameHTML} />;
return (
<div className='notification notification-follow'>
<div className='notification__message'>
<div className='notification__favourite-icon-wrapper'>
<i className='fa fa-fw fa-user-plus' />
</div>
<FormattedMessage id='notification.follow' defaultMessage='{name} followed you' values={{ name: link }} />
{dismiss}
</div>
<AccountContainer id={account.get('id')} withNote={false} />
</div>
);
}
}

View File

@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
// Our imports //
import StatusContainer from '../status/container';
import FollowNotification from './follow_notification';
import NotificationFollow from './follow';
export default class Notification extends ImmutablePureComponent {
@@ -20,8 +20,8 @@ export default class Notification extends ImmutablePureComponent {
renderFollow (notification) {
return (
<FollowNotification
notificationId={notification.get('id')}
<NotificationFollow
id={notification.get('id')}
account={notification.get('account')}
onDeleteNotification={this.props.onDeleteNotification}
/>