forked from treehouse/mastodon
Refactor notifications cleaning mode
parent
3591621edc
commit
8924743349
|
@ -2,18 +2,14 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import Icon from 'flavours/glitch/components/icon';
|
import Icon from 'flavours/glitch/components/icon';
|
||||||
|
|
||||||
import NotificationPurgeButtonsContainer from 'flavours/glitch/containers/notification_purge_buttons_container';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
||||||
moveLeft: { id: 'column_header.moveLeft_settings', defaultMessage: 'Move column to the left' },
|
moveLeft: { id: 'column_header.moveLeft_settings', defaultMessage: 'Move column to the left' },
|
||||||
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
|
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
|
||||||
enterNotifCleaning : { id: 'notification_purge.start', defaultMessage: 'Enter notification cleaning mode' },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
|
@ -28,27 +24,21 @@ class ColumnHeader extends React.PureComponent {
|
||||||
title: PropTypes.node,
|
title: PropTypes.node,
|
||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
localSettings : ImmutablePropTypes.map,
|
|
||||||
multiColumn: PropTypes.bool,
|
multiColumn: PropTypes.bool,
|
||||||
extraButton: PropTypes.node,
|
extraButton: PropTypes.node,
|
||||||
showBackButton: PropTypes.bool,
|
showBackButton: PropTypes.bool,
|
||||||
notifCleaning: PropTypes.bool, // true only for the notification column
|
|
||||||
notifCleaningActive: PropTypes.bool,
|
|
||||||
onEnterCleaningMode: PropTypes.func,
|
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
pinned: PropTypes.bool,
|
pinned: PropTypes.bool,
|
||||||
placeholder: PropTypes.bool,
|
placeholder: PropTypes.bool,
|
||||||
onPin: PropTypes.func,
|
onPin: PropTypes.func,
|
||||||
onMove: PropTypes.func,
|
onMove: PropTypes.func,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
appendContent: PropTypes.node,
|
appendContent: PropTypes.node,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
collapsed: true,
|
collapsed: true,
|
||||||
animating: false,
|
animating: false,
|
||||||
animatingNCD: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
historyBack = (skip) => {
|
historyBack = (skip) => {
|
||||||
|
@ -90,10 +80,6 @@ class ColumnHeader extends React.PureComponent {
|
||||||
this.setState({ animating: false });
|
this.setState({ animating: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTransitionEndNCD = () => {
|
|
||||||
this.setState({ animatingNCD: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePin = () => {
|
handlePin = () => {
|
||||||
if (!this.props.pinned) {
|
if (!this.props.pinned) {
|
||||||
this.historyBack();
|
this.historyBack();
|
||||||
|
@ -101,16 +87,9 @@ class ColumnHeader extends React.PureComponent {
|
||||||
this.props.onPin();
|
this.props.onPin();
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnterCleaningMode = () => {
|
|
||||||
this.setState({ animatingNCD: true });
|
|
||||||
this.props.onEnterCleaningMode(!this.props.notifCleaningActive);
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, notifCleaning, notifCleaningActive, placeholder, appendContent } = this.props;
|
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent } = this.props;
|
||||||
const { collapsed, animating, animatingNCD } = this.state;
|
const { collapsed, animating } = this.state;
|
||||||
|
|
||||||
let title = this.props.title;
|
|
||||||
|
|
||||||
const wrapperClassName = classNames('column-header__wrapper', {
|
const wrapperClassName = classNames('column-header__wrapper', {
|
||||||
'active': active,
|
'active': active,
|
||||||
|
@ -129,20 +108,8 @@ class ColumnHeader extends React.PureComponent {
|
||||||
'active': !collapsed,
|
'active': !collapsed,
|
||||||
});
|
});
|
||||||
|
|
||||||
const notifCleaningButtonClassName = classNames('column-header__button', {
|
|
||||||
'active': notifCleaningActive,
|
|
||||||
});
|
|
||||||
|
|
||||||
const notifCleaningDrawerClassName = classNames('ncd column-header__collapsible', {
|
|
||||||
'collapsed': !notifCleaningActive,
|
|
||||||
'animating': animatingNCD,
|
|
||||||
});
|
|
||||||
|
|
||||||
let extraContent, pinButton, moveButtons, backButton, collapseButton;
|
let extraContent, pinButton, moveButtons, backButton, collapseButton;
|
||||||
|
|
||||||
//*glitch
|
|
||||||
const msgEnterNotifCleaning = intl.formatMessage(messages.enterNotifCleaning);
|
|
||||||
|
|
||||||
if (children) {
|
if (children) {
|
||||||
extraContent = (
|
extraContent = (
|
||||||
<div key='extra-content' className='column-header__collapsible__extra'>
|
<div key='extra-content' className='column-header__collapsible__extra'>
|
||||||
|
@ -203,28 +170,10 @@ class ColumnHeader extends React.PureComponent {
|
||||||
<div className='column-header__buttons'>
|
<div className='column-header__buttons'>
|
||||||
{hasTitle && backButton}
|
{hasTitle && backButton}
|
||||||
{extraButton}
|
{extraButton}
|
||||||
{ notifCleaning ? (
|
|
||||||
<button
|
|
||||||
aria-label={msgEnterNotifCleaning}
|
|
||||||
title={msgEnterNotifCleaning}
|
|
||||||
onClick={this.onEnterCleaningMode}
|
|
||||||
className={notifCleaningButtonClassName}
|
|
||||||
>
|
|
||||||
<Icon id='eraser' />
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
{collapseButton}
|
{collapseButton}
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{ notifCleaning ? (
|
|
||||||
<div className={notifCleaningDrawerClassName} onTransitionEnd={this.handleTransitionEndNCD}>
|
|
||||||
<div className='column-header__collapsible-inner nopad-drawer'>
|
|
||||||
{(notifCleaningActive || animatingNCD) ? (<NotificationPurgeButtonsContainer />) : null }
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<div className={collapsibleClassName} tabIndex={collapsed ? -1 : null} onTransitionEnd={this.handleTransitionEnd}>
|
<div className={collapsibleClassName} tabIndex={collapsed ? -1 : null} onTransitionEnd={this.handleTransitionEnd}>
|
||||||
<div className='column-header__collapsible-inner'>
|
<div className='column-header__collapsible-inner'>
|
||||||
{(!collapsed || animating) && collapsedContent}
|
{(!collapsed || animating) && collapsedContent}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import Column from 'flavours/glitch/components/column';
|
||||||
|
@ -22,9 +23,13 @@ import { List as ImmutableList } from 'immutable';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
||||||
import LoadGap from 'flavours/glitch/components/load_gap';
|
import LoadGap from 'flavours/glitch/components/load_gap';
|
||||||
|
import Icon from 'flavours/glitch/components/icon';
|
||||||
|
|
||||||
|
import NotificationPurgeButtonsContainer from 'flavours/glitch/containers/notification_purge_buttons_container';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
title: { id: 'column.notifications', defaultMessage: 'Notifications' },
|
||||||
|
enterNotifCleaning : { id: 'notification_purge.start', defaultMessage: 'Enter notification cleaning mode' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const getNotifications = createSelector([
|
const getNotifications = createSelector([
|
||||||
|
@ -94,6 +99,10 @@ class Notifications extends React.PureComponent {
|
||||||
trackScroll: true,
|
trackScroll: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
animatingNCD: false,
|
||||||
|
};
|
||||||
|
|
||||||
handleLoadGap = (maxId) => {
|
handleLoadGap = (maxId) => {
|
||||||
this.props.dispatch(expandNotifications({ maxId }));
|
this.props.dispatch(expandNotifications({ maxId }));
|
||||||
};
|
};
|
||||||
|
@ -176,8 +185,19 @@ class Notifications extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTransitionEndNCD = () => {
|
||||||
|
this.setState({ animatingNCD: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnterCleaningMode = () => {
|
||||||
|
this.setState({ animatingNCD: true });
|
||||||
|
this.props.onEnterCleaningMode(!this.props.notifCleaningActive);
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar } = this.props;
|
const { intl, notifications, shouldUpdateScroll, isLoading, isUnread, columnId, multiColumn, hasMore, numPending, showFilterBar } = this.props;
|
||||||
|
const { notifCleaning, notifCleaningActive } = this.props;
|
||||||
|
const { animatingNCD } = this.state;
|
||||||
const pinned = !!columnId;
|
const pinned = !!columnId;
|
||||||
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />;
|
const emptyMessage = <FormattedMessage id='empty_column.notifications' defaultMessage="You don't have any notifications yet. Interact with others to start the conversation." />;
|
||||||
|
|
||||||
|
@ -232,6 +252,36 @@ class Notifications extends React.PureComponent {
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const notifCleaningButtonClassName = classNames('column-header__button', {
|
||||||
|
'active': notifCleaningActive,
|
||||||
|
});
|
||||||
|
|
||||||
|
const notifCleaningDrawerClassName = classNames('ncd column-header__collapsible', {
|
||||||
|
'collapsed': !notifCleaningActive,
|
||||||
|
'animating': animatingNCD,
|
||||||
|
});
|
||||||
|
|
||||||
|
const msgEnterNotifCleaning = intl.formatMessage(messages.enterNotifCleaning);
|
||||||
|
|
||||||
|
const notifCleaningButton = (
|
||||||
|
<button
|
||||||
|
aria-label={msgEnterNotifCleaning}
|
||||||
|
title={msgEnterNotifCleaning}
|
||||||
|
onClick={this.onEnterCleaningMode}
|
||||||
|
className={notifCleaningButtonClassName}
|
||||||
|
>
|
||||||
|
<Icon id='eraser' />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
|
||||||
|
const notifCleaningDrawer = (
|
||||||
|
<div className={notifCleaningDrawerClassName} onTransitionEnd={this.handleTransitionEndNCD}>
|
||||||
|
<div className='column-header__collapsible-inner nopad-drawer'>
|
||||||
|
{(notifCleaningActive || animatingNCD) ? (<NotificationPurgeButtonsContainer />) : null }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column
|
<Column
|
||||||
bindToDocument={!multiColumn}
|
bindToDocument={!multiColumn}
|
||||||
|
@ -250,9 +300,8 @@ class Notifications extends React.PureComponent {
|
||||||
pinned={pinned}
|
pinned={pinned}
|
||||||
multiColumn={multiColumn}
|
multiColumn={multiColumn}
|
||||||
localSettings={this.props.localSettings}
|
localSettings={this.props.localSettings}
|
||||||
notifCleaning
|
extraButton={notifCleaningButton}
|
||||||
notifCleaningActive={this.props.notifCleaningActive} // this is used to toggle the header text
|
appendContent={notifCleaningDrawer}
|
||||||
onEnterCleaningMode={this.props.onEnterCleaningMode}
|
|
||||||
>
|
>
|
||||||
<ColumnSettingsContainer />
|
<ColumnSettingsContainer />
|
||||||
</ColumnHeader>
|
</ColumnHeader>
|
||||||
|
|
Loading…
Reference in New Issue