Mailspring/app/internal_packages/composer/lib/send-action-button.jsx
Ben Gotow 1a3cca8d0a
Totally overhauled composer based on Slate (#524)
* Remove the composer contenteditable, replace with basic <textarea>

* Beginning broader cleanup of draft session

* DraftJS composer with color, style support

* Serialization/unserialization of basic styles, toolbar working

* WIP

* Switch to draft-js-plugins approach, need to revisit HTML

* Move HTML conversion functionality into plugins

* Add spellcheck context menu to editor

* Initial work on quoted text

* Further work on quoted text

* BLOCK approach

* Entity approach - better, does not bump out to top level

* Hiding and showing quoted text via CSS

* Get rid of ability to inject another subject line component

* Clean up specs, DraftFactory to ES6

* Remove old initial focus hack

* Fix focusing, initial text selection

* Remove participant “collapsing” support, it can be confusing

* Correctly terminate links on carriage returns

* Initial signature support, allow removal of uneditable blocks

* Sync body string with body editorstate

* Simplify draft editor session, finish signatures

* Templates

* Minor fixes

* Simplify link/open tracking, ensure it works

* Reorg composer, rework template editor

* Omg the slowness is all the stupid emoji button

* Polish and small fixes

* Performance improvements, new templates UI

* Don’t assume nodes are elements

* Fix for sending drafts twice due to back-to-back saves

* Fix order of operations on app quit to save drafts reliably

* Improve DraftJS-Convert whitespace handling

* Use contentID throughout attachment lifecycle

* Try to fix images

* Switch to Slate instead of DraftJS… much better

* Fix newline handling

* Bug fixes

* Cleanup

* Finish templates plugin

* Clean up text editing / support for Gmail email styles

* Support for color + size on the same node, clean trailing whitespace

* Restore emoji typeahead / emoji picker

* Fix scrolling in template editor

* Fix specs

* Fix newlines

* Re-implement spellcheck to be faster

* Make spellcheck decorator changes invisible to the undo/redo stack

* Remove comment

* Polish themplates panel

* Fix #521
2018-01-11 15:55:56 -08:00

130 lines
3.7 KiB
JavaScript

import { React, PropTypes, Actions, SendActionsStore, SoundRegistry } from 'mailspring-exports';
import { Menu, RetinaImg, ButtonDropdown, ListensToFluxStore } from 'mailspring-component-kit';
class SendActionButton extends React.Component {
static displayName = 'SendActionButton';
static containerRequired = false;
static propTypes = {
draft: PropTypes.object,
isValidDraft: PropTypes.func,
sendActions: PropTypes.array,
};
/* This component is re-rendered constantly because `draft` changes in random ways.
We only use the draft prop when you click send, so update with more discretion. */
shouldComponentUpdate(nextProps) {
return (
nextProps.sendActions.map(a => a.configKey).join(',') !==
this.props.sendActions.map(a => a.configKey).join(',')
);
}
primarySend() {
this._onPrimaryClick();
}
_onPrimaryClick = () => {
this._onSendWithAction(this.props.sendActions[0]);
};
_onSendWithAction = sendAction => {
if (this.props.isValidDraft()) {
if (AppEnv.config.get('core.sending.sounds')) {
SoundRegistry.playSound('hit-send');
}
Actions.sendDraft(this.props.draft.headerMessageId, { actionKey: sendAction.configKey });
}
};
_renderSendActionItem = ({ iconUrl }) => {
let plusHTML = '';
let additionalImg = false;
if (iconUrl) {
plusHTML = <span>&nbsp;+&nbsp;</span>;
additionalImg = <RetinaImg url={iconUrl} mode={RetinaImg.Mode.ContentIsMask} />;
}
return (
<span>
<RetinaImg name="icon-composer-send.png" mode={RetinaImg.Mode.ContentIsMask} />
<span className="text">Send{plusHTML}</span>
{additionalImg}
</span>
);
};
_renderSingleButton() {
return (
<button
tabIndex={-1}
className={'btn btn-toolbar btn-normal btn-emphasis btn-text btn-send'}
style={{ order: -100 }}
onClick={this._onPrimaryClick}
>
{this._renderSendActionItem(this.props.sendActions[0])}
</button>
);
}
_renderButtonDropdown() {
const { sendActions } = this.props;
const menu = (
<Menu
items={sendActions.slice(1)}
itemKey={actionConfig => actionConfig.configKey}
itemContent={this._renderSendActionItem}
onSelect={this._onSendWithAction}
/>
);
return (
<ButtonDropdown
className={'btn-send btn-emphasis btn-text'}
style={{ order: -100 }}
primaryItem={this._renderSendActionItem(sendActions[0])}
primaryTitle={sendActions[0].title}
primaryClick={this._onPrimaryClick}
closeOnMenuClick
menu={menu}
/>
);
}
render() {
return this.props.sendActions.length === 1
? this._renderSingleButton()
: this._renderButtonDropdown();
}
}
const EnhancedSendActionButton = ListensToFluxStore(SendActionButton, {
stores: [SendActionsStore],
getStateFromStores(props) {
return {
sendActions: SendActionsStore.orderedSendActionsForDraft(props.draft),
};
},
});
// TODO this is a hack so that the send button can still expose
// the `primarySend` method required by the ComposerView. Ideally, this
// decorator mechanism should expose whatever instance methods are exposed
// by the component its wrapping.
// However, I think the better fix will happen when mail merge lives in its
// own window and doesn't need to override the Composer's send button, which
// is already a bit of a hack.
Object.assign(EnhancedSendActionButton.prototype, {
primarySend() {
if (this._composedComponent) {
this._composedComponent.primarySend();
}
},
});
EnhancedSendActionButton.UndecoratedSendActionButton = SendActionButton;
export default EnhancedSendActionButton;