From 6ec84561c4323f39b919d50c518deca065ec6b95 Mon Sep 17 00:00:00 2001 From: Evan Morikawa Date: Tue, 10 Mar 2015 09:52:47 -0700 Subject: [PATCH] feat(composer): popout only closes when message sending succeeds Summary: This is a WIP to fix the blatant case of messages dissapearing when there's an error. It's pending a better through through notification UI Test Plan: edgehill --test Reviewers: bengotow Reviewed By: bengotow Differential Revision: https://review.inboxapp.com/D1270 --- .../notifications/lib/notifications-store.coffee | 7 +++++++ src/browser/edgehill-application.coffee | 2 +- src/flux/actions.coffee | 12 ++++++++++-- src/flux/stores/draft-store.coffee | 12 +++++++++--- src/flux/tasks/destroy-draft.coffee | 5 ++++- src/flux/tasks/send-draft.coffee | 14 ++++++++++---- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/internal_packages/notifications/lib/notifications-store.coffee b/internal_packages/notifications/lib/notifications-store.coffee index 13f075210..674b2ecdf 100644 --- a/internal_packages/notifications/lib/notifications-store.coffee +++ b/internal_packages/notifications/lib/notifications-store.coffee @@ -47,6 +47,8 @@ NotificationStore = Reflux.createStore @_removeNotification(notification)() @listenTo Actions.postNotification, (data) => @_postNotification(new Notification(data)) + @listenTo Actions.multiWindowNotification, (data={}, context={}) => + @_postNotification(new Notification(data)) if @_inWindowContext(context) ######### PUBLIC ####################################################### @@ -82,3 +84,8 @@ NotificationStore = Reflux.createStore console.log "Removed #{notification}" if VERBOSE delete @_notifications[notification.id] @trigger() + + # If the window matches the given context then we can show a + # notification. + _inWindowContext: (context={}) -> + return true diff --git a/src/browser/edgehill-application.coffee b/src/browser/edgehill-application.coffee index 4f3331f3b..0f9966767 100644 --- a/src/browser/edgehill-application.coffee +++ b/src/browser/edgehill-application.coffee @@ -465,7 +465,7 @@ class AtomApplication if parts.protocol is 'mailto:' query = qs.parse(parts.query) query.to = "#{parts.auth}@#{parts.host}" - + json = { subject: query.subject || '', body: query.body || '', diff --git a/src/flux/actions.coffee b/src/flux/actions.coffee index 8236c0e3c..becda8e90 100644 --- a/src/flux/actions.coffee +++ b/src/flux/actions.coffee @@ -16,7 +16,15 @@ globalActions = [ "uploadStateChanged", "fileAborted", "downloadStateChanged", - "fileUploaded" + "fileUploaded", + + "multiWindowNotification", + + # Draft actions + "sendDraftSuccess", + "sendDraftError", + "destroyDraftSuccess", + "destroyDraftError" ] # These actions are rebroadcast through the ActionBridge to the @@ -71,7 +79,7 @@ windowActions = [ # Notification actions "postNotification", "notificationActionTaken", - + # FullContact Sidebar "getFullContactDetails", diff --git a/src/flux/stores/draft-store.coffee b/src/flux/stores/draft-store.coffee index d95c8a73b..9ae83098d 100644 --- a/src/flux/stores/draft-store.coffee +++ b/src/flux/stores/draft-store.coffee @@ -39,6 +39,8 @@ DraftStore = Reflux.createStore @listenTo Actions.removeFile, @_onRemoveFile @listenTo Actions.attachFileComplete, @_onAttachFileComplete + @listenTo Actions.sendDraftSuccess, @_closeWindow + @listenTo Actions.destroyDraftSuccess, @_closeWindow @_drafts = [] @_draftSessions = {} @@ -66,7 +68,7 @@ DraftStore = Reflux.createStore else # Continue closing return true - + DatabaseStore.findAll(Message, draft: true).then (drafts) => @_drafts = drafts @trigger({}) @@ -154,6 +156,12 @@ DraftStore = Reflux.createStore DatabaseStore.persistModel(draft) + # We only want to close the popout window if we're sure various draft + # actions succeeded. + _closeWindow: (draftLocalId) -> + if atom.state.mode is "composer" and @_draftSessions[draftLocalId]? + atom.close() + # The logic to create a new Draft used to be in the DraftStore (which is # where it should be). It got moved to composer/lib/main.cjsx becaues # of an obscure atom-shell/Chrome bug whereby database requests firing right @@ -173,7 +181,6 @@ DraftStore = Reflux.createStore # Queue the task to destroy the draft Actions.queueTask(new DestroyDraftTask(draftLocalId)) - atom.close() if atom.state.mode is "composer" _onSendDraft: (draftLocalId) -> # Immediately save any pending changes so we don't save after sending @@ -181,7 +188,6 @@ DraftStore = Reflux.createStore save.then -> # Queue the task to send the draft Actions.queueTask(new SendDraftTask(draftLocalId)) - atom.close() if atom.state.mode is "composer" _onAttachFileComplete: ({file, messageLocalId}) -> @sessionForLocalId(messageLocalId).prepare().then (proxy) -> diff --git a/src/flux/tasks/destroy-draft.coffee b/src/flux/tasks/destroy-draft.coffee index 66fb04d92..c15a13fc4 100644 --- a/src/flux/tasks/destroy-draft.coffee +++ b/src/flux/tasks/destroy-draft.coffee @@ -42,7 +42,9 @@ class DestroyDraftTask extends Task body: version: @draft.version returnsModel: false - success: resolve + success: (args...) => + Actions.destroyDraftSuccess(@draftLocalId) + resolve(args...) error: reject onAPIError: (apiError) -> @@ -55,6 +57,7 @@ class DestroyDraftTask extends Task # do but finish return true else + Actions.destroyDraftError(@draftLocalId) @_rollbackLocal() onOtherError: -> Promise.resolve() diff --git a/src/flux/tasks/send-draft.coffee b/src/flux/tasks/send-draft.coffee index 8b286065e..986941899 100644 --- a/src/flux/tasks/send-draft.coffee +++ b/src/flux/tasks/send-draft.coffee @@ -23,13 +23,14 @@ class SendDraftTask extends Task # already sent when they haven't! return Promise.reject("Attempt to call SendDraftTask.performLocal without @draftLocalId") unless @draftLocalId Actions.postNotification({message: "Sending messageā€¦", type: 'info'}) + Promise.resolve() performRemote: -> new Promise (resolve, reject) => # Fetch the latest draft data to make sure we make the request with the most # recent draft version - DatabaseStore.findByLocalId(Message, @draftLocalId).then (draft) -> + DatabaseStore.findByLocalId(Message, @draftLocalId).then (draft) => # The draft may have been deleted by another task. Nothing we can do. return reject(new Error("We couldn't find the saved draft.")) unless draft @@ -45,25 +46,30 @@ class SendDraftTask extends Task method: 'POST' body: body returnsModel: true - success: -> + success: => atom.playSound('mail_sent.ogg') Actions.postNotification({message: "Sent!", type: 'success'}) + Actions.sendDraftSuccess(@draftLocalId) DatabaseStore.unpersistModel(draft).then(resolve) error: reject .catch(reject) - onAPIError: -> - msg = "Our server is having problems. Your message has not been sent." + onAPIError: (apiError) -> + msg = apiError.message ? "Our server is having problems. Your message has not been sent." + Actions.sendDraftError(@draftLocalId, msg) @notifyErrorMessage(msg) onOtherError: -> msg = "We had a serious issue while sending. Your message has not been sent." + Actions.sendDraftError(@draftLocalId, msg) @notifyErrorMessage(msg) onTimeoutError: -> msg = "The server is taking an abnormally long time to respond. Your message has not been sent." + Actions.sendDraftError(@draftLocalId, msg) @notifyErrorMessage(msg) onOfflineError: -> msg = "You are offline. Your message has NOT been sent. Please send your message when you come back online." + Actions.sendDraftError(@draftLocalId, msg) @notifyErrorMessage(msg)