diff options
4 files changed, 148 insertions, 154 deletions
diff --git a/app/javascript/flavours/glitch/features/compose/components/header.js b/app/javascript/flavours/glitch/features/compose/components/header.js new file mode 100644 index 000000000..2e29084f2 --- /dev/null +++ b/app/javascript/flavours/glitch/features/compose/components/header.js @@ -0,0 +1,124 @@ +// Package imports. +import PropTypes from 'prop-types'; +import React from 'react'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { injectIntl, defineMessages } from 'react-intl'; +import { Link } from 'react-router-dom'; +import ImmutablePureComponent from 'react-immutable-pure-component'; + +// Components. +import Icon from 'flavours/glitch/components/icon'; + +// Utils. +import { conditionalRender } from 'flavours/glitch/util/react_helpers'; +import { signOutLink } from 'flavours/glitch/util/backend_links'; + +// Messages. +const messages = defineMessages({ + community: { + defaultMessage: 'Local timeline', + id: 'navigation_bar.community_timeline', + }, + home_timeline: { + defaultMessage: 'Home', + id: 'tabs_bar.home', + }, + logout: { + defaultMessage: 'Logout', + id: 'navigation_bar.logout', + }, + notifications: { + defaultMessage: 'Notifications', + id: 'tabs_bar.notifications', + }, + public: { + defaultMessage: 'Federated timeline', + id: 'navigation_bar.public_timeline', + }, + settings: { + defaultMessage: 'App settings', + id: 'navigation_bar.app_settings', + }, + start: { + defaultMessage: 'Getting started', + id: 'getting_started.heading', + }, +}); + +export default @injectIntl +class Header extends ImmutablePureComponent { + static propTypes = { + columns: ImmutablePropTypes.list, + unreadNotifications: PropTypes.number, + showNotificationsBadge: PropTypes.bool, + intl: PropTypes.object, + onSettingsClick: PropTypes.func, + }; + + render () { + const { intl, columns, unreadNotifications, showNotificationsBadge, onSettingsClick } = this.props; + + // Only renders the component if the column isn't being shown. + const renderForColumn = conditionalRender.bind(null, + columnId => !columns || !columns.some( + column => column.get('id') === columnId + ) + ); + + // The result. + return ( + <nav className='drawer--header'> + <Link + aria-label={intl.formatMessage(messages.start)} + title={intl.formatMessage(messages.start)} + to='/getting-started' + ><Icon icon='asterisk' /></Link> + {renderForColumn('HOME', ( + <Link + aria-label={intl.formatMessage(messages.home_timeline)} + title={intl.formatMessage(messages.home_timeline)} + to='/timelines/home' + ><Icon icon='home' /></Link> + ))} + {renderForColumn('NOTIFICATIONS', ( + <Link + aria-label={intl.formatMessage(messages.notifications)} + title={intl.formatMessage(messages.notifications)} + to='/notifications' + > + <span className='icon-badge-wrapper'> + <Icon icon='bell' /> + { showNotificationsBadge && unreadNotifications > 0 && <div className='icon-badge' />} + </span> + </Link> + ))} + {renderForColumn('COMMUNITY', ( + <Link + aria-label={intl.formatMessage(messages.community)} + title={intl.formatMessage(messages.community)} + to='/timelines/public/local' + ><Icon icon='users' /></Link> + ))} + {renderForColumn('PUBLIC', ( + <Link + aria-label={intl.formatMessage(messages.public)} + title={intl.formatMessage(messages.public)} + to='/timelines/public' + ><Icon icon='globe' /></Link> + ))} + <a + aria-label={intl.formatMessage(messages.settings)} + onClick={onSettingsClick} + href='#' + title={intl.formatMessage(messages.settings)} + ><Icon icon='cogs' /></a> + <a + aria-label={intl.formatMessage(messages.logout)} + data-method='delete' + href={ signOutLink } + title={intl.formatMessage(messages.logout)} + ><Icon icon='sign-out' /></a> + </nav> + ); + }; +} diff --git a/app/javascript/flavours/glitch/features/compose/containers/header_container.js b/app/javascript/flavours/glitch/features/compose/containers/header_container.js new file mode 100644 index 000000000..6f1978807 --- /dev/null +++ b/app/javascript/flavours/glitch/features/compose/containers/header_container.js @@ -0,0 +1,21 @@ +import { openModal } from 'flavours/glitch/actions/modal'; +import { connect } from 'react-redux'; +import Header from '../components/header'; + +const mapStateToProps = state => { + return { + columns: state.getIn(['settings', 'columns']), + unreadNotifications: state.getIn(['notifications', 'unread']), + showNotificationsBadge: state.getIn(['local_settings', 'notifications', 'tab_badge']), + }; +}; + +const mapDispatchToProps = (dispatch, { intl }) => ({ + onOpenSettings (e) { + e.preventDefault(); + e.stopPropagation(); + dispatch(openModal('SETTINGS', {})); + }, +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Header); diff --git a/app/javascript/flavours/glitch/features/compose/header/index.js b/app/javascript/flavours/glitch/features/compose/header/index.js deleted file mode 100644 index da5599732..000000000 --- a/app/javascript/flavours/glitch/features/compose/header/index.js +++ /dev/null @@ -1,127 +0,0 @@ -// Package imports. -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages } from 'react-intl'; -import { Link } from 'react-router-dom'; - -// Components. -import Icon from 'flavours/glitch/components/icon'; - -// Utils. -import { conditionalRender } from 'flavours/glitch/util/react_helpers'; -import { signOutLink } from 'flavours/glitch/util/backend_links'; - -// Messages. -const messages = defineMessages({ - community: { - defaultMessage: 'Local timeline', - id: 'navigation_bar.community_timeline', - }, - home_timeline: { - defaultMessage: 'Home', - id: 'tabs_bar.home', - }, - logout: { - defaultMessage: 'Logout', - id: 'navigation_bar.logout', - }, - notifications: { - defaultMessage: 'Notifications', - id: 'tabs_bar.notifications', - }, - public: { - defaultMessage: 'Federated timeline', - id: 'navigation_bar.public_timeline', - }, - settings: { - defaultMessage: 'App settings', - id: 'navigation_bar.app_settings', - }, - start: { - defaultMessage: 'Getting started', - id: 'getting_started.heading', - }, -}); - -// The component. -export default function DrawerHeader ({ - columns, - unreadNotifications, - showNotificationsBadge, - intl, - onSettingsClick, -}) { - - // Only renders the component if the column isn't being shown. - const renderForColumn = conditionalRender.bind(null, - columnId => !columns || !columns.some( - column => column.get('id') === columnId - ) - ); - - // The result. - return ( - <nav className='drawer--header'> - <Link - aria-label={intl.formatMessage(messages.start)} - title={intl.formatMessage(messages.start)} - to='/getting-started' - ><Icon icon='asterisk' /></Link> - {renderForColumn('HOME', ( - <Link - aria-label={intl.formatMessage(messages.home_timeline)} - title={intl.formatMessage(messages.home_timeline)} - to='/timelines/home' - ><Icon icon='home' /></Link> - ))} - {renderForColumn('NOTIFICATIONS', ( - <Link - aria-label={intl.formatMessage(messages.notifications)} - title={intl.formatMessage(messages.notifications)} - to='/notifications' - > - <span className='icon-badge-wrapper'> - <Icon icon='bell' /> - { showNotificationsBadge && unreadNotifications > 0 && <div className='icon-badge' />} - </span> - </Link> - ))} - {renderForColumn('COMMUNITY', ( - <Link - aria-label={intl.formatMessage(messages.community)} - title={intl.formatMessage(messages.community)} - to='/timelines/public/local' - ><Icon icon='users' /></Link> - ))} - {renderForColumn('PUBLIC', ( - <Link - aria-label={intl.formatMessage(messages.public)} - title={intl.formatMessage(messages.public)} - to='/timelines/public' - ><Icon icon='globe' /></Link> - ))} - <a - aria-label={intl.formatMessage(messages.settings)} - onClick={onSettingsClick} - href='#' - title={intl.formatMessage(messages.settings)} - ><Icon icon='cogs' /></a> - <a - aria-label={intl.formatMessage(messages.logout)} - data-method='delete' - href={ signOutLink } - title={intl.formatMessage(messages.logout)} - ><Icon icon='sign-out' /></a> - </nav> - ); -} - -// Props. -DrawerHeader.propTypes = { - columns: ImmutablePropTypes.list, - unreadNotifications: PropTypes.number, - showNotificationsBadge: PropTypes.bool, - intl: PropTypes.object, - onSettingsClick: PropTypes.func, -}; diff --git a/app/javascript/flavours/glitch/features/compose/index.js b/app/javascript/flavours/glitch/features/compose/index.js index 9fe510028..923d379ec 100644 --- a/app/javascript/flavours/glitch/features/compose/index.js +++ b/app/javascript/flavours/glitch/features/compose/index.js @@ -7,12 +7,11 @@ import { injectIntl, defineMessages } from 'react-intl'; import classNames from 'classnames'; // Actions. -import { openModal } from 'flavours/glitch/actions/modal'; import { cycleElefriendCompose } from 'flavours/glitch/actions/compose'; // Components. import Composer from 'flavours/glitch/features/composer'; -import DrawerHeader from './header'; +import HeaderContainer from './containers/header_container'; import SearchContainer from './containers/search_container'; import SearchResultsContainer from './containers/search_results_container'; import NavigationContainer from './containers/navigation_container'; @@ -29,11 +28,8 @@ const messages = defineMessages({ // State mapping. const mapStateToProps = (state, ownProps) => ({ - columns: state.getIn(['settings', 'columns']), elefriend: state.getIn(['compose', 'elefriend']), showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage, - unreadNotifications: state.getIn(['notifications', 'unread']), - showNotificationsBadge: state.getIn(['local_settings', 'notifications', 'tab_badge']), }); // Dispatch mapping. @@ -41,11 +37,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ onClickElefriend () { dispatch(cycleElefriendCompose()); }, - onOpenSettings (e) { - e.preventDefault(); - e.stopPropagation(); - dispatch(openModal('SETTINGS', {})); - }, }); // The component. @@ -59,28 +50,21 @@ class Compose extends React.PureComponent { showSearch: PropTypes.bool, // State props. - columns: ImmutablePropTypes.list, elefriend: PropTypes.number, unreadNotifications: PropTypes.number, - showNotificationsBadge: PropTypes.bool, // Dispatch props. onClickElefriend: PropTypes.func, - onOpenSettings: PropTypes.func, }; // Rendering. render () { const { - columns, elefriend, intl, multiColumn, onClickElefriend, - onOpenSettings, isSearchPage, - unreadNotifications, - showNotificationsBadge, showSearch, } = this.props; const computedClass = classNames('drawer', `mbstobon-${elefriend}`); @@ -88,16 +72,8 @@ class Compose extends React.PureComponent { // The result. return ( <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}> - {multiColumn && ( - <DrawerHeader - columns={columns} - unreadNotifications={unreadNotifications} - showNotificationsBadge={showNotificationsBadge} - intl={intl} - onSettingsClick={onOpenSettings} - /> - )} - {(multiColumn || isSearchPage) && <SearchContainer /> } + {multiColumn && <HeaderContainer />} + {(multiColumn || isSearchPage) && <SearchContainer />} <div className='drawer__pager'> {!isSearchPage && <div className='drawer__inner'> <NavigationContainer /> |