diff --git a/exports/nylas-store.coffee b/exports/nylas-store.coffee new file mode 100644 index 000000000..59769ccac --- /dev/null +++ b/exports/nylas-store.coffee @@ -0,0 +1,11 @@ +{Listener, Publisher} = require '../src/flux/modules/reflux-coffee' +CoffeeHelpers = require '../src/flux/coffee-helpers' + +# A simple Flux implementation +class NylasStore + @include: CoffeeHelpers.includeModule + + @include Publisher + @include Listener + +module.exports = NylasStore diff --git a/internal_packages/onboarding/lib/connect-account-page.cjsx b/internal_packages/onboarding/lib/connect-account-page.cjsx new file mode 100644 index 000000000..9fa8dcc77 --- /dev/null +++ b/internal_packages/onboarding/lib/connect-account-page.cjsx @@ -0,0 +1,31 @@ +React = require 'react' +Page = require './page' +{RetinaImg} = require 'nylas-component-kit' +{EdgehillAPI} = require 'nylas-exports' +OnboardingActions = require './onboarding-actions' + +class ConnectAccountPage extends Page + @displayName: "ConnectAccountPage" + + render: => +
+ {@_renderClose("close")} + + + +

Connect an Account

+ + + +
+
Link accounts from other services to supercharge your email.
+ +
+ +
+ + _fireAuthAccount: (service) => + url = EdgehillAPI.urlForConnecting(service) + OnboardingActions.moveToPage "add-account-auth", {url} + +module.exports = ConnectAccountPage diff --git a/internal_packages/onboarding/lib/container-view.cjsx b/internal_packages/onboarding/lib/container-view.cjsx deleted file mode 100644 index 198734a34..000000000 --- a/internal_packages/onboarding/lib/container-view.cjsx +++ /dev/null @@ -1,181 +0,0 @@ -React = require 'react/addons' -ReactCSSTransitionGroup = React.addons.CSSTransitionGroup -OnboardingActions = require './onboarding-actions' -OnboardingStore = require './onboarding-store' -querystring = require 'querystring' -{EdgehillAPI} = require 'nylas-exports' -{RetinaImg} = require 'nylas-component-kit' - -class ContainerView extends React.Component - @displayName: 'ContainerView' - @containerRequired: false - - constructor: (@props) -> - @state = @getStateFromStore() - - getStateFromStore: => - page: OnboardingStore.page() - error: OnboardingStore.error() - environment: OnboardingStore.environment() - connectType: OnboardingStore.connectType() - - componentDidMount: => - @unsubscribe = OnboardingStore.listen(@_onStateChanged, @) - - # It's important that every React class explicitly stops listening to - # atom events before it unmounts. Thank you event-kit - # This can be fixed via a Reflux mixin - componentWillUnmount: => - @unsubscribe() if @unsubscribe - - componentDidUpdate: => - webview = @refs['connect-iframe'] - if webview - node = React.findDOMNode(webview) - if node.hasListeners is undefined - # Remove as soon as possible. Initial src is not correctly loaded - # on webview, and this fixes it. Electron 0.26.0. (Still in 0.28.1) - setTimeout -> - node.src = node.src - ,10 - node.addEventListener 'new-window', (e) -> - require('shell').openExternal(e.url) - node.addEventListener 'did-start-loading', (e) -> - if node.hasMobileUserAgent is undefined - node.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53") - node.hasMobileUserAgent = true - node.reload() - node.addEventListener 'did-finish-load', (e) -> - if node.getUrl().indexOf('/connect/complete') != -1 - query = node.getUrl().split('?')[1] - query = query[0..-2] if query[query.length - 1] is '#' - token = querystring.decode(query) - OnboardingActions.finishedConnect(token) - if node.getUrl().indexOf('cancelled') != -1 - OnboardingActions.moveToPreviousPage() - - render: => -
- - {@_pageComponent()} -
-
-
- - _pageComponent: => - if @state.error - alert =
{@state.error}
- else - alert =
- - if @state.page is 'welcome' -
-
- -
- -

Welcome to Nylas

- - - -
-
Enter your email address:
- - - {@_environmentComponent()} -
- -
- - else if @state.page == 'add-account' -
-
- -
- -

Connect an Account

- - - -
-
Link accounts from other services to supercharge your email.
- - -
-
- - else if @state.page == 'add-account-auth' -
- { - React.createElement('webview',{ - "ref": "connect-iframe", - "key": @state.page, - "src": @_connectWebViewURL() - }) - } -
- -
-
- - else if @state.page == 'add-account-success' - # http://codepen.io/stevenfabre/pen/NPWeVb -
-
- - - -
-
- - _environmentComponent: => - return [] unless atom.inDevMode() -
- -
- - _connectWebViewURL: => - EdgehillAPI.urlForConnecting(@state.connectType, @state.email) - - _onStateChanged: => - @setState(@getStateFromStore()) - - _onValueChange: (event) => - changes = {} - changes[event.target.id] = event.target.value - @setState(changes) - - _fireDismiss: => - atom.close() - - _fireQuit: => - require('ipc').send('command', 'application:quit') - - _fireSetEnvironment: (event) => - OnboardingActions.setEnvironment(event.target.value) - - _fireStart: (e) => - OnboardingActions.startConnect('inbox') - - _fireAuthAccount: (service) => - OnboardingActions.startConnect(service) - - _fireMoveToPage: (page) => - OnboardingActions.moveToPage(page) - - _fireMoveToPrevPage: => - OnboardingActions.moveToPreviousPage() - - -module.exports = ContainerView diff --git a/internal_packages/onboarding/lib/external-auth-webview-page.cjsx b/internal_packages/onboarding/lib/external-auth-webview-page.cjsx new file mode 100644 index 000000000..368a8b99e --- /dev/null +++ b/internal_packages/onboarding/lib/external-auth-webview-page.cjsx @@ -0,0 +1,95 @@ +React = require 'react' +Page = require './page' +querystring = require 'querystring' +{RetinaImg} = require 'nylas-component-kit' +{EdgehillAPI} = require 'nylas-exports' +OnboardingActions = require './onboarding-actions' + +class ExternalAuthWebviewPage extends Page + @displayName: "ExternalAuthWebviewPage" + + render: => +
+ { + React.createElement('webview',{ + "ref": "connect-iframe", + "src": @props.pageData.url + "style": {position: "relative", zIndex: 1} + }) + } + {@_renderSpinner()} + {@_renderAction()} +
+ + componentDidMount: => + @_listeners = {} + webview = @refs['connect-iframe'] + return unless webview + webview = React.findDOMNode(webview) + @_setupWebviewListeners(webview) + + componentWillUnmount: -> + webview = @refs['connect-iframe'] + webview = React.findDOMNode(webview) + @_teardownWebviewListeners(webview) + + _fireMoveToPrevPage: => + OnboardingActions.moveToPreviousPage() + + _teardownWebviewListeners: (webview) -> + for event, listener of @_listeners + webview.removeEventListener event, listener + + _renderAction: -> + if @props.pageData.noPreviousPage + @_renderClose() + else +
+ +
+ + _setupWebviewListeners: (webview) -> + # Remove as soon as possible. Initial src is not correctly loaded + # on webview, and this fixes it. Electron 0.26.0. (Still in 0.28.1) + setTimeout -> + webview.src = webview.src + , 20 + + @_listeners = + "new-window": (e) -> + require('shell').openExternal(e.url) + "did-start-loading": (e) => + @_setUserAgent(e, webview) + "did-finish-load": (e) => + @_onDidFinishLoad(e, webview) + + for event, listener of @_listeners + webview.addEventListener event, listener + + _setUserAgent: (e, webview) -> + if webview.hasMobileUserAgent is undefined + webview.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 7_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D167 Safari/9537.53") + webview.hasMobileUserAgent = true + webview.reload() + + _onDidFinishLoad: (e, webview) => + return unless webview + + # We can't use `setState` because that'll blow away the webview :( + React.findDOMNode(@refs.spinner).style.visibility = "hidden" + + url = webview.getUrl() + if url.indexOf('/connect/complete') != -1 + query = url.split('?')[1] + query = query[0..-2] if query[query.length - 1] is '#' + token = querystring.decode(query) + + EdgehillAPI.addTokens([token]) + OnboardingActions.moveToPage('add-account-success') + else if url.indexOf('cancelled') != -1 + OnboardingActions.moveToPreviousPage() + + + +module.exports = ExternalAuthWebviewPage diff --git a/internal_packages/onboarding/lib/login-page.cjsx b/internal_packages/onboarding/lib/login-page.cjsx new file mode 100644 index 000000000..d120c4950 --- /dev/null +++ b/internal_packages/onboarding/lib/login-page.cjsx @@ -0,0 +1,87 @@ +React = require 'react' + +{RetinaImg} = require 'nylas-component-kit' +{EdgehillAPI} = require 'nylas-exports' + +Page = require './page' +OnboardingActions = require './onboarding-actions' +NylasApiEnvironmentStore = require './nylas-api-environment-store' + +class LoginPage extends Page + @displayName: "LoginPage" + + constructor: (@props) -> + @state = + email: "" + environment: NylasApiEnvironmentStore.getEnvironment() + + componentDidMount: -> + @_usub = NylasApiEnvironmentStore.listen => + @setState environment: NylasApiEnvironmentStore.getEnvironment() + + componentWillUnmount: -> + @_usub?() + + render: => +
+ {@_renderClose("quit")} + + + +

Welcome to Nylas

+ + + +
+
Enter your email address:
+ + + + + {@_environmentComponent()} +
+ +
+ + _renderError: -> + if @state.error +
+ {@state.error} +
+ else
+ + _onEmailChange: (event) => + @setState email: event.target.value + + _onSubmit: (e) => + valid = React.findDOMNode(@refs.form).reportValidity() + if valid + url = EdgehillAPI.urlForConnecting("inbox", @state.email) + OnboardingActions.moveToPage("add-account-auth", {url}) + else + e.preventDefault() + + _environmentComponent: => + return
unless atom.inDevMode() +
+ +
+ + _onEnvChange: (event) => + OnboardingActions.changeAPIEnvironment event.target.value + +module.exports = LoginPage diff --git a/internal_packages/onboarding/lib/main.cjsx b/internal_packages/onboarding/lib/main.cjsx index 89119beca..2f3c9bbe1 100644 --- a/internal_packages/onboarding/lib/main.cjsx +++ b/internal_packages/onboarding/lib/main.cjsx @@ -1,11 +1,14 @@ -ContainerView = require './container-view' +PageRouter = require "./page-router" {WorkspaceStore, ComponentRegistry} = require 'nylas-exports' module.exports = item: null activate: (@state) -> + # This package does nothing in other windows + return unless atom.getWindowType() is 'onboarding' + WorkspaceStore.defineSheet 'Main', {root: true}, list: ['Center'] - ComponentRegistry.register ContainerView, + ComponentRegistry.register PageRouter, location: WorkspaceStore.Location.Center diff --git a/internal_packages/onboarding/lib/nylas-api-environment-store.coffee b/internal_packages/onboarding/lib/nylas-api-environment-store.coffee new file mode 100644 index 000000000..18efc33bb --- /dev/null +++ b/internal_packages/onboarding/lib/nylas-api-environment-store.coffee @@ -0,0 +1,18 @@ +Actions = require './onboarding-actions' +NylasStore = require 'nylas-store' + +class NylasApiEnvironmentStore extends NylasStore + constructor: -> + @listenTo Actions.changeAPIEnvironment, @_setEnvironment + + defaultEnv = if atom.inDevMode() then 'staging' else 'staging' + @_setEnvironment(defaultEnv) unless atom.config.get('env') + + getEnvironment: -> atom.config.get('env') + + _setEnvironment: (env) -> + throw new Error("Environment #{env} is not allowed") unless env in ['development', 'staging', 'production'] + atom.config.set('env', env) + @trigger() + +module.exports = new NylasApiEnvironmentStore() diff --git a/internal_packages/onboarding/lib/onboarding-actions.coffee b/internal_packages/onboarding/lib/onboarding-actions.coffee index 51e35b01a..0075f44ef 100644 --- a/internal_packages/onboarding/lib/onboarding-actions.coffee +++ b/internal_packages/onboarding/lib/onboarding-actions.coffee @@ -1,13 +1,14 @@ Reflux = require 'reflux' -actions = [ - "setEnvironment", - "authErrorOccurred", - "startConnect", - "finishedConnect", - "moveToPreviousPage", +OnboardingActions = Reflux.createActions [ + "changeAPIEnvironment" + "loadExternalAuthPage" + + "moveToPreviousPage" "moveToPage" ] -module.exports = -Actions = Reflux.createActions(actions) +for key, action of OnboardingActions + action.sync = true + +module.exports = OnboardingActions diff --git a/internal_packages/onboarding/lib/onboarding-store.coffee b/internal_packages/onboarding/lib/onboarding-store.coffee deleted file mode 100644 index 7473cf348..000000000 --- a/internal_packages/onboarding/lib/onboarding-store.coffee +++ /dev/null @@ -1,64 +0,0 @@ -Reflux = require 'reflux' -Actions = require './onboarding-actions' -{EdgehillAPI} = require 'nylas-exports' -ipc = require 'ipc' - -return unless atom.getWindowType() is "onboarding" - -module.exports = -OnboardingStore = Reflux.createStore - init: -> - @_error = '' - @_page = atom.getLoadSettings().page || 'welcome' - - @_pageStack = [@_page] - - # For the time being, always use staging - defaultEnv = if atom.inDevMode() then 'staging' else 'staging' - atom.config.set('env', defaultEnv) unless atom.config.get('env') - - @listenTo Actions.setEnvironment, @_onSetEnvironment - @listenTo Actions.moveToPreviousPage, @_onMoveToPreviousPage - @listenTo Actions.moveToPage, @_onMoveToPage - @listenTo Actions.startConnect, @_onStartConnect - @listenTo Actions.finishedConnect, @_onFinishedConnect - - page: -> - @_page - - error: -> - @_error - - environment: -> - atom.config.get('env') - - connectType: -> - @_connectType - - _onMoveToPreviousPage: -> - current = @_pageStack.pop() - prev = @_pageStack.pop() - @_onMoveToPage(prev) - - _onMoveToPage: (page) -> - @_error = null - @_pageStack.push(page) - @_page = page - @trigger() - - _onStartConnect: (service) -> - @_connectType = service - @_onMoveToPage('add-account-auth') - - _onFinishedConnect: (token) -> - EdgehillAPI.addTokens([token]) - @_onMoveToPage('add-account-success') - - setTimeout -> - atom.close() - , 2500 - - _onSetEnvironment: (env) -> - throw new Error("Environment #{env} is not allowed") unless env in ['development', 'staging', 'production'] - atom.config.set('env', env) - @trigger() diff --git a/internal_packages/onboarding/lib/page-router-store.coffee b/internal_packages/onboarding/lib/page-router-store.coffee new file mode 100644 index 000000000..77eff3e63 --- /dev/null +++ b/internal_packages/onboarding/lib/page-router-store.coffee @@ -0,0 +1,41 @@ +Reflux = require 'reflux' +OnboardingActions = require './onboarding-actions' +NylasStore = require 'nylas-store' +ipc = require 'ipc' + +return unless atom.getWindowType() is "onboarding" + +class PageRouterStore extends NylasStore + constructor: -> + atom.onWindowPropsReceived @_onWindowPropsChagned + + @_page = atom.getWindowProps().page ? '' + @_pageData = atom.getWindowProps().pageData ? {} + + @_pageStack = [{page: @_page, pageData: @_pageData}] + + @listenTo OnboardingActions.moveToPreviousPage, @_onMoveToPreviousPage + @listenTo OnboardingActions.moveToPage, @_onMoveToPage + + _onWindowPropsChagned: ({page, pageData}={}) => + @_onMoveToPage(page, pageData) + + page: -> @_page + + pageData: -> @_pageData + + connectType: -> + @_connectType + + _onMoveToPreviousPage: -> + current = @_pageStack.pop() + prev = @_pageStack.pop() + @_onMoveToPage(prev.page, prev.pageData) + + _onMoveToPage: (page, pageData={}) -> + @_pageStack.push({page, pageData}) + @_page = page + @_pageData = pageData + @trigger() + +module.exports = new PageRouterStore() diff --git a/internal_packages/onboarding/lib/page-router.cjsx b/internal_packages/onboarding/lib/page-router.cjsx new file mode 100644 index 000000000..78136abc7 --- /dev/null +++ b/internal_packages/onboarding/lib/page-router.cjsx @@ -0,0 +1,62 @@ +React = require 'react/addons' +OnboardingActions = require './onboarding-actions' +ReactCSSTransitionGroup = React.addons.CSSTransitionGroup +PageRouterStore = require './page-router-store' + +LoginPage = require './login-page' +ConnectAccountPage = require './connect-account-page' +ExternalAuthWebviewPage = require './external-auth-webview-page' +SuccessPage = require './success-page' + +class PageRouter extends React.Component + @displayName: 'PageRouter' + @containerRequired: false + + constructor: (@props) -> + @state = @_getStateFromStore() + window.OnboardingActions = OnboardingActions + + _getStateFromStore: => + page: PageRouterStore.page() + pageData: PageRouterStore.pageData() + + componentDidMount: => + @unsubscribe = PageRouterStore.listen(@_onStateChanged, @) + + _onStateChanged: => @setState(@_getStateFromStore()) + + componentWillUnmount: => @unsubscribe?() + + render: => +
+ + {@_renderCurrentPage()} + {@_renderDragRegion()} + +
+ + _renderCurrentPage: => + switch @state.page + when "welcome" + + when "add-account" + + when "add-account-auth" + + when "add-account-success" + + else +
+ + _renderDragRegion: -> + styles = + top:0 + left:40 + right:0 + height: 20 + zIndex:100 + position: 'absolute' + "WebkitAppRegion": "drag" +
+ +module.exports = PageRouter diff --git a/internal_packages/onboarding/lib/page.cjsx b/internal_packages/onboarding/lib/page.cjsx new file mode 100644 index 000000000..e69054f07 --- /dev/null +++ b/internal_packages/onboarding/lib/page.cjsx @@ -0,0 +1,36 @@ +React = require 'react' +{RetinaImg} = require 'nylas-component-kit' + +class Page extends React.Component + @displayName: "Page" + + constructor: (@props) -> + + _renderClose: (action="close") -> + if action is "close" + onClick = -> atom.close() + else if action is "quit" + onClick = -> + require('ipc').send('command', 'application:quit') + else onClick = -> + +
+ +
+ + _renderSpinner: -> + styles = + position: "absolute" + zIndex: 10 + top: "50%" + left: "50%" + width: "256px" + marginLeft: "-128px" + marginTop: "-128px" + + + +module.exports = Page diff --git a/internal_packages/onboarding/lib/success-page.cjsx b/internal_packages/onboarding/lib/success-page.cjsx new file mode 100644 index 000000000..c5b88fda4 --- /dev/null +++ b/internal_packages/onboarding/lib/success-page.cjsx @@ -0,0 +1,23 @@ +React = require 'react' +Page = require './page' +{RetinaImg} = require 'nylas-component-kit' + +class SuccessPage extends Page + @displayName: "SuccessPage" + + componentDidMount: -> + setTimeout -> + atom.close() + , 2500 + + render: => + # http://codepen.io/stevenfabre/pen/NPWeVb +
+
+ + + +
+
+ +module.exports = SuccessPage diff --git a/internal_packages/onboarding/package.json b/internal_packages/onboarding/package.json index cbbd09686..676e88b21 100755 --- a/internal_packages/onboarding/package.json +++ b/internal_packages/onboarding/package.json @@ -9,5 +9,8 @@ "atom": "*" }, "dependencies": { + }, + "windowTypes": { + "onboarding": true } } diff --git a/internal_packages/onboarding/spec/login-page-spec.cjsx b/internal_packages/onboarding/spec/login-page-spec.cjsx new file mode 100644 index 000000000..f051cc956 --- /dev/null +++ b/internal_packages/onboarding/spec/login-page-spec.cjsx @@ -0,0 +1,45 @@ +_ = require "underscore" +React = require "react/addons" +ReactTestUtils = React.addons.TestUtils + +LoginPage = require '../lib/login-page' +OnboardingActions = require '../lib/onboarding-actions' + +describe "LoginPage", -> + + it "shows env picker in Dev Mode", -> + spyOn(atom, "inDevMode").andReturn true + @loginPage = ReactTestUtils.renderIntoDocument() + picker = ReactTestUtils.findRenderedDOMComponentWithClass(@loginPage, "environment-selector") + expect(picker).toBeDefined() + + it "hides env picker in other modes", -> + spyOn(atom, "inDevMode").andReturn false + @loginPage = ReactTestUtils.renderIntoDocument() + expect(-> ReactTestUtils.findRenderedDOMComponentWithClass(@loginPage, "environment-selector")).toThrow() + + it 'can change the environment', -> + spyOn(atom, "inDevMode").andReturn true + spyOn(OnboardingActions, "changeAPIEnvironment") + @loginPage = ReactTestUtils.renderIntoDocument() + sel = ReactTestUtils.findRenderedDOMComponentWithTag(@loginPage, "select") + ReactTestUtils.Simulate.change(sel, {target: {value: 'staging'}}) + expect(OnboardingActions.changeAPIEnvironment).toHaveBeenCalledWith("staging") + + describe "logging in", -> + beforeEach -> + @connectURL = "foo" + spyOn(OnboardingActions, "moveToPage") + @loginPage = ReactTestUtils.renderIntoDocument() + + hasEmail = (email) -> + page = OnboardingActions.moveToPage.calls[0].args[0] + data = OnboardingActions.moveToPage.calls[0].args[1] + expect(page).toBe "add-account-auth" + expect(data.url.length).toBeGreaterThan 0 + + it "submits information when the form submits", -> + @loginPage.setState email: "test@nylas.com" + form = ReactTestUtils.findRenderedDOMComponentWithClass(@loginPage, 'email-form') + ReactTestUtils.Simulate.submit(form) + hasEmail("test@nylas.com") diff --git a/internal_packages/onboarding/spec/nylas-api-environment-store-spec.coffee b/internal_packages/onboarding/spec/nylas-api-environment-store-spec.coffee new file mode 100644 index 000000000..c6da261b6 --- /dev/null +++ b/internal_packages/onboarding/spec/nylas-api-environment-store-spec.coffee @@ -0,0 +1,35 @@ +Actions = require '../lib/onboarding-actions' +NylasApiEnvironmentStore = require '../lib/nylas-api-environment-store' +storeConstructor = NylasApiEnvironmentStore.constructor + +describe "NylasApiEnvironmentStore", -> + beforeEach -> + spyOn(atom.config, "set") + + it "doesn't set if it alreayd exists", -> + spyOn(atom.config, "get").andReturn "staging" + store = new storeConstructor() + expect(atom.config.set).not.toHaveBeenCalled() + + it "initializes with the correct default in dev mode", -> + spyOn(atom, "inDevMode").andReturn true + spyOn(atom.config, "get").andReturn undefined + store = new storeConstructor() + expect(atom.config.set).toHaveBeenCalledWith("env", "staging") + + it "initializes with the correct default in production", -> + spyOn(atom, "inDevMode").andReturn false + spyOn(atom.config, "get").andReturn undefined + store = new storeConstructor() + expect(atom.config.set).toHaveBeenCalledWith("env", "staging") + + describe "when setting the environment", -> + it "sets from the desired action", -> + Actions.changeAPIEnvironment("production") + expect(atom.config.set).toHaveBeenCalledWith("env", "production") + + it "throws if the env is invalid", -> + expect( -> Actions.changeAPIEnvironment("bad")).toThrow() + + it "throws if the env is blank", -> + expect( -> Actions.changeAPIEnvironment()).toThrow() diff --git a/internal_packages/onboarding/stylesheets/onboarding.less b/internal_packages/onboarding/stylesheets/onboarding.less index c7bc4f9f3..9efcbf6e9 100644 --- a/internal_packages/onboarding/stylesheets/onboarding.less +++ b/internal_packages/onboarding/stylesheets/onboarding.less @@ -19,7 +19,7 @@ 100% { opacity: 1; border-width: 0; } } -.onboarding-container { +.page-frame { width:100%; height:100%; background-color: @gray-lighter; @@ -82,6 +82,9 @@ width:100%; height:100%; padding-top:15%; + &.no-top { + padding-top: 0; + } } .quit { diff --git a/src/atom.coffee b/src/atom.coffee index d3d13bdda..647a8a1f4 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -607,16 +607,15 @@ class Atom extends Model @commands.add 'atom-workspace', 'atom-workspace:add-account': => - options = + @newWindow title: 'Add an Account' - page: 'add-account' width: 340 height: 550 toolbar: false resizable: false windowType: 'onboarding' - windowPackages: ['onboarding'] - ipc.send('new-window', options) + windowProps: + page: 'add-account' # Make sure we can't be made so small that the interface looks like crap @getCurrentWindow().setMinimumSize(875, 500) diff --git a/src/browser/window-manager.coffee b/src/browser/window-manager.coffee index 5a857e226..8020e9c87 100644 --- a/src/browser/window-manager.coffee +++ b/src/browser/window-manager.coffee @@ -108,9 +108,9 @@ class WindowManager height: 550 resizable: false windowType: 'onboarding' - windowPackages: ['onboarding'] windowProps: - 'uniqueId': 'onboarding' + page: "welcome" + uniqueId: 'onboarding' # Makes a new window appear of a certain `windowType`. # @@ -188,7 +188,7 @@ class WindowManager # - windowPackages - A list of additional packages to load into a # window in addition to those declared in various `package.json`s # - registerHotWindow: ({windowType, replenishNum, windowPackages}={}) -> + registerHotWindow: ({windowType, replenishNum, windowPackages, windowOptions}={}) -> if not windowType throw new Error("registerHotWindow: please provide a windowType") @@ -197,6 +197,7 @@ class WindowManager @_hotWindows[windowType].replenishNum ?= (replenishNum ? 1) @_hotWindows[windowType].loadedWindows ?= [] @_hotWindows[windowType].windowPackages ?= (windowPackages ? []) + @_hotWindows[windowType].windowOptions ?= (windowOptions ? {}) @_replenishHotWindows() @@ -248,6 +249,8 @@ class WindowManager newColdWindow: (options={}) -> options = _.extend(@defaultWindowOptions(), options) win = new AtomWindow(options) + newLoadSettings = _.extend(win.loadSettings(), options) + win.setLoadSettings(newLoadSettings) win.showWhenLoaded() return win @@ -262,9 +265,9 @@ class WindowManager win = null if not hotWindowParams? - console.log "WindowManager: Warning! The requested windowType '#{options.windowType}' - has not been registered. Be sure to call `registerWindowType` first - in your packages setup." + console.log "WindowManager: Warning! The requested windowType + '#{options.windowType}' has not been registered. Be sure to call + `registerWindowType` first in your packages setup." return @newColdWindow(options) supportedHotWindowKeys = [ @@ -279,22 +282,25 @@ class WindowManager ] unsupported = _.difference(Object.keys(options), supportedHotWindowKeys) + if unsupported.length > 0 - console.log "WindowManager: Nylas will open a new hot window of type #{options.windowType}, - but you are passing options that can't be applied to the preloaded window - (#{JSON.stringify(unsupported)}). Please change the options or pass the - `coldStart:true` option to use a new window instead of a hot window. If - it's just data for the window, please put them in the `windowProps` param." + console.log "WindowManager: For the winodw of type + #{options.windowType}, you are passing options that can't be + applied to the preloaded window (#{JSON.stringify(unsupported)}). + Please change the options or pass the `coldStart:true` option to use + a new window instead of a hot window. If it's just data for the + window, please put them in the `windowProps` param." if hotWindowParams.loadedWindows.length is 0 # No windows ready + console.log "No windows ready. Loading a new coldWindow" options.windowPackages = hotWindowParams.windowPackages win = @newColdWindow(options) else [win] = hotWindowParams.loadedWindows.splice(0,1) + newLoadSettings = _.extend(win.loadSettings(), options) win.setLoadSettings(newLoadSettings) - win.showWhenLoaded() win.browserWindow.setTitle options.title ? "" @@ -307,12 +313,11 @@ class WindowManager h = options.height ? h win.browserWindow.setSize(w,h) - console.log JSON.stringify(options) if options.bounds - console.log "------------- SETTING BOUNDS" - console.log JSON.stringify(options.bounds) win.browserWindow.setBounds options.bounds + win.showWhenLoaded() + @_replenishHotWindows() return win @@ -340,7 +345,7 @@ class WindowManager numOfType = data.replenishNum - data.loadedWindows.length maxWin = Math.max(numOfType, maxWin) if numOfType > 0 - options = @defaultWindowOptions() + options = _.extend {}, @defaultWindowOptions(), data.windowOptions options.windowType = windowType options.windowPackages = data.windowPackages queues[windowType] ?= [] diff --git a/src/flux/coffee-helpers.coffee b/src/flux/coffee-helpers.coffee index a5defd94e..54d20c874 100644 --- a/src/flux/coffee-helpers.coffee +++ b/src/flux/coffee-helpers.coffee @@ -1,6 +1,6 @@ _ = require 'underscore' -module.exports = +module.exports = CoffeeHelpers = # This copied out CoffeeScript includeModule: (mixin) -> if not mixin diff --git a/static/images/empty-state/Setup-Spinner.gif b/static/images/empty-state/Setup-Spinner.gif new file mode 100644 index 000000000..558316475 Binary files /dev/null and b/static/images/empty-state/Setup-Spinner.gif differ