mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-04 11:44:47 +08:00
fix(composer): fix flashing and focus losing in the composer
This commit is contained in:
parent
e62bebb8a1
commit
dec047b18c
4 changed files with 43 additions and 25 deletions
|
@ -27,6 +27,7 @@ export default class ComposerHeader extends React.Component {
|
|||
static propTypes = {
|
||||
draft: React.PropTypes.object.isRequired,
|
||||
session: React.PropTypes.object.isRequired,
|
||||
initiallyFocused: React.PropTypes.bool,
|
||||
}
|
||||
|
||||
static contextTypes = {
|
||||
|
@ -35,12 +36,12 @@ export default class ComposerHeader extends React.Component {
|
|||
|
||||
constructor(props = {}) {
|
||||
super(props)
|
||||
this.state = this._initialStateForDraft(this.props.draft);
|
||||
this.state = this._initialStateForDraft(this.props.draft, props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.session !== nextProps.session) {
|
||||
this.setState(this._initialStateForDraft(nextProps.draft));
|
||||
this.setState(this._initialStateForDraft(nextProps.draft, nextProps));
|
||||
} else {
|
||||
this._ensureFilledFieldsEnabled(nextProps.draft);
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ export default class ComposerHeader extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
_initialStateForDraft(draft) {
|
||||
_initialStateForDraft(draft, props) {
|
||||
const enabledFields = [Fields.To];
|
||||
if (!_.isEmpty(draft.cc)) {
|
||||
enabledFields.push(Fields.Cc);
|
||||
|
@ -94,8 +95,8 @@ export default class ComposerHeader extends React.Component {
|
|||
}
|
||||
|
||||
return {
|
||||
enabledFields: enabledFields,
|
||||
participantsFocused: false,
|
||||
enabledFields,
|
||||
participantsFocused: props.initiallyFocused,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ export default class ComposerView extends React.Component {
|
|||
ref="header"
|
||||
draft={this.props.draft}
|
||||
session={this.props.session}
|
||||
initiallyFocused={this.props.draft.to.length === 0}
|
||||
/>
|
||||
<div
|
||||
className="compose-body"
|
||||
|
|
|
@ -24,7 +24,7 @@ class ComposerWithWindowProps extends React.Component {
|
|||
super(props);
|
||||
|
||||
// We'll now always have windowProps by the time we construct this.
|
||||
const windowProps = NylasEnv.getWindowProps()
|
||||
const windowProps = NylasEnv.getWindowProps();
|
||||
const {draftJSON, draftClientId} = windowProps;
|
||||
if (!draftJSON) {
|
||||
throw new Error("Initialize popout composer windows with valid draftJSON")
|
||||
|
@ -34,30 +34,34 @@ class ComposerWithWindowProps extends React.Component {
|
|||
this.state = windowProps
|
||||
}
|
||||
|
||||
onDraftReady = () => {
|
||||
componentWillUnmount() {
|
||||
if (this._usub) {this._usub()}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.refs.composer.focus()
|
||||
}
|
||||
|
||||
_onDraftReady = () => {
|
||||
this.refs.composer.focus().then(() => {
|
||||
NylasEnv.displayWindow();
|
||||
|
||||
if (this.state.errorMessage) {
|
||||
this._showInitialErrorDialog(this.state.errorMessage);
|
||||
}
|
||||
|
||||
// Give the composer some time to render before hitting another wall
|
||||
// of javascript.
|
||||
window.setTimeout(() => {
|
||||
NylasEnv.getCurrentWindow().updateLoadSettings({
|
||||
windowType: "composer",
|
||||
// This will start loading the rest of the composer's plugins. This
|
||||
// may take a while (hundreds of ms) depending on how many plugins
|
||||
// you have installed. For some reason it takes two frames to
|
||||
// reliably get the basic composer (Send button, etc) painted
|
||||
// properly.
|
||||
window.requestAnimationFrame(() => {
|
||||
window.requestAnimationFrame(() => {
|
||||
NylasEnv.getCurrentWindow().updateLoadSettings({
|
||||
windowType: "composer",
|
||||
})
|
||||
})
|
||||
|
||||
// The call to updateLoadSettings will start loading the remaining
|
||||
// packages. Once those packages load it'll cause a change in the
|
||||
// root Sheet-level InjectedComponentSet, which will cause
|
||||
// everything to re-render losing our focus. We have to manually
|
||||
// refocus it but defer it so the event loop of the package
|
||||
// activation happens first.
|
||||
window.setTimeout(() => {
|
||||
this.refs.composer.focus()
|
||||
}, 32)
|
||||
}, 32)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -65,7 +69,7 @@ class ComposerWithWindowProps extends React.Component {
|
|||
return (
|
||||
<ComposerViewForDraftClientId
|
||||
ref="composer"
|
||||
onDraftReady={this.onDraftReady}
|
||||
onDraftReady={this._onDraftReady}
|
||||
draftClientId={this.state.draftClientId}
|
||||
className="composer-full-window"
|
||||
/>
|
||||
|
|
|
@ -160,7 +160,19 @@ class ComponentRegistry
|
|||
|
||||
return [].concat(results)
|
||||
|
||||
triggerDebounced: _.debounce(( -> @trigger(@)), 1)
|
||||
# We debounce because a single plugin may activate many components in
|
||||
# their `activate` methods. Furthermore, when the window loads several
|
||||
# plugins may load in sequence. Plugin loading takes a while (dozens of
|
||||
# ms) since javascript is being read and `require` trees are being
|
||||
# traversed.
|
||||
#
|
||||
# Triggering the ComponentRegistry is fairly expensive since many very
|
||||
# high-level components (like the <Sheet />) listen and re-render when
|
||||
# this triggers.
|
||||
#
|
||||
# We set the debouce interval to 2 "frames" (33ms) to balance
|
||||
# responsiveness and efficient batching.
|
||||
triggerDebounced: _.debounce(( -> @trigger(@)), 33)
|
||||
|
||||
_removeDeprecatedRoles: (displayName, roles) ->
|
||||
newRoles = _.clone(roles)
|
||||
|
|
Loading…
Add table
Reference in a new issue