mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 02:42:17 -05:00
[WO-207] implement accout selection
This commit is contained in:
parent
5748ee36c0
commit
9568922bc4
BIN
src/img/google_logo.png
Normal file
BIN
src/img/google_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
src/img/outlook_logo.jpg
Normal file
BIN
src/img/outlook_logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
BIN
src/img/tonline_logo.jpg
Normal file
BIN
src/img/tonline_logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
src/img/yahoo_logo.png
Normal file
BIN
src/img/yahoo_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 178 KiB |
@ -195,12 +195,6 @@ define(function(require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cachedEmailAddress) {
|
|
||||||
// not first time login... address cached
|
|
||||||
callback(null, cachedEmailAddress);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cachedEmailAddress && !self.isOnline()) {
|
if (!cachedEmailAddress && !self.isOnline()) {
|
||||||
// first time login... must be online
|
// first time login... must be online
|
||||||
callback({
|
callback({
|
||||||
@ -209,14 +203,7 @@ define(function(require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fetchOAuthToken(function(err, oauth) {
|
callback(null, cachedEmailAddress);
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, oauth.emailAddress);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ require([
|
|||||||
'angular',
|
'angular',
|
||||||
'js/controller/dialog',
|
'js/controller/dialog',
|
||||||
'js/controller/popover',
|
'js/controller/popover',
|
||||||
|
'js/controller/add-account',
|
||||||
'js/controller/account',
|
'js/controller/account',
|
||||||
'js/controller/login',
|
'js/controller/login',
|
||||||
'js/controller/login-initial',
|
'js/controller/login-initial',
|
||||||
@ -17,7 +18,7 @@ require([
|
|||||||
'cryptoLib/util',
|
'cryptoLib/util',
|
||||||
'angularRoute',
|
'angularRoute',
|
||||||
'angularTouch'
|
'angularTouch'
|
||||||
], function(angular, DialogCtrl, PopoverCtrl, AccountCtrl, LoginCtrl, LoginInitialCtrl, LoginNewDeviceCtrl, LoginExistingCtrl, MailListCtrl, ReadCtrl, WriteCtrl, NavigationCtrl, util) {
|
], function(angular, DialogCtrl, PopoverCtrl, AddAccountCtrl, AccountCtrl, LoginCtrl, LoginInitialCtrl, LoginNewDeviceCtrl, LoginExistingCtrl, MailListCtrl, ReadCtrl, WriteCtrl, NavigationCtrl, util) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// reset window.name
|
// reset window.name
|
||||||
@ -28,6 +29,10 @@ require([
|
|||||||
|
|
||||||
// set router paths
|
// set router paths
|
||||||
app.config(function($routeProvider) {
|
app.config(function($routeProvider) {
|
||||||
|
$routeProvider.when('/add-account', {
|
||||||
|
templateUrl: 'tpl/add-account.html',
|
||||||
|
controller: AddAccountCtrl
|
||||||
|
});
|
||||||
$routeProvider.when('/login', {
|
$routeProvider.when('/login', {
|
||||||
templateUrl: 'tpl/login.html',
|
templateUrl: 'tpl/login.html',
|
||||||
controller: LoginCtrl
|
controller: LoginCtrl
|
||||||
|
31
src/js/controller/add-account.js
Normal file
31
src/js/controller/add-account.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
define(function(require) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var appController = require('js/app-controller'),
|
||||||
|
errorUtil = require('js/util/error');
|
||||||
|
|
||||||
|
var AddAccountCtrl = function($scope, $location) {
|
||||||
|
// global state... inherited to all child scopes
|
||||||
|
$scope.$root.state = {};
|
||||||
|
// attach global error handler
|
||||||
|
errorUtil.attachHandler($scope);
|
||||||
|
|
||||||
|
$scope.connectToGoogle = function() {
|
||||||
|
appController.fetchOAuthToken(function(err) {
|
||||||
|
if (err) {
|
||||||
|
$scope.onError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function redirect() {
|
||||||
|
$location.path('/login');
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return AddAccountCtrl;
|
||||||
|
});
|
@ -33,6 +33,12 @@ define(function(require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if account needs to be selected
|
||||||
|
if (!emailAddress) {
|
||||||
|
firstLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// initiate controller by creating email dao
|
// initiate controller by creating email dao
|
||||||
appController.init({
|
appController.init({
|
||||||
emailAddress: emailAddress
|
emailAddress: emailAddress
|
||||||
@ -47,6 +53,11 @@ define(function(require) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function firstLogin() {
|
||||||
|
$location.path('/add-account');
|
||||||
|
$scope.$apply();
|
||||||
|
}
|
||||||
|
|
||||||
function redirect(availableKeys) {
|
function redirect(availableKeys) {
|
||||||
// redirect if needed
|
// redirect if needed
|
||||||
if (typeof availableKeys === 'undefined') {
|
if (typeof availableKeys === 'undefined') {
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
// Views
|
// Views
|
||||||
@import "views/shared";
|
@import "views/shared";
|
||||||
|
@import "views/add-account";
|
||||||
@import "views/account";
|
@import "views/account";
|
||||||
@import "views/dialog";
|
@import "views/dialog";
|
||||||
@import "views/navigation";
|
@import "views/navigation";
|
||||||
|
125
src/sass/views/_add-account.scss
Normal file
125
src/sass/views/_add-account.scss
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
.view-add-account {
|
||||||
|
height: 100%;
|
||||||
|
background-color: $color-grey-lightest;
|
||||||
|
color: $color-grey-dark;
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
padding: 60px 0 50px 0;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
width: 320px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: $color-grey-lighter;
|
||||||
|
|
||||||
|
li {
|
||||||
|
position: relative;
|
||||||
|
height: 68px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.google {
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 164px;
|
||||||
|
height: 58px;
|
||||||
|
margin: 0px auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 164px;
|
||||||
|
height: 58px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.whiteout {
|
||||||
|
background-color: $color-grey-lightest;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 210px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 15px 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.outlook {
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 256px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 13px 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.yahoo {
|
||||||
|
background-color: $color-grey-lightest;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 181px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tonline {
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 271px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.other {
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 68px;
|
||||||
|
font-size: 21px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.enabled {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 1;
|
||||||
|
top: 1px;
|
||||||
|
left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
src/tpl/add-account.html
Normal file
92
src/tpl/add-account.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<div class="view-add-account">
|
||||||
|
|
||||||
|
<h1>Select email account</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li class="google enabled" popover="#google-info" ng-click="connectToGoogle()">
|
||||||
|
<div><img src="img/google_logo.png" alt="Google Mail"></div>
|
||||||
|
</li>
|
||||||
|
<li class="whiteout disabled" popover="#whiteout-info">
|
||||||
|
<div><img src="img/whiteout_logo.svg" alt="Whiteout Mailbox"></div>
|
||||||
|
</li>
|
||||||
|
<li class="outlook disabled" popover="#outlook-info">
|
||||||
|
<div><img src="img/outlook_logo.jpg" alt="Outlook.com"></div>
|
||||||
|
</li>
|
||||||
|
<li class="yahoo disabled" popover="#yahoo-info">
|
||||||
|
<div><img src="img/yahoo_logo.png" alt="Yahoo! Mail"></div>
|
||||||
|
</li>
|
||||||
|
<li class="tonline disabled" popover="#tonline-info">
|
||||||
|
<div><img src="img/tonline_logo.jpg" alt="T-Online"></div>
|
||||||
|
</li>
|
||||||
|
<li class="other disabled" popover="#custom-info">
|
||||||
|
<h3>Custom server...</h3>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- lightbox -->
|
||||||
|
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||||
|
<div class="lightbox lightbox-effect view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- popovers -->
|
||||||
|
<div id="google-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>Google Account</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your Gmail or Google Apps account.</p>
|
||||||
|
<p>Encrypted and cleartext messages are stored on Google's servers.</p>
|
||||||
|
<p>No data is sent to our servers.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
||||||
|
|
||||||
|
<div id="whiteout-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>Whiteout Mailbox (coming soon)</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your secure Whiteout Mailbox.</p>
|
||||||
|
<p>All incoming messages are encrypted at rest and can only be read on your device.</p>
|
||||||
|
<p>Whiteout Mailbox is an email service hosted in Germany.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
||||||
|
|
||||||
|
<div id="outlook-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>Outlook.com Account (coming soon)</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your Outlook.com account.</p>
|
||||||
|
<p>Encrypted and cleartext messages are stored on Microsoft's servers.</p>
|
||||||
|
<p>No data is sent to our servers.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
||||||
|
|
||||||
|
<div id="yahoo-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>Yahoo Mail (coming soon)</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your Yahoo Mail account.</p>
|
||||||
|
<p>Encrypted and cleartext messages are stored on Yahoo's servers.</p>
|
||||||
|
<p>No data is sent to our servers.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
||||||
|
|
||||||
|
<div id="tonline-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>T-Online Account (coming soon)</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your T-Online account.</p>
|
||||||
|
<p>Encrypted and cleartext messages are stored on T-Online's servers.</p>
|
||||||
|
<p>No data is sent to our servers.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
||||||
|
|
||||||
|
<div id="custom-info" class="popover right" ng-controller="PopoverCtrl">
|
||||||
|
<div class="arrow"></div>
|
||||||
|
<div class="popover-title"><b>Custom server (coming soon)</b></div>
|
||||||
|
<div class="popover-content">
|
||||||
|
<p>Connect Whiteout Mail to your own email server.</p>
|
||||||
|
<p>Encrypted and cleartext messages are stored on your server.</p>
|
||||||
|
<p>No data is sent to our servers.</p>
|
||||||
|
</div>
|
||||||
|
</div><!--/.popover-->
|
72
test/new-unit/add-account-ctrl-test.js
Normal file
72
test/new-unit/add-account-ctrl-test.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
define(function(require) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var expect = chai.expect,
|
||||||
|
angular = require('angular'),
|
||||||
|
mocks = require('angularMocks'),
|
||||||
|
AddAccountCtrl = require('js/controller/add-account'),
|
||||||
|
appController = require('js/app-controller');
|
||||||
|
|
||||||
|
describe('Add Account Controller unit test', function() {
|
||||||
|
var scope, location, ctrl,
|
||||||
|
fetchOAuthTokenStub;
|
||||||
|
|
||||||
|
describe('connectToGoogle', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
// remember original module to restore later, then replace it
|
||||||
|
fetchOAuthTokenStub = sinon.stub(appController, 'fetchOAuthToken');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
// restore the app controller module
|
||||||
|
location && location.path && location.path.restore && location.path.restore();
|
||||||
|
fetchOAuthTokenStub.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail on fetchOAuthToken error', function(done) {
|
||||||
|
angular.module('addaccounttest', []);
|
||||||
|
mocks.module('addaccounttest');
|
||||||
|
mocks.inject(function($controller, $rootScope) {
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
scope.state = {};
|
||||||
|
ctrl = $controller(AddAccountCtrl, {
|
||||||
|
$location: location,
|
||||||
|
$scope: scope
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
scope.onError = function(err) {
|
||||||
|
expect(err).to.equal(42);
|
||||||
|
expect(fetchOAuthTokenStub.calledOnce).to.be.true;
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
fetchOAuthTokenStub.yields(42);
|
||||||
|
|
||||||
|
scope.connectToGoogle();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should forward to login', function(done) {
|
||||||
|
angular.module('addaccounttest', []);
|
||||||
|
mocks.module('addaccounttest');
|
||||||
|
mocks.inject(function($controller, $rootScope, $location) {
|
||||||
|
location = $location;
|
||||||
|
sinon.stub(location, 'path', function(path) {
|
||||||
|
expect(path).to.equal('/login');
|
||||||
|
expect(fetchOAuthTokenStub.calledOnce).to.be.true;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
scope.state = {};
|
||||||
|
ctrl = $controller(AddAccountCtrl, {
|
||||||
|
$location: location,
|
||||||
|
$scope: scope
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchOAuthTokenStub.yields();
|
||||||
|
|
||||||
|
scope.connectToGoogle();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -177,34 +177,6 @@ define(function(require) {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail due to error in fetchOAuthToken', function(done) {
|
|
||||||
appConfigStoreStub.listItems.yields(null, []);
|
|
||||||
isOnlineStub.returns(true);
|
|
||||||
fetchOAuthTokenStub.yields({});
|
|
||||||
|
|
||||||
controller.getEmailAddress(function(err, emailAddress) {
|
|
||||||
expect(err).to.exist;
|
|
||||||
expect(emailAddress).to.not.exist;
|
|
||||||
expect(fetchOAuthTokenStub.calledOnce).to.be.true;
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fail work when fetching oauth token', function(done) {
|
|
||||||
appConfigStoreStub.listItems.yields(null, []);
|
|
||||||
isOnlineStub.returns(true);
|
|
||||||
fetchOAuthTokenStub.yields(null, {
|
|
||||||
emailAddress: 'asfd@example.com'
|
|
||||||
});
|
|
||||||
|
|
||||||
controller.getEmailAddress(function(err, emailAddress) {
|
|
||||||
expect(err).to.not.exist;
|
|
||||||
expect(emailAddress).to.equal('asfd@example.com');
|
|
||||||
expect(fetchOAuthTokenStub.calledOnce).to.be.true;
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('fetchOAuthToken', function() {
|
describe('fetchOAuthToken', function() {
|
||||||
|
@ -39,6 +39,7 @@ function startTests() {
|
|||||||
'test/new-unit/keychain-dao-test',
|
'test/new-unit/keychain-dao-test',
|
||||||
'test/new-unit/devicestorage-dao-test',
|
'test/new-unit/devicestorage-dao-test',
|
||||||
'test/new-unit/dialog-ctrl-test',
|
'test/new-unit/dialog-ctrl-test',
|
||||||
|
'test/new-unit/add-account-ctrl-test',
|
||||||
'test/new-unit/account-ctrl-test',
|
'test/new-unit/account-ctrl-test',
|
||||||
'test/new-unit/login-existing-ctrl-test',
|
'test/new-unit/login-existing-ctrl-test',
|
||||||
'test/new-unit/login-initial-ctrl-test',
|
'test/new-unit/login-initial-ctrl-test',
|
||||||
|
Loading…
Reference in New Issue
Block a user