mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-03-01 10:33:14 +08:00
feat(composer): better composer plugin loading
This commit is contained in:
parent
31fb621d6b
commit
ebba673671
4 changed files with 131 additions and 16 deletions
78
internal_packages/composer/lib/action-bar-plugins.jsx
Normal file
78
internal_packages/composer/lib/action-bar-plugins.jsx
Normal file
|
@ -0,0 +1,78 @@
|
|||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import {ComponentRegistry} from 'nylas-exports'
|
||||
import {InjectedComponentSet} from 'nylas-component-kit'
|
||||
|
||||
export default class ActionBarPlugins extends React.Component {
|
||||
static displayName = "ActionBarPlugins";
|
||||
|
||||
static ROLE = "Composer:ActionButton"
|
||||
|
||||
static propTypes = {
|
||||
draft: React.PropTypes.object,
|
||||
session: React.PropTypes.session,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = this._getStateFromStores()
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._usub = ComponentRegistry.listen(this._onComponentsChange)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._usub();
|
||||
}
|
||||
|
||||
_onComponentsChange = () => {
|
||||
if (this._getPluginsLength() > 0) {
|
||||
// The `InjectedComponentSet` also listens to the ComponentRegistry.
|
||||
// Since we can't guarantee the order the listeners are fired in and
|
||||
// we want to make sure we add the class after the injected component
|
||||
// set has rendered, put the call in this requestAnimationFrame
|
||||
//
|
||||
// It also takes 2 frames to reliably get all of the icons painted.
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
this.setState(this._getStateFromStores())
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_getPluginsLength() {
|
||||
const role = ActionBarPlugins.ROLE
|
||||
return ComponentRegistry.findComponentsMatching({role}).length;
|
||||
}
|
||||
|
||||
_getStateFromStores() {
|
||||
return {
|
||||
pluginsLoaded: this._getPluginsLength() > 0,
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const className = classnames({
|
||||
"action-bar-animation-wrap": true,
|
||||
"plugins-loaded": this.state.pluginsLoaded,
|
||||
});
|
||||
|
||||
return (
|
||||
<span className={className}>
|
||||
<div className="action-bar-cover"></div>
|
||||
<InjectedComponentSet
|
||||
className="composer-action-bar-plugins"
|
||||
matching={{role: ActionBarPlugins.ROLE}}
|
||||
exposedProps={{
|
||||
draft: this.props.draft,
|
||||
threadId: this.props.draft.threadId,
|
||||
draftClientId: this.props.draft.clientId,
|
||||
session: this.props.session,
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -27,8 +27,9 @@ import FileUpload from './file-upload';
|
|||
import ImageFileUpload from './image-file-upload';
|
||||
|
||||
import ComposerEditor from './composer-editor';
|
||||
import SendActionButton from './send-action-button';
|
||||
import ComposerHeader from './composer-header';
|
||||
import SendActionButton from './send-action-button';
|
||||
import ActionBarPlugins from './action-bar-plugins'
|
||||
|
||||
import Fields from './fields';
|
||||
|
||||
|
@ -329,16 +330,7 @@ export default class ComposerView extends React.Component {
|
|||
_renderActionsRegion() {
|
||||
return (
|
||||
<div className="composer-action-bar-content">
|
||||
<InjectedComponentSet
|
||||
className="composer-action-bar-plugins"
|
||||
matching={{role: "Composer:ActionButton"}}
|
||||
exposedProps={{
|
||||
draft: this.props.draft,
|
||||
threadId: this.props.draft.threadId,
|
||||
draftClientId: this.props.draft.clientId,
|
||||
session: this.props.session,
|
||||
}}
|
||||
/>
|
||||
<ActionBarPlugins draft={this.props.draft} session={this.props.session} />
|
||||
|
||||
<button
|
||||
tabIndex={-1}
|
||||
|
|
|
@ -23,6 +23,13 @@ body.platform-win32 {
|
|||
}
|
||||
}
|
||||
|
||||
.action-bar-cover-gen() {
|
||||
.action-bar-cover {
|
||||
background-image: -webkit-linear-gradient(left, fade(@action-bar-bg, 0) 0%,
|
||||
@action-bar-bg 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.composer-inner-wrap {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
@ -53,14 +60,17 @@ body.platform-win32 {
|
|||
}
|
||||
|
||||
.composer-action-bar-wrap {
|
||||
@action-bar-bg: @background-off-primary;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
background: @background-off-primary;
|
||||
background: @action-bar-bg;
|
||||
border-top: 1px solid darken(@background-off-primary, 7%);
|
||||
box-shadow: inset 0 2px 1px rgba(0,0,0,0.03);
|
||||
border-bottom: 0;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
.action-bar-cover-gen;
|
||||
|
||||
// Buttons in the composer footer
|
||||
.btn.btn-toolbar:not(.btn-emphasis) {
|
||||
background: transparent;
|
||||
|
@ -101,6 +111,35 @@ body.platform-win32 {
|
|||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.action-bar-animation-wrap {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.composer-action-bar-plugins {
|
||||
opacity: 0;
|
||||
transition: opacity 30ms;
|
||||
}
|
||||
|
||||
.action-bar-cover {
|
||||
transition: left 200ms ease-out;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&.plugins-loaded {
|
||||
.composer-action-bar-plugins {
|
||||
opacity: 1;
|
||||
}
|
||||
.action-bar-cover {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.composer-content-wrap {
|
||||
|
@ -293,9 +332,11 @@ body.platform-win32 {
|
|||
.composer-inner-wrap {
|
||||
|
||||
.composer-action-bar-wrap {
|
||||
background: darken(@background-primary, 1%);
|
||||
@action-bar-bg: darken(@background-primary, 1%);
|
||||
background: @action-bar-bg;
|
||||
border-top: 1px solid darken(@background-primary, 8%);
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,0.03);
|
||||
.action-bar-cover-gen;
|
||||
}
|
||||
|
||||
.composer-action-bar-content {
|
||||
|
@ -329,7 +370,9 @@ body.platform-win32 {
|
|||
background: linear-gradient(to right, fade(@blurred-primary-color, 0%) 0%, fade(@blurred-primary-color, 100%) 40%);
|
||||
}
|
||||
.composer-action-bar-wrap {
|
||||
background: @blurred-off-primary-color;
|
||||
@action-bar-bg: @blurred-off-primary-color;
|
||||
background: @action-bar-bg;
|
||||
.action-bar-cover-gen;
|
||||
}
|
||||
}
|
||||
.message-item-white-wrap.composer-outer-wrap.focused {
|
||||
|
@ -339,7 +382,9 @@ body.platform-win32 {
|
|||
background: linear-gradient(to right, fade(@background-primary, 0%) 0%, fade(@background-primary, 100%) 40%);
|
||||
}
|
||||
.composer-action-bar-wrap {
|
||||
background: @background-off-primary;
|
||||
@action-bar-bg: @background-off-primary;
|
||||
background: @action-bar-bg;
|
||||
.action-bar-cover-gen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class DraftChangeSet
|
|||
clearTimeout(@_timer)
|
||||
@_timer = null
|
||||
|
||||
add: (changes, {doesNotAffectPristine}) =>
|
||||
add: (changes, {doesNotAffectPristine}={}) =>
|
||||
@_pending = _.extend(@_pending, changes)
|
||||
@_pending['pristine'] = false unless doesNotAffectPristine
|
||||
@_onAltered()
|
||||
|
|
Loading…
Reference in a new issue