diff --git a/internal_packages/onboarding/lib/account-choose-page.cjsx b/internal_packages/onboarding/lib/account-choose-page.cjsx index 224ce3cec..aa4163f8b 100644 --- a/internal_packages/onboarding/lib/account-choose-page.cjsx +++ b/internal_packages/onboarding/lib/account-choose-page.cjsx @@ -1,5 +1,5 @@ React = require 'react' - +_ = require 'underscore' {RetinaImg} = require 'nylas-component-kit' {EdgehillAPI, Utils} = require 'nylas-exports' @@ -61,26 +61,32 @@ class AccountChoosePage extends Page _onChooseProvider: (provider) => if provider.name is 'gmail' - provider.clientKey = Utils.generateTempId()[6..]+'-'+Utils.generateTempId()[6..] - shell = require 'shell' - googleUrl = url.format({ - protocol: 'https' - host: 'accounts.google.com/o/oauth2/auth' - query: - response_type: 'code' - state: provider.clientKey - client_id: '372024217839-cdsnrrqfr4d6b4gmlqepd7v0n0l0ip9q.apps.googleusercontent.com' - redirect_uri: 'http://localhost:5009/oauth/google/callback' - access_type: 'offline' - scope: 'https://www.googleapis.com/auth/userinfo.email \ - https://www.googleapis.com/auth/userinfo.profile \ - https://mail.google.com/ \ - https://www.google.com/m8/feeds \ - https://www.googleapis.com/auth/calendar' - }) - shell.openExternal(googleUrl) + # Show the "Sign in to Gmail" prompt for a moment before actually bouncing + # to Gmail. (400msec animation + 200msec to read) + _.delay => + @_onBounceToGmail(provider) + , 600 OnboardingActions.moveToPage("account-settings", {provider}) + _onBounceToGmail: (provider) => + provider.clientKey = Utils.generateTempId()[6..]+'-'+Utils.generateTempId()[6..] + shell = require 'shell' + googleUrl = url.format({ + protocol: 'https' + host: 'accounts.google.com/o/oauth2/auth' + query: + response_type: 'code' + state: provider.clientKey + client_id: '372024217839-cdsnrrqfr4d6b4gmlqepd7v0n0l0ip9q.apps.googleusercontent.com' + redirect_uri: "#{EdgehillAPI.APIRoot}/oauth/google/callback" + access_type: 'offline' + scope: 'https://www.googleapis.com/auth/userinfo.email \ + https://www.googleapis.com/auth/userinfo.profile \ + https://mail.google.com/ \ + https://www.google.com/m8/feeds \ + https://www.googleapis.com/auth/calendar' + }) + shell.openExternal(googleUrl) _onSubmit: (e) => valid = React.findDOMNode(@refs.form).reportValidity() diff --git a/internal_packages/onboarding/lib/page-router.cjsx b/internal_packages/onboarding/lib/page-router.cjsx index ec8a82dce..47143cef7 100644 --- a/internal_packages/onboarding/lib/page-router.cjsx +++ b/internal_packages/onboarding/lib/page-router.cjsx @@ -22,17 +22,18 @@ class PageRouter extends React.Component pageData: PageRouterStore.pageData() componentDidMount: => - atom.setSize(667,482) @unsubscribe = PageRouterStore.listen(@_onStateChanged, @) + {width, height} = React.findDOMNode(@refs.activePage).getBoundingClientRect() + atom.center() + atom.setSizeAnimated(width, height, 0) + atom.show() componentDidUpdate: => - setTimeout( => - @_resizePage() - ,10) + setTimeout(@_resizePage, 10) _resizePage: => - {width,height} = React.findDOMNode(@refs.container).getBoundingClientRect() - atom.setSizeAnimated(width,height) + {width, height} = React.findDOMNode(@refs.activePage).getBoundingClientRect() + atom.setSizeAnimated(width, height) _onStateChanged: => @setState(@_getStateFromStore()) @@ -41,20 +42,17 @@ class PageRouter extends React.Component render: =>
{@_renderDragRegion()} -
{@_renderCurrentPage()} -
- {@_renderGradients()} - -
+ {@_renderCurrentPageGradient()} + +
- _renderGradients: => + _renderCurrentPageGradient: => gradient = @state.pageData?.provider?.color if gradient background = "linear-gradient(to top, #f6f7f8, #{gradient})" @@ -62,22 +60,20 @@ class PageRouter extends React.Component background = "linear-gradient(to top, #f6f7f8 0%, rgba(255,255,255,0) 100%), linear-gradient(to right, #e1e58f 0%, #a8d29e 50%, #8bc9c9 100%)" -
+
_renderCurrentPage: => - switch @state.page - when "welcome" - - when "account-choose" - - when "account-settings" - - when "initial-preferences" - - when "initial-packages" - - else -
+ Component = { + "welcome": WelcomePage + "account-choose": AccountChoosePage + "account-settings": AccountSettingsPage + "initial-preferences": InitialPreferencesPage + "initial-packages": InitialPackagesPage + }[@state.page] + +
+ +
_renderDragRegion: -> styles = diff --git a/internal_packages/onboarding/stylesheets/onboarding.less b/internal_packages/onboarding/stylesheets/onboarding.less index 67170ae04..8bae8bb4f 100644 --- a/internal_packages/onboarding/stylesheets/onboarding.less +++ b/internal_packages/onboarding/stylesheets/onboarding.less @@ -86,17 +86,15 @@ .page-container { z-index: 10; - display: inline-block; - position: relative; + position: absolute; + top: 0; + left: 0; + width: 100%; } .page { - //position: absolute; - //top: 0; - //width: 100%; - //height: 100%; + margin:auto; padding-top: 10%; - z-index: 10; &.no-top { padding-top: 0; } @@ -169,24 +167,20 @@ position:absolute; } .welcome-image-enter { - transform: translate(10%, 0); opacity: 0; - transition: all .3s linear; + transition: opacity .3s linear; } .welcome-image-enter.welcome-image-enter-active { opacity: 1; - transform: translate(0%, 0); } .welcome-image-leave { opacity: 1; - transform: translate(0%, 0); - transition: all .3s linear; + transition: opacity .3s linear; } .welcome-image-leave.welcome-image-leave-active { opacity: 0; - transform: translate(-10%, 0); } .check { diff --git a/internal_packages/preferences/lib/tabs/preferences-accounts.cjsx b/internal_packages/preferences/lib/tabs/preferences-accounts.cjsx index 8a688b5f7..2ec109b37 100644 --- a/internal_packages/preferences/lib/tabs/preferences-accounts.cjsx +++ b/internal_packages/preferences/lib/tabs/preferences-accounts.cjsx @@ -26,10 +26,6 @@ class PreferencesAccounts extends React.Component
{@_renderLinkedAccounts()} - -
- -
_renderAccounts: => @@ -123,8 +119,4 @@ class PreferencesAccounts extends React.Component EdgehillAPI.unlinkToken(token) return - _onLogout: => - atom.logout() - - module.exports = PreferencesAccounts diff --git a/menus/darwin.cson b/menus/darwin.cson index 12dd00f1b..47d9923f3 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -6,8 +6,7 @@ { type: 'separator' } { label: 'Preferences', command: 'application:open-preferences' } { type: 'separator' } - { label: 'Link External Account', command: 'atom-workspace:add-account' } - { label: 'Log Out', command: 'application:logout' } + { label: 'Add Account...', command: 'atom-workspace:add-account' } { label: 'VERSION', enabled: false } { label: 'Restart and Install Update', command: 'application:install-update', visible: false} { label: 'Check for Update', command: 'application:check-for-update', visible: false} diff --git a/menus/linux.cson b/menus/linux.cson index 2f260f8d8..c66355f1b 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -5,8 +5,7 @@ { label: '&New Message', command: 'application:new-message' } { type: 'separator' } { label: 'Preferences', command: 'application:open-preferences' } - { label: 'Link External Account', command: 'atom-workspace:add-account' } - { label: 'Log Out', command: 'application:logout' } + { label: 'Add Account...', command: 'atom-workspace:add-account' } { label: 'Clos&e Window', command: 'window:close' } { label: 'Quit', command: 'application:quit' } ] diff --git a/menus/win32.cson b/menus/win32.cson index 161d25e98..1506c7138 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -1,5 +1,5 @@ 'menu': [ - { label: 'Link External Account', command: 'atom-workspace:add-account' } + { label: 'Add Account...', command: 'atom-workspace:add-account' } { label: '&Edit' submenu: [ @@ -55,7 +55,6 @@ } { type: 'separator' } { label: 'Preferences', command: 'application:open-preferences' } - { label: 'Log Out', command: 'application:logout' } { type: 'separator' } { label: 'E&xit', command: 'application:quit' } ] diff --git a/spec-nylas/action-bridge-spec.coffee b/spec-nylas/action-bridge-spec.coffee index 186f3e967..5c88cb669 100644 --- a/spec-nylas/action-bridge-spec.coffee +++ b/spec-nylas/action-bridge-spec.coffee @@ -83,19 +83,19 @@ describe "ActionBridge", -> describe "when called with TargetWindows.ALL", -> it "should broadcast the action over IPC to all windows", -> spyOn(ipc, 'send') - Actions.logout.firing = false - @bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'logout', [{oldModel: '1', newModel: 2}]) - expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-all', 'popout', 'logout', '[{"oldModel":"1","newModel":2}]') + Actions.didPassivelyReceiveNewModels.firing = false + @bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'didPassivelyReceiveNewModels', [{oldModel: '1', newModel: 2}]) + expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-all', 'popout', 'didPassivelyReceiveNewModels', '[{"oldModel":"1","newModel":2}]') describe "when called with TargetWindows.WORK", -> it "should broadcast the action over IPC to the main window only", -> spyOn(ipc, 'send') - Actions.logout.firing = false - @bridge.onRebroadcast(ActionBridge.TargetWindows.WORK, 'logout', [{oldModel: '1', newModel: 2}]) - expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-work', 'popout', 'logout', '[{"oldModel":"1","newModel":2}]') + Actions.didPassivelyReceiveNewModels.firing = false + @bridge.onRebroadcast(ActionBridge.TargetWindows.WORK, 'didPassivelyReceiveNewModels', [{oldModel: '1', newModel: 2}]) + expect(ipc.send).toHaveBeenCalledWith('action-bridge-rebroadcast-to-work', 'popout', 'didPassivelyReceiveNewModels', '[{"oldModel":"1","newModel":2}]') it "should not do anything if the current invocation of the Action was triggered by itself", -> spyOn(ipc, 'send') - Actions.logout.firing = true - @bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'logout', [{oldModel: '1', newModel: 2}]) + Actions.didPassivelyReceiveNewModels.firing = true + @bridge.onRebroadcast(ActionBridge.TargetWindows.ALL, 'didPassivelyReceiveNewModels', [{oldModel: '1', newModel: 2}]) expect(ipc.send).not.toHaveBeenCalled() diff --git a/spec-nylas/nylas-api-spec.coffee b/spec-nylas/nylas-api-spec.coffee index 372b154e1..8a5f76c52 100644 --- a/spec-nylas/nylas-api-spec.coffee +++ b/spec-nylas/nylas-api-spec.coffee @@ -52,7 +52,7 @@ describe "NylasAPI", -> spyOn(Actions, 'postNotification') NylasAPI._handle401('/threads/1234') expect(Actions.postNotification).toHaveBeenCalled() - expect(Actions.postNotification.mostRecentCall.args[0].message).toEqual("Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please log out and sign in again.") + expect(Actions.postNotification.mostRecentCall.args[0].message).toEqual("Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please unlink your account and sign in again.") describe "handleModelResponse", -> diff --git a/src/atom.coffee b/src/atom.coffee index 875315227..4cbf17d2d 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -389,9 +389,6 @@ class Atom extends Model isReleasedVersion: -> not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix - logout: -> - ipc.send('command', 'application:logout') - # Public: Get the directory path to Atom's configuration area. # # Returns the absolute path to `~/.atom`. @@ -443,16 +440,23 @@ class Atom extends Model # * `duration` The {Number} of pixels. setSizeAnimated: (width, height, duration=400) -> cubicInOut = (t) -> if t<.5 then 4*t**3 else (t-1)*(2*t-2)**2+1 - {width:startWidth,height:startHeight} = @getSize() + win = @getCurrentWindow() + startBounds = win.getBounds() + startTime = Date.now() - while (t = (Date.now() - startTime) / (duration)) < 1 + boundsForI = (i) -> + x: Math.round(startBounds.x + (width-startBounds.width) * -0.5 * i) + y: Math.round(startBounds.y + (height-startBounds.height) * -0.5 * i) + width: Math.round(startBounds.width + (width-startBounds.width) * i) + height: Math.round(startBounds.height + (height-startBounds.height) * i) + + tick = -> + t = Math.min(1, (Date.now() - startTime) / (duration)) i = cubicInOut(t) - @setSize( - Math.round(startWidth + (width-startWidth) * i), - Math.round(startHeight + (height-startHeight) * i)) - @setSize(width, height) - - + win.setBounds(boundsForI(i)) + unless t is 1 + _.defer(tick) + tick() setMinimumWidth: (minWidth) -> win = @getCurrentWindow() diff --git a/src/browser/application.coffee b/src/browser/application.coffee index ea8bbce0a..dc61b95cf 100644 --- a/src/browser/application.coffee +++ b/src/browser/application.coffee @@ -159,9 +159,10 @@ class Application @windowManager.showMainWindow() @windowManager.ensureWorkWindow() else - @windowManager.newOnboardingWindow().showWhenLoaded() - - _logout: => + @windowManager.newOnboardingWindow() + # The onboarding window automatically shows when it's ready + + _resetConfigAndRelaunch: => @setDatabasePhase('close') @windowManager.closeAllWindows() @_deleteDatabase => @@ -247,7 +248,7 @@ class Application @on 'application:run-benchmarks', -> @runBenchmarks() - @on 'application:logout', @_logout + @on 'application:reset-config-and-relaunch', @_resetConfigAndRelaunch @on 'application:quit', => app.quit() @on 'application:inspect', ({x,y, atomWindow}) -> diff --git a/src/browser/window-manager.coffee b/src/browser/window-manager.coffee index 217baa25a..c9601226d 100644 --- a/src/browser/window-manager.coffee +++ b/src/browser/window-manager.coffee @@ -128,9 +128,8 @@ class WindowManager @newWindow title: 'Welcome to Nylas' toolbar: false - width: 340 - height: 550 resizable: false + hidden: true windowType: 'onboarding' windowProps: page: "welcome" diff --git a/src/flux/actions.coffee b/src/flux/actions.coffee index e5716d349..96282044d 100644 --- a/src/flux/actions.coffee +++ b/src/flux/actions.coffee @@ -74,14 +74,6 @@ class Actions ### @didPassivelyReceiveNewModels: ActionScopeGlobal - ### - Public: Log out the current user. Closes the main application window and takes - the user back to the sign-in window. - - *Scope: Global* - ### - @logout: ActionScopeGlobal - @uploadStateChanged: ActionScopeGlobal @fileAborted: ActionScopeGlobal @downloadStateChanged: ActionScopeGlobal @@ -371,7 +363,7 @@ class Actions Public: Fire to display an in-window notification to the user in the app's standard notification interface. - *Scope: Window* + *Scope: Global* ``` # A simple notification @@ -396,13 +388,13 @@ class Actions ``` ### - @postNotification: ActionScopeWindow + @postNotification: ActionScopeGlobal ### Public: Listen to this action to handle user interaction with notifications you published via `postNotification`. - *Scope: Window* + *Scope: Global* ``` @_unlisten = Actions.notificationActionTaken.listen(@_onActionTaken, @) @@ -412,7 +404,7 @@ class Actions # perform action ``` ### - @notificationActionTaken: ActionScopeWindow + @notificationActionTaken: ActionScopeGlobal # FullContact Sidebar @getFullContactDetails: ActionScopeWindow diff --git a/src/flux/nylas-api.coffee b/src/flux/nylas-api.coffee index 43e711509..4cb568806 100644 --- a/src/flux/nylas-api.coffee +++ b/src/flux/nylas-api.coffee @@ -134,8 +134,13 @@ class NylasAPI @APITokens = tokens.map (t) -> t.access_token env = atom.config.get('env') + if not env + env = 'production' + console.error("NylasAPI: config.cson does not contain an environment \ + value. Defaulting to `production`.") + if env in ['production'] - @AppID = 'c96gge1jo29pl2rebcb7utsbp' + @AppID = 'eco3rpsghu81xdc48t5qugwq7' @APIRoot = 'https://api.nylas.com' else if env in ['staging', 'development'] @AppID = '54miogmnotxuo5st254trcmb9' @@ -229,17 +234,18 @@ class NylasAPI type: 'error' tag: '401' sticky: true - message: "Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please log out and sign in again.", + message: "Nylas can no longer authenticate with your mail provider. You will not be able to send or receive mail. Please unlink your account and sign in again.", icon: 'fa-sign-out' actions: [{ - label: 'Log Out' - id: '401:logout' + label: 'Unlink' + id: '401:unlink' }] unless @_notificationUnlisten handler = ({notification, action}) -> - if action.id is '401:logout' - atom.logout() + if action.id is '401:unlink' + ipc = require 'ipc' + ipc.send('command', 'application:reset-config-and-relaunch') @_notificationUnlisten = Actions.notificationActionTaken.listen(handler, @) return Promise.resolve()