mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 02:42:17 -05:00
commit
2272f3d58f
@ -159,7 +159,6 @@ module.exports = function(grunt) {
|
|||||||
'test/unit/util/dialog-test.js',
|
'test/unit/util/dialog-test.js',
|
||||||
'test/unit/util/connection-doctor-test.js',
|
'test/unit/util/connection-doctor-test.js',
|
||||||
'test/unit/util/update-handler-test.js',
|
'test/unit/util/update-handler-test.js',
|
||||||
'test/unit/util/backbutton-handler-test.js',
|
|
||||||
'test/unit/util/status-display-test.js',
|
'test/unit/util/status-display-test.js',
|
||||||
'test/unit/crypto/pgp-test.js',
|
'test/unit/crypto/pgp-test.js',
|
||||||
'test/unit/crypto/crypto-test.js',
|
'test/unit/crypto/crypto-test.js',
|
||||||
|
@ -48,7 +48,7 @@ For development you can start a connect dev server:
|
|||||||
|
|
||||||
grunt dev
|
grunt dev
|
||||||
|
|
||||||
Then visit [http://localhost:8580/dist/#/desktop?dev=true](http://localhost:8580/dist/#/desktop?dev=true) for front-end code or [http://localhost:8580/test/unit/](http://localhost:8580/test/unit/) to test JavaScript changes. You can also start a watch task so you don't have rebuild everytime you make a change:
|
Then visit [http://localhost:8580/dist/#/account?dev=true](http://localhost:8580/dist/#/account?dev=true) for front-end code or [http://localhost:8580/test/unit/](http://localhost:8580/test/unit/) to test JavaScript changes. You can also start a watch task so you don't have rebuild everytime you make a change:
|
||||||
|
|
||||||
grunt watch
|
grunt watch
|
||||||
|
|
||||||
|
@ -35,8 +35,7 @@ var axe = require('axe-logger'),
|
|||||||
WriteCtrl = require('./controller/app/write'),
|
WriteCtrl = require('./controller/app/write'),
|
||||||
NavigationCtrl = require('./controller/app/navigation'),
|
NavigationCtrl = require('./controller/app/navigation'),
|
||||||
ActionBarCtrl = require('./controller/app/action-bar'),
|
ActionBarCtrl = require('./controller/app/action-bar'),
|
||||||
StatusDisplayCtrl = require('./controller/app/status-display'),
|
StatusDisplayCtrl = require('./controller/app/status-display');
|
||||||
backButtonUtil = require('./util/backbutton-handler');
|
|
||||||
|
|
||||||
// include angular modules
|
// include angular modules
|
||||||
require('./app-config');
|
require('./app-config');
|
||||||
@ -104,9 +103,10 @@ app.config(function($routeProvider, $animateProvider) {
|
|||||||
templateUrl: 'tpl/login-privatekey-download.html',
|
templateUrl: 'tpl/login-privatekey-download.html',
|
||||||
controller: LoginPrivateKeyDownloadCtrl
|
controller: LoginPrivateKeyDownloadCtrl
|
||||||
});
|
});
|
||||||
$routeProvider.when('/desktop', {
|
$routeProvider.when('/account', {
|
||||||
templateUrl: 'tpl/desktop.html',
|
templateUrl: 'tpl/desktop.html',
|
||||||
controller: NavigationCtrl
|
controller: NavigationCtrl,
|
||||||
|
reloadOnSearch: false // don't reload controllers in main app when query params change
|
||||||
});
|
});
|
||||||
$routeProvider.otherwise({
|
$routeProvider.otherwise({
|
||||||
redirectTo: '/login'
|
redirectTo: '/login'
|
||||||
@ -119,10 +119,6 @@ app.config(function($routeProvider, $animateProvider) {
|
|||||||
app.run(function($rootScope) {
|
app.run(function($rootScope) {
|
||||||
// global state... inherited to all child scopes
|
// global state... inherited to all child scopes
|
||||||
$rootScope.state = {};
|
$rootScope.state = {};
|
||||||
|
|
||||||
// attach the back button handler to the root scope
|
|
||||||
backButtonUtil.attachHandler($rootScope);
|
|
||||||
|
|
||||||
// attach fastclick
|
// attach fastclick
|
||||||
FastClick.attach(document.body);
|
FastClick.attach(document.body);
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
var AboutCtrl = function($scope, appConfig) {
|
var AboutCtrl = function($scope, appConfig) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.about = {
|
$scope.state.about = {
|
||||||
toggle: function(to) {
|
toggle: function(to) {
|
||||||
$scope.state.lightbox = (to) ? 'about' : undefined;
|
$scope.state.lightbox = (to) ? 'about' : undefined;
|
||||||
@ -15,9 +19,6 @@ var AboutCtrl = function($scope, appConfig) {
|
|||||||
$scope.version = appConfig.config.appVersion + ' (beta)';
|
$scope.version = appConfig.config.appVersion + ' (beta)';
|
||||||
$scope.date = new Date();
|
$scope.date = new Date();
|
||||||
|
|
||||||
//
|
|
||||||
// scope functions
|
|
||||||
//
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AboutCtrl;
|
module.exports = AboutCtrl;
|
@ -6,6 +6,10 @@ var AccountCtrl = function($scope, auth, keychain, pgp, appConfig, download, dia
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.account = {
|
$scope.state.account = {
|
||||||
toggle: function(to) {
|
toggle: function(to) {
|
||||||
$scope.state.lightbox = (to) ? 'account' : undefined;
|
$scope.state.lightbox = (to) ? 'account' : undefined;
|
||||||
@ -46,6 +50,7 @@ var AccountCtrl = function($scope, auth, keychain, pgp, appConfig, download, dia
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AccountCtrl;
|
module.exports = AccountCtrl;
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
var JUNK_FOLDER_TYPE = 'Junk';
|
var JUNK_FOLDER_TYPE = 'Junk';
|
||||||
|
|
||||||
var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
var ActionBarCtrl = function($scope, email, dialog, status) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move a single message from the currently selected folder to another folder
|
* Move a single message from the currently selected folder to another folder
|
||||||
@ -15,9 +19,9 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
$scope.state.read.open = false;
|
status.setReading(false);
|
||||||
|
// show message
|
||||||
statusDisplay.update('Moving message...');
|
status.update('Moving message...');
|
||||||
|
|
||||||
email.moveMessage({
|
email.moveMessage({
|
||||||
folder: currentFolder(),
|
folder: currentFolder(),
|
||||||
@ -28,14 +32,14 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
// show errors where appropriate
|
// show errors where appropriate
|
||||||
if (err.code === 42) {
|
if (err.code === 42) {
|
||||||
$scope.select(message);
|
$scope.select(message);
|
||||||
statusDisplay.update('Unable to move message in offline mode!');
|
status.update('Unable to move message in offline mode!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusDisplay.update('Error during move!');
|
status.update('Error during move!');
|
||||||
dialog.error(err);
|
dialog.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusDisplay.update('Message moved.');
|
status.update('Message moved.');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -76,9 +80,8 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
$scope.state.read.open = false;
|
status.setReading(false);
|
||||||
|
status.update('Deleting message...');
|
||||||
statusDisplay.update('Deleting message...');
|
|
||||||
|
|
||||||
email.deleteMessage({
|
email.deleteMessage({
|
||||||
folder: currentFolder(),
|
folder: currentFolder(),
|
||||||
@ -88,14 +91,14 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
// show errors where appropriate
|
// show errors where appropriate
|
||||||
if (err.code === 42) {
|
if (err.code === 42) {
|
||||||
$scope.select(message);
|
$scope.select(message);
|
||||||
statusDisplay.update('Unable to delete message in offline mode!');
|
status.update('Unable to delete message in offline mode!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusDisplay.update('Error during delete!');
|
status.update('Error during delete!');
|
||||||
dialog.error(err);
|
dialog.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
statusDisplay.update('Message deleted.');
|
status.update('Message deleted.');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -118,11 +121,11 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusDisplay.update('Updating unread flag...');
|
status.update('Updating unread flag...');
|
||||||
|
|
||||||
// close read state
|
// close read state
|
||||||
if (!keepOpen) {
|
if (!keepOpen) {
|
||||||
$scope.state.read.open = false;
|
status.setReading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var originalState = message.unread;
|
var originalState = message.unread;
|
||||||
@ -134,17 +137,17 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
if (err && err.code === 42) {
|
if (err && err.code === 42) {
|
||||||
// offline, restore
|
// offline, restore
|
||||||
message.unread = originalState;
|
message.unread = originalState;
|
||||||
statusDisplay.update('Unable to mark message in offline mode!');
|
status.update('Unable to mark message in offline mode!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
statusDisplay.update('Error on sync!');
|
status.update('Error on sync!');
|
||||||
dialog.error(err);
|
dialog.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusDisplay.update('Online');
|
status.update('Online');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -169,7 +172,7 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusDisplay.update(flagged ? 'Adding star to message...' : 'Removing star from message');
|
status.update(flagged ? 'Adding star to message...' : 'Removing star from message');
|
||||||
|
|
||||||
var originalState = message.flagged;
|
var originalState = message.flagged;
|
||||||
message.flagged = flagged;
|
message.flagged = flagged;
|
||||||
@ -180,17 +183,17 @@ var ActionBarCtrl = function($scope, email, dialog, statusDisplay) {
|
|||||||
if (err && err.code === 42) {
|
if (err && err.code === 42) {
|
||||||
// offline, restore
|
// offline, restore
|
||||||
message.unread = originalState;
|
message.unread = originalState;
|
||||||
statusDisplay.update('Unable to ' + (flagged ? 'add star to' : 'remove star from') + ' message in offline mode!');
|
status.update('Unable to ' + (flagged ? 'add star to' : 'remove star from') + ' message in offline mode!');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
statusDisplay.update('Error on sync!');
|
status.update('Error on sync!');
|
||||||
dialog.error(err);
|
dialog.error(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusDisplay.update('Online');
|
status.update('Online');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
|
|
||||||
var ContactsCtrl = function($scope, keychain, pgp, dialog) {
|
var ContactsCtrl = function($scope, keychain, pgp, dialog) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.contacts = {
|
$scope.state.contacts = {
|
||||||
toggle: function(to) {
|
toggle: function(to) {
|
||||||
$scope.state.lightbox = (to) ? 'contacts' : undefined;
|
$scope.state.lightbox = (to) ? 'contacts' : undefined;
|
||||||
|
|
||||||
$scope.listKeys();
|
$scope.listKeys();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -93,6 +96,7 @@ var ContactsCtrl = function($scope, keychain, pgp, dialog) {
|
|||||||
$scope.listKeys();
|
$scope.listKeys();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
var DialogCtrl = function($scope, dialog) {
|
var DialogCtrl = function($scope, dialog) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.dialog = {
|
$scope.state.dialog = {
|
||||||
open: false
|
open: false
|
||||||
};
|
};
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var searchTimeout, firstSelect;
|
var searchTimeout;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constants
|
// Constants
|
||||||
//
|
//
|
||||||
|
|
||||||
var INIT_DISPLAY_LEN = 20,
|
var INIT_DISPLAY_LEN = 50,
|
||||||
SCROLL_DISPLAY_LEN = 10,
|
SCROLL_DISPLAY_LEN = 10,
|
||||||
FOLDER_TYPE_INBOX = 'Inbox',
|
FOLDER_TYPE_INBOX = 'Inbox',
|
||||||
NOTIFICATION_INBOX_TIMEOUT = 5000;
|
NOTIFICATION_INBOX_TIMEOUT = 5000;
|
||||||
|
|
||||||
var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDisplay, notification, email, keychain, dialog, search, dummy) {
|
var MailListCtrl = function($scope, $timeout, $location, $filter, status, notification, email, keychain, dialog, search, dummy) {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Init
|
// scope state
|
||||||
//
|
//
|
||||||
|
|
||||||
$scope.state.mailList = {};
|
$scope.state.mailList = {};
|
||||||
@ -24,6 +24,30 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
*/
|
*/
|
||||||
$scope.pendingNotifications = [];
|
$scope.pendingNotifications = [];
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the route to a message which will go to read mode
|
||||||
|
*/
|
||||||
|
$scope.navigate = function(message) {
|
||||||
|
$location.search('uid', message.uid);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.loc = $location;
|
||||||
|
$scope.$watch('(loc.search()).uid', function(uid) {
|
||||||
|
if (typeof uid === 'undefined') {
|
||||||
|
// no uid specified in url... select no message
|
||||||
|
$scope.select();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// select the message specified by the uid in the url
|
||||||
|
$scope.select(_.findWhere(currentFolder().messages, {
|
||||||
|
uid: typeof uid === 'string' ? parseInt(uid, 10) : uid
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// scope functions
|
// scope functions
|
||||||
//
|
//
|
||||||
@ -62,11 +86,10 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
|
|
||||||
$scope.state.mailList.selected = message;
|
$scope.state.mailList.selected = message;
|
||||||
|
|
||||||
if (!firstSelect) {
|
if ($location.search().dev) {
|
||||||
// only toggle to read view on 2nd select in mobile mode
|
// stop here in dev mode
|
||||||
$scope.state.read.toggle(true);
|
return;
|
||||||
}
|
}
|
||||||
firstSelect = false;
|
|
||||||
|
|
||||||
keychain.refreshKeyForUserId({
|
keychain.refreshKeyForUserId({
|
||||||
userId: message.from[0].address
|
userId: message.from[0].address
|
||||||
@ -132,8 +155,8 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
$scope.searchText = undefined;
|
$scope.searchText = undefined;
|
||||||
|
|
||||||
// in development, display dummy mail objects
|
// in development, display dummy mail objects
|
||||||
if ($routeParams.dev) {
|
if ($location.search().dev) {
|
||||||
statusDisplay.update('Last update: ', new Date());
|
status.update('Last update: ', new Date());
|
||||||
currentFolder().messages = dummy.listMails();
|
currentFolder().messages = dummy.listMails();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -148,15 +171,13 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sort message by uid
|
// sort message by uid
|
||||||
currentFolder().messages.sort(byUidDescending);
|
messages.sort(byUidDescending);
|
||||||
// set display buffer to first messages
|
// Unselect message if it has been deleted from the messages array
|
||||||
$scope.displayMessages = currentFolder().messages.slice(0, INIT_DISPLAY_LEN);
|
if (messages.indexOf(currentMessage()) === -1) {
|
||||||
|
$scope.select();
|
||||||
// Shows the next message based on the uid of the currently selected element
|
|
||||||
if (currentFolder().messages.indexOf(currentMessage()) === -1) {
|
|
||||||
firstSelect = true; // reset first selection
|
|
||||||
$scope.select($scope.displayMessages[0]);
|
|
||||||
}
|
}
|
||||||
|
// set display buffer to first messages
|
||||||
|
$scope.displayMessages = messages.slice(0, INIT_DISPLAY_LEN);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -200,20 +221,20 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
if (!searchText) {
|
if (!searchText) {
|
||||||
// set display buffer to first messages
|
// set display buffer to first messages
|
||||||
$scope.displayMessages = currentFolder().messages.slice(0, INIT_DISPLAY_LEN);
|
$scope.displayMessages = currentFolder().messages.slice(0, INIT_DISPLAY_LEN);
|
||||||
statusDisplay.setSearching(false);
|
status.setSearching(false);
|
||||||
statusDisplay.update('Online');
|
status.update('Online');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// display searching spinner
|
// display searching spinner
|
||||||
statusDisplay.setSearching(true);
|
status.setSearching(true);
|
||||||
statusDisplay.update('Searching ...');
|
status.update('Searching ...');
|
||||||
searchTimeout = setTimeout(function() {
|
searchTimeout = setTimeout(function() {
|
||||||
$scope.$apply(function() {
|
$scope.$apply(function() {
|
||||||
// filter relevant messages
|
// filter relevant messages
|
||||||
$scope.displayMessages = search.filter(currentFolder().messages, searchText);
|
$scope.displayMessages = search.filter(currentFolder().messages, searchText);
|
||||||
statusDisplay.setSearching(false);
|
status.setSearching(false);
|
||||||
statusDisplay.update('Matches in this folder');
|
status.update('Matches in this folder');
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
@ -225,10 +246,10 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
// wait one cycle for the status display controllers to init
|
// wait one cycle for the status display controllers to init
|
||||||
$timeout(function() {
|
$timeout(function() {
|
||||||
if (isOnline) {
|
if (isOnline) {
|
||||||
statusDisplay.update('Online');
|
status.update('Online');
|
||||||
openCurrentFolder();
|
openCurrentFolder();
|
||||||
} else {
|
} else {
|
||||||
statusDisplay.update('Offline mode');
|
status.update('Offline mode');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, true);
|
}, true);
|
||||||
@ -268,7 +289,7 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
// Notification API
|
// Notification API
|
||||||
//
|
//
|
||||||
|
|
||||||
(email || {}).onIncomingMessage = function(msgs) {
|
email.onIncomingMessage = function(msgs) {
|
||||||
var note, title, message, unreadMsgs;
|
var note, title, message, unreadMsgs;
|
||||||
|
|
||||||
unreadMsgs = msgs.filter(function(msg) {
|
unreadMsgs = msgs.filter(function(msg) {
|
||||||
@ -291,17 +312,13 @@ var MailListCtrl = function($scope, $timeout, $routeParams, $filter, statusDispl
|
|||||||
title: title,
|
title: title,
|
||||||
message: message,
|
message: message,
|
||||||
onClick: function() {
|
onClick: function() {
|
||||||
// force toggle into read mode when notification is clicked
|
|
||||||
firstSelect = false;
|
|
||||||
|
|
||||||
// remove from pending notificatiosn
|
// remove from pending notificatiosn
|
||||||
var index = $scope.pendingNotifications.indexOf(note);
|
var index = $scope.pendingNotifications.indexOf(note);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
$scope.pendingNotifications.splice(index, 1);
|
$scope.pendingNotifications.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
// open the message
|
||||||
// mark message as read
|
$scope.navigate(_.findWhere(currentFolder().messages, {
|
||||||
$scope.select(_.findWhere(currentFolder().messages, {
|
|
||||||
uid: unreadMsgs[0].uid
|
uid: unreadMsgs[0].uid
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var backBtnHandler = require('../../util/backbutton-handler');
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Constants
|
// Constants
|
||||||
//
|
//
|
||||||
@ -13,8 +11,8 @@ var NOTIFICATION_SENT_TIMEOUT = 2000;
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var NavigationCtrl = function($scope, $routeParams, $location, account, email, outbox, notification, appConfig, dialog) {
|
var NavigationCtrl = function($scope, $location, account, email, outbox, notification, appConfig, dialog, dummy) {
|
||||||
if (!$routeParams.dev && !account.isLoggedIn()) {
|
if (!$location.search().dev && !account.isLoggedIn()) {
|
||||||
$location.path('/'); // init app
|
$location.path('/'); // init app
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -23,7 +21,7 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
config = appConfig.config;
|
config = appConfig.config;
|
||||||
|
|
||||||
//
|
//
|
||||||
// scope functions
|
// scope state
|
||||||
//
|
//
|
||||||
|
|
||||||
$scope.state.nav = {
|
$scope.state.nav = {
|
||||||
@ -33,6 +31,36 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
$scope.loc = $location;
|
||||||
|
|
||||||
|
// nav open/close state url watcher
|
||||||
|
$scope.$watch('(loc.search()).nav', function(open) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.nav.toggle(!!open);
|
||||||
|
});
|
||||||
|
$scope.$watch('state.nav.open', function(value) {
|
||||||
|
// synchronize the scope state to the url
|
||||||
|
$location.search('nav', value ? true : null);
|
||||||
|
});
|
||||||
|
|
||||||
|
// lightbox state url watcher
|
||||||
|
$scope.$watch('(loc.search()).lightbox', function(value) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.lightbox = (value) ? value : undefined;
|
||||||
|
});
|
||||||
|
$scope.$watch('state.lightbox', function(value) {
|
||||||
|
// synchronize the scope state to the url
|
||||||
|
$location.search('lightbox', value ? value : null);
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
$scope.openFolder = function(folder) {
|
$scope.openFolder = function(folder) {
|
||||||
$scope.state.nav.currentFolder = folder;
|
$scope.state.nav.currentFolder = folder;
|
||||||
$scope.state.nav.toggle(false);
|
$scope.state.nav.toggle(false);
|
||||||
@ -72,15 +100,23 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
// Start
|
// Start
|
||||||
//
|
//
|
||||||
|
|
||||||
// handle back button
|
|
||||||
backBtnHandler.start();
|
|
||||||
// init folders
|
// init folders
|
||||||
initializeFolders();
|
initializeFolders();
|
||||||
|
|
||||||
// select inbox as the current folder on init
|
// folder index url watcher
|
||||||
if ($scope.account.folders && $scope.account.folders.length > 0) {
|
$scope.$watch('(loc.search()).folder', function(folderIndex) {
|
||||||
$scope.openFolder($scope.account.folders[0]);
|
if (typeof folderIndex === 'undefined') {
|
||||||
|
$location.search('folder', 0); // navigate to inbox by default
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
// select current folder
|
||||||
|
folderIndex = typeof folderIndex === 'string' ? parseInt(folderIndex, 10) : folderIndex;
|
||||||
|
if ($scope.account.folders && $scope.account.folders.length > folderIndex) {
|
||||||
|
// navigate to the selected folder index
|
||||||
|
$scope.openFolder($scope.account.folders[folderIndex]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// connect imap/smtp clients on first startup
|
// connect imap/smtp clients on first startup
|
||||||
account.onConnect(function(err) {
|
account.onConnect(function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -101,8 +137,9 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
|
|
||||||
function initializeFolders() {
|
function initializeFolders() {
|
||||||
// create dummy folder in dev environment only
|
// create dummy folder in dev environment only
|
||||||
if ($routeParams.dev) {
|
if ($location.search().dev) {
|
||||||
createDummyFolders();
|
$scope.$root.account = {};
|
||||||
|
$scope.account.folders = dummy.listFolders();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,33 +159,6 @@ var NavigationCtrl = function($scope, $routeParams, $location, account, email, o
|
|||||||
timeout: NOTIFICATION_SENT_TIMEOUT
|
timeout: NOTIFICATION_SENT_TIMEOUT
|
||||||
}, function() {});
|
}, function() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// attach dummy folders for development
|
|
||||||
function createDummyFolders() {
|
|
||||||
$scope.$root.account = {};
|
|
||||||
$scope.account.folders = [{
|
|
||||||
type: 'Inbox',
|
|
||||||
count: 2,
|
|
||||||
path: 'INBOX'
|
|
||||||
}, {
|
|
||||||
type: 'Sent',
|
|
||||||
count: 0,
|
|
||||||
path: 'SENT'
|
|
||||||
}, {
|
|
||||||
type: config.outboxMailboxType,
|
|
||||||
count: 0,
|
|
||||||
path: config.outboxMailboxPath
|
|
||||||
}, {
|
|
||||||
type: 'Drafts',
|
|
||||||
count: 0,
|
|
||||||
path: 'DRAFTS'
|
|
||||||
}, {
|
|
||||||
type: 'Trash',
|
|
||||||
count: 0,
|
|
||||||
path: 'TRASH'
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -4,6 +4,10 @@ var util = require('crypto-lib').util;
|
|||||||
|
|
||||||
var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.privateKeyUpload = {
|
$scope.state.privateKeyUpload = {
|
||||||
toggle: function(to) {
|
toggle: function(to) {
|
||||||
// open lightbox
|
// open lightbox
|
||||||
@ -33,6 +37,10 @@ var PrivateKeyUploadCtrl = function($scope, keychain, pgp, dialog, auth) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
$scope.checkServerForKey = function(callback) {
|
$scope.checkServerForKey = function(callback) {
|
||||||
var keyParams = pgp.getKeyParams();
|
var keyParams = pgp.getKeyParams();
|
||||||
keychain.hasPrivateKey({
|
keychain.hasPrivateKey({
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) {
|
var ReadCtrl = function($scope, $location, email, invitation, outbox, pgp, keychain, appConfig, download, auth, dialog) {
|
||||||
|
|
||||||
var str = appConfig.string;
|
var str = appConfig.string;
|
||||||
|
|
||||||
// set default value so that the popover height is correct on init
|
//
|
||||||
$scope.keyId = 'No key found.';
|
// scope state
|
||||||
|
//
|
||||||
|
|
||||||
$scope.state.read = {
|
$scope.state.read = {
|
||||||
open: false,
|
open: false,
|
||||||
@ -18,7 +19,39 @@ var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appCon
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.$on('read', function(e, state) {
|
||||||
|
$scope.state.read.toggle(state);
|
||||||
|
});
|
||||||
|
|
||||||
|
// set default value so that the popover height is correct on init
|
||||||
|
$scope.keyId = 'No key found.';
|
||||||
|
|
||||||
|
//
|
||||||
|
// url/history handling
|
||||||
|
//
|
||||||
|
|
||||||
|
// read state url watcher
|
||||||
|
$scope.loc = $location;
|
||||||
|
$scope.$watch('(loc.search()).uid', function(uid) {
|
||||||
|
// synchronize the url to the scope state
|
||||||
|
$scope.state.read.toggle(!!uid);
|
||||||
|
});
|
||||||
|
$scope.$watch('state.read.open', function(value) {
|
||||||
|
// close read mode by navigating to folder view
|
||||||
|
if (!value) {
|
||||||
|
$location.search('uid', null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// scope functions
|
||||||
|
//
|
||||||
|
|
||||||
$scope.getKeyId = function(address) {
|
$scope.getKeyId = function(address) {
|
||||||
|
if ($location.search().dev || !address) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.keyId = 'Searching...';
|
$scope.keyId = 'Searching...';
|
||||||
keychain.getReceiverPublicKey(address, function(err, pubkey) {
|
keychain.getReceiverPublicKey(address, function(err, pubkey) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -41,7 +74,7 @@ var ReadCtrl = function($scope, email, invitation, outbox, pgp, keychain, appCon
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.$watch('state.mailList.selected', function(mail) {
|
$scope.$watch('state.mailList.selected', function(mail) {
|
||||||
if (!mail) {
|
if ($location.search().dev || !mail) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ var LoginExistingCtrl = function($scope, $location, $routeParams, email, auth, k
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$location.path('/desktop');
|
$location.path('/account');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ var LoginInitialCtrl = function($scope, $location, $routeParams, newsletter, ema
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$location.path('/desktop');
|
$location.path('/account');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -95,7 +95,7 @@ var LoginExistingCtrl = function($scope, $location, $routeParams, email, auth, p
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$location.path('/desktop');
|
$location.path('/account');
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams, auth
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.goTo('/desktop');
|
$scope.goTo('/account');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ var LoginCtrl = function($scope, $timeout, $location, updateHandler, account, au
|
|||||||
return dialog.error(err);
|
return dialog.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.goTo('/desktop');
|
$scope.goTo('/account');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (availableKeys && availableKeys.publicKey && !availableKeys.privateKey) {
|
} else if (availableKeys && availableKeys.publicKey && !availableKeys.privateKey) {
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var axe = require('axe-logger'),
|
|
||||||
DEBUG_TAG = 'backbutton handler';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The back button handler introduces meaningful behavior fo rthe back button:
|
|
||||||
* if there's an open lightbox, close it;
|
|
||||||
* if the reader is open in mobile mode, close it;
|
|
||||||
* if the navigation is open, close it;
|
|
||||||
* if there's nothing else open, shut down the app;
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
var backBtnHandler = {
|
|
||||||
attachHandler: function(scope) {
|
|
||||||
this.scope = scope;
|
|
||||||
},
|
|
||||||
start: function() {
|
|
||||||
document.addEventListener("backbutton", handleBackButton, false);
|
|
||||||
},
|
|
||||||
stop: function() {
|
|
||||||
document.removeEventListener("backbutton", handleBackButton, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function handleBackButton(event) {
|
|
||||||
axe.debug(DEBUG_TAG, 'back button pressed');
|
|
||||||
|
|
||||||
// this disarms the default behavior which we NEVER want
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
|
|
||||||
if (backBtnHandler.scope.state.lightbox) {
|
|
||||||
// closes the lightbox (error msgs, writer, ...)
|
|
||||||
backBtnHandler.scope.state.lightbox = undefined;
|
|
||||||
axe.debug(DEBUG_TAG, 'lightbox closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else if (backBtnHandler.scope.state.read && backBtnHandler.scope.state.read.open) {
|
|
||||||
// closes the reader
|
|
||||||
backBtnHandler.scope.state.read.toggle(false);
|
|
||||||
axe.debug(DEBUG_TAG, 'reader closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else if (backBtnHandler.scope.state.nav && backBtnHandler.scope.state.nav.open) {
|
|
||||||
// closes the navigation
|
|
||||||
backBtnHandler.scope.state.nav.toggle(false);
|
|
||||||
axe.debug(DEBUG_TAG, 'navigation closed');
|
|
||||||
backBtnHandler.scope.$apply();
|
|
||||||
} else {
|
|
||||||
// exits the app
|
|
||||||
navigator.app.exitApp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = backBtnHandler;
|
|
@ -6,6 +6,50 @@ module.exports = Dummy;
|
|||||||
|
|
||||||
function Dummy() {}
|
function Dummy() {}
|
||||||
|
|
||||||
|
Dummy.prototype.listFolders = function() {
|
||||||
|
var dummies = [{
|
||||||
|
type: 'Inbox',
|
||||||
|
count: 2,
|
||||||
|
path: 'INBOX',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
type: 'Sent',
|
||||||
|
count: 0,
|
||||||
|
path: 'SENT',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
type: 'Outbox',
|
||||||
|
count: 0,
|
||||||
|
path: 'OUTBOX',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
type: 'Drafts',
|
||||||
|
count: 0,
|
||||||
|
path: 'DRAFTS',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
type: 'Trash',
|
||||||
|
count: 0,
|
||||||
|
path: 'TRASH',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
type: 'Flagged',
|
||||||
|
count: 0,
|
||||||
|
path: 'FLAGGED',
|
||||||
|
wellknown: true
|
||||||
|
}, {
|
||||||
|
name: 'Archive',
|
||||||
|
count: 0,
|
||||||
|
path: 'ARCHIVE'
|
||||||
|
}, {
|
||||||
|
name: 'Junk',
|
||||||
|
count: 0,
|
||||||
|
path: 'JUNK'
|
||||||
|
}];
|
||||||
|
|
||||||
|
return dummies;
|
||||||
|
};
|
||||||
|
|
||||||
Dummy.prototype.listMails = function() {
|
Dummy.prototype.listMails = function() {
|
||||||
var uid = 1000000;
|
var uid = 1000000;
|
||||||
|
|
||||||
|
@ -7,6 +7,6 @@ require('./dummy');
|
|||||||
require('./dialog');
|
require('./dialog');
|
||||||
require('./connection-doctor');
|
require('./connection-doctor');
|
||||||
require('./update/update-handler');
|
require('./update/update-handler');
|
||||||
require('./status-display');
|
require('./status');
|
||||||
require('./download');
|
require('./download');
|
||||||
require('./notification');
|
require('./notification');
|
@ -1,13 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var ngModule = angular.module('woUtil');
|
var ngModule = angular.module('woUtil');
|
||||||
ngModule.service('statusDisplay', StatusDisplay);
|
ngModule.service('status', Status);
|
||||||
module.exports = StatusDisplay;
|
module.exports = Status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A central service to display status updates to the user
|
* A central service to display status updates to the user
|
||||||
*/
|
*/
|
||||||
function StatusDisplay($rootScope, axe) {
|
function Status($rootScope, axe) {
|
||||||
this._rootScope = $rootScope;
|
this._rootScope = $rootScope;
|
||||||
this._axe = axe;
|
this._axe = axe;
|
||||||
}
|
}
|
||||||
@ -17,7 +17,7 @@ function StatusDisplay($rootScope, axe) {
|
|||||||
* @param {String} text The status message that is to be displayed to the user
|
* @param {String} text The status message that is to be displayed to the user
|
||||||
* @param {Date} time The time of the last update
|
* @param {Date} time The time of the last update
|
||||||
*/
|
*/
|
||||||
StatusDisplay.prototype.update = function(text, time) {
|
Status.prototype.update = function(text, time) {
|
||||||
this._axe.info('status display', text);
|
this._axe.info('status display', text);
|
||||||
this._rootScope.$broadcast('status', text, time);
|
this._rootScope.$broadcast('status', text, time);
|
||||||
};
|
};
|
||||||
@ -26,6 +26,14 @@ StatusDisplay.prototype.update = function(text, time) {
|
|||||||
* Update the searching status to show a spinner while searching
|
* Update the searching status to show a spinner while searching
|
||||||
* @param {Boolean} state If the spinner should be displayed or not
|
* @param {Boolean} state If the spinner should be displayed or not
|
||||||
*/
|
*/
|
||||||
StatusDisplay.prototype.setSearching = function(state) {
|
Status.prototype.setSearching = function(state) {
|
||||||
this._rootScope.$broadcast('searching', state);
|
this._rootScope.$broadcast('searching', state);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the reading status to communicate between controllers, if we're in read mode.
|
||||||
|
* @param {Boolean} state If the reade mode should be open or not
|
||||||
|
*/
|
||||||
|
Status.prototype.setReading = function(state) {
|
||||||
|
this._rootScope.$broadcast('read', state);
|
||||||
|
};
|
@ -130,11 +130,6 @@
|
|||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
// allow scrolling on iOS
|
// allow scrolling on iOS
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
// hide scrollbar in webkit
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
&__entries {
|
&__entries {
|
||||||
display: table; // import for mail list entry desktop layout
|
display: table; // import for mail list entry desktop layout
|
||||||
@ -295,7 +290,8 @@
|
|||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
|
|
||||||
&:hover {
|
&:hover,
|
||||||
|
&.wo-touch-active {
|
||||||
background-color: rgba($color-main, 0.15);
|
background-color: rgba($color-main, 0.15);
|
||||||
}
|
}
|
||||||
&--unread {
|
&--unread {
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<p class="typo-paragraph">
|
<p class="typo-paragraph">
|
||||||
<br>
|
<br>
|
||||||
<a href="javascript:;" wo-touch='showDetails = !showDetails; $event.preventDefault()'>
|
<a href="#" wo-touch="$event.preventDefault(); showDetails = !showDetails">
|
||||||
{{showDetails ? "Hide Options" : "Show Options"}}
|
{{showDetails ? "Hide Options" : "Show Options"}}
|
||||||
</a>
|
</a>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
infinite-scroll-distance="1" infinite-scroll-parent="true">
|
infinite-scroll-distance="1" infinite-scroll-parent="true">
|
||||||
<li class="mail-list-entry"
|
<li class="mail-list-entry"
|
||||||
ng-class="{'mail-list-entry--active': email === state.mailList.selected, 'mail-list-entry--unread': email.unread, 'mail-list-entry--attachment': email.attachments !== undefined && email.attachments.length > 0}"
|
ng-class="{'mail-list-entry--active': email === state.mailList.selected, 'mail-list-entry--unread': email.unread, 'mail-list-entry--attachment': email.attachments !== undefined && email.attachments.length > 0}"
|
||||||
wo-touch="select(email)"
|
wo-touch="navigate(email)"
|
||||||
ng-repeat="email in displayMessages">
|
ng-repeat="email in displayMessages">
|
||||||
<ul class="mail-list-entry__flags">
|
<ul class="mail-list-entry__flags">
|
||||||
<li class="mail-list-entry__flags-unread"></li>
|
<li class="mail-list-entry__flags-unread"></li>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<ul class="nav__folders">
|
<ul class="nav__folders">
|
||||||
<li ng-repeat="folder in account.folders" ng-if="folder.wellknown" ng-hide="folder.type === 'Outbox' && folder.count < 1"
|
<li ng-repeat="folder in account.folders" ng-if="folder.wellknown" ng-hide="folder.type === 'Outbox' && folder.count < 1"
|
||||||
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
||||||
<a href="#" wo-touch="$event.preventDefault(); openFolder(folder)">
|
<a href="#/account?folder={{$index}}">
|
||||||
<svg ng-if="folder.type === 'Inbox'" role="presentation">
|
<svg ng-if="folder.type === 'Inbox'" role="presentation">
|
||||||
<use xlink:href="#icon-inbox" />
|
<use xlink:href="#icon-inbox" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -38,7 +38,7 @@
|
|||||||
<ul class="nav__folders">
|
<ul class="nav__folders">
|
||||||
<li ng-repeat="folder in account.folders" ng-if="!folder.wellknown"
|
<li ng-repeat="folder in account.folders" ng-if="!folder.wellknown"
|
||||||
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
class="nav__folder" ng-class="{'nav__folder--open': state.nav.currentFolder === folder}">
|
||||||
<a href="#" wo-touch="$event.preventDefault(); openFolder(folder)">
|
<a href="#/account?folder={{$index}}">
|
||||||
<svg role="presentation"><use xlink:href="#icon-folder" /></svg>
|
<svg role="presentation"><use xlink:href="#icon-folder" /></svg>
|
||||||
{{folder.name}}
|
{{folder.name}}
|
||||||
<span ng-show="folder.count > 0" class="nav__counter">{{folder.count}}</span>
|
<span ng-show="folder.count > 0" class="nav__counter">{{folder.count}}</span>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<div class="read__folder-toolbar">
|
<div class="read__folder-toolbar">
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<a class="toolbar__label" href="javascript:;" wo-touch="state.read.toggle(false)">
|
<a class="toolbar__label" href="#" wo-touch="$event.preventDefault(); state.read.toggle(false)">
|
||||||
<svg><use xlink:href="#icon-back" /><title>Back</title></svg>
|
<svg><use xlink:href="#icon-back" /><title>Back</title></svg>
|
||||||
{{state.nav.currentFolder.wellknown ? state.nav.currentFolder.type : state.nav.currentFolder.name}}
|
{{state.nav.currentFolder.wellknown ? state.nav.currentFolder.type : state.nav.currentFolder.name}}
|
||||||
</a>
|
</a>
|
||||||
|
20
test/main.js
20
test/main.js
@ -26,26 +26,6 @@ if (!Function.prototype.bind) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// a warm round of applause for phantomjs for missing events
|
|
||||||
(function() {
|
|
||||||
if (!window.CustomEvent) {
|
|
||||||
var CustomEvent = function(event, params) {
|
|
||||||
params = params || {
|
|
||||||
bubbles: false,
|
|
||||||
cancelable: false,
|
|
||||||
detail: undefined
|
|
||||||
};
|
|
||||||
var evt = document.createEvent('CustomEvent');
|
|
||||||
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
|
||||||
return evt;
|
|
||||||
};
|
|
||||||
|
|
||||||
CustomEvent.prototype = window.Event.prototype;
|
|
||||||
|
|
||||||
window.CustomEvent = CustomEvent;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test setup
|
// Test setup
|
||||||
//
|
//
|
||||||
|
@ -2,26 +2,22 @@
|
|||||||
|
|
||||||
var Email = require('../../../../src/js/email/email'),
|
var Email = require('../../../../src/js/email/email'),
|
||||||
Dialog = require('../../../../src/js/util/dialog'),
|
Dialog = require('../../../../src/js/util/dialog'),
|
||||||
StatusDisplay = require('../../../../src/js/util/status-display'),
|
Status = require('../../../../src/js/util/status'),
|
||||||
ActionBarCtrl = require('../../../../src/js/controller/app/action-bar');
|
ActionBarCtrl = require('../../../../src/js/controller/app/action-bar');
|
||||||
|
|
||||||
describe('Action Bar Controller unit test', function() {
|
describe('Action Bar Controller unit test', function() {
|
||||||
var scope, actionBarCtrl, emailMock, dialogMock, statusDisplayMock;
|
var scope, actionBarCtrl, emailMock, dialogMock, statusMock;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
emailMock = sinon.createStubInstance(Email);
|
emailMock = sinon.createStubInstance(Email);
|
||||||
dialogMock = sinon.createStubInstance(Dialog);
|
dialogMock = sinon.createStubInstance(Dialog);
|
||||||
statusDisplayMock = sinon.createStubInstance(StatusDisplay);
|
statusMock = sinon.createStubInstance(Status);
|
||||||
|
|
||||||
angular.module('actionbartest', []);
|
angular.module('actionbartest', ['woUtil']);
|
||||||
angular.mock.module('actionbartest');
|
angular.mock.module('actionbartest');
|
||||||
angular.mock.inject(function($rootScope, $controller) {
|
angular.mock.inject(function($rootScope, $controller) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
scope.state = {
|
scope.state = {};
|
||||||
mailList: {
|
|
||||||
updateStatus: function() {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
scope.state.nav = {
|
scope.state.nav = {
|
||||||
currentFolder: {
|
currentFolder: {
|
||||||
@ -35,15 +31,11 @@ describe('Action Bar Controller unit test', function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
scope.state.read = {
|
|
||||||
open: true
|
|
||||||
};
|
|
||||||
|
|
||||||
actionBarCtrl = $controller(ActionBarCtrl, {
|
actionBarCtrl = $controller(ActionBarCtrl, {
|
||||||
$scope: scope,
|
$scope: scope,
|
||||||
email: emailMock,
|
email: emailMock,
|
||||||
dialog: dialogMock,
|
dialog: dialogMock,
|
||||||
statusDisplay: statusDisplayMock
|
status: statusMock
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -60,8 +52,8 @@ describe('Action Bar Controller unit test', function() {
|
|||||||
|
|
||||||
scope.deleteMessage({});
|
scope.deleteMessage({});
|
||||||
|
|
||||||
|
expect(statusMock.setReading.withArgs(false).calledOnce).to.be.true;
|
||||||
expect(emailMock.deleteMessage.calledOnce).to.be.true;
|
expect(emailMock.deleteMessage.calledOnce).to.be.true;
|
||||||
expect(scope.state.read.open).to.be.false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -92,8 +84,8 @@ describe('Action Bar Controller unit test', function() {
|
|||||||
|
|
||||||
scope.moveMessage({}, {});
|
scope.moveMessage({}, {});
|
||||||
|
|
||||||
|
expect(statusMock.setReading.withArgs(false).calledOnce).to.be.true;
|
||||||
expect(emailMock.moveMessage.calledOnce).to.be.true;
|
expect(emailMock.moveMessage.calledOnce).to.be.true;
|
||||||
expect(scope.state.read.open).to.be.false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -157,8 +149,17 @@ describe('Action Bar Controller unit test', function() {
|
|||||||
|
|
||||||
scope.markMessage({}, true);
|
scope.markMessage({}, true);
|
||||||
|
|
||||||
|
expect(statusMock.setReading.withArgs(false).calledOnce).to.be.true;
|
||||||
|
expect(emailMock.setFlags.calledOnce).to.be.true;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark the selected mail and close read mode', function() {
|
||||||
|
emailMock.setFlags.yields();
|
||||||
|
|
||||||
|
scope.markMessage({}, true, true);
|
||||||
|
|
||||||
|
expect(statusMock.setReading.calledOnce).to.be.false;
|
||||||
expect(emailMock.setFlags.calledOnce).to.be.true;
|
expect(emailMock.setFlags.calledOnce).to.be.true;
|
||||||
expect(scope.state.read.open).to.be.false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,34 +3,15 @@
|
|||||||
var MailListCtrl = require('../../../../src/js/controller/app/mail-list'),
|
var MailListCtrl = require('../../../../src/js/controller/app/mail-list'),
|
||||||
EmailDAO = require('../../../../src/js/email/email'),
|
EmailDAO = require('../../../../src/js/email/email'),
|
||||||
KeychainDAO = require('../../../../src/js/service/keychain'),
|
KeychainDAO = require('../../../../src/js/service/keychain'),
|
||||||
StatusDisplay = require('../../../../src/js/util/status-display'),
|
Status = require('../../../../src/js/util/status'),
|
||||||
Dialog = require('../../../../src/js/util/dialog'),
|
Dialog = require('../../../../src/js/util/dialog'),
|
||||||
Search = require('../../../../src/js/email/search');
|
Search = require('../../../../src/js/email/search');
|
||||||
|
|
||||||
describe('Mail List controller unit test', function() {
|
describe('Mail List controller unit test', function() {
|
||||||
var scope, ctrl, statusDisplayMock, notificationMock, emailMock, keychainMock, dialogMock, searchMock,
|
var scope, ctrl, statusMock, notificationMock, emailMock, keychainMock, dialogMock, searchMock,
|
||||||
emailAddress, emails,
|
emailAddress, emails, location;
|
||||||
hasChrome, hasSocket, hasRuntime, hasIdentity;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
hasChrome = !!window.chrome;
|
|
||||||
hasSocket = !!window.chrome.socket;
|
|
||||||
hasIdentity = !!window.chrome.identity;
|
|
||||||
if (!hasChrome) {
|
|
||||||
window.chrome = {};
|
|
||||||
}
|
|
||||||
if (!hasSocket) {
|
|
||||||
window.chrome.socket = {};
|
|
||||||
}
|
|
||||||
if (!hasRuntime) {
|
|
||||||
window.chrome.runtime = {
|
|
||||||
getURL: function() {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (!hasIdentity) {
|
|
||||||
window.chrome.identity = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
emails = [{
|
emails = [{
|
||||||
unread: true
|
unread: true
|
||||||
}, {
|
}, {
|
||||||
@ -46,7 +27,7 @@ describe('Mail List controller unit test', function() {
|
|||||||
close: function() {}
|
close: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
statusDisplayMock = sinon.createStubInstance(StatusDisplay);
|
statusMock = sinon.createStubInstance(Status);
|
||||||
emailMock = sinon.createStubInstance(EmailDAO);
|
emailMock = sinon.createStubInstance(EmailDAO);
|
||||||
keychainMock = sinon.createStubInstance(KeychainDAO);
|
keychainMock = sinon.createStubInstance(KeychainDAO);
|
||||||
dialogMock = sinon.createStubInstance(Dialog);
|
dialogMock = sinon.createStubInstance(Dialog);
|
||||||
@ -54,19 +35,16 @@ describe('Mail List controller unit test', function() {
|
|||||||
|
|
||||||
angular.module('maillisttest', ['woEmail', 'woServices', 'woUtil']);
|
angular.module('maillisttest', ['woEmail', 'woServices', 'woUtil']);
|
||||||
angular.mock.module('maillisttest');
|
angular.mock.module('maillisttest');
|
||||||
angular.mock.inject(function($rootScope, $controller) {
|
angular.mock.inject(function($rootScope, $controller, $location) {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
scope.state = {
|
location = $location;
|
||||||
read: {
|
scope.state = {};
|
||||||
toggle: function() {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
scope.loadVisibleBodies = function() {};
|
scope.loadVisibleBodies = function() {};
|
||||||
ctrl = $controller(MailListCtrl, {
|
ctrl = $controller(MailListCtrl, {
|
||||||
$scope: scope,
|
$scope: scope,
|
||||||
$routeParams: {},
|
$location: location,
|
||||||
statusDisplay: statusDisplayMock,
|
status: statusMock,
|
||||||
notification: notificationMock,
|
notification: notificationMock,
|
||||||
email: emailMock,
|
email: emailMock,
|
||||||
keychain: keychainMock,
|
keychain: keychainMock,
|
||||||
@ -76,20 +54,7 @@ describe('Mail List controller unit test', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {});
|
||||||
if (!hasSocket) {
|
|
||||||
delete window.chrome.socket;
|
|
||||||
}
|
|
||||||
if (!hasRuntime) {
|
|
||||||
delete window.chrome.runtime;
|
|
||||||
}
|
|
||||||
if (!hasChrome) {
|
|
||||||
delete window.chrome;
|
|
||||||
}
|
|
||||||
if (!hasIdentity) {
|
|
||||||
delete window.chrome.identity;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('displayMore', function() {
|
describe('displayMore', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
@ -132,21 +97,21 @@ describe('Mail List controller unit test', function() {
|
|||||||
|
|
||||||
it('should show initial message on empty', function() {
|
it('should show initial message on empty', function() {
|
||||||
scope.displaySearchResults();
|
scope.displaySearchResults();
|
||||||
expect(statusDisplayMock.setSearching.withArgs(false).calledOnce).to.be.true;
|
expect(statusMock.setSearching.withArgs(false).calledOnce).to.be.true;
|
||||||
expect(statusDisplayMock.update.withArgs('Online').calledOnce).to.be.true;
|
expect(statusMock.update.withArgs('Online').calledOnce).to.be.true;
|
||||||
expect(scope.displayMessages.length).to.equal(2);
|
expect(scope.displayMessages.length).to.equal(2);
|
||||||
});
|
});
|
||||||
it('should show initial message on empty', function() {
|
it('should show initial message on empty', function() {
|
||||||
searchMock.filter.returns(['a']);
|
searchMock.filter.returns(['a']);
|
||||||
|
|
||||||
scope.displaySearchResults('query');
|
scope.displaySearchResults('query');
|
||||||
expect(statusDisplayMock.setSearching.withArgs(true).calledOnce).to.be.true;
|
expect(statusMock.setSearching.withArgs(true).calledOnce).to.be.true;
|
||||||
expect(statusDisplayMock.update.withArgs('Searching ...').calledOnce).to.be.true;
|
expect(statusMock.update.withArgs('Searching ...').calledOnce).to.be.true;
|
||||||
clock.tick(500);
|
clock.tick(500);
|
||||||
|
|
||||||
expect(scope.displayMessages).to.deep.equal(['a']);
|
expect(scope.displayMessages).to.deep.equal(['a']);
|
||||||
expect(statusDisplayMock.setSearching.withArgs(false).calledOnce).to.be.true;
|
expect(statusMock.setSearching.withArgs(false).calledOnce).to.be.true;
|
||||||
expect(statusDisplayMock.update.withArgs('Matches in this folder').calledOnce).to.be.true;
|
expect(statusMock.update.withArgs('Matches in this folder').calledOnce).to.be.true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -160,10 +125,12 @@ describe('Mail List controller unit test', function() {
|
|||||||
describe('push notification', function() {
|
describe('push notification', function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
scope._stopWatchTask();
|
scope._stopWatchTask();
|
||||||
|
sinon.stub(scope, 'navigate');
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
notificationMock.create.restore();
|
notificationMock.create.restore();
|
||||||
|
scope.navigate.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should succeed for single mail', function(done) {
|
it('should succeed for single mail', function(done) {
|
||||||
@ -181,7 +148,7 @@ describe('Mail List controller unit test', function() {
|
|||||||
expect(opts.message).to.equal(mail.subject);
|
expect(opts.message).to.equal(mail.subject);
|
||||||
|
|
||||||
opts.onClick();
|
opts.onClick();
|
||||||
expect(scope.state.mailList.selected).to.equal(mail);
|
expect(scope.navigate.withArgs(mail).calledOnce).to.be.true;
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -224,7 +191,7 @@ describe('Mail List controller unit test', function() {
|
|||||||
expect(opts.message).to.equal(mails[0].subject + '\n' + mails[1].subject);
|
expect(opts.message).to.equal(mails[0].subject + '\n' + mails[1].subject);
|
||||||
|
|
||||||
opts.onClick();
|
opts.onClick();
|
||||||
expect(scope.state.mailList.selected).to.equal(mails[0]);
|
expect(scope.navigate.withArgs(mails[0]).calledOnce).to.be.true;
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -358,7 +325,7 @@ describe('Mail List controller unit test', function() {
|
|||||||
}));
|
}));
|
||||||
it('should output date only if date is not today', angular.mock.inject(function($filter) {
|
it('should output date only if date is not today', angular.mock.inject(function($filter) {
|
||||||
var yesterday = new Date();
|
var yesterday = new Date();
|
||||||
yesterday.setTime(yesterday.getTime() - 24*60*60*1000);
|
yesterday.setTime(yesterday.getTime() - 24 * 60 * 60 * 1000);
|
||||||
|
|
||||||
var expected = $filter('date')(yesterday, 'mediumDate');
|
var expected = $filter('date')(yesterday, 'mediumDate');
|
||||||
expect(scope.formatDate(yesterday)).to.equal(expected);
|
expect(scope.formatDate(yesterday)).to.equal(expected);
|
||||||
|
@ -119,7 +119,7 @@ describe('Login Controller unit test', function() {
|
|||||||
expect(dialogMock.error.calledOnce).to.be.true;
|
expect(dialogMock.error.calledOnce).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should redirect to /desktop', function() {
|
it('should redirect to /account', function() {
|
||||||
authMock.init.yields();
|
authMock.init.yields();
|
||||||
authMock.getEmailAddress.yields(null, {
|
authMock.getEmailAddress.yields(null, {
|
||||||
emailAddress: emailAddress
|
emailAddress: emailAddress
|
||||||
@ -133,7 +133,7 @@ describe('Login Controller unit test', function() {
|
|||||||
|
|
||||||
createController();
|
createController();
|
||||||
|
|
||||||
expect(goToStub.withArgs('/desktop').calledOnce).to.be.true;
|
expect(goToStub.withArgs('/account').calledOnce).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail for keychain.requestPrivateKeyDownload', function() {
|
it('should fail for keychain.requestPrivateKeyDownload', function() {
|
||||||
|
@ -60,7 +60,7 @@ describe('Login (existing user) Controller unit test', function() {
|
|||||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||||
expect(pathSpy.calledOnce).to.be.true;
|
expect(pathSpy.calledOnce).to.be.true;
|
||||||
expect(pathSpy.calledWith('/desktop')).to.be.true;
|
expect(pathSpy.calledWith('/account')).to.be.true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not work when keypair unavailable', function() {
|
it('should not work when keypair unavailable', function() {
|
||||||
|
@ -102,7 +102,7 @@ describe('Login (initial user) Controller unit test', function() {
|
|||||||
expect(scope.errMsg).to.not.exist;
|
expect(scope.errMsg).to.not.exist;
|
||||||
expect(scope.state.ui).to.equal(2);
|
expect(scope.state.ui).to.equal(2);
|
||||||
expect(newsletterStub.called).to.be.true;
|
expect(newsletterStub.called).to.be.true;
|
||||||
expect(location.$$path).to.equal('/desktop');
|
expect(location.$$path).to.equal('/account');
|
||||||
expect(emailMock.unlock.calledOnce).to.be.true;
|
expect(emailMock.unlock.calledOnce).to.be.true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -152,7 +152,7 @@ describe('Login Private Key Download Controller unit test', function() {
|
|||||||
scope.decryptAndStorePrivateKeyLocally();
|
scope.decryptAndStorePrivateKeyLocally();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should goto /desktop on emailDao.unlock success', function(done) {
|
it('should goto /account on emailDao.unlock success', function(done) {
|
||||||
keychainMock.decryptAndStorePrivateKeyLocally.yields(null, {
|
keychainMock.decryptAndStorePrivateKeyLocally.yields(null, {
|
||||||
encryptedKey: 'keyArmored'
|
encryptedKey: 'keyArmored'
|
||||||
});
|
});
|
||||||
@ -160,7 +160,7 @@ describe('Login Private Key Download Controller unit test', function() {
|
|||||||
authMock.storeCredentials.yields();
|
authMock.storeCredentials.yields();
|
||||||
|
|
||||||
scope.goTo = function(location) {
|
scope.goTo = function(location) {
|
||||||
expect(location).to.equal('/desktop');
|
expect(location).to.equal('/account');
|
||||||
expect(keychainMock.decryptAndStorePrivateKeyLocally.calledOnce).to.be.true;
|
expect(keychainMock.decryptAndStorePrivateKeyLocally.calledOnce).to.be.true;
|
||||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||||
done();
|
done();
|
||||||
@ -173,10 +173,10 @@ describe('Login Private Key Download Controller unit test', function() {
|
|||||||
describe('goTo', function() {
|
describe('goTo', function() {
|
||||||
it('should work', function() {
|
it('should work', function() {
|
||||||
sinon.stub(location, 'path', function(path) {
|
sinon.stub(location, 'path', function(path) {
|
||||||
expect(path).to.equal('/desktop');
|
expect(path).to.equal('/account');
|
||||||
});
|
});
|
||||||
|
|
||||||
scope.goTo('/desktop');
|
scope.goTo('/account');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -1,64 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
var btnHandler = require('../../../src/js/util/backbutton-handler');
|
|
||||||
|
|
||||||
describe('Backbutton Handler', function() {
|
|
||||||
chai.config.includeStack = true;
|
|
||||||
|
|
||||||
var scope, event;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
scope = {
|
|
||||||
state: {},
|
|
||||||
$apply: function() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
event = new CustomEvent('backbutton');
|
|
||||||
|
|
||||||
// this is a precondition for the test. throw an exception
|
|
||||||
// if this would produce side effects
|
|
||||||
expect(navigator.app).to.not.exist;
|
|
||||||
navigator.app = {};
|
|
||||||
|
|
||||||
btnHandler.attachHandler(scope);
|
|
||||||
btnHandler.start();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
btnHandler.stop();
|
|
||||||
delete navigator.app;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close lightbox', function() {
|
|
||||||
scope.state.lightbox = 'asd';
|
|
||||||
document.dispatchEvent(event);
|
|
||||||
expect(scope.state.lightbox).to.be.undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close reader', function() {
|
|
||||||
scope.state.read = {
|
|
||||||
open: true,
|
|
||||||
toggle: function(state) {
|
|
||||||
scope.state.read.open = state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.dispatchEvent(event);
|
|
||||||
expect(scope.state.read.open).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close navigation', function() {
|
|
||||||
scope.state.nav = {
|
|
||||||
open: true,
|
|
||||||
toggle: function(state) {
|
|
||||||
scope.state.nav.open = state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.dispatchEvent(event);
|
|
||||||
expect(scope.state.nav.open).to.be.false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should close app', function(done) {
|
|
||||||
navigator.app.exitApp = done;
|
|
||||||
document.dispatchEvent(event);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,14 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('Status Display Service unit test', function() {
|
describe('Status Service unit test', function() {
|
||||||
var statusDisplay, logInfoStub, rootScope, broadcastSpy;
|
var status, logInfoStub, rootScope, broadcastSpy;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
angular.module('statusDisplay-test', ['woUtil']);
|
angular.module('status-test', ['woUtil']);
|
||||||
angular.mock.module('statusDisplay-test');
|
angular.mock.module('status-test');
|
||||||
angular.mock.inject(function($injector, axe) {
|
angular.mock.inject(function($injector, axe) {
|
||||||
logInfoStub = sinon.stub(axe, 'info');
|
logInfoStub = sinon.stub(axe, 'info');
|
||||||
statusDisplay = $injector.get('statusDisplay');
|
status = $injector.get('status');
|
||||||
rootScope = $injector.get('$rootScope');
|
rootScope = $injector.get('$rootScope');
|
||||||
broadcastSpy = sinon.spy(rootScope, '$broadcast');
|
broadcastSpy = sinon.spy(rootScope, '$broadcast');
|
||||||
});
|
});
|
||||||
@ -23,7 +23,7 @@ describe('Status Display Service unit test', function() {
|
|||||||
var message = 'Tada!',
|
var message = 'Tada!',
|
||||||
time = new Date();
|
time = new Date();
|
||||||
|
|
||||||
statusDisplay.update(message, time);
|
status.update(message, time);
|
||||||
|
|
||||||
expect(broadcastSpy.withArgs('status', message, time).calledOnce).to.be.true;
|
expect(broadcastSpy.withArgs('status', message, time).calledOnce).to.be.true;
|
||||||
expect(logInfoStub.withArgs('status display', message).calledOnce).to.be.true;
|
expect(logInfoStub.withArgs('status display', message).calledOnce).to.be.true;
|
||||||
@ -32,10 +32,18 @@ describe('Status Display Service unit test', function() {
|
|||||||
|
|
||||||
describe('setSearching', function() {
|
describe('setSearching', function() {
|
||||||
it('should work', function() {
|
it('should work', function() {
|
||||||
statusDisplay.setSearching(true);
|
status.setSearching(true);
|
||||||
|
|
||||||
expect(broadcastSpy.withArgs('searching', true).calledOnce).to.be.true;
|
expect(broadcastSpy.withArgs('searching', true).calledOnce).to.be.true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('setReading', function() {
|
||||||
|
it('should work', function() {
|
||||||
|
status.setReading(true);
|
||||||
|
|
||||||
|
expect(broadcastSpy.withArgs('read', true).calledOnce).to.be.true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user