diff --git a/app/internal_packages/category-picker/lib/label-picker.jsx b/app/internal_packages/category-picker/lib/label-picker.jsx
deleted file mode 100644
index 4af13691f..000000000
--- a/app/internal_packages/category-picker/lib/label-picker.jsx
+++ /dev/null
@@ -1,83 +0,0 @@
-const { Actions, AccountStore, React, PropTypes, WorkspaceStore } = require('mailspring-exports');
-const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
-
-const LabelPickerPopover = require('./label-picker-popover').default;
-
-// This changes the category on one or more threads.
-class LabelPicker extends React.Component {
- static displayName = 'LabelPicker';
- static containerRequired = false;
- static propTypes = { items: PropTypes.array };
- static contextTypes = { sheetDepth: PropTypes.number };
-
- constructor(props) {
- super(props);
- this._account = AccountStore.accountForItems(this.props.items);
- }
-
- // If the threads we're picking categories for change, (like when they
- // get their categories updated), we expect our parents to pass us new
- // props. We don't listen to the DatabaseStore ourselves.
- componentWillReceiveProps(nextProps) {
- return (this._account = AccountStore.accountForItems(nextProps.items));
- }
-
- _keymapHandlers() {
- return { 'core:change-labels': this._onOpenCategoryPopover };
- }
-
- _onOpenCategoryPopover = () => {
- if (!(this.props.items.length > 0)) {
- return;
- }
- if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
- return;
- }
- const buttonRect = this._buttonEl.getBoundingClientRect();
- Actions.openPopover(, {
- originRect: buttonRect,
- direction: 'down',
- });
- };
-
- render() {
- if (!this._account) {
- return ;
- }
- if (!this._account.usesLabels()) {
- return ;
- }
- const btnClasses = 'btn btn-toolbar btn-category-picker';
-
- return (
-
-
-
- );
- }
-}
-
-module.exports = LabelPicker;
diff --git a/app/internal_packages/category-picker/lib/main.jsx b/app/internal_packages/category-picker/lib/main.jsx
index 200c24d24..99f360293 100644
--- a/app/internal_packages/category-picker/lib/main.jsx
+++ b/app/internal_packages/category-picker/lib/main.jsx
@@ -1,17 +1,12 @@
-const MovePicker = require('./move-picker');
-const LabelPicker = require('./label-picker');
-
+const ToolbarCategoryPicker = require('./toolbar-category-picker');
const { ComponentRegistry } = require('mailspring-exports');
module.exports = {
- activate(state = {}) {
- this.state = state;
- ComponentRegistry.register(MovePicker, { role: 'ThreadActionsToolbarButton' });
- ComponentRegistry.register(LabelPicker, { role: 'ThreadActionsToolbarButton' });
+ activate() {
+ ComponentRegistry.register(ToolbarCategoryPicker, { role: 'ThreadActionsToolbarButton' });
},
deactivate() {
- ComponentRegistry.unregister(MovePicker);
- ComponentRegistry.unregister(LabelPicker);
+ ComponentRegistry.unregister(ToolbarCategoryPicker);
},
};
diff --git a/app/internal_packages/category-picker/lib/move-picker.jsx b/app/internal_packages/category-picker/lib/move-picker.jsx
deleted file mode 100644
index c895a454a..000000000
--- a/app/internal_packages/category-picker/lib/move-picker.jsx
+++ /dev/null
@@ -1,82 +0,0 @@
-const { Actions, React, PropTypes, AccountStore, WorkspaceStore } = require('mailspring-exports');
-const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
-
-const MovePickerPopover = require('./move-picker-popover').default;
-
-// This sets the folder / label on one or more threads.
-class MovePicker extends React.Component {
- static displayName = 'MovePicker';
- static containerRequired = false;
-
- static propTypes = { items: PropTypes.array };
- static contextTypes = { sheetDepth: PropTypes.number };
-
- constructor(props) {
- super(props);
-
- this._account = AccountStore.accountForItems(this.props.items);
- }
-
- // If the threads we're picking categories for change, (like when they
- // get their categories updated), we expect our parents to pass us new
- // props. We don't listen to the DatabaseStore ourselves.
- componentWillReceiveProps(nextProps) {
- this._account = AccountStore.accountForItems(nextProps.items);
- }
-
- _keymapHandlers() {
- return { 'core:change-folders': this._onOpenCategoryPopover };
- }
-
- _onOpenCategoryPopover = () => {
- if (!(this.props.items.length > 0)) {
- return;
- }
- if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
- return;
- }
- const buttonRect = this._buttonEl.getBoundingClientRect();
- Actions.openPopover(, {
- originRect: buttonRect,
- direction: 'down',
- });
- };
-
- render() {
- if (!this._account) {
- return ;
- }
- const btnClasses = 'btn btn-toolbar btn-category-picker';
-
- return (
-
-
-
- );
- }
-}
-
-module.exports = MovePicker;
diff --git a/app/internal_packages/category-picker/lib/toolbar-category-picker.jsx b/app/internal_packages/category-picker/lib/toolbar-category-picker.jsx
new file mode 100644
index 000000000..436820e1c
--- /dev/null
+++ b/app/internal_packages/category-picker/lib/toolbar-category-picker.jsx
@@ -0,0 +1,114 @@
+const { Actions, React, PropTypes, AccountStore, WorkspaceStore } = require('mailspring-exports');
+const { RetinaImg, KeyCommandsRegion } = require('mailspring-component-kit');
+
+const MovePickerPopover = require('./move-picker-popover').default;
+const LabelPickerPopover = require('./label-picker-popover').default;
+
+// This sets the folder / label on one or more threads.
+class MovePicker extends React.Component {
+ static displayName = 'MovePicker';
+ static containerRequired = false;
+
+ static propTypes = { items: PropTypes.array };
+ static contextTypes = { sheetDepth: PropTypes.number };
+
+ constructor(props) {
+ super(props);
+
+ this._account = AccountStore.accountForItems(this.props.items);
+ }
+
+ // If the threads we're picking categories for change, (like when they
+ // get their categories updated), we expect our parents to pass us new
+ // props. We don't listen to the DatabaseStore ourselves.
+ componentWillReceiveProps(nextProps) {
+ this._account = AccountStore.accountForItems(nextProps.items);
+ }
+
+ _onOpenLabelsPopover = () => {
+ if (!(this.props.items.length > 0)) {
+ return;
+ }
+ if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
+ return;
+ }
+ Actions.openPopover(, {
+ originRect: this._labelEl.getBoundingClientRect(),
+ direction: 'down',
+ });
+ };
+
+ _onOpenMovePopover = () => {
+ if (!(this.props.items.length > 0)) {
+ return;
+ }
+ if (this.context.sheetDepth !== WorkspaceStore.sheetStack().length - 1) {
+ return;
+ }
+ Actions.openPopover(, {
+ originRect: this._moveEl.getBoundingClientRect(),
+ direction: 'down',
+ });
+ };
+
+ render() {
+ if (!this._account) {
+ return ;
+ }
+
+ const handlers = {
+ 'core:change-folders': this._onOpenMovePopover,
+ };
+ const submenu = [
+ {
+ label: 'Move to Folder...',
+ command: 'core:change-folders',
+ position: 'endof=thread-actions',
+ },
+ ];
+
+ if (this._account.usesLabels()) {
+ Object.assign(handlers, {
+ 'core:change-labels': this._onOpenLabelsPopover,
+ });
+
+ submenu.push({
+ label: 'Apply Labels...',
+ command: 'core:change-labels',
+ position: 'endof=thread-actions',
+ });
+ }
+
+ return (
+
+
+
+ {this._account.usesLabels() && (
+
+ )}
+
+
+ );
+ }
+}
+
+module.exports = MovePicker;
diff --git a/app/internal_packages/thread-list/lib/main.es6 b/app/internal_packages/thread-list/lib/main.es6
index cce7488e7..7bfae39b0 100644
--- a/app/internal_packages/thread-list/lib/main.es6
+++ b/app/internal_packages/thread-list/lib/main.es6
@@ -6,15 +6,7 @@ import ThreadListEmptyFolderBar from './thread-list-empty-folder-bar';
import MessageListToolbar from './message-list-toolbar';
import SelectedItemsStack from './selected-items-stack';
-import {
- UpButton,
- DownButton,
- TrashButton,
- ArchiveButton,
- MarkAsSpamButton,
- ToggleUnreadButton,
- ToggleStarredButton,
-} from './thread-toolbar-buttons';
+import { UpButton, DownButton, MoveButtons, FlagButtons } from './thread-toolbar-buttons';
export function activate() {
ComponentRegistry.register(ThreadListEmptyFolderBar, {
@@ -50,23 +42,11 @@ export function activate() {
modes: ['list'],
});
- ComponentRegistry.register(ArchiveButton, {
+ ComponentRegistry.register(MoveButtons, {
role: 'ThreadActionsToolbarButton',
});
- ComponentRegistry.register(TrashButton, {
- role: 'ThreadActionsToolbarButton',
- });
-
- ComponentRegistry.register(MarkAsSpamButton, {
- role: 'ThreadActionsToolbarButton',
- });
-
- ComponentRegistry.register(ToggleStarredButton, {
- role: 'ThreadActionsToolbarButton',
- });
-
- ComponentRegistry.register(ToggleUnreadButton, {
+ ComponentRegistry.register(FlagButtons, {
role: 'ThreadActionsToolbarButton',
});
}
@@ -76,11 +56,8 @@ export function deactivate() {
ComponentRegistry.unregister(SelectedItemsStack);
ComponentRegistry.unregister(ThreadListToolbar);
ComponentRegistry.unregister(MessageListToolbar);
- ComponentRegistry.unregister(ArchiveButton);
- ComponentRegistry.unregister(TrashButton);
- ComponentRegistry.unregister(MarkAsSpamButton);
- ComponentRegistry.unregister(ToggleUnreadButton);
- ComponentRegistry.unregister(ToggleStarredButton);
+ ComponentRegistry.unregister(MoveButtons);
+ ComponentRegistry.unregister(FlagButtons);
ComponentRegistry.unregister(UpButton);
ComponentRegistry.unregister(DownButton);
}
diff --git a/app/internal_packages/thread-list/lib/thread-toolbar-buttons.jsx b/app/internal_packages/thread-list/lib/thread-toolbar-buttons.jsx
index 2db292636..fb3e09451 100644
--- a/app/internal_packages/thread-list/lib/thread-toolbar-buttons.jsx
+++ b/app/internal_packages/thread-list/lib/thread-toolbar-buttons.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
-import { RetinaImg } from 'mailspring-component-kit';
+import { RetinaImg, CreateButtonGroup } from 'mailspring-component-kit';
import {
Actions,
TaskFactory,
@@ -33,17 +33,11 @@ export class ArchiveButton extends React.Component {
render() {
const allowed = FocusedPerspectiveStore.current().canArchiveThreads(this.props.items);
if (!allowed) {
- return ;
+ return false;
}
return (
-