fix(dropdown_menu): Open as modal on mobile (#4295)

* fix(dropdown_menu): Open as modal on mobile

* fix(dropdown_menu): Open modal on touch

* fix(dropdown_menu): Show status

* fix(dropdown_menu): Max dimensions and reduce padding

* chore(dropdown_menu): Test new functionality

* refactor: Use DropdownMenuContainer instead of DropdownMenu

* feat(privacy_dropdown): Open as modal on touch devices

* feat(modal_root): Do not load actions-modal async
This commit is contained in:
Sorin Davidoi
2017-07-27 22:31:59 +02:00
committed by Eugen Rochko
parent aa803153e2
commit 50d38d7605
12 changed files with 276 additions and 40 deletions

View File

@ -24,6 +24,10 @@ const iconStyle = {
export default class PrivacyDropdown extends React.PureComponent {
static propTypes = {
isUserTouching: PropTypes.func,
isModalOpen: PropTypes.bool.isRequired,
onModalOpen: PropTypes.func,
onModalClose: PropTypes.func,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
@ -34,7 +38,25 @@ export default class PrivacyDropdown extends React.PureComponent {
};
handleToggle = () => {
this.setState({ open: !this.state.open });
if (this.props.isUserTouching()) {
if (this.state.open) {
this.props.onModalClose();
} else {
this.props.onModalOpen({
actions: this.options.map(option => ({ ...option, active: option.value === this.props.value })),
onClick: this.handleModalActionClick,
});
}
} else {
this.setState({ open: !this.state.open });
}
}
handleModalActionClick = (e) => {
e.preventDefault();
const { value } = this.options[e.currentTarget.getAttribute('data-index')];
this.props.onModalClose();
this.props.onChange(value);
}
handleClick = (e) => {
@ -50,6 +72,17 @@ export default class PrivacyDropdown extends React.PureComponent {
}
}
componentWillMount () {
const { intl: { formatMessage } } = this.props;
this.options = [
{ icon: 'globe', value: 'public', text: formatMessage(messages.public_short), meta: formatMessage(messages.public_long) },
{ icon: 'unlock-alt', value: 'unlisted', text: formatMessage(messages.unlisted_short), meta: formatMessage(messages.unlisted_long) },
{ icon: 'lock', value: 'private', text: formatMessage(messages.private_short), meta: formatMessage(messages.private_long) },
{ icon: 'envelope', value: 'direct', text: formatMessage(messages.direct_short), meta: formatMessage(messages.direct_long) },
];
}
componentDidMount () {
window.addEventListener('click', this.onGlobalClick);
window.addEventListener('touchstart', this.onGlobalClick);
@ -68,25 +101,18 @@ export default class PrivacyDropdown extends React.PureComponent {
const { value, intl } = this.props;
const { open } = this.state;
const options = [
{ icon: 'globe', value: 'public', shortText: intl.formatMessage(messages.public_short), longText: intl.formatMessage(messages.public_long) },
{ icon: 'unlock-alt', value: 'unlisted', shortText: intl.formatMessage(messages.unlisted_short), longText: intl.formatMessage(messages.unlisted_long) },
{ icon: 'lock', value: 'private', shortText: intl.formatMessage(messages.private_short), longText: intl.formatMessage(messages.private_long) },
{ icon: 'envelope', value: 'direct', shortText: intl.formatMessage(messages.direct_short), longText: intl.formatMessage(messages.direct_long) },
];
const valueOption = options.find(item => item.value === value);
const valueOption = this.options.find(item => item.value === value);
return (
<div ref={this.setRef} className={`privacy-dropdown ${open ? 'active' : ''}`}>
<div className='privacy-dropdown__value'><IconButton className='privacy-dropdown__value-icon' icon={valueOption.icon} title={intl.formatMessage(messages.change_privacy)} size={18} active={open} inverted onClick={this.handleToggle} style={iconStyle} /></div>
<div className='privacy-dropdown__dropdown'>
{open && options.map(item =>
{open && this.options.map(item =>
<div role='button' tabIndex='0' key={item.value} data-index={item.value} onClick={this.handleClick} className={`privacy-dropdown__option ${item.value === value ? 'active' : ''}`}>
<div className='privacy-dropdown__option__icon'><i className={`fa fa-fw fa-${item.icon}`} /></div>
<div className='privacy-dropdown__option__content'>
<strong>{item.shortText}</strong>
{item.longText}
<strong>{item.text}</strong>
{item.meta}
</div>
</div>
)}

View File

@ -1,8 +1,11 @@
import { connect } from 'react-redux';
import PrivacyDropdown from '../components/privacy_dropdown';
import { changeComposeVisibility } from '../../../actions/compose';
import { openModal, closeModal } from '../../../actions/modal';
import { isUserTouching } from '../../../is_mobile';
const mapStateToProps = state => ({
isModalOpen: state.get('modal').modalType === 'ACTIONS',
value: state.getIn(['compose', 'privacy']),
});
@ -12,6 +15,10 @@ const mapDispatchToProps = dispatch => ({
dispatch(changeComposeVisibility(value));
},
isUserTouching,
onModalOpen: props => dispatch(openModal('ACTIONS', props)),
onModalClose: () => dispatch(closeModal()),
});
export default connect(mapStateToProps, mapDispatchToProps)(PrivacyDropdown);