From f051b52e8c71ec55f38d1483b36deb7fd5b2d8e0 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Tue, 5 Sep 2017 13:15:37 -0700 Subject: [PATCH] Destroy drafts using ids not headerMessageIds --- .../composer/lib/composer-editor.jsx | 2 +- .../composer/lib/composer-header.jsx | 14 ++-- .../composer/lib/composer-view.jsx | 22 +++--- .../draft-list/lib/draft-list.cjsx | 2 +- .../draft-list/lib/draft-toolbar-buttons.cjsx | 2 +- .../print/assets/nylas-print-logo.png | Bin 6888 -> 0 bytes .../print/lib/print-window.es6 | 2 - .../stores/draft-editing-session-spec.coffee | 6 -- app/src/components/list-tabular.jsx | 15 +++-- .../overlaid-components.jsx | 10 ++- .../decorators/inflates-draft-client-id.jsx | 3 +- app/src/flux/mailsync-bridge.es6 | 3 +- app/src/flux/stores/attachment-store.es6 | 1 + app/src/flux/stores/draft-editing-session.es6 | 63 ++++++++++++------ app/src/flux/stores/draft-store.es6 | 6 +- app/src/flux/tasks/destroy-draft-task.es6 | 5 +- 16 files changed, 94 insertions(+), 62 deletions(-) delete mode 100644 app/internal_packages/print/assets/nylas-print-logo.png diff --git a/app/internal_packages/composer/lib/composer-editor.jsx b/app/internal_packages/composer/lib/composer-editor.jsx index 791753775..5a77cbe0c 100644 --- a/app/internal_packages/composer/lib/composer-editor.jsx +++ b/app/internal_packages/composer/lib/composer-editor.jsx @@ -270,7 +270,7 @@ class ComposerEditor extends Component { shouldAcceptDrop={this._shouldAcceptDrop} > { this._contenteditableComponent = cm; }} + ref={(cm) => { if (cm) { this._contenteditableComponent = cm; } }} value={this.props.body} onChange={this.props.onBodyChanged} onFilePaste={this.props.onFilePaste} diff --git a/app/internal_packages/composer/lib/composer-header.jsx b/app/internal_packages/composer/lib/composer-header.jsx index 0ab7f4b3e..3cdec195e 100644 --- a/app/internal_packages/composer/lib/composer-header.jsx +++ b/app/internal_packages/composer/lib/composer-header.jsx @@ -214,7 +214,7 @@ export default class ComposerHeader extends React.Component { return ( { this._els.participantsContainer = el; }} + ref={(el) => { if (el) { this._els.participantsContainer = el; } }} className="expanded-participants" onFocusIn={this._onFocusInParticipants} onFocusOut={this._onFocusOutParticipants} @@ -232,12 +232,12 @@ export default class ComposerHeader extends React.Component { return ( { this._els.subjectContainer = el; }} + ref={(el) => { if (el) { this._els.subjectContainer = el; } }} onFocusIn={this._onFocusInSubject} onFocusOut={this._onFocusOutSubject} > { this._els[Fields.Subject] = el; }} + ref={(el) => { if (el) { this._els[Fields.Subject] = el; } }} key="subject-wrap" matching={{role: 'Composer:SubjectTextField'}} exposedProps={{ @@ -264,7 +264,7 @@ export default class ComposerHeader extends React.Component { fields.push( { this._els[Fields.To] = el; }} + ref={(el) => { if (el) { this._els[Fields.To] = el; } }} key="to" field="to" change={this._onChangeParticipants} @@ -278,7 +278,7 @@ export default class ComposerHeader extends React.Component { if (this.state.enabledFields.includes(Fields.Cc)) { fields.push( { this._els[Fields.Cc] = el; }} + ref={(el) => { if (el) { this._els[Fields.Cc] = el; } }} key="cc" field="cc" change={this._onChangeParticipants} @@ -294,7 +294,7 @@ export default class ComposerHeader extends React.Component { if (this.state.enabledFields.includes(Fields.Bcc)) { fields.push( { this._els[Fields.Bcc] = el; }} + ref={(el) => { if (el) { this._els[Fields.Bcc] = el; } }} key="bcc" field="bcc" change={this._onChangeParticipants} @@ -311,7 +311,7 @@ export default class ComposerHeader extends React.Component { fields.push( { this._els[Fields.From] = el; }} + ref={(el) => { if (el) { this._els[Fields.From] = el; } }} value={from[0]} draft={this.props.draft} session={this.props.session} diff --git a/app/internal_packages/composer/lib/composer-view.jsx b/app/internal_packages/composer/lib/composer-view.jsx index dcdd262ee..85122ec86 100644 --- a/app/internal_packages/composer/lib/composer-view.jsx +++ b/app/internal_packages/composer/lib/composer-view.jsx @@ -148,12 +148,15 @@ export default class ComposerView extends React.Component { } } + _setSREl = (el) => { + this._els.scrollregion = el; + } _renderContentScrollRegion() { if (NylasEnv.isComposerWindow()) { return ( { this._els.scrollregion = el; }} + ref={(el) => { if (el) { this._els.scrollregion = el; } }} > {this._renderContent()} @@ -172,7 +175,7 @@ export default class ComposerView extends React.Component { return (
{ this._els.header = el; }} + ref={(el) => { if (el) { this._els.header = el; } }} draft={this.props.draft} session={this.props.session} initiallyFocused={this.props.draft.to.length === 0} @@ -180,7 +183,7 @@ export default class ComposerView extends React.Component { />
{ this._els.composeBody = el; }} + ref={(el) => { if (el) { this._els.composeBody = el; } }} onMouseUp={this._onMouseUpComposerBody} onMouseDown={this._onMouseDownComposerBody} > @@ -197,7 +200,10 @@ export default class ComposerView extends React.Component { session: this.props.session, } return ( -
{ this._els.composerBodyWrap = el; }} className="composer-body-wrap"> +
{ if (el) { this._els.composerBodyWrap = el; } }} + className="composer-body-wrap" + > {this._renderEditor()} @@ -221,7 +227,7 @@ export default class ComposerView extends React.Component { return ( { this._els[Fields.Body] = el; }} + ref={(el) => { if (el) { this._els[Fields.Body] = el; } }} className="body-field" matching={{role: "Composer:Editor"}} fallback={ComposerEditor} @@ -390,7 +396,7 @@ export default class ComposerView extends React.Component { { this._els.sendActionButton = el; }} + ref={(el) => { if (el) { this._els.sendActionButton = el; } }} tabIndex={-1} style={{order: -100}} matching={{role: "Composer:SendActionButton"}} @@ -564,7 +570,7 @@ export default class ComposerView extends React.Component { _onDestroyDraft = () => { const {draft} = this.props; - Actions.destroyDraft(draft.accountId, draft.headerMessageId); + Actions.destroyDraft(draft); } _onSelectAttachment = () => { @@ -579,7 +585,7 @@ export default class ComposerView extends React.Component { { this._els.composerWrap = el; }} + ref={(el) => { if (el) { this._els.composerWrap = el; } }} tabIndex="-1" > diff --git a/app/internal_packages/draft-list/lib/draft-list.cjsx b/app/internal_packages/draft-list/lib/draft-list.cjsx index 24321f7ae..f74fec175 100644 --- a/app/internal_packages/draft-list/lib/draft-list.cjsx +++ b/app/internal_packages/draft-list/lib/draft-list.cjsx @@ -47,6 +47,6 @@ class DraftList extends React.Component _onRemoveFromView: => drafts = DraftListStore.dataSource().selection.items() - Actions.destroyDraft(draft.accountId, draft.headerMessageId) for draft in drafts + Actions.destroyDraft(draft) for draft in drafts module.exports = DraftList diff --git a/app/internal_packages/draft-list/lib/draft-toolbar-buttons.cjsx b/app/internal_packages/draft-list/lib/draft-toolbar-buttons.cjsx index 81894ba52..2ed9744e7 100644 --- a/app/internal_packages/draft-list/lib/draft-toolbar-buttons.cjsx +++ b/app/internal_packages/draft-list/lib/draft-toolbar-buttons.cjsx @@ -19,7 +19,7 @@ class DraftDeleteButton extends React.Component _destroySelected: => for item in @props.selection.items() - Actions.destroyDraft(item.accountId, item.headerMessageId) + Actions.destroyDraft(item) @props.selection.clear() return diff --git a/app/internal_packages/print/assets/nylas-print-logo.png b/app/internal_packages/print/assets/nylas-print-logo.png deleted file mode 100644 index 43d3269c5eecfece8179a726dd4542105243ade5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6888 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 V)h<`2eDyCSjG?(fiJoi3e* { return (`
  • ${part.name} <${part.email}>
  • `); }).join(''); @@ -30,7 +29,6 @@ export default class PrintWindow { Print
    - nylas-logo

    ${subject}

    diff --git a/app/spec/stores/draft-editing-session-spec.coffee b/app/spec/stores/draft-editing-session-spec.coffee index 304f79eff..2ef0bfea0 100644 --- a/app/spec/stores/draft-editing-session-spec.coffee +++ b/app/spec/stores/draft-editing-session-spec.coffee @@ -212,12 +212,6 @@ xdescribe "DraftEditingSession Specs", -> @session.changes.commit().then => expect(updated.body).toBe "123" - it "doesn't queues a SyncbackDraftTask if no Syncback is passed", -> - spyOn(DatabaseStore, "run").andReturn(Promise.resolve(@draft)) - waitsForPromise => - @session.changes.commit({noSyncback: true}).then => - expect(Actions.queueTask).not.toHaveBeenCalled() - describe "when findBy does not return a draft", -> it "continues and persists it's local draft reference, so it is resaved and draft editing can continue", -> spyOn(DatabaseStore, "run").andReturn(Promise.resolve(null)) diff --git a/app/src/components/list-tabular.jsx b/app/src/components/list-tabular.jsx index d57448261..e06cc54c1 100644 --- a/app/src/components/list-tabular.jsx +++ b/app/src/components/list-tabular.jsx @@ -142,7 +142,7 @@ class ListTabular extends Component { // If our view has been swapped out for an entirely different one, // reset our scroll position to the top. if (prevProps.dataSource !== this.props.dataSource) { - this.refs.container.scrollTop = 0; + this._scrollRegion.scrollTop = 0; } if (!this.updateRangeStateFiring) { @@ -222,16 +222,19 @@ class ListTabular extends Component { } scrollTo(node) { - this.refs.container.scrollTo(node); + if (!this._scrollRegion) { return; } + this._scrollRegion.scrollTo(node); } scrollByPage(direction) { - const height = ReactDOM.findDOMNode(this.refs.container).clientHeight; - this.refs.container.scrollTop += height * direction; + if (!this._scrollRegion) { return; } + const height = ReactDOM.findDOMNode(this._scrollRegion).clientHeight; + this._scrollRegion.scrollTop += height * direction; } updateRangeState() { - const {scrollTop} = this.refs.container; + if (!this._scrollRegion) { return; } + const {scrollTop} = this._scrollRegion; const {itemHeight} = this.props // Determine the exact range of rows we want onscreen @@ -344,7 +347,7 @@ class ListTabular extends Component { return (
    { this._scrollRegion = cm; }} onScroll={this.onScroll} tabIndex="-1" scrollTooltipComponent={scrollTooltipComponent} diff --git a/app/src/components/overlaid-components/overlaid-components.jsx b/app/src/components/overlaid-components/overlaid-components.jsx index f789a8949..de36ed022 100644 --- a/app/src/components/overlaid-components/overlaid-components.jsx +++ b/app/src/components/overlaid-components/overlaid-components.jsx @@ -220,7 +220,10 @@ export default class OverlaidComponents extends React.Component { const toggle = (previewToggleVisible) ? this._renderPreviewToggle() : false; return ( -
    { this._overlaidComponentsEl = el; }}> +
    { if (el) { this._overlaidComponentsEl = el; } }} + > {toggle} {els}
    @@ -231,7 +234,10 @@ export default class OverlaidComponents extends React.Component { const {className} = this.props return (
    -
    { this._anchorContainerEl = el; }} > +
    { if (el) { this._anchorContainerEl = el; } }} + > {this.props.children}
    {this._renderOverlaidComponents()} diff --git a/app/src/decorators/inflates-draft-client-id.jsx b/app/src/decorators/inflates-draft-client-id.jsx index 24120baa6..b5a957064 100644 --- a/app/src/decorators/inflates-draft-client-id.jsx +++ b/app/src/decorators/inflates-draft-client-id.jsx @@ -80,8 +80,7 @@ function InflatesDraftClientId(ComposedComponent) { return; } if (this.state.draft.pristine) { - const {accountId, headerMessageId} = this.state.draft; - Actions.destroyDraft(accountId, headerMessageId); + Actions.destroyDraft(this.state.draft); } } diff --git a/app/src/flux/mailsync-bridge.es6 b/app/src/flux/mailsync-bridge.es6 index 17db75deb..98d86ccf9 100644 --- a/app/src/flux/mailsync-bridge.es6 +++ b/app/src/flux/mailsync-bridge.es6 @@ -181,7 +181,8 @@ export default class MailsyncBridge { if (!this._clients[accountId]) { const err = new Error(`No mailsync worker is running.`); err.accountId = accountId; - throw err; + NylasEnv.reportError(err); + return; } this._clients[accountId].sendMessage(json); } diff --git a/app/src/flux/stores/attachment-store.es6 b/app/src/flux/stores/attachment-store.es6 index 37673ad8d..f31b0da40 100644 --- a/app/src/flux/stores/attachment-store.es6 +++ b/app/src/flux/stores/attachment-store.es6 @@ -393,6 +393,7 @@ class AttachmentStore extends NylasStore { } const file = new File({ + id: Utils.generateTempId(), filename: filename, size: stats.size, contentType: null, diff --git a/app/src/flux/stores/draft-editing-session.es6 b/app/src/flux/stores/draft-editing-session.es6 index 7b4d8a25a..72447063c 100644 --- a/app/src/flux/stores/draft-editing-session.es6 +++ b/app/src/flux/stores/draft-editing-session.es6 @@ -2,6 +2,7 @@ import _ from 'underscore' import EventEmitter from 'events'; import NylasStore from 'nylas-store'; +import TaskQueue from './task-queue'; import Message from '../models/message' import Actions from '../actions' import AccountStore from './account-store' @@ -11,6 +12,7 @@ import UndoStack from '../../undo-stack' import DraftHelpers from '../stores/draft-helpers' import {Composer as ComposerExtensionRegistry} from '../../registries/extension-registry' import SyncbackDraftTask from '../tasks/syncback-draft-task' +import DestroyDraftTask from '../tasks/destroy-draft-task' const MetadataChangePrefix = 'metadata.'; let DraftStore = null; @@ -68,7 +70,7 @@ class DraftChangeSet extends EventEmitter { this.add(changes, {doesNotAffectPristine: true}); } - commit({noSyncback} = {}) { + commit() { if (this._timer) { clearTimeout(this._timer); } @@ -79,7 +81,7 @@ class DraftChangeSet extends EventEmitter { this._saving = this._pending; this._pending = {}; - return this.callbacks.onCommit({noSyncback}).then(() => { + return this.callbacks.onCommit().then(() => { this._saving = {} }); }; @@ -232,26 +234,51 @@ export default class DraftEditingSession extends NylasStore { // This function makes sure the draft is attached to a valid account, and changes // it's accountId if the from address does not match the account for the from - // address + // address. // - // If the account is updated it makes a request to delete the draft with the - // old accountId - async ensureCorrectAccount({noSyncback} = {}) { - const account = AccountStore.accountForEmail(this._draft.from[0].email); + async ensureCorrectAccount() { + const draft = this.draft(); + const account = AccountStore.accountForEmail(draft.from[0].email); if (!account) { throw new Error("DraftEditingSession::ensureCorrectAccount - you can only send drafts from a configured account."); } - if (account.id !== this._draft.accountId) { - // todo bg decide what to do here to sync - // NylasAPIHelpers.makeDraftDeletionRequest(this._draft) - this.changes.add({ - accountId: account.id, - version: null, - threadId: null, - replyToMessageId: null, + if (account.id !== draft.accountId) { + // Create a new draft in the new account (with a new ID). + // Because we use the headerMessageId /exclusively/ as the + // identifier we'll be fine. + // + // Then destroy the old one, since it may be synced to the server + // and require cleanup! + // + const create = new SyncbackDraftTask({ + headerMessageId: draft.headerMessageId, + draft: new Message({ + from: draft.from, + version: 0, + to: draft.to, + cc: draft.cc, + bcc: draft.bcc, + body: draft.body, + files: draft.files, + replyTo: draft.replyTo, + subject: draft.subject, + headerMessageId: draft.headerMessageId, + accountId: account.id, + unread: false, + starred: false, + draft: true, + }), }); - await this.changes.commit({noSyncback}); + + const destroy = new DestroyDraftTask({ + messageIds: [draft.id], + accountId: draft.accountId, + }); + + Actions.queueTask(create); + await TaskQueue.waitForPerformLocal(create); + Actions.queueTask(destroy); } return this; @@ -334,13 +361,12 @@ export default class DraftEditingSession extends NylasStore { } } - // TODO BG noSyncback is gone async changeSetCommit() { if (this._destroyed || !this._draft) { return; } - // Set a variable here to protect againg this._draft getting set from + // Set a variable here to protect against this._draft getting set from // underneath us const inMemoryDraft = this._draft; const draft = await DatabaseStore @@ -356,7 +382,6 @@ export default class DraftEditingSession extends NylasStore { // by creating a new draft const baseDraft = draft || inMemoryDraft; const updatedDraft = this.changes.applyToModel(baseDraft); - console.log("Queueing SyncbackDraftTask"); Actions.queueTask(new SyncbackDraftTask({draft: updatedDraft})); } diff --git a/app/src/flux/stores/draft-store.es6 b/app/src/flux/stores/draft-store.es6 index 40737612a..bf3b07200 100644 --- a/app/src/flux/stores/draft-store.es6 +++ b/app/src/flux/stores/draft-store.es6 @@ -112,7 +112,7 @@ class DraftStore extends NylasStore { if (draft && draft.pristine) { Actions.queueTask(new DestroyDraftTask({ accountId: draft.accountId, - headerMessageId: draft.headerMessageId, + messageIds: [draft.headerMessageId], })); } else { promises.push(session.changes.commit()); @@ -316,7 +316,7 @@ class DraftStore extends NylasStore { }); } - _onDestroyDraft = (accountId, headerMessageId) => { + _onDestroyDraft = ({accountId, headerMessageId, id}) => { const session = this._draftSessions[headerMessageId]; // Immediately reset any pending changes so no saves occur @@ -335,7 +335,7 @@ class DraftStore extends NylasStore { }) // Queue the task to destroy the draft - Actions.queueTask(new DestroyDraftTask({accountId, headerMessageId})); + Actions.queueTask(new DestroyDraftTask({accountId, messageIds: [id]})); if (NylasEnv.isComposerWindow()) { NylasEnv.close(); diff --git a/app/src/flux/tasks/destroy-draft-task.es6 b/app/src/flux/tasks/destroy-draft-task.es6 index 24543c79a..4d8b1343e 100644 --- a/app/src/flux/tasks/destroy-draft-task.es6 +++ b/app/src/flux/tasks/destroy-draft-task.es6 @@ -2,10 +2,9 @@ import Task from './task'; import Attributes from '../attributes'; export default class DestroyDraftTask extends Task { - static attributes = Object.assign({}, Task.attributes, { - headerMessageId: Attributes.String({ - modelKey: 'headerMessageId', + messageIds: Attributes.Collection({ + modelKey: 'messageIds', }), }); }