mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-06 20:54:26 +08:00
Fixes T1363: move file success to task and listen to DB event
Test Plan: edgehill --test Reviewers: bengotow Reviewed By: bengotow Maniphest Tasks: T1363 Differential Revision: https://phab.nylas.com/D1548
This commit is contained in:
parent
8b7509e50d
commit
f97a3a7b86
5 changed files with 45 additions and 44 deletions
|
@ -6,6 +6,7 @@ Message = require '../../src/flux/models/message'
|
||||||
Actions = require '../../src/flux/actions'
|
Actions = require '../../src/flux/actions'
|
||||||
|
|
||||||
NamespaceStore = require "../../src/flux/stores/namespace-store"
|
NamespaceStore = require "../../src/flux/stores/namespace-store"
|
||||||
|
DraftStore = require "../../src/flux/stores/draft-store"
|
||||||
|
|
||||||
FileUploadTask = proxyquire "../../src/flux/tasks/file-upload-task",
|
FileUploadTask = proxyquire "../../src/flux/tasks/file-upload-task",
|
||||||
fs:
|
fs:
|
||||||
|
@ -79,6 +80,14 @@ describe "FileUploadTask", ->
|
||||||
spyOn(NylasAPI, 'makeRequest').andCallFake (reqParams) =>
|
spyOn(NylasAPI, 'makeRequest').andCallFake (reqParams) =>
|
||||||
reqParams.success(testResponse) if reqParams.success
|
reqParams.success(testResponse) if reqParams.success
|
||||||
return @req
|
return @req
|
||||||
|
@testFiles = []
|
||||||
|
@changes = []
|
||||||
|
spyOn(DraftStore, "sessionForLocalId").andCallFake =>
|
||||||
|
Promise.resolve(
|
||||||
|
draft: => files: @testFiles
|
||||||
|
changes:
|
||||||
|
add: ({files}) => @changes = files
|
||||||
|
)
|
||||||
|
|
||||||
it "notifies when the task starts remote", ->
|
it "notifies when the task starts remote", ->
|
||||||
waitsForPromise =>
|
waitsForPromise =>
|
||||||
|
@ -93,18 +102,13 @@ describe "FileUploadTask", ->
|
||||||
expect(options.method).toBe('POST')
|
expect(options.method).toBe('POST')
|
||||||
expect(options.formData.file.value).toBe("Read Stream")
|
expect(options.formData.file.value).toBe("Read Stream")
|
||||||
|
|
||||||
it "passes the file to the completed notification function", ->
|
it "attaches the file to the draft", ->
|
||||||
spyOn(@task, "_completedNotification").andReturn(100)
|
|
||||||
waitsForPromise => @task.performRemote().then =>
|
waitsForPromise => @task.performRemote().then =>
|
||||||
expect(@task._completedNotification).toHaveBeenCalledWith(equivalentFile)
|
expect(@changes).toEqual [equivalentFile]
|
||||||
|
|
||||||
describe "file upload notifications", ->
|
describe "file upload notifications", ->
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
@fileUploadFiredLast = false
|
spyOn(Actions, "fileUploaded")
|
||||||
spyOn(Actions, "attachFileComplete").andCallFake =>
|
|
||||||
@fileUploadFiredLast = false
|
|
||||||
spyOn(Actions, "fileUploaded").andCallFake =>
|
|
||||||
@fileUploadFiredLast = true
|
|
||||||
spyOn(@task, "_getBytesUploaded").andReturn(1000)
|
spyOn(@task, "_getBytesUploaded").andReturn(1000)
|
||||||
|
|
||||||
runs =>
|
runs =>
|
||||||
|
@ -113,16 +117,6 @@ describe "FileUploadTask", ->
|
||||||
waitsFor ->
|
waitsFor ->
|
||||||
Actions.fileUploaded.calls.length > 0
|
Actions.fileUploaded.calls.length > 0
|
||||||
|
|
||||||
it "calls the `attachFileComplete` action first", ->
|
|
||||||
runs ->
|
|
||||||
expect(@fileUploadFiredLast).toBe true
|
|
||||||
|
|
||||||
it "correctly fires the attachFileComplete action", ->
|
|
||||||
runs ->
|
|
||||||
expect(Actions.attachFileComplete).toHaveBeenCalledWith
|
|
||||||
file: equivalentFile
|
|
||||||
messageLocalId: localId
|
|
||||||
|
|
||||||
it "correctly fires the fileUploaded action", ->
|
it "correctly fires the fileUploaded action", ->
|
||||||
runs ->
|
runs ->
|
||||||
expect(Actions.fileUploaded).toHaveBeenCalledWith
|
expect(Actions.fileUploaded).toHaveBeenCalledWith
|
||||||
|
|
|
@ -93,7 +93,6 @@ class Actions
|
||||||
@fileAborted: ActionScopeGlobal
|
@fileAborted: ActionScopeGlobal
|
||||||
@downloadStateChanged: ActionScopeGlobal
|
@downloadStateChanged: ActionScopeGlobal
|
||||||
@fileUploaded: ActionScopeGlobal
|
@fileUploaded: ActionScopeGlobal
|
||||||
@attachFileComplete: ActionScopeGlobal
|
|
||||||
@multiWindowNotification: ActionScopeGlobal
|
@multiWindowNotification: ActionScopeGlobal
|
||||||
@sendDraftSuccess: ActionScopeGlobal
|
@sendDraftSuccess: ActionScopeGlobal
|
||||||
@sendToAllWindows: ActionScopeGlobal
|
@sendToAllWindows: ActionScopeGlobal
|
||||||
|
@ -400,12 +399,24 @@ class Actions
|
||||||
@createTemplate: ActionScopeWindow
|
@createTemplate: ActionScopeWindow
|
||||||
@showTemplates: ActionScopeWindow
|
@showTemplates: ActionScopeWindow
|
||||||
|
|
||||||
|
###
|
||||||
|
Public: Remove a file from a draft.
|
||||||
|
|
||||||
|
*Scope: Window*
|
||||||
|
|
||||||
|
```
|
||||||
|
Actions.removeFile
|
||||||
|
file: fileObject
|
||||||
|
messageLocalId: draftLocalId
|
||||||
|
```
|
||||||
|
###
|
||||||
|
@removeFile: ActionScopeWindow
|
||||||
|
|
||||||
# File Actions
|
# File Actions
|
||||||
# Some file actions only need to be processed in their current window
|
# Some file actions only need to be processed in their current window
|
||||||
@attachFile: ActionScopeWindow
|
@attachFile: ActionScopeWindow
|
||||||
@attachFilePath: ActionScopeWindow
|
@attachFilePath: ActionScopeWindow
|
||||||
@abortUpload: ActionScopeWindow
|
@abortUpload: ActionScopeWindow
|
||||||
@removeFile: ActionScopeWindow
|
|
||||||
@fetchAndOpenFile: ActionScopeWindow
|
@fetchAndOpenFile: ActionScopeWindow
|
||||||
@fetchAndSaveFile: ActionScopeWindow
|
@fetchAndSaveFile: ActionScopeWindow
|
||||||
@fetchFile: ActionScopeWindow
|
@fetchFile: ActionScopeWindow
|
||||||
|
|
|
@ -45,6 +45,8 @@ class DraftChangeSet
|
||||||
|
|
||||||
DatabaseStore = require './database-store'
|
DatabaseStore = require './database-store'
|
||||||
DatabaseStore.findByLocalId(Message, @localId).then (draft) =>
|
DatabaseStore.findByLocalId(Message, @localId).then (draft) =>
|
||||||
|
if not draft
|
||||||
|
throw new Error("Tried to commit a draft that had already been removed from the database. DraftId: #{@localId}")
|
||||||
draft = @applyToModel(draft)
|
draft = @applyToModel(draft)
|
||||||
DatabaseStore.persistModel(draft).then =>
|
DatabaseStore.persistModel(draft).then =>
|
||||||
@_pending = {}
|
@_pending = {}
|
||||||
|
@ -123,7 +125,8 @@ class DraftStoreProxy
|
||||||
# Is this change an update to our draft?
|
# Is this change an update to our draft?
|
||||||
myDraft = _.find(change.objects, (obj) => obj.id == @_draft.id)
|
myDraft = _.find(change.objects, (obj) => obj.id == @_draft.id)
|
||||||
if myDraft
|
if myDraft
|
||||||
@_setDraft(myDraft)
|
@_draft = _.extend @_draft, myDraft
|
||||||
|
@trigger()
|
||||||
|
|
||||||
_onDraftSwapped: (change) ->
|
_onDraftSwapped: (change) ->
|
||||||
# A draft was saved with a new ID. Since we use the draft ID to
|
# A draft was saved with a new ID. Since we use the draft ID to
|
||||||
|
|
|
@ -59,7 +59,6 @@ class DraftStore
|
||||||
@listenTo Actions.destroyDraft, @_onDestroyDraft
|
@listenTo Actions.destroyDraft, @_onDestroyDraft
|
||||||
|
|
||||||
@listenTo Actions.removeFile, @_onRemoveFile
|
@listenTo Actions.removeFile, @_onRemoveFile
|
||||||
@listenTo Actions.attachFileComplete, @_onAttachFileComplete
|
|
||||||
|
|
||||||
atom.onBeforeUnload @_onBeforeUnload
|
atom.onBeforeUnload @_onBeforeUnload
|
||||||
|
|
||||||
|
@ -165,6 +164,7 @@ class DraftStore
|
||||||
return unless change.objectClass is Message.name
|
return unless change.objectClass is Message.name
|
||||||
containsDraft = _.some(change.objects, (msg) -> msg.draft)
|
containsDraft = _.some(change.objects, (msg) -> msg.draft)
|
||||||
return unless containsDraft
|
return unless containsDraft
|
||||||
|
@trigger(change)
|
||||||
|
|
||||||
_isMe: (contact={}) =>
|
_isMe: (contact={}) =>
|
||||||
contact.email is NamespaceStore.current().me().email
|
contact.email is NamespaceStore.current().me().email
|
||||||
|
@ -390,12 +390,6 @@ class DraftStore
|
||||||
continue unless extension.finalizeSessionBeforeSending
|
continue unless extension.finalizeSessionBeforeSending
|
||||||
extension.finalizeSessionBeforeSending(session)
|
extension.finalizeSessionBeforeSending(session)
|
||||||
|
|
||||||
_onAttachFileComplete: ({file, messageLocalId}) =>
|
|
||||||
@sessionForLocalId(messageLocalId).then (session) ->
|
|
||||||
files = _.clone(session.draft().files) ? []
|
|
||||||
files.push(file)
|
|
||||||
session.changes.add({files}, true)
|
|
||||||
|
|
||||||
_onRemoveFile: ({file, messageLocalId}) =>
|
_onRemoveFile: ({file, messageLocalId}) =>
|
||||||
@sessionForLocalId(messageLocalId).then (session) ->
|
@sessionForLocalId(messageLocalId).then (session) ->
|
||||||
files = _.clone(session.draft().files) ? []
|
files = _.clone(session.draft().files) ? []
|
||||||
|
|
|
@ -41,14 +41,9 @@ class FileUploadTask extends Task
|
||||||
try
|
try
|
||||||
json = JSON.parse(rawResponseString)
|
json = JSON.parse(rawResponseString)
|
||||||
file = (new File).fromJSON(json[0])
|
file = (new File).fromJSON(json[0])
|
||||||
Actions.uploadStateChanged @_uploadData("completed")
|
|
||||||
@_completedNotification(file)
|
|
||||||
|
|
||||||
clearInterval(@progress)
|
|
||||||
@req = null
|
|
||||||
resolve()
|
|
||||||
catch error
|
catch error
|
||||||
reject(error)
|
reject(error)
|
||||||
|
@_onRemoteSuccess(file, resolve, reject)
|
||||||
|
|
||||||
@progress = setInterval =>
|
@progress = setInterval =>
|
||||||
Actions.uploadStateChanged(@_uploadData("progress"))
|
Actions.uploadStateChanged(@_uploadData("progress"))
|
||||||
|
@ -90,17 +85,21 @@ class FileUploadTask extends Task
|
||||||
Actions.postNotification({message: msg, type: "error"})
|
Actions.postNotification({message: msg, type: "error"})
|
||||||
Actions.uploadStateChanged @_uploadData("failed")
|
Actions.uploadStateChanged @_uploadData("failed")
|
||||||
|
|
||||||
# The `fileUploaded` action is needed to notify all other windows (like
|
_onRemoteSuccess: (file, resolve, reject) =>
|
||||||
# composers) that the file has finished uploading.
|
clearInterval(@progress)
|
||||||
_completedNotification: (file) ->
|
@req = null
|
||||||
setTimeout =>
|
@_attachFileToDraft(file).then =>
|
||||||
# We need these to be two separate actions in this sequence so
|
Actions.uploadStateChanged @_uploadData("completed")
|
||||||
# stores (like the DrafStore) can attach the file to their objects
|
|
||||||
# before we take action (like sending and closing the message) upon
|
|
||||||
# upload completion
|
|
||||||
Actions.attachFileComplete({file, @messageLocalId})
|
|
||||||
Actions.fileUploaded(uploadData: @_uploadData("completed"))
|
Actions.fileUploaded(uploadData: @_uploadData("completed"))
|
||||||
, 1000 # To see the success state for a little bit
|
resolve()
|
||||||
|
.catch(reject)
|
||||||
|
|
||||||
|
_attachFileToDraft: (file) ->
|
||||||
|
DraftStore = require '../stores/draft-store'
|
||||||
|
DraftStore.sessionForLocalId(@messageLocalId).then (session) =>
|
||||||
|
files = _.clone(session.draft().files) ? []
|
||||||
|
files.push(file)
|
||||||
|
return session.changes.add({files}, true)
|
||||||
|
|
||||||
_formData: ->
|
_formData: ->
|
||||||
file: # Must be named `file` as per the Nylas API spec
|
file: # Must be named `file` as per the Nylas API spec
|
||||||
|
|
Loading…
Add table
Reference in a new issue