mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-01-18 22:18:01 +08:00
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:
parent
2e2ecf0647
commit
b515a5e0e2
10 changed files with 90 additions and 11 deletions
|
@ -61,6 +61,18 @@
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleDocumentTypes</key>
|
<key>CFBundleDocumentTypes</key>
|
||||||
<array>
|
<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>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Actions,
|
Actions,
|
||||||
Contact,
|
Contact,
|
||||||
Message,
|
Message,
|
||||||
|
Account,
|
||||||
DraftStore,
|
DraftStore,
|
||||||
AccountStore,
|
AccountStore,
|
||||||
DatabaseStore,
|
DatabaseStore,
|
||||||
|
@ -993,3 +994,27 @@ describe "DraftStore", ->
|
||||||
expect(actual instanceof Contact).toBe(true)
|
expect(actual instanceof Contact).toBe(true)
|
||||||
expect(actual.email).toEqual(expected.email)
|
expect(actual.email).toEqual(expected.email)
|
||||||
expect(actual.name).toEqual(expected.name)
|
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')
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe 'FileUploadStore', ->
|
||||||
@session =
|
@session =
|
||||||
changes:
|
changes:
|
||||||
add: jasmine.createSpy('session.changes.add')
|
add: jasmine.createSpy('session.changes.add')
|
||||||
|
commit: ->
|
||||||
draft: => @draft
|
draft: => @draft
|
||||||
spyOn(NylasEnv, "isMainWindow").andReturn true
|
spyOn(NylasEnv, "isMainWindow").andReturn true
|
||||||
spyOn(FileUploadStore, "_onAttachFileError").andCallFake (msg) ->
|
spyOn(FileUploadStore, "_onAttachFileError").andCallFake (msg) ->
|
||||||
|
|
|
@ -130,14 +130,16 @@ class Application
|
||||||
@launchWithOptions(options)
|
@launchWithOptions(options)
|
||||||
|
|
||||||
# Opens a new window based on the options provided.
|
# 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
|
if specMode
|
||||||
exitWhenDone = true
|
exitWhenDone = true
|
||||||
@runSpecs({exitWhenDone, showSpecsInWindow, @resourcePath, specDirectory, specFilePattern, logFile})
|
@runSpecs({exitWhenDone, showSpecsInWindow, @resourcePath, specDirectory, specFilePattern, logFile})
|
||||||
else
|
else
|
||||||
@openWindowsForTokenState()
|
@openWindowsForTokenState()
|
||||||
for urlToOpen in (urlsToOpen || [])
|
if pathsToOpen instanceof Array
|
||||||
@openUrl(urlToOpen)
|
@openComposerWithFiles(pathsToOpen)
|
||||||
|
if urlsToOpen instanceof Array
|
||||||
|
@openUrl(urlToOpen) for urlToOpen in urlsToOpen
|
||||||
|
|
||||||
# Creates server to listen for additional N1 application launches.
|
# Creates server to listen for additional N1 application launches.
|
||||||
#
|
#
|
||||||
|
@ -339,7 +341,8 @@ class Application
|
||||||
@setDatabasePhase('close')
|
@setDatabasePhase('close')
|
||||||
@deleteSocketFile()
|
@deleteSocketFile()
|
||||||
|
|
||||||
app.on 'open-file', (event, pathToOpen) ->
|
app.on 'open-file', (event, pathToOpen) =>
|
||||||
|
@openComposerWithFiles([pathToOpen])
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
app.on 'open-url', (event, urlToOpen) =>
|
app.on 'open-url', (event, urlToOpen) =>
|
||||||
|
@ -515,6 +518,9 @@ class Application
|
||||||
else
|
else
|
||||||
console.log "Ignoring unknown URL type: #{urlToOpen}"
|
console.log "Ignoring unknown URL type: #{urlToOpen}"
|
||||||
|
|
||||||
|
openComposerWithFiles: (pathsToOpen) ->
|
||||||
|
@windowManager.sendToMainWindow('mailfiles', pathsToOpen)
|
||||||
|
|
||||||
# Opens up a new {NylasWindow} to run specs within.
|
# Opens up a new {NylasWindow} to run specs within.
|
||||||
#
|
#
|
||||||
# options -
|
# options -
|
||||||
|
|
|
@ -19,11 +19,16 @@ start = ->
|
||||||
addUrlToOpen = (event, urlToOpen) ->
|
addUrlToOpen = (event, urlToOpen) ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
args.urlsToOpen.push(urlToOpen)
|
args.urlsToOpen.push(urlToOpen)
|
||||||
|
|
||||||
app.on 'open-url', addUrlToOpen
|
app.on 'open-url', addUrlToOpen
|
||||||
|
|
||||||
|
addFileToOpen = (event, fileToOpen) ->
|
||||||
|
event.preventDefault()
|
||||||
|
args.filesToOpen.push(fileToOpen)
|
||||||
|
app.on 'open-file', addFileToOpen
|
||||||
|
|
||||||
app.on 'ready', ->
|
app.on 'ready', ->
|
||||||
app.removeListener 'open-url', addUrlToOpen
|
app.removeListener 'open-url', addUrlToOpen
|
||||||
|
app.removeListener 'open-file', addFileToOpen
|
||||||
|
|
||||||
Application = require path.join(args.resourcePath, 'src', 'browser', 'application')
|
Application = require path.join(args.resourcePath, 'src', 'browser', 'application')
|
||||||
Application.open(args)
|
Application.open(args)
|
||||||
|
@ -141,11 +146,12 @@ parseCommandLine = ->
|
||||||
path.dirname(path.dirname(__dirname)))
|
path.dirname(path.dirname(__dirname)))
|
||||||
|
|
||||||
urlsToOpen = []
|
urlsToOpen = []
|
||||||
|
filesToOpen = []
|
||||||
|
|
||||||
# On Yosemite the $PATH is not inherited by the "open" command, so we
|
# 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.
|
# have to explicitly pass it by command line, see http://git.io/YC8_Ew.
|
||||||
process.env.PATH = args['path-environment'] if args['path-environment']
|
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()
|
start()
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
mkdirp = require('mkdirp');
|
mkdirp = require('mkdirp');
|
||||||
|
|
||||||
start = function() {
|
start = function() {
|
||||||
var addUrlToOpen, args, configDirPath;
|
var addFileToOpen, addUrlToOpen, args, configDirPath;
|
||||||
args = parseCommandLine();
|
args = parseCommandLine();
|
||||||
global.errorLogger = setupErrorLogger(args);
|
global.errorLogger = setupErrorLogger(args);
|
||||||
configDirPath = setupConfigDir(args);
|
configDirPath = setupConfigDir(args);
|
||||||
|
@ -28,9 +28,15 @@
|
||||||
return args.urlsToOpen.push(urlToOpen);
|
return args.urlsToOpen.push(urlToOpen);
|
||||||
};
|
};
|
||||||
app.on('open-url', addUrlToOpen);
|
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() {
|
return app.on('ready', function() {
|
||||||
var Application;
|
var Application;
|
||||||
app.removeListener('open-url', addUrlToOpen);
|
app.removeListener('open-url', addUrlToOpen);
|
||||||
|
app.removeListener('open-file', addFileToOpen);
|
||||||
Application = require(path.join(args.resourcePath, 'src', 'browser', 'application'));
|
Application = require(path.join(args.resourcePath, 'src', 'browser', 'application'));
|
||||||
Application.open(args);
|
Application.open(args);
|
||||||
if (!args.specMode) {
|
if (!args.specMode) {
|
||||||
|
@ -103,7 +109,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
parseCommandLine = function() {
|
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();
|
version = app.getVersion();
|
||||||
options = declareOptions(process.argv.slice(1));
|
options = declareOptions(process.argv.slice(1));
|
||||||
args = options.argv;
|
args = options.argv;
|
||||||
|
@ -126,6 +132,7 @@
|
||||||
showSpecsInWindow = specMode === "window";
|
showSpecsInWindow = specMode === "window";
|
||||||
resourcePath = path.resolve((ref = args['resource-path']) != null ? ref : path.dirname(path.dirname(__dirname)));
|
resourcePath = path.resolve((ref = args['resource-path']) != null ? ref : path.dirname(path.dirname(__dirname)));
|
||||||
urlsToOpen = [];
|
urlsToOpen = [];
|
||||||
|
filesToOpen = [];
|
||||||
if (args['path-environment']) {
|
if (args['path-environment']) {
|
||||||
process.env.PATH = args['path-environment'];
|
process.env.PATH = args['path-environment'];
|
||||||
}
|
}
|
||||||
|
@ -141,7 +148,8 @@
|
||||||
specFilePattern: specFilePattern,
|
specFilePattern: specFilePattern,
|
||||||
showSpecsInWindow: showSpecsInWindow,
|
showSpecsInWindow: showSpecsInWindow,
|
||||||
resourcePath: resourcePath,
|
resourcePath: resourcePath,
|
||||||
urlsToOpen: urlsToOpen
|
urlsToOpen: urlsToOpen,
|
||||||
|
filesToOpen: filesToOpen
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,12 +107,12 @@ class NylasWindow
|
||||||
@setLoadSettings(loadSettings)
|
@setLoadSettings(loadSettings)
|
||||||
|
|
||||||
@browserWindow.once 'window:loaded', =>
|
@browserWindow.once 'window:loaded', =>
|
||||||
@emit 'window:loaded'
|
|
||||||
@loaded = true
|
@loaded = true
|
||||||
if @mainWindow
|
if @mainWindow
|
||||||
@browserWindow.setResizable(true)
|
@browserWindow.setResizable(true)
|
||||||
if @browserWindow.loadSettingsChangedSinceGetURL
|
if @browserWindow.loadSettingsChangedSinceGetURL
|
||||||
@browserWindow.webContents.send('load-settings-changed', @browserWindow.loadSettings)
|
@browserWindow.webContents.send('load-settings-changed', @browserWindow.loadSettings)
|
||||||
|
@emit 'window:loaded'
|
||||||
|
|
||||||
@browserWindow.loadURL(@getURL(loadSettings))
|
@browserWindow.loadURL(@getURL(loadSettings))
|
||||||
@browserWindow.focusOnWebView() if @isSpec
|
@browserWindow.focusOnWebView() if @isSpec
|
||||||
|
|
|
@ -102,6 +102,7 @@ class DraftStore
|
||||||
@_draftsSending = {}
|
@_draftsSending = {}
|
||||||
|
|
||||||
ipcRenderer.on 'mailto', @_onHandleMailtoLink
|
ipcRenderer.on 'mailto', @_onHandleMailtoLink
|
||||||
|
ipcRenderer.on 'mailfiles', @_onHandleMailFiles
|
||||||
|
|
||||||
######### PUBLIC #######################################################
|
######### PUBLIC #######################################################
|
||||||
|
|
||||||
|
@ -492,6 +493,21 @@ class DraftStore
|
||||||
@_finalizeAndPersistNewMessage(draft).then ({draftClientId}) =>
|
@_finalizeAndPersistNewMessage(draft).then ({draftClientId}) =>
|
||||||
@_onPopoutDraftClientId(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) =>
|
_onDestroyDraft: (draftClientId) =>
|
||||||
session = @_draftSessions[draftClientId]
|
session = @_draftSessions[draftClientId]
|
||||||
|
|
||||||
|
|
|
@ -144,4 +144,10 @@ class FileUploadStore extends NylasStore
|
||||||
uploads = changeFunction(session.draft().uploads)
|
uploads = changeFunction(session.draft().uploads)
|
||||||
session.changes.add({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()
|
module.exports = new FileUploadStore()
|
||||||
|
|
|
@ -65,7 +65,6 @@ function setupWindow (loadSettings) {
|
||||||
setupCsonCache(CompileCache.getCacheDirectory())
|
setupCsonCache(CompileCache.getCacheDirectory())
|
||||||
|
|
||||||
require(loadSettings.bootstrapScript)
|
require(loadSettings.bootstrapScript)
|
||||||
require('electron').ipcRenderer.send('window-command', 'window:loaded')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupCsonCache (cacheDir) {
|
function setupCsonCache (cacheDir) {
|
||||||
|
|
Loading…
Reference in a new issue