diff options
author | Ondřej Hruška <ondra@ondrovo.com> | 2017-07-14 17:03:43 +0200 |
---|---|---|
committer | beatrix <beatrix.bitrot@gmail.com> | 2017-07-14 11:03:43 -0400 |
commit | 75aafc932e42b5dba1030700bb47be0db41b1ab5 (patch) | |
tree | 12c19b09e3ec5e96d71e219ddee0e99e4c2ff7e2 /app/javascript/glitch/components/notification | |
parent | 6ce806f91304937174fb593ea1f343b528fa7cd6 (diff) |
Added buttons and menu items to dismiss individual notifications (#76)
* Added DELETE verb for notifications * Added notification dismiss button to status dropdown * Added reveal-on-hover notif dismiss button, added FollowNotification component
Diffstat (limited to 'app/javascript/glitch/components/notification')
3 files changed, 97 insertions, 21 deletions
diff --git a/app/javascript/glitch/components/notification/container.js b/app/javascript/glitch/components/notification/container.js index c58ef4bd2..60303537d 100644 --- a/app/javascript/glitch/components/notification/container.js +++ b/app/javascript/glitch/components/notification/container.js @@ -6,6 +6,7 @@ import { makeGetNotification } from '../../../mastodon/selectors'; // Our imports // import Notification from '.'; +import { deleteNotification } from '../../../mastodon/actions/notifications'; const makeMapStateToProps = () => { const getNotification = makeGetNotification(); @@ -18,4 +19,10 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export default connect(makeMapStateToProps)(Notification); +const mapDispatchToProps = (dispatch) => ({ + onDeleteNotification (id) { + dispatch(deleteNotification(id)); + }, +}); + +export default connect(makeMapStateToProps, mapDispatchToProps)(Notification); diff --git a/app/javascript/glitch/components/notification/follow_notification.js b/app/javascript/glitch/components/notification/follow_notification.js new file mode 100644 index 000000000..7cabd91f6 --- /dev/null +++ b/app/javascript/glitch/components/notification/follow_notification.js @@ -0,0 +1,78 @@ +// 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> + ); + } + +} diff --git a/app/javascript/glitch/components/notification/index.js b/app/javascript/glitch/components/notification/index.js index 83ac8dfc1..0cdc03cbe 100644 --- a/app/javascript/glitch/components/notification/index.js +++ b/app/javascript/glitch/components/notification/index.js @@ -1,42 +1,30 @@ // Package imports // import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { FormattedMessage } from 'react-intl'; -import escapeTextContentForBrowser from 'escape-html'; import ImmutablePureComponent from 'react-immutable-pure-component'; +import PropTypes from 'prop-types'; // Mastodon imports // -import AccountContainer from '../../../mastodon/containers/account_container'; -import Permalink from '../../../mastodon/components/permalink'; -import emojify from '../../../mastodon/emoji'; // Our imports // import StatusContainer from '../status/container'; +import FollowNotification from './follow_notification'; export default class Notification extends ImmutablePureComponent { static propTypes = { notification: ImmutablePropTypes.map.isRequired, settings: ImmutablePropTypes.map.isRequired, + onDeleteNotification: PropTypes.func.isRequired, }; renderFollow (notification) { - const account = notification.get('account'); - 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 }} /> - </div> - - <AccountContainer id={account.get('id')} withNote={false} /> - </div> + <FollowNotification + notificationId={notification.get('id')} + account={notification.get('account')} + onDeleteNotification={this.props.onDeleteNotification} + /> ); } @@ -44,6 +32,7 @@ export default class Notification extends ImmutablePureComponent { return ( <StatusContainer id={notification.get('status')} + notificationId={notification.get('id')} withDismiss /> ); @@ -56,6 +45,7 @@ export default class Notification extends ImmutablePureComponent { account={notification.get('account')} prepend='favourite' muted + notificationId={notification.get('id')} withDismiss /> ); @@ -68,6 +58,7 @@ export default class Notification extends ImmutablePureComponent { account={notification.get('account')} prepend='reblog' muted + notificationId={notification.get('id')} withDismiss /> ); |