feat(dock-icon): Drop files to attach them to new msg

Summary:
Fix specs

Fix responding to mailto, files at launch

It's super important that `window:loaded` is /not/ sent from index.js because `loadSettings.bootstrapScript` is async and nothing is actually loaded yet. This was causing the app to dispatch the mailto:// links into the main window before a DraftStore existed.

I think this was necessary at one point because we had NylasWindows not using a bootstrapScript? Should not be here anymore...

Test Plan: Run a few new tests

Reviewers: juan, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D2737
This commit is contained in:
Ben Gotow 2016-03-17 13:14:55 -07:00
parent 2e2ecf0647
commit b515a5e0e2
10 changed files with 90 additions and 11 deletions

View file

@ -61,6 +61,18 @@
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeName</key>
<string>File</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>*</string>
</array>
</dict>
</array>
</dict>
</plist>

View file

@ -4,6 +4,7 @@
Actions,
Contact,
Message,
Account,
DraftStore,
AccountStore,
DatabaseStore,
@ -993,3 +994,27 @@ describe "DraftStore", ->
expect(actual instanceof Contact).toBe(true)
expect(actual.email).toEqual(expected.email)
expect(actual.name).toEqual(expected.name)
describe "mailfiles handling", ->
it "should popout a new draft", ->
defaultMe = new Contact()
spyOn(DraftStore, '_onPopoutDraftClientId')
spyOn(DatabaseTransaction.prototype, 'persistModel')
spyOn(Account.prototype, 'defaultMe').andReturn(defaultMe)
spyOn(Actions, 'addAttachment')
DraftStore._onHandleMailFiles({}, ['/Users/ben/file1.png', '/Users/ben/file2.png'])
waitsFor ->
DatabaseTransaction.prototype.persistModel.callCount > 0
runs ->
{body, subject, from} = DatabaseTransaction.prototype.persistModel.calls[0].args[0]
expect({body, subject, from}).toEqual({body:'', subject:'', from: [defaultMe]})
expect(DraftStore._onPopoutDraftClientId).toHaveBeenCalled()
it "should call addAttachment for each provided file path", ->
spyOn(Actions, 'addAttachment')
DraftStore._onHandleMailFiles({}, ['/Users/ben/file1.png', '/Users/ben/file2.png'])
waitsFor ->
Actions.addAttachment.callCount is 2
runs ->
expect(Actions.addAttachment.calls[0].args[0].filePath).toEqual('/Users/ben/file1.png')
expect(Actions.addAttachment.calls[1].args[0].filePath).toEqual('/Users/ben/file2.png')

View file

@ -19,6 +19,7 @@ describe 'FileUploadStore', ->
@session =
changes:
add: jasmine.createSpy('session.changes.add')
commit: ->
draft: => @draft
spyOn(NylasEnv, "isMainWindow").andReturn true
spyOn(FileUploadStore, "_onAttachFileError").andCallFake (msg) ->

View file

@ -130,14 +130,16 @@ class Application
@launchWithOptions(options)
# Opens a new window based on the options provided.
launchWithOptions: ({urlsToOpen, specMode, devMode, safeMode, specDirectory, specFilePattern, logFile, showSpecsInWindow}) ->
launchWithOptions: ({urlsToOpen, pathsToOpen, specMode, safeMode, specDirectory, specFilePattern, logFile, showSpecsInWindow}) ->
if specMode
exitWhenDone = true
@runSpecs({exitWhenDone, showSpecsInWindow, @resourcePath, specDirectory, specFilePattern, logFile})
else
@openWindowsForTokenState()
for urlToOpen in (urlsToOpen || [])
@openUrl(urlToOpen)
if pathsToOpen instanceof Array
@openComposerWithFiles(pathsToOpen)
if urlsToOpen instanceof Array
@openUrl(urlToOpen) for urlToOpen in urlsToOpen
# Creates server to listen for additional N1 application launches.
#
@ -339,7 +341,8 @@ class Application
@setDatabasePhase('close')
@deleteSocketFile()
app.on 'open-file', (event, pathToOpen) ->
app.on 'open-file', (event, pathToOpen) =>
@openComposerWithFiles([pathToOpen])
event.preventDefault()
app.on 'open-url', (event, urlToOpen) =>
@ -515,6 +518,9 @@ class Application
else
console.log "Ignoring unknown URL type: #{urlToOpen}"
openComposerWithFiles: (pathsToOpen) ->
@windowManager.sendToMainWindow('mailfiles', pathsToOpen)
# Opens up a new {NylasWindow} to run specs within.
#
# options -

View file

@ -19,11 +19,16 @@ start = ->
addUrlToOpen = (event, urlToOpen) ->
event.preventDefault()
args.urlsToOpen.push(urlToOpen)
app.on 'open-url', addUrlToOpen
addFileToOpen = (event, fileToOpen) ->
event.preventDefault()
args.filesToOpen.push(fileToOpen)
app.on 'open-file', addFileToOpen
app.on 'ready', ->
app.removeListener 'open-url', addUrlToOpen
app.removeListener 'open-file', addFileToOpen
Application = require path.join(args.resourcePath, 'src', 'browser', 'application')
Application.open(args)
@ -141,11 +146,12 @@ parseCommandLine = ->
path.dirname(path.dirname(__dirname)))
urlsToOpen = []
filesToOpen = []
# On Yosemite the $PATH is not inherited by the "open" command, so we
# have to explicitly pass it by command line, see http://git.io/YC8_Ew.
process.env.PATH = args['path-environment'] if args['path-environment']
return {version, devMode, background, logFile, specMode, safeMode, configDirPath, specDirectory, specFilePattern, showSpecsInWindow, resourcePath, urlsToOpen}
return {version, devMode, background, logFile, specMode, safeMode, configDirPath, specDirectory, specFilePattern, showSpecsInWindow, resourcePath, urlsToOpen, filesToOpen}
start()

View file

@ -13,7 +13,7 @@
mkdirp = require('mkdirp');
start = function() {
var addUrlToOpen, args, configDirPath;
var addFileToOpen, addUrlToOpen, args, configDirPath;
args = parseCommandLine();
global.errorLogger = setupErrorLogger(args);
configDirPath = setupConfigDir(args);
@ -28,9 +28,15 @@
return args.urlsToOpen.push(urlToOpen);
};
app.on('open-url', addUrlToOpen);
addFileToOpen = function(event, fileToOpen) {
event.preventDefault();
return args.filesToOpen.push(fileToOpen);
};
app.on('open-file', addFileToOpen);
return app.on('ready', function() {
var Application;
app.removeListener('open-url', addUrlToOpen);
app.removeListener('open-file', addFileToOpen);
Application = require(path.join(args.resourcePath, 'src', 'browser', 'application'));
Application.open(args);
if (!args.specMode) {
@ -103,7 +109,7 @@
};
parseCommandLine = function() {
var args, background, configDirPath, devMode, logFile, options, ref, resourcePath, safeMode, showSpecsInWindow, specDirectory, specFilePattern, specMode, urlsToOpen, version;
var args, background, configDirPath, devMode, filesToOpen, logFile, options, ref, resourcePath, safeMode, showSpecsInWindow, specDirectory, specFilePattern, specMode, urlsToOpen, version;
version = app.getVersion();
options = declareOptions(process.argv.slice(1));
args = options.argv;
@ -126,6 +132,7 @@
showSpecsInWindow = specMode === "window";
resourcePath = path.resolve((ref = args['resource-path']) != null ? ref : path.dirname(path.dirname(__dirname)));
urlsToOpen = [];
filesToOpen = [];
if (args['path-environment']) {
process.env.PATH = args['path-environment'];
}
@ -141,7 +148,8 @@
specFilePattern: specFilePattern,
showSpecsInWindow: showSpecsInWindow,
resourcePath: resourcePath,
urlsToOpen: urlsToOpen
urlsToOpen: urlsToOpen,
filesToOpen: filesToOpen
};
};

View file

@ -107,12 +107,12 @@ class NylasWindow
@setLoadSettings(loadSettings)
@browserWindow.once 'window:loaded', =>
@emit 'window:loaded'
@loaded = true
if @mainWindow
@browserWindow.setResizable(true)
if @browserWindow.loadSettingsChangedSinceGetURL
@browserWindow.webContents.send('load-settings-changed', @browserWindow.loadSettings)
@emit 'window:loaded'
@browserWindow.loadURL(@getURL(loadSettings))
@browserWindow.focusOnWebView() if @isSpec

View file

@ -102,6 +102,7 @@ class DraftStore
@_draftsSending = {}
ipcRenderer.on 'mailto', @_onHandleMailtoLink
ipcRenderer.on 'mailfiles', @_onHandleMailFiles
######### PUBLIC #######################################################
@ -492,6 +493,21 @@ class DraftStore
@_finalizeAndPersistNewMessage(draft).then ({draftClientId}) =>
@_onPopoutDraftClientId(draftClientId)
_onHandleMailFiles: (event, paths) =>
account = @_getAccountForNewMessage()
draft = new Message
body: ''
subject: ''
from: [account.defaultMe()]
date: (new Date)
draft: true
pristine: true
accountId: account.id
@_finalizeAndPersistNewMessage(draft).then ({draftClientId}) =>
for path in paths
Actions.addAttachment({filePath: path, messageClientId: draftClientId})
@_onPopoutDraftClientId(draftClientId)
_onDestroyDraft: (draftClientId) =>
session = @_draftSessions[draftClientId]

View file

@ -144,4 +144,10 @@ class FileUploadStore extends NylasStore
uploads = changeFunction(session.draft().uploads)
session.changes.add({uploads})
# In some scenarios (like dropping attachments on the dock icon), files
# are added to drafts which may be open in another composer window.
# Committing here ensures the files appear immediately, no matter where the
# user is now viewing the draft.
session.changes.commit()
module.exports = new FileUploadStore()

View file

@ -65,7 +65,6 @@ function setupWindow (loadSettings) {
setupCsonCache(CompileCache.getCacheDirectory())
require(loadSettings.bootstrapScript)
require('electron').ipcRenderer.send('window-command', 'window:loaded')
}
function setupCsonCache (cacheDir) {