/* eslint jsx-a11y/tabindex-no-positive: 0 */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Menu, RetinaImg, LabelColorizer, BoldedSearchResult } from 'nylas-component-kit'; import { Utils, Actions, TaskQueue, Label, SyncbackCategoryTask, ChangeLabelsTask, } from 'mailspring-exports'; import { Categories } from 'nylas-observables'; export default class LabelPickerPopover extends Component { static propTypes = { threads: PropTypes.array.isRequired, account: PropTypes.object.isRequired, }; constructor(props) { super(props); this._labels = []; this.state = this._recalculateState(this.props, { searchValue: '' }); } componentDidMount() { this._registerObservables(); } componentWillReceiveProps(nextProps) { this._registerObservables(nextProps); this.setState(this._recalculateState(nextProps)); } componentWillUnmount() { this._unregisterObservables(); } _registerObservables = (props = this.props) => { this._unregisterObservables(); this.disposables = [ Categories.forAccount(props.account) .sort() .subscribe(this._onLabelsChanged), ]; }; _unregisterObservables = () => { if (this.disposables) { this.disposables.forEach(disp => disp.dispose()); } }; _recalculateState = (props = this.props, { searchValue = this.state.searchValue || '' } = {}) => { const { threads } = props; if (threads.length === 0) { return { categoryData: [], searchValue }; } const categoryData = this._labels .filter(label => Utils.wordSearchRegExp(searchValue).test(label.displayName)) .map(label => { return { id: label.id, category: label, displayName: label.displayName, backgroundColor: LabelColorizer.backgroundColorDark(label), usage: threads.filter(t => t.categories.find(c => c.id === label.id)).length, numThreads: threads.length, }; }); if (searchValue.length > 0) { categoryData.push({ searchValue: searchValue, newCategoryItem: true, id: 'category-create-new', }); } return { categoryData, searchValue }; }; _onLabelsChanged = categories => { this._labels = categories.filter(c => { return c instanceof Label && !c.role; }); this.setState(this._recalculateState()); }; _onEscape = () => { Actions.closePopover(); }; _onSelectLabel = item => { const { account, threads } = this.props; if (threads.length === 0) return; if (item.newCategoryItem) { const syncbackTask = new SyncbackCategoryTask({ path: this.state.searchValue, accountId: account.id, }); TaskQueue.waitForPerformRemote(syncbackTask).then(finishedTask => { if (!finishedTask.created) { AppEnv.showErrorDialog({ title: 'Error', message: `Could not create label.` }); return; } Actions.queueTask( new ChangeLabelsTask({ source: 'Category Picker: New Category', threads: threads, labelsToRemove: [], labelsToAdd: [finishedTask.created], }) ); }); Actions.queueTask(syncbackTask); } else if (item.usage === threads.length) { Actions.queueTask( new ChangeLabelsTask({ source: 'Category Picker: Existing Category', threads: threads, labelsToRemove: [item.category], labelsToAdd: [], }) ); } else { Actions.queueTask( new ChangeLabelsTask({ source: 'Category Picker: Existing Category', threads: threads, labelsToRemove: [], labelsToAdd: [item.category], }) ); } Actions.closePopover(); }; _onSearchValueChange = event => { this.setState(this._recalculateState(this.props, { searchValue: event.target.value })); }; _renderCheckbox = item => { const styles = {}; let checkStatus; styles.backgroundColor = item.backgroundColor; if (item.usage === 0) { checkStatus = ; } else if (item.usage < item.numThreads) { checkStatus = ( this._onSelectLabel(item)} /> ); } else { checkStatus = ( this._onSelectLabel(item)} /> ); } return (
this._onSelectLabel(item)} /> {checkStatus}
); }; _renderCreateNewItem = ({ searchValue }) => { return (
“{searchValue}” (create new)
); }; _renderItem = item => { if (item.divider) { return ; } else if (item.newCategoryItem) { return this._renderCreateNewItem(item); } return (
{this._renderCheckbox(item)}
); }; render() { const headerComponents = [ , ]; return (
item.id} itemContent={this._renderItem} onSelect={this._onSelectLabel} onEscape={this._onEscape} defaultSelectedIndex={this.state.searchValue === '' ? -1 : 0} />
); } }