Mailspring/src/browser/atom-window.coffee
Ben Gotow 21a32ac57f fix(*): Message list container styles, logout exceptions, composer logic cleanup
Summary:
This diff makes a couple changes:

- New drafts are no longer created in the composer component. Draft creation is back in the draft store where it belongs!
  - This means that the Draft List doesn't *always* contain two extra drafts, which are the unopened hot windows.
- Windows never show until they're loaded, which means windows open slowly vs. opening empty. I think the former is preferable but it's easy to change.
- Login window is now sized *before* it's shown instead of afterwards
- The mailto: behavior is now handled by the DraftStore, which gets rid of the whole draftInitialJSON thing that never made any sense.

fix(login) Make login window show at the correct size

logout from edgehill completely

Fix draft delete issue

Don't show windows, hot or cold, until they've loaded

Move logic for responding to mailto links into the draft store

Always fire `windowPropsChanged` after packages load or the window is shown

Show more error codes in red in activity bar

Make sure DraftStoreProxy doesn't interrupt the rendering of the composer with a new draft

Fix account-sidebar scroll issue, maybe?

Test Plan: Run tests!

Reviewers: evan

Reviewed By: evan

Differential Revision: https://review.inboxapp.com/D1479
2015-05-07 14:42:39 -07:00

257 lines
7.4 KiB
CoffeeScript

BrowserWindow = require 'browser-window'
app = require 'app'
path = require 'path'
fs = require 'fs'
url = require 'url'
_ = require 'underscore-plus'
{EventEmitter} = require 'events'
module.exports =
class AtomWindow
_.extend @prototype, EventEmitter.prototype
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'edgehill.png')
@includeShellLoadTime: true
browserWindow: null
loaded: null
isSpec: null
constructor: (settings={}) ->
{frame,
title,
width,
height,
resizable,
pathToOpen,
hideMenuBar,
@isSpec,
@devMode,
@safeMode,
@neverClose,
@mainWindow,
@resourcePath,
@exitWhenDone} = settings
# Normalize to make sure drive letter case is consistent on Windows
@resourcePath = path.normalize(@resourcePath) if @resourcePath
options =
show: false
title: title ? 'Nilas'
frame: frame ? true
width: width
height: height
resizable: resizable ? true
icon: @constructor.iconPath
'auto-hide-menu-bar': hideMenuBar
'web-preferences':
'direct-write': true
'subpixel-font-scaling': false
# Don't set icon on Windows so the exe's ico will be used as window and
# taskbar's icon. See https://github.com/atom/atom/issues/4811 for more.
if process.platform is 'linux'
options.icon = @constructor.iconPath
@browserWindow = new BrowserWindow options
global.atomApplication.addWindow(this)
@handleEvents()
loadSettings = _.extend({}, settings)
loadSettings.windowState ?= '{}'
loadSettings.appVersion = app.getVersion()
loadSettings.resourcePath = @resourcePath
loadSettings.devMode ?= false
loadSettings.safeMode ?= false
loadSettings.mainWindow ?= @mainWindow
loadSettings.windowType ?= "default"
# Only send to the first non-spec window created
if @constructor.includeShellLoadTime and not @isSpec
@constructor.includeShellLoadTime = false
loadSettings.shellLoadTime ?= Date.now() - global.shellStartTime
loadSettings.initialPath = pathToOpen
if fs.statSyncNoException(pathToOpen).isFile?()
loadSettings.initialPath = path.dirname(pathToOpen)
@setLoadSettings(loadSettings)
@browserWindow.once 'window:loaded', =>
@emit 'window:loaded'
@loaded = true
if @browserWindow.loadSettingsChangedSinceGetURL
@browserWindow.webContents.send('load-settings-changed', @browserWindow.loadSettings)
@browserWindow.loadUrl @getUrl(loadSettings)
@browserWindow.focusOnWebView() if @isSpec
@openPath(pathToOpen) unless @isSpecWindow()
loadSettings: -> @browserWindow.loadSettings
setLoadSettings: (loadSettings) ->
@browserWindow.loadSettings = loadSettings
@browserWindow.loadSettingsChangedSinceGetURL = true
@browserWindow.webContents.send('load-settings-changed', loadSettings) if @loaded
getUrl: (loadSettingsObj) ->
# Ignore the windowState when passing loadSettings via URL, since it could
# be quite large.
loadSettings = _.clone(loadSettingsObj)
delete loadSettings['windowState']
@browserWindow.loadSettingsChangedSinceGetURL = false
url.format
protocol: 'file'
pathname: "#{@resourcePath}/static/index.html"
slashes: true
query: {loadSettings: JSON.stringify(loadSettings)}
hasProjectPath: -> @projectPath?.length > 0
getInitialPath: ->
@browserWindow.loadSettings.initialPath
setupContextMenu: ->
ContextMenu = null
@browserWindow.on 'context-menu', (menuTemplate) =>
ContextMenu ?= require './context-menu'
new ContextMenu(menuTemplate, this)
containsPath: (pathToCheck) ->
initialPath = @getInitialPath()
if not initialPath
false
else if not pathToCheck
false
else if pathToCheck is initialPath
true
else if fs.statSyncNoException(pathToCheck).isDirectory?()
false
else if pathToCheck.indexOf(path.join(initialPath, path.sep)) is 0
true
else
false
handleEvents: ->
@browserWindow.on 'close', (event) =>
if @neverClose and !global.atomApplication.quitting
event.preventDefault()
@browserWindow.hide()
@emit 'window:close-prevented'
@browserWindow.on 'closed', =>
global.atomApplication.removeWindow(this)
@browserWindow.on 'unresponsive', =>
return if @isSpec
dialog = require 'dialog'
chosen = dialog.showMessageBox @browserWindow,
type: 'warning'
buttons: ['Close', 'Keep Waiting']
message: 'Editor is not responding'
detail: 'The editor is not responding. Would you like to force close it or just keep waiting?'
@browserWindow.destroy() if chosen is 0
@browserWindow.webContents.on 'crashed', =>
global.atomApplication.exit(100) if @exitWhenDone
dialog = require 'dialog'
chosen = dialog.showMessageBox @browserWindow,
type: 'warning'
buttons: ['Close Window', 'Reload', 'Keep It Open']
message: 'The editor has crashed'
detail: 'Please report this issue to https://github.com/atom/atom'
switch chosen
when 0 then @browserWindow.destroy()
when 1 then @browserWindow.restart()
@setupContextMenu()
if @isSpec
# Workaround for https://github.com/atom/atom-shell/issues/380
# Don't focus the window when it is being blurred during close or
# else the app will crash on Windows.
if process.platform is 'win32'
@browserWindow.on 'close', => @isWindowClosing = true
# Spec window's web view should always have focus
@browserWindow.on 'blur', =>
@browserWindow.focusOnWebView() unless @isWindowClosing
openPath: (pathToOpen) ->
if @loaded
@focus()
@sendMessage 'open-path', pathToOpen
else
@browserWindow.once 'window:loaded', => @openPath(pathToOpen)
sendMessage: (message, detail) ->
@browserWindow.webContents.send 'message', message, detail
sendCommand: (command, args...) ->
if @isSpecWindow()
unless global.atomApplication.sendCommandToFirstResponder(command)
switch command
when 'window:reload' then @reload()
when 'window:toggle-dev-tools' then @toggleDevTools()
when 'window:close' then @close()
else if @isWebViewFocused()
@sendCommandToBrowserWindow(command, args...)
else
unless global.atomApplication.sendCommandToFirstResponder(command)
@sendCommandToBrowserWindow(command, args...)
sendCommandToBrowserWindow: (command, args...) ->
@browserWindow.webContents.send 'command', command, args...
getDimensions: ->
[x, y] = @browserWindow.getPosition()
[width, height] = @browserWindow.getSize()
{x, y, width, height}
close: -> @browserWindow.close()
hide: -> @browserWindow.hide()
show: -> @browserWindow.show()
showWhenLoaded: ->
if @loaded
@show()
@focus()
else
@once 'window:loaded', =>
@show()
@focus()
focus: -> @browserWindow.focus()
minimize: -> @browserWindow.minimize()
maximize: -> @browserWindow.maximize()
restore: -> @browserWindow.restore()
handlesAtomCommands: ->
not @isSpecWindow() and @isWebViewFocused()
isFocused: -> @browserWindow.isFocused()
isMinimized: -> @browserWindow.isMinimized()
isVisible: -> @browserWindow.isVisible()
isWebViewFocused: -> @browserWindow.isWebViewFocused()
isSpecWindow: -> @isSpec
reload: -> @browserWindow.restart()
toggleDevTools: -> @browserWindow.toggleDevTools()