feat(onboarding): improve onboarding flow
Summary: Now with more CSS Also fixed flow for when you're just adding an account Fixes T3805 Test Plan: manual :( Reviewers: drew, bengotow Reviewed By: bengotow Maniphest Tasks: T3805 Differential Revision: https://phab.nylas.com/D2071
|
@ -115,9 +115,8 @@ class AccountSwitcher extends React.Component
|
|||
@setState(showing: false)
|
||||
|
||||
_onAddAccount: =>
|
||||
ipc = require('ipc')
|
||||
ipc.send('command', 'application:add-account')
|
||||
@setState(showing: false)
|
||||
require('remote').getGlobal('application').windowManager.newOnboardingWindow(addingAccount: true)
|
||||
@setState showing: false
|
||||
|
||||
_getStateFromStores: =>
|
||||
accounts: AccountStore.items()
|
||||
|
|
BIN
internal_packages/onboarding/assets/cloud@2x.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
internal_packages/onboarding/assets/gear-large@2x.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
internal_packages/onboarding/assets/gear-small@2x.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
internal_packages/onboarding/assets/lock@2x.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
internal_packages/onboarding/assets/nylas-pictograph@2x.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
internal_packages/onboarding/assets/shapes-left@2x.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
internal_packages/onboarding/assets/shapes-right@2x.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
internal_packages/onboarding/assets/wrench@2x.png
Normal file
After Width: | Height: | Size: 14 KiB |
|
@ -25,16 +25,15 @@ class AccountChoosePage extends React.Component
|
|||
@_usub?()
|
||||
|
||||
render: =>
|
||||
closeType = if @props.pageData.addingAccount then "close" else "quit"
|
||||
<div className="page account-choose">
|
||||
<div className="quit" onClick={ => atom.close() }>
|
||||
<div className="quit" onClick={ => atom[closeType]() }>
|
||||
<RetinaImg name="onboarding-close.png" mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
|
||||
<div className="logo-container">
|
||||
<RetinaImg name="onboarding-logo.png" mode={RetinaImg.Mode.ContentPreserve} className="logo"/>
|
||||
</div>
|
||||
<RetinaImg url="nylas://onboarding/assets/nylas-pictograph@2x.png" mode={RetinaImg.Mode.ContentIsMask} style={zoom: 0.29} className="logo"/>
|
||||
|
||||
<div className="caption" style={marginBottom:20}>Select your email provider</div>
|
||||
<div className="caption" style={marginTop: 15, marginBottom:20}>Select your email provider</div>
|
||||
|
||||
{@_renderProviders()}
|
||||
|
||||
|
@ -47,7 +46,7 @@ class AccountChoosePage extends React.Component
|
|||
<div className="icon-container">
|
||||
<RetinaImg name={provider.icon} mode={RetinaImg.Mode.ContentPreserve} className="icon"/>
|
||||
</div>
|
||||
{provider.displayName}
|
||||
<span className="provider-name">{provider.displayName}</span>
|
||||
</div>
|
||||
|
||||
_renderError: ->
|
||||
|
|
|
@ -158,15 +158,15 @@ class AccountSettingsPage extends React.Component
|
|||
|
||||
_renderButton: =>
|
||||
pages = @state.provider.pages || []
|
||||
if pages.length > @state.pageNumber + 1
|
||||
<button className="btn btn-large btn-gradient" type="button" onClick={@_onNextButton}>Next</button>
|
||||
if pages.length > @state.pageNumber+1
|
||||
<button className="btn btn-large btn-gradient" type="button" onClick={@_onNextButton}>Continue</button>
|
||||
else if @state.provider.name isnt 'gmail'
|
||||
if @state.tryingToAuthenticate
|
||||
<button className="btn btn-large btn-gradient btn-setup-spinning" type="button">
|
||||
<RetinaImg name="sending-spinner.gif" width={15} height={15} mode={RetinaImg.Mode.ContentPreserve} /> Setting up…
|
||||
<RetinaImg name="sending-spinner.gif" width={15} height={15} mode={RetinaImg.Mode.ContentPreserve} /> Adding account…
|
||||
</button>
|
||||
else
|
||||
<button className="btn btn-large btn-gradient" type="button" onClick={@_onSubmit}>Set up account</button>
|
||||
<button className="btn btn-large btn-gradient" type="button" onClick={@_onSubmit}>Add account</button>
|
||||
|
||||
_onNextButton: (event) =>
|
||||
@setState(pageNumber: @state.pageNumber + 1)
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
Providers = [
|
||||
{
|
||||
name: 'gmail'
|
||||
displayName: 'Gmail'
|
||||
icon: 'ic-settings-account-gmail.png'
|
||||
header_icon: 'setup-icon-provider-gmail.png'
|
||||
color: '#e99999'
|
||||
settings: []
|
||||
}, {
|
||||
name: 'exchange'
|
||||
displayName: 'Microsoft Exchange / Live'
|
||||
icon: 'ic-settings-account-eas.png'
|
||||
|
@ -34,38 +41,6 @@ Providers = [
|
|||
}
|
||||
]
|
||||
}, {
|
||||
# name: 'outlook'
|
||||
# displayName: 'Outlook / Hotmail'
|
||||
# icon: 'ic-settings-account-eas.png'
|
||||
# header_icon: 'setup-icon-provider-hotmail.png'
|
||||
# color: '#308acd'
|
||||
# fields: [
|
||||
# {
|
||||
# name: 'name'
|
||||
# type: 'text'
|
||||
# placeholder: 'Ashton Letterman'
|
||||
# label: 'Name'
|
||||
# }, {
|
||||
# name: 'email'
|
||||
# type: 'text'
|
||||
# placeholder: 'you@hotmail.com'
|
||||
# label: 'Email'
|
||||
# }
|
||||
# ]
|
||||
# settings: [
|
||||
# {
|
||||
# name: 'username'
|
||||
# type: 'text'
|
||||
# placeholder: 'MYCORP\\bob (if known)'
|
||||
# label: 'Username (optional)'
|
||||
# },{
|
||||
# name: 'password'
|
||||
# type: 'password'
|
||||
# placeholder: 'Password'
|
||||
# label: 'Password'
|
||||
# }
|
||||
# ]
|
||||
# }, {
|
||||
name: 'icloud'
|
||||
displayName: 'iCloud'
|
||||
icon: 'ic-settings-account-icloud.png'
|
||||
|
@ -90,13 +65,6 @@ Providers = [
|
|||
placeholder: 'Password'
|
||||
label: 'Password'
|
||||
}]
|
||||
}, {
|
||||
name: 'gmail'
|
||||
displayName: 'Gmail'
|
||||
icon: 'ic-settings-account-gmail.png'
|
||||
header_icon: 'setup-icon-provider-gmail.png'
|
||||
color: '#e99999'
|
||||
settings: []
|
||||
}, {
|
||||
name: 'yahoo'
|
||||
displayName: 'Yahoo'
|
||||
|
@ -246,4 +214,4 @@ Providers = [
|
|||
}
|
||||
]
|
||||
|
||||
module.exports = Providers
|
||||
module.exports = Providers
|
||||
|
|
|
@ -61,7 +61,11 @@ class InitialPackagesPage extends React.Component
|
|||
@displayName: "InitialPackagesPage"
|
||||
|
||||
render: =>
|
||||
closeType = if @props.pageData.addingAccount then "close" else "quit"
|
||||
<div className="page no-top opaque" style={width:900, height:650}>
|
||||
<div className="quit" onClick={ => atom[closeType]() }>
|
||||
<RetinaImg name="onboarding-close.png" mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
<div className="back" onClick={@_onPrevPage}>
|
||||
<RetinaImg name="onboarding-back.png" mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
|
|
|
@ -80,7 +80,11 @@ class InitialPreferencesPage extends React.Component
|
|||
@displayName: "InitialPreferencesPage"
|
||||
|
||||
render: =>
|
||||
closeType = if @props.pageData.addingAccount then "close" else "quit"
|
||||
<div className="page no-top opaque" style={width:900, height:620}>
|
||||
<div className="quit" onClick={ => atom[closeType]() }>
|
||||
<RetinaImg name="onboarding-close.png" mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
<h1 style={paddingTop: 100}>Welcome to N1</h1>
|
||||
<h4 style={marginBottom: 70}>Let's set things up to your liking.</h4>
|
||||
<ConfigPropContainer>
|
||||
|
|
|
@ -64,11 +64,11 @@ class PageRouter extends React.Component
|
|||
gradient = @state.pageData?.provider?.color
|
||||
if gradient
|
||||
background = "linear-gradient(to top, #f6f7f8, #{gradient})"
|
||||
height = 200
|
||||
else
|
||||
background = "linear-gradient(to top, #f6f7f8 0%, rgba(255,255,255,0) 100%),
|
||||
linear-gradient(to right, #e1e58f 0%, #a8d29e 50%, #8bc9c9 100%)"
|
||||
|
||||
<div className="page-gradient" key={"#{@state.page}-gradient"} style={background: background}/>
|
||||
background = "linear-gradient(to top, #f6f7f8 0%, rgba(255,255,255,0) 100%), linear-gradient(to right, #e1e58f 0%, #a8d29e 50%, #8bc9c9 100%)"
|
||||
height = 330
|
||||
<div className="page-gradient" key={"#{@state.page}-gradient"} style={background: background, height: height}/>
|
||||
|
||||
_renderCurrentPage: =>
|
||||
Component = {
|
||||
|
@ -86,9 +86,9 @@ class PageRouter extends React.Component
|
|||
_renderDragRegion: ->
|
||||
styles =
|
||||
top:0
|
||||
left:40
|
||||
left: 26
|
||||
right:0
|
||||
height: 20
|
||||
height: 27
|
||||
zIndex:100
|
||||
position: 'absolute'
|
||||
"WebkitAppRegion": "drag"
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
React = require 'react'
|
||||
shell = require 'shell'
|
||||
classnames = require 'classnames'
|
||||
{RetinaImg, TimeoutTransitionGroup} = require 'nylas-component-kit'
|
||||
OnboardingActions = require './onboarding-actions'
|
||||
|
||||
|
@ -8,44 +10,107 @@ class WelcomePage extends React.Component
|
|||
constructor: (@props) ->
|
||||
@state =
|
||||
step: 0
|
||||
lastStep: 0
|
||||
|
||||
render: =>
|
||||
buttons = []
|
||||
if @state.step > 0
|
||||
buttons.push <button key="back" className="btn btn-large" style={marginRight: 10} onClick={@_onBack}>Back</button>
|
||||
buttons.push <button key="next" className="btn btn-large" onClick={@_onContinue}>Continue</button>
|
||||
|
||||
<div className="page no-top opaque" style={width: 667, display: "inline-block"}>
|
||||
<div className="quit" onClick={ => atom.close() }>
|
||||
render: ->
|
||||
closeType = if @props.pageData.addingAccount then "close" else "quit"
|
||||
<div className="welcome-page page no-top opaque">
|
||||
<div className="quit" onClick={ => atom[closeType]() }>
|
||||
<RetinaImg name="onboarding-close.png" mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
|
||||
<TimeoutTransitionGroup leaveTimeout={300}
|
||||
enterTimeout={300}
|
||||
className="welcome-image-container"
|
||||
transitionName="welcome-image">
|
||||
{@_renderStep()}
|
||||
</TimeoutTransitionGroup>
|
||||
|
||||
<div style={textAlign:'center', paddingTop:30, paddingBottom:30}>
|
||||
{buttons}
|
||||
</div>
|
||||
<div className="steps-container">{@_renderSteps()}</div>
|
||||
<div className="footer">{@_renderButtons()}</div>
|
||||
</div>
|
||||
|
||||
_renderStep: =>
|
||||
if @state.step is 0
|
||||
<div className="welcome-image" key="step-0">
|
||||
<RetinaImg name="welcome1bg.png" mode={RetinaImg.Mode.ContentPreserve} />
|
||||
<RetinaImg name="welcome1icon.png" mode={RetinaImg.Mode.ContentPreserve} style={position:'absolute', top:'50%', left:'50%', transform:'translate(-50%, -50%)'}/>
|
||||
</div>
|
||||
else if @state.step is 1
|
||||
<div className="welcome-image" key="step-1">
|
||||
<RetinaImg name="welcome2bg.png" mode={RetinaImg.Mode.ContentPreserve} />
|
||||
</div>
|
||||
else if @state.step is 2
|
||||
<div className="welcome-image" key="step-2">
|
||||
<RetinaImg name="welcome3bg.png" mode={RetinaImg.Mode.ContentPreserve} />
|
||||
_renderButtons: ->
|
||||
buttons = []
|
||||
# if @state.step > 0
|
||||
# buttons.push <span key="back" className="btn-back" onClick={@_onBack}>Back</span>
|
||||
btnText = if @state.step is 2 then "Get Started" else "Continue"
|
||||
buttons.push <button key="next" className="btn btn-large btn-continue" onClick={@_onContinue}>{btnText}</button>
|
||||
return buttons
|
||||
|
||||
_renderSteps: -> [
|
||||
@_renderStep0()
|
||||
@_renderStep1()
|
||||
@_renderStep2()
|
||||
]
|
||||
|
||||
_stepClass: (n) ->
|
||||
obj =
|
||||
"step-wrap": true
|
||||
"active": @state.step is n
|
||||
obj["step-#{n}-wrap"] = true
|
||||
className = classnames(obj)
|
||||
return className
|
||||
|
||||
_renderStep0: ->
|
||||
<div className={@_stepClass(0)} key="step-0">
|
||||
<p className="hero-text" style={marginTop: 25}>N1 is a new email app that is fast,<br/>friendly, and easy to use.</p>
|
||||
<RetinaImg className="logo" style={zoom: 0.35, marginTop: 13} url="nylas://onboarding/assets/nylas-pictograph@2x.png" mode={RetinaImg.Mode.ContentIsMask} />
|
||||
<RetinaImg className="icons" style={position: "absolute", left: -45, top: 130} url="nylas://onboarding/assets/shapes-left@2x.png" mode={RetinaImg.Mode.ContentIsMask} />
|
||||
<RetinaImg className="icons" style={position: "absolute", right: -40, top: 130} url="nylas://onboarding/assets/shapes-right@2x.png" mode={RetinaImg.Mode.ContentIsMask} />
|
||||
<p className="sub-text" style={marginTop: 17}>It is the foundation for a highly extensible email experience</p>
|
||||
{@_renderNavBubble(0)}
|
||||
</div>
|
||||
|
||||
_renderStep1: ->
|
||||
<div className={@_stepClass(1)} key="step-1">
|
||||
<p className="hero-text" style={marginTop: 40}>Under the hood, N1 is built for developers.</p>
|
||||
<div className="gear-outer-container"><div className="gear-container">
|
||||
{@_gears()}
|
||||
</div></div>
|
||||
<RetinaImg className="gear-small" mode={RetinaImg.Mode.ContentPreserve}
|
||||
url="nylas://onboarding/assets/gear-small@2x.png" />
|
||||
<RetinaImg className="wrench" mode={RetinaImg.Mode.ContentPreserve}
|
||||
url="nylas://onboarding/assets/wrench@2x.png" />
|
||||
|
||||
<p className="sub-text">You can extend it using packages and build your own components.</p>
|
||||
{@_renderNavBubble(1)}
|
||||
</div>
|
||||
|
||||
_gears: ->
|
||||
gears = []
|
||||
for i in [0..3]
|
||||
gears.push <RetinaImg className="gear-large gear-large-#{i}"
|
||||
mode={RetinaImg.Mode.ContentPreserve}
|
||||
url="nylas://onboarding/assets/gear-large@2x.png" />
|
||||
return gears
|
||||
|
||||
_renderStep2: ->
|
||||
<div className={@_stepClass(2)} key="step-2">
|
||||
<p className="hero-text" style={marginTop: 40}>N1 is secured and enhanced by the Nylas Sync Engine</p>
|
||||
<div className="cell-wrap">
|
||||
<div className="cell" style={float: "left"}>
|
||||
<RetinaImg mode={RetinaImg.Mode.ContentPreserve}
|
||||
url="nylas://onboarding/assets/lock@2x.png" />
|
||||
<p>Secured using<br/>bank-grade encryption</p>
|
||||
<a onClick={=> @_open("https://nylas.com/security/")}>more info</a>
|
||||
</div>
|
||||
<div className="cell" style={float: "right"}>
|
||||
<RetinaImg mode={RetinaImg.Mode.ContentPreserve}
|
||||
style={paddingTop: 4, paddingBottom: 4}
|
||||
url="nylas://onboarding/assets/cloud@2x.png" />
|
||||
<p>Synced by Nylas to be<br/>faster and more extensible</p>
|
||||
<a onClick={=> @_open("https://github.com/nylas/sync-engine")}>more info</a>
|
||||
</div>
|
||||
</div>
|
||||
{@_renderNavBubble(2)}
|
||||
</div>
|
||||
|
||||
_open: (link) ->
|
||||
shell.openExternal(link)
|
||||
return
|
||||
|
||||
_renderNavBubble: (step=0) ->
|
||||
bubbles = [0..2].map (n) =>
|
||||
active = if n is step then "active" else ""
|
||||
<div className="nav-bubble #{active}"
|
||||
onClick={ => @setState step: n }></div>
|
||||
|
||||
<div className="nav-bubbles">
|
||||
{bubbles}
|
||||
</div>
|
||||
|
||||
_onBack: =>
|
||||
@setState(step: @state.step - 1)
|
||||
|
|
|
@ -109,10 +109,6 @@
|
|||
padding: 0 15px;
|
||||
width: 330px
|
||||
}
|
||||
&.account-choose {
|
||||
width: 330px;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
&.opaque {
|
||||
background-color: @gray-lighter;
|
||||
}
|
||||
|
@ -139,8 +135,9 @@
|
|||
|
||||
.quit {
|
||||
position: absolute;
|
||||
top:5px;
|
||||
left:5px;
|
||||
z-index: 100;
|
||||
top: 1px;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
.back,
|
||||
|
@ -167,30 +164,6 @@
|
|||
opacity: 0.01;
|
||||
}
|
||||
|
||||
.welcome-image-container {
|
||||
height:391px;
|
||||
display:block;
|
||||
}
|
||||
.welcome-image {
|
||||
position:absolute;
|
||||
}
|
||||
.welcome-image-enter {
|
||||
opacity: 0;
|
||||
transition: opacity .3s linear;
|
||||
}
|
||||
|
||||
.welcome-image-enter.welcome-image-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
.welcome-image-leave {
|
||||
opacity: 1;
|
||||
transition: opacity .3s linear;
|
||||
}
|
||||
|
||||
.welcome-image-leave.welcome-image-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.check {
|
||||
width: @checkSize;
|
||||
height: @checkSize;
|
||||
|
@ -242,25 +215,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.provider {
|
||||
text-align: left;
|
||||
border-top: 1px solid rgba(0,0,0,0.05);
|
||||
cursor: default;
|
||||
|
||||
img.icon {
|
||||
}
|
||||
.icon-container {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: inline-block;
|
||||
box-sizing: content-box;
|
||||
padding: 5px 15px;
|
||||
}
|
||||
}
|
||||
.provider:hover{
|
||||
background: rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
.errormsg {
|
||||
color: #A33;
|
||||
margin-bottom:5px;
|
||||
|
@ -338,6 +292,44 @@
|
|||
}
|
||||
}
|
||||
|
||||
.page.account-choose {
|
||||
width: 388px;
|
||||
height: 602px;
|
||||
img.logo.content-mask {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-size: 17px;
|
||||
color: rgba(0,0,0,0.56);
|
||||
}
|
||||
|
||||
.provider-name {
|
||||
font-size: 20px;
|
||||
font-weight: 300;
|
||||
color: rgba(0,0,0,0.7);
|
||||
}
|
||||
|
||||
.provider {
|
||||
text-align: left;
|
||||
border-top: 1px solid rgba(0,0,0,0.05);
|
||||
cursor: default;
|
||||
|
||||
img.icon {
|
||||
}
|
||||
.icon-container {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: inline-block;
|
||||
box-sizing: content-box;
|
||||
padding: 10px 25px;
|
||||
}
|
||||
}
|
||||
.provider:hover{
|
||||
background: rgba(255,255,255,0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.initial-package {
|
||||
display:block;
|
||||
margin:auto;
|
||||
|
@ -361,3 +353,266 @@
|
|||
max-width:500px;
|
||||
}
|
||||
}
|
||||
|
||||
.welcome-page {
|
||||
width: 675px;
|
||||
height: 480px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@-webkit-keyframes slideIn {
|
||||
from {
|
||||
transform: translate3d(20,0,0);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0,0,0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(255,255,255,0.7);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.7);
|
||||
&:hover {
|
||||
cursor: default;
|
||||
color: white;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
}
|
||||
|
||||
.steps-container {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.step-wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
transition: all 0.3s;
|
||||
z-index: 1;
|
||||
|
||||
opacity: 0;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
background: #ececec;
|
||||
border-top: 1px solid #d4d4d4;
|
||||
|
||||
.btn-continue {
|
||||
font-size: 18px;
|
||||
font-weight: 300;
|
||||
margin: 20px 0;
|
||||
padding: 12px 0;
|
||||
width: 296px;
|
||||
}
|
||||
.btn-back {
|
||||
color: rgba(0,0,0,0.4);
|
||||
&:hover {
|
||||
color: rgba(0,0,0,0.7);
|
||||
cursor: default;
|
||||
}
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
p.hero-text {
|
||||
font-weight: 200;
|
||||
-webkit-font-smoothing: subpixel-antialiased;
|
||||
}
|
||||
p.sub-text {
|
||||
font-size: 17px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.nylas-wash-light-bg {
|
||||
background-image: linear-gradient(to bottom, rgba(236,236,236,0) 0%, rgba(236,236,236,1) 88%), linear-gradient(to right, rgba(213,224,0,0.47) 0%,rgba(88,182,63,0.47) 50%,rgba(12,162,163,0.47) 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nylas-wash-bg {
|
||||
background: rgba(101, 191, 191, 0.44);
|
||||
background-image: linear-gradient(to right, rgba(213,224,0,0.35) 0%,rgba(88,182,63,0.35) 50%,rgba(12,162,163,0.35) 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nylas-static-wash-bg {
|
||||
background-image: linear-gradient(to right, rgba(162,210,128,1) 0%,rgba(113,193,154,1) 50%,rgba(89,187,187,1) 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nylas-dark-bg {
|
||||
background: rgba(58, 68, 74, 1);
|
||||
color: rgba(255,255,255,0.7);
|
||||
.sub-text {
|
||||
color: rgba(255,255,255,0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.nylas-blue-wash-bg {
|
||||
background-image: linear-gradient(to right, rgba(79,186,151,1) 0%,rgba(113,193,154,1) 50%,rgba(34,172,187,1) 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.step-0-wrap {
|
||||
.nylas-static-wash-bg;
|
||||
|
||||
.hero-text {
|
||||
font-size: 36px;
|
||||
line-height: 41px;
|
||||
}
|
||||
|
||||
img.logo.content-mask {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
img.icons.content-mask {
|
||||
background-color: rgba(255,255,255,0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.step-1-wrap {
|
||||
.nylas-dark-bg;
|
||||
|
||||
.hero-text {
|
||||
font-size: 29px;
|
||||
}
|
||||
.gear-outer-container {
|
||||
background: #69767f;
|
||||
border: 1px solid #161f25;
|
||||
width: 210px;
|
||||
height: 210px;
|
||||
margin: 20px auto;
|
||||
border-radius: 105px;
|
||||
}
|
||||
.gear-container {
|
||||
position: relative;
|
||||
background: #182025;
|
||||
border: 4px solid #161f25;
|
||||
width: 204px;
|
||||
height: 204px;
|
||||
margin: 3px auto;
|
||||
border-radius: 102px;
|
||||
overflow: hidden;
|
||||
// http://stackoverflow.com/questions/5736503/how-to-make-css3-rounded-corners-hide-overflow-in-chrome-opera
|
||||
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
|
||||
}
|
||||
|
||||
&.active {
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(720deg); }
|
||||
}
|
||||
@keyframes rotate-2 {
|
||||
from { transform: rotate(7deg); }
|
||||
to { transform: rotate(727deg); }
|
||||
}
|
||||
|
||||
.gear-large {
|
||||
animation: rotate 20s ease-in-out;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
.gear-large-0{
|
||||
animation-name: rotate-2;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
}
|
||||
|
||||
.gear-large {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.gear-large-0 {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -150px;
|
||||
margin-top: -150px;
|
||||
transform: rotate(7deg);
|
||||
}
|
||||
.gear-large-1 {
|
||||
left: -147px;
|
||||
top: -147px;
|
||||
}
|
||||
.gear-large-2 {
|
||||
right: -147px;
|
||||
top: -147px;
|
||||
}
|
||||
.gear-large-3 {
|
||||
left: 50%;
|
||||
margin-left: -148px;
|
||||
bottom: -226px;
|
||||
}
|
||||
|
||||
.gear-small {
|
||||
position: absolute;
|
||||
top: 470px;
|
||||
left: 390px;
|
||||
}
|
||||
.wrench {
|
||||
position: absolute;
|
||||
right: 310px;
|
||||
top: 370px;
|
||||
}
|
||||
}
|
||||
|
||||
.step-2-wrap {
|
||||
.nylas-blue-wash-bg;
|
||||
.cell-wrap {
|
||||
width: 514px;
|
||||
margin: 30px auto 0 auto;
|
||||
}
|
||||
|
||||
.cell {
|
||||
width: 242px;
|
||||
background: rgba(247, 251, 251, 0.25);
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 1px 1px rgba(0,0,0,0.09), inset 0px 0px 1px rgba(255,255,255,0.15);
|
||||
padding: 30px 0;
|
||||
|
||||
p {
|
||||
margin-top: 1em;
|
||||
color: rgba(255,255,255,0.7);
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
}
|
||||
a {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.hero-text {
|
||||
font-size: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bubbles {
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 50%;
|
||||
margin-left: -24px;
|
||||
display: flex;
|
||||
width: 48px;
|
||||
}
|
||||
.nav-bubble {
|
||||
margin: 4px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
&:hover {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
&.active {
|
||||
background-color: rgba(255,255,255,0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -401,6 +401,9 @@ class Atom extends Model
|
|||
close: ->
|
||||
@getCurrentWindow().close()
|
||||
|
||||
quit: ->
|
||||
remote.require('app').quit()
|
||||
|
||||
# Essential: Get the size of current window.
|
||||
#
|
||||
# Returns an {Object} in the format `{width: 1000, height: 700}`
|
||||
|
@ -631,7 +634,10 @@ class Atom extends Model
|
|||
CommandInstaller.installApmCommand resourcePath, false, (error) ->
|
||||
console.warn error.message if error?
|
||||
@commands.add 'atom-workspace',
|
||||
'atom-workspace:add-account': @addAccount
|
||||
'atom-workspace:add-account': @onAddAccount
|
||||
|
||||
onAddAccount: =>
|
||||
require('remote').getGlobal('application').windowManager.newOnboardingWindow(addingAccount: true)
|
||||
|
||||
# Call this method when establishing a secondary application window
|
||||
# displaying a specific set of packages.
|
||||
|
@ -766,17 +772,6 @@ class Atom extends Model
|
|||
executeJavaScriptInDevTools: (code) ->
|
||||
ipc.send('call-window-method', 'executeJavaScriptInDevTools', code)
|
||||
|
||||
addAccount: =>
|
||||
@newWindow
|
||||
title: 'Add an Account'
|
||||
width: 340
|
||||
height: 550
|
||||
toolbar: false
|
||||
resizable: false
|
||||
windowType: 'onboarding'
|
||||
windowProps:
|
||||
page: 'add-account'
|
||||
|
||||
###
|
||||
Section: Private
|
||||
###
|
||||
|
|
|
@ -159,7 +159,7 @@ class Application
|
|||
@windowManager.showMainWindow(loadingMessage)
|
||||
@windowManager.ensureWorkWindow()
|
||||
else
|
||||
@windowManager.newOnboardingWindow({welcome: true})
|
||||
@windowManager.newOnboardingWindow()
|
||||
# The onboarding window automatically shows when it's ready
|
||||
|
||||
_resetConfigAndRelaunch: =>
|
||||
|
@ -169,7 +169,7 @@ class Application
|
|||
@config.set('nylas', null)
|
||||
@config.set('edgehill', null)
|
||||
@setDatabasePhase('setup')
|
||||
@windowManager.newOnboardingWindow({welcome: true})
|
||||
@windowManager.newOnboardingWindow()
|
||||
|
||||
_deleteDatabase: (callback) ->
|
||||
@deleteFileWithRetry path.join(configDirPath,'edgehill.db'), callback
|
||||
|
|
|
@ -132,23 +132,20 @@ class WindowManager
|
|||
|
||||
# Returns a new onboarding window
|
||||
#
|
||||
newOnboardingWindow: ({welcome} = {}) ->
|
||||
options =
|
||||
newOnboardingWindow: ({addingAccount}={}) ->
|
||||
page = if addingAccount then "account-choose" else "welcome"
|
||||
title = if addingAccount then "Add an Account" else "Welcome to N1"
|
||||
win = @newWindow
|
||||
title: title
|
||||
toolbar: false
|
||||
resizable: false
|
||||
hidden: true
|
||||
title: 'Add an Account'
|
||||
hidden: true # The `PageRouter` will center and show on load
|
||||
windowType: 'onboarding'
|
||||
windowProps:
|
||||
page: 'account-choose'
|
||||
page: page
|
||||
pageData: {addingAccount}
|
||||
uniqueId: 'onboarding'
|
||||
|
||||
if welcome
|
||||
options.title = "Welcome to N1"
|
||||
options.windowProps.page = "welcome"
|
||||
|
||||
@newWindow(options)
|
||||
|
||||
# Makes a new window appear of a certain `windowType`.
|
||||
#
|
||||
# In almost all cases, instead of booting up a new window from scratch,
|
||||
|
|
|
@ -108,7 +108,7 @@ class RetinaImg extends React.Component
|
|||
|
||||
style = @props.style ? {}
|
||||
style.WebkitUserDrag = 'none'
|
||||
style.zoom = if pathIsRetina then 0.5 else 1
|
||||
style.zoom ?= if pathIsRetina then 0.5 else 1
|
||||
style.width = style.width / style.zoom if style.width
|
||||
style.height = style.height / style.zoom if style.height
|
||||
|
||||
|
|