WIP <Compose> Refactor; <Drawer> ed.

This commit is contained in:
kibigo!
2017-12-26 16:54:28 -08:00
parent 924ffe81d4
commit 3c29f57404
18 changed files with 723 additions and 455 deletions

View File

@@ -2,197 +2,147 @@
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { injectIntl, defineMessages } from 'react-intl';
import spring from 'react-motion/lib/spring';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
// Actions.
import { changeComposing } from 'flavours/glitch/actions/compose';
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
import { openModal } from 'flavours/glitch/actions/modal';
import {
changeSearch,
clearSearch,
showSearch,
submitSearch,
} from 'flavours/glitch/actions/search';
// Components.
import Icon from 'flavours/glitch/components/icon';
import Compose from 'flavours/glitch/features/compose';
import NavigationContainer from './containers/navigation_container';
import SearchContainer from './containers/search_container';
import SearchResultsContainer from './containers/search_results_container';
import DrawerHeader from './header';
import DrawerPager from './pager';
import DrawerResults from './results';
import DrawerSearch from './search';
// Utils.
import Motion from 'flavours/glitch/util/optional_motion';
import {
assignHandlers,
conditionalRender,
} from 'flavours/glitch/util/react_helpers';
// 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',
},
});
import { me } from 'flavours/glitch/util/initial_state';
import { wrap } from 'flavours/glitch/util/redux_helpers';
// State mapping.
const mapStateToProps = state => ({
account: state.getIn(['accounts', me]),
columns: state.getIn(['settings', 'columns']),
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
isComposing: state.getIn(['compose', 'is_composing']),
results: state.getIn(['search', 'results']),
searchHidden: state.getIn(['search', 'hidden']),
searchValue: state.getIn(['search', 'value']),
submitted: state.getIn(['search', 'submitted']),
});
// Dispatch mapping.
const mapDispatchToProps = dispatch => ({
onBlur () {
change (value) {
dispatch(changeSearch(value));
},
changeComposingOff () {
dispatch(changeComposing(false));
},
onFocus () {
changeComposingOn () {
dispatch(changeComposing(true));
},
onSettingsOpen () {
clear () {
dispatch(clearSearch());
},
show () {
dispatch(showSearch());
},
submit () {
dispatch(submitSearch());
},
openSettings () {
dispatch(openModal('SETTINGS', {}));
},
});
// The component.
@connect(mapStateToProps, mapDispatchToProps)
@injectIntl
export default function Drawer ({
columns,
intl,
multiColumn,
onBlur,
onFocus,
onSettingsOpen,
showSearch,
}) {
class Drawer extends React.Component {
// Only renders the component if the column isn't being shown.
const renderForColumn = conditionalRender.bind(
columnId => !columns.some(column => column.get('id') === columnId)
);
// Constructor.
constructor (props) {
super(props);
}
// The result.
return (
<div className='drawer'>
{multiColumn ? (
<nav className='drawer__header'>
<Link
aria-label={intl.formatMessage(messages.start)}
className='drawer__tab'
title={intl.formatMessage(messages.start)}
to='/getting-started'
><Icon icon='asterisk' /></Link>
{renderForColumn('HOME', (
<Link
aria-label={intl.formatMessage(messages.home_timeline)}
className='drawer__tab'
title={intl.formatMessage(messages.home_timeline)}
to='/timelines/home'
><Icon icon='home' /></Link>
))}
{renderForColumn('NOTIFICATIONS', (
<Link
aria-label={intl.formatMessage(messages.notifications)}
className='drawer__tab'
title={intl.formatMessage(messages.notifications)}
to='/notifications'
><Icon icon='bell' /></Link>
))}
{renderForColumn('COMMUNITY', (
<Link
aria-label={intl.formatMessage(messages.community)}
className='drawer__tab'
title={intl.formatMessage(messages.community)}
to='/timelines/public/local'
><Icon icon='users' /></Link>
))}
{renderForColumn('PUBLIC', (
<Link
aria-label={intl.formatMessage(messages.public)}
className='drawer__tab'
title={intl.formatMessage(messages.public)}
to='/timelines/public'
><Icon icon='globe' /></Link>
))}
<a
aria-label={intl.formatMessage(messages.settings)}
className='drawer__tab'
onClick={settings}
role='button'
title={intl.formatMessage(messages.settings)}
tabIndex='0'
><Icon icon='cogs' /></a>
<a
aria-label={intl.formatMessage(messages.logout)}
className='drawer__tab'
data-method='delete'
href='/auth/sign_out'
title={intl.formatMessage(messages.logout)}
><Icon icon='sign-out' /></a>
</nav>
) : null}
<SearchContainer />
<div className='drawer__pager'>
<div
className='drawer__inner scrollable optionally-scrollable'
onFocus={focus}
>
<NavigationContainer onClose={blur} />
<Compose />
</div>
<Motion
defaultStyle={{ x: -100 }}
style={{
x: spring(showSearch ? 0 : -100, {
stiffness: 210,
damping: 20,
})
}}
>
{({ x }) => (
<div
className='drawer__inner darker scrollable optionally-scrollable'
style={{
transform: `translateX(${x}%)`,
visibility: x === -100 ? 'hidden' : 'visible'
}}
><SearchResultsContainer /></div>
)}
</Motion>
// Rendering.
render () {
const {
dispatch: {
change,
changeComposingOff,
changeComposingOn,
clear,
openSettings,
show,
submit,
},
intl,
multiColumn,
state: {
account,
columns,
isComposing,
results,
searchHidden,
searchValue,
submitted,
},
} = this.props;
// The result.
return (
<div className='drawer'>
{multiColumn ? (
<DrawerHeader
columns={columns}
intl={intl}
onSettingsClick={openSettings}
/>
) : null}
<DrawerSearch
intl={intl}
onChange={change}
onClear={clear}
onShow={show}
onSubmit={submit}
submitted={submitted}
value={searchValue}
/>
<DrawerPager
account={account}
active={isComposing}
onBlur={changeComposingOff}
onFocus={changeComposingOn}
/>
<DrawerResults
results={results}
visible={submitted && !searchHidden}
/>
</div>
</div>
);
);
}
}
// Props.
Drawer.propTypes = {
dispatch: PropTypes.func.isRequired,
columns: ImmutablePropTypes.list.isRequired,
multiColumn: PropTypes.bool,
showSearch: PropTypes.bool,
intl: PropTypes.object.isRequired,
multiColumn: PropTypes.bool,
state: PropTypes.shape({
account: ImmutablePropTypes.map,
columns: ImmutablePropTypes.list,
isComposing: PropTypes.bool,
results: ImmutablePropTypes.map,
searchHidden: PropTypes.bool,
searchValue: PropTypes.string,
submitted: PropTypes.bool,
}).isRequired,
};
// Connecting and export.
export { Drawer as WrappedComponent };
export default wrap(Drawer, mapStateToProps, mapDispatchToProps, true);