mirror of
https://github.com/moparisthebest/mail
synced 2024-11-23 01:12:19 -05:00
commit
5fef73ab99
@ -12,8 +12,15 @@
|
||||
<script src="require-config.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</head>
|
||||
|
||||
|
||||
<body key-shortcuts>
|
||||
|
||||
<div ng-view class="main-app-view"></div>
|
||||
|
||||
<!-- error dialog lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div><!--/.lightbox-overlay-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -20,6 +20,13 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div ng-view class="main-app-view ios-spacer"></div>
|
||||
|
||||
<!-- error dialog lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div><!--/.lightbox-overlay-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -19,9 +19,11 @@ requirejs([
|
||||
'js/controller/write',
|
||||
'js/controller/navigation',
|
||||
'cryptoLib/util',
|
||||
'js/util/error',
|
||||
'angularSanitize',
|
||||
'angularRoute',
|
||||
'angularTouch'
|
||||
'angularTouch',
|
||||
'angularAnimate'
|
||||
], function(
|
||||
angular,
|
||||
DialogCtrl,
|
||||
@ -39,7 +41,8 @@ requirejs([
|
||||
ReadCtrl,
|
||||
WriteCtrl,
|
||||
NavigationCtrl,
|
||||
util
|
||||
util,
|
||||
errorUtil
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
@ -51,6 +54,7 @@ requirejs([
|
||||
'ngSanitize',
|
||||
'ngRoute',
|
||||
'ngTouch',
|
||||
'ngAnimate',
|
||||
'navigation',
|
||||
'mail-list',
|
||||
'write',
|
||||
@ -91,6 +95,13 @@ requirejs([
|
||||
});
|
||||
});
|
||||
|
||||
app.run(function($rootScope) {
|
||||
// global state... inherited to all child scopes
|
||||
$rootScope.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($rootScope);
|
||||
});
|
||||
|
||||
// inject controllers from ng-included view templates
|
||||
app.controller('ReadCtrl', ReadCtrl);
|
||||
app.controller('WriteCtrl', WriteCtrl);
|
||||
|
@ -10,9 +10,8 @@ define(function(require) {
|
||||
var AboutCtrl = function($scope) {
|
||||
|
||||
$scope.state.about = {
|
||||
open: false,
|
||||
toggle: function(to) {
|
||||
this.open = to;
|
||||
$scope.state.lightbox = (to) ? 'about' : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -15,9 +15,8 @@ define(function(require) {
|
||||
pgp = appController._crypto;
|
||||
|
||||
$scope.state.account = {
|
||||
open: false,
|
||||
toggle: function(to) {
|
||||
this.open = to;
|
||||
$scope.state.lightbox = (to) ? 'account' : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,15 +1,9 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller'),
|
||||
errorUtil = require('js/util/error');
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
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._auth.getCredentials({}, function(err) {
|
||||
if (err) {
|
||||
|
@ -15,9 +15,9 @@ define(function(require) {
|
||||
pgp = appController._crypto;
|
||||
|
||||
$scope.state.contacts = {
|
||||
open: false,
|
||||
toggle: function(to) {
|
||||
this.open = to;
|
||||
$scope.state.lightbox = (to) ? 'contacts' : undefined;
|
||||
|
||||
$scope.listKeys();
|
||||
}
|
||||
};
|
||||
|
@ -1,15 +1,9 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller'),
|
||||
errorUtil = require('js/util/error');
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginExistingCtrl = function($scope, $location) {
|
||||
// global state... inherited to all child scopes
|
||||
$scope.$root.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($scope);
|
||||
|
||||
var emailDao = appController._emailDao;
|
||||
|
||||
$scope.buttonEnabled = true;
|
||||
|
@ -1,18 +1,12 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller'),
|
||||
errorUtil = require('js/util/error');
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginInitialCtrl = function($scope, $location) {
|
||||
var emailDao = appController._emailDao,
|
||||
states, termsMsg = 'You must accept the Terms of Service to continue.';
|
||||
|
||||
// global state... inherited to all child scopes
|
||||
$scope.$root.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($scope);
|
||||
|
||||
states = {
|
||||
IDLE: 1,
|
||||
PROCESSING: 2,
|
||||
|
@ -2,15 +2,9 @@ define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var angular = require('angular'),
|
||||
errorUtil = require('js/util/error'),
|
||||
appController = require('js/app-controller');
|
||||
|
||||
var LoginExistingCtrl = function($scope, $location) {
|
||||
// global state... inherited to all child scopes
|
||||
$scope.$root.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($scope);
|
||||
|
||||
var emailDao = appController._emailDao,
|
||||
pgp = appController._crypto;
|
||||
|
||||
|
@ -1,15 +1,9 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var appController = require('js/app-controller'),
|
||||
errorUtil = require('js/util/error');
|
||||
var appController = require('js/app-controller');
|
||||
|
||||
var LoginCtrl = function($scope, $location) {
|
||||
// global state... inherited to all child scopes
|
||||
$scope.$root.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($scope);
|
||||
|
||||
// check for app update
|
||||
appController.checkForUpdate();
|
||||
|
||||
|
@ -44,7 +44,7 @@ define(function(require) {
|
||||
}
|
||||
|
||||
// display fetched body
|
||||
$scope.$apply();
|
||||
$scope.$digest();
|
||||
|
||||
// automatically decrypt if it's the selected email
|
||||
if (email === $scope.state.mailList.selected) {
|
||||
@ -164,7 +164,7 @@ define(function(require) {
|
||||
var index = getFolder().messages.indexOf(email);
|
||||
// show the next mail
|
||||
if (getFolder().messages.length > 1) {
|
||||
// if we're about to delete the last entry of the array, show the previous (i.e. the one below in the list),
|
||||
// if we're about to delete the last entry of the array, show the previous (i.e. the one below in the list),
|
||||
// otherwise show the next one (i.e. the one above in the list)
|
||||
$scope.select(_.last(getFolder().messages) === email ? getFolder().messages[index - 1] : getFolder().messages[index + 1]);
|
||||
} else {
|
||||
@ -209,7 +209,6 @@ define(function(require) {
|
||||
$timeout(function() {
|
||||
// display and select first
|
||||
selectFirstMessage();
|
||||
$scope.$apply();
|
||||
});
|
||||
|
||||
$scope.synchronize();
|
||||
@ -289,6 +288,8 @@ define(function(require) {
|
||||
}]; // sender address
|
||||
this.to = [{
|
||||
address: 'max.musterman@gmail.com'
|
||||
}, {
|
||||
address: 'max.musterman@gmail.com'
|
||||
}]; // list of receivers
|
||||
this.cc = [{
|
||||
address: 'john.doe@gmail.com'
|
||||
@ -399,11 +400,13 @@ define(function(require) {
|
||||
//
|
||||
|
||||
var ngModule = angular.module('mail-list', []);
|
||||
ngModule.directive('ngIscroll', function() {
|
||||
|
||||
ngModule.directive('ngIscroll', function($timeout) {
|
||||
return {
|
||||
link: function(scope, elm, attrs) {
|
||||
var model = attrs.ngIscroll,
|
||||
listEl = elm[0];
|
||||
listEl = elm[0],
|
||||
myScroll;
|
||||
|
||||
/*
|
||||
* iterates over the mails in the mail list and loads their bodies if they are visible in the viewport
|
||||
@ -418,7 +421,7 @@ define(function(require) {
|
||||
isPartiallyVisibleTop, isPartiallyVisibleBottom, isVisible;
|
||||
|
||||
for (var i = 0, len = listItems.length; i < len; i++) {
|
||||
// the n-th list item (the dom representation of an email) corresponds to
|
||||
// the n-th list item (the dom representation of an email) corresponds to
|
||||
// the n-th message model in the filteredMessages array
|
||||
listItem = listItems.item(i).getBoundingClientRect();
|
||||
message = scope.filteredMessages[i];
|
||||
@ -439,18 +442,22 @@ define(function(require) {
|
||||
}
|
||||
};
|
||||
|
||||
// re-init iScroll when model length changes
|
||||
scope.$watch(model, function() {
|
||||
var myScroll;
|
||||
// activate iscroll
|
||||
myScroll = new IScroll(listEl, {
|
||||
mouseWheel: true
|
||||
});
|
||||
// activate iscroll
|
||||
myScroll = new IScroll(listEl, {
|
||||
mouseWheel: true,
|
||||
scrollbars: true,
|
||||
fadeScrollbars: true
|
||||
});
|
||||
myScroll.on('scrollEnd', scope.loadVisibleBodies);
|
||||
|
||||
// refresh iScroll when model length changes
|
||||
scope.$watchCollection(model, function() {
|
||||
$timeout(function() {
|
||||
myScroll.refresh();
|
||||
});
|
||||
// load the visible message bodies, when the list is re-initialized and when scrolling stopped
|
||||
scope.loadVisibleBodies();
|
||||
myScroll.on('scrollEnd', scope.loadVisibleBodies);
|
||||
}, true);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ define(function(require) {
|
||||
var angular = require('angular'),
|
||||
str = require('js/app-config').string,
|
||||
appController = require('js/app-controller'),
|
||||
errorUtil = require('js/util/error'),
|
||||
notification = require('js/util/notification'),
|
||||
_ = require('underscore'),
|
||||
emailDao, outboxBo;
|
||||
@ -14,11 +13,6 @@ define(function(require) {
|
||||
//
|
||||
|
||||
var NavigationCtrl = function($scope) {
|
||||
// global state... inherited to all child scopes
|
||||
$scope.$root.state = {};
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($scope);
|
||||
|
||||
emailDao = appController._emailDao;
|
||||
outboxBo = appController._outboxBo;
|
||||
|
||||
@ -149,51 +143,46 @@ define(function(require) {
|
||||
|
||||
var modifier = e.ctrlKey || e.metaKey;
|
||||
|
||||
if (modifier && e.keyCode === 78 && scope.state.writer && !scope.state.writer.open) {
|
||||
if (modifier && e.keyCode === 78 && scope.state.lightbox !== 'write') {
|
||||
// n -> new mail
|
||||
e.preventDefault();
|
||||
scope.state.writer.write();
|
||||
scope.$apply();
|
||||
|
||||
} else if (modifier && e.keyCode === 70 && !scope.state.writer.open) {
|
||||
} else if (modifier && e.keyCode === 70 && scope.state.lightbox !== 'write') {
|
||||
// f -> find
|
||||
e.preventDefault();
|
||||
scope.state.mailList.searching = true;
|
||||
$timeout(function() {
|
||||
scope.state.mailList.searching = false;
|
||||
}, 200);
|
||||
scope.$apply();
|
||||
|
||||
} else if (modifier && e.keyCode === 82 && scope.state.writer && !scope.state.writer.open && scope.state.mailList.selected) {
|
||||
} else if (modifier && e.keyCode === 82 && scope.state.lightbox !== 'write' && scope.state.mailList.selected) {
|
||||
// r -> reply
|
||||
e.preventDefault();
|
||||
scope.state.writer.write(scope.state.mailList.selected);
|
||||
scope.$apply();
|
||||
|
||||
} else if (modifier && e.keyCode === 83 && scope.state.writer && !scope.state.writer.open && scope.state.mailList.synchronize) {
|
||||
} else if (modifier && e.keyCode === 83 && scope.state.lightbox !== 'write' && scope.state.mailList.synchronize) {
|
||||
// s -> sync folder
|
||||
e.preventDefault();
|
||||
scope.state.mailList.synchronize();
|
||||
scope.$apply();
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.writer.open) {
|
||||
// escape -> close writer
|
||||
} else if (e.keyCode === 27 && scope.state.lightbox !== undefined) {
|
||||
// escape -> close current lightbox
|
||||
e.preventDefault();
|
||||
scope.state.writer.close();
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.account.open) {
|
||||
// escape -> close account view
|
||||
e.preventDefault();
|
||||
scope.state.account.toggle(false);
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.contacts.open) {
|
||||
// escape -> close contacts view
|
||||
e.preventDefault();
|
||||
scope.state.contacts.toggle(false);
|
||||
scope.state.lightbox = undefined;
|
||||
scope.$apply();
|
||||
|
||||
} else if (e.keyCode === 27 && scope.state.nav.open) {
|
||||
// escape -> close nav view
|
||||
e.preventDefault();
|
||||
scope.state.nav.toggle(false);
|
||||
scope.$apply();
|
||||
}
|
||||
|
||||
scope.$apply();
|
||||
});
|
||||
};
|
||||
});
|
||||
|
@ -13,9 +13,8 @@ define(function(require) {
|
||||
pgp = appController._crypto;
|
||||
|
||||
$scope.state.setPassphrase = {
|
||||
open: false,
|
||||
toggle: function(to) {
|
||||
this.open = to;
|
||||
$scope.state.lightbox = (to) ? 'set-passphrase' : undefined;
|
||||
|
||||
$scope.newPassphrase = undefined;
|
||||
$scope.oldPassphrase = undefined;
|
||||
|
@ -25,9 +25,8 @@ define(function(require) {
|
||||
//
|
||||
|
||||
$scope.state.writer = {
|
||||
open: false,
|
||||
write: function(replyTo, replyAll, forward) {
|
||||
this.open = true;
|
||||
$scope.state.lightbox = 'write';
|
||||
$scope.replyTo = replyTo;
|
||||
|
||||
resetFields();
|
||||
@ -39,7 +38,7 @@ define(function(require) {
|
||||
$scope.verify($scope.to[0]);
|
||||
},
|
||||
close: function() {
|
||||
this.open = false;
|
||||
$scope.state.lightbox = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
@ -48,9 +47,11 @@ define(function(require) {
|
||||
$scope.to = [{
|
||||
address: ''
|
||||
}];
|
||||
$scope.showCC = false;
|
||||
$scope.cc = [{
|
||||
address: ''
|
||||
}];
|
||||
$scope.showBCC = false;
|
||||
$scope.bcc = [{
|
||||
address: ''
|
||||
}];
|
||||
@ -85,6 +86,7 @@ define(function(require) {
|
||||
$scope.cc.unshift({
|
||||
address: recipient.address
|
||||
});
|
||||
$scope.showCC = true;
|
||||
});
|
||||
$scope.cc.forEach($scope.verify);
|
||||
}
|
||||
@ -172,7 +174,7 @@ define(function(require) {
|
||||
}
|
||||
|
||||
$scope.checkSendStatus();
|
||||
$scope.$apply();
|
||||
$scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
@ -332,10 +334,9 @@ define(function(require) {
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
// view -> model
|
||||
elm.on('keyup keydown', function() {
|
||||
scope.$apply(function() {
|
||||
// set model
|
||||
ctrl.$setViewValue(elm[0].innerText);
|
||||
});
|
||||
// set model
|
||||
ctrl.$setViewValue(elm[0].innerText);
|
||||
scope.$digest();
|
||||
});
|
||||
|
||||
// model -> view
|
||||
@ -404,6 +405,11 @@ define(function(require) {
|
||||
scope.$apply();
|
||||
}
|
||||
|
||||
function removeInput(field, index, scope) {
|
||||
field.splice(index, 1);
|
||||
scope.$apply();
|
||||
}
|
||||
|
||||
function checkForEmptyInput(field) {
|
||||
var emptyFieldExists = false;
|
||||
field.forEach(function(recipient) {
|
||||
@ -415,6 +421,18 @@ define(function(require) {
|
||||
return emptyFieldExists;
|
||||
}
|
||||
|
||||
function cleanupEmptyInputs(field, scope) {
|
||||
var i;
|
||||
|
||||
for (i = field.length - 2; i >= 0; i--) {
|
||||
if (!field[i].address) {
|
||||
field.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
scope.$apply();
|
||||
}
|
||||
|
||||
ngModule.directive('field', function() {
|
||||
return {
|
||||
//scope: true, // optionally create a child scope
|
||||
@ -455,12 +473,14 @@ define(function(require) {
|
||||
// create new field input
|
||||
addInput(field, scope);
|
||||
}
|
||||
|
||||
cleanupEmptyInputs(field, scope);
|
||||
});
|
||||
|
||||
element.on('keydown', function(e) {
|
||||
var code = e.keyCode;
|
||||
|
||||
scope.$apply();
|
||||
scope.$digest();
|
||||
|
||||
if (code === 32 || code === 188 || code === 186) {
|
||||
// catch space, comma, semicolon
|
||||
@ -476,8 +496,7 @@ define(function(require) {
|
||||
// backspace, delete on empty input
|
||||
// remove input
|
||||
e.preventDefault();
|
||||
field.splice(index, 1);
|
||||
scope.$apply();
|
||||
removeInput(field, index, scope);
|
||||
// focus on previous id
|
||||
var previousId = fieldName + (index - 1);
|
||||
document.getElementById(previousId).focus();
|
||||
@ -503,7 +522,7 @@ define(function(require) {
|
||||
mimeType: file.type,
|
||||
content: new Uint8Array(e.target.result)
|
||||
});
|
||||
scope.$apply();
|
||||
scope.$digest();
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ define(function() {
|
||||
var er = {};
|
||||
|
||||
er.attachHandler = function(scope) {
|
||||
scope.$root.onError = function(options) {
|
||||
scope.onError = function(options) {
|
||||
if (!options) {
|
||||
scope.$apply();
|
||||
return;
|
||||
|
27
src/lib/angular/angular-animate.min.js
vendored
Executable file
27
src/lib/angular/angular-animate.min.js
vendored
Executable file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
AngularJS v1.2.13
|
||||
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(z,f,T){'use strict';f.module("ngAnimate",["ng"]).factory("$$animateReflow",["$window","$timeout","$document",function(f,h,d){var n=f.requestAnimationFrame||f.webkitRequestAnimationFrame||function(d){return h(d,10,!1)},w=f.cancelAnimationFrame||f.webkitCancelAnimationFrame||function(d){return h.cancel(d)};return function(d){var f=n(function(){d()});return function(){w(f)}}}]).factory("$$asyncQueueBuffer",["$timeout",function(f){var h,d=[];return function(n){f.cancel(h);d.push(n);h=f(function(){for(var f=
|
||||
0;f<d.length;f++)d[f]();d=[]},0,!1)}}]).config(["$provide","$animateProvider",function($,h){function d(d){for(var f=0;f<d.length;f++){var l=d[f];if(l.nodeType==da)return l}}function n(l){return f.element(d(l))}var w=f.noop,D=f.forEach,ia=h.$$selectors,da=1,l="$$ngAnimateState",U="ng-animate",s={running:!0};$.decorator("$animate",["$delegate","$injector","$sniffer","$rootElement","$$asyncQueueBuffer","$rootScope","$document",function(x,z,ca,F,J,B,T){function V(a){if(a){var c=[],e={};a=a.substr(1).split(".");
|
||||
(ca.transitions||ca.animations)&&a.push("");for(var A=0;A<a.length;A++){var d=a[A],f=ia[d];f&&!e[d]&&(c.push(z.get(f)),e[d]=!0)}return c}}function t(a,c,e,d,k,C,s){function t(b){var g=e.data(l);b=b||!g||!g.active[c]||m&&g.active[c].event!=a;K();!0===b?G():(g.active[c].done=G,n(L,"after",G))}function n(b,g,ja){"after"==g?H():x();var fa=g+"End";D(b,function(d,f){var A=function(){a:{var a=g+"Complete",c=b[f];c[a]=!0;(c[fa]||w)();for(c=0;c<b.length;c++)if(!b[c][a])break a;ja()}};"before"!=g||"enter"!=
|
||||
a&&"move"!=a?d[g]?d[fa]=F?d[g](e,E,z,A):m?d[g](e,c,A):d[g](e,A):A():A()})}function h(b){var g="$animate:"+b;u&&(u[g]&&0<u[g].length)&&J(function(){e.triggerHandler(g,{event:a,className:c})})}function x(){h("before")}function H(){h("after")}function B(){h("close");s&&J(function(){s()})}function K(){K.hasBeenRun||(K.hasBeenRun=!0,C())}function G(){if(!G.hasBeenRun){G.hasBeenRun=!0;var b=e.data(l);b&&(m?M(e,c):(J(function(){var b=e.data(l)||{};Q==b.index&&M(e,c,a)}),e.data(l,b)));B()}}var E,z,F="setClass"==
|
||||
a;F&&(E=c[0],z=c[1],c=E+" "+z);var v,y=e[0];y&&(v=y.className,v=v+" "+c);if(y&&W(v)){var u=f.element._data(y),u=u&&u.events,y=(" "+v).replace(/\s+/g,".");d||(d=k?k.parent():e.parent());var q=V(y),m="addClass"==a||"removeClass"==a||F,I=e.data(l)||{};k=I.active||{};y=I.totalActive||0;v=I.last;if(R(e,d)||0===q.length)K(),x(),H(),G();else{var L=[];m&&(I.disabled||v&&!v.classBased)||D(q,function(b){if(!b.allowCancel||b.allowCancel(e,a,c)){var g=b[a];"leave"==a?(b=g,g=null):b=b["before"+a.charAt(0).toUpperCase()+
|
||||
a.substr(1)];L.push({before:b,after:g})}});if(0===L.length)K(),x(),H(),B();else{d=!1;if(0<y){q=[];if(m)"setClass"==v.event?(q.push(v),M(e,c)):k[c]&&(N=k[c],N.event==a?d=!0:(q.push(N),M(e,c)));else if("leave"==a&&k["ng-leave"])d=!0;else{for(var N in k)q.push(k[N]),M(e,N);k={};y=0}0<q.length&&f.forEach(q,function(b){(b.done||w)(!0);X(b.animations)})}!m||(F||d)||(d="addClass"==a==e.hasClass(c));if(d)x(),H(),B();else{e.addClass(U);var Q=S++;v={classBased:m,event:a,animations:L,done:t};y++;k[c]=v;e.data(l,
|
||||
{last:v,active:k,index:Q,totalActive:y});n(L,"before",t)}}}}else K(),x(),H(),B()}function Y(a){a=d(a);D(a.querySelectorAll("."+U),function(a){a=f.element(a);(a=a.data(l))&&a.active&&f.forEach(a.active,function(a){(a.done||w)(!0);X(a.animations)})})}function X(a){D(a,function(a){a.beforeComplete||(a.beforeEnd||w)(!0);a.afterComplete||(a.afterEnd||w)(!0)})}function M(a,c){if(d(a)==d(F))s.disabled||(s.running=!1,s.structural=!1);else if(c){var e=a.data(l)||{},f=!0===c;!f&&(e.active&&e.active[c])&&(e.totalActive--,
|
||||
delete e.active[c]);if(f||!e.totalActive)a.removeClass(U),a.removeData(l)}}function R(a,c){if(s.disabled)return!0;if(d(a)==d(F))return s.disabled||s.running;do{if(0===c.length)break;var e=d(c)==d(F),f=e?s:c.data(l),f=f&&(!!f.disabled||f.running||0<f.totalActive);if(e||f)return f;if(e)break}while(c=c.parent());return!0}var S=0;F.data(l,s);B.$$postDigest(function(){B.$$postDigest(function(){s.running=!1})});var Z=h.classNameFilter(),W=Z?function(a){return Z.test(a)}:function(){return!0};return{enter:function(a,
|
||||
c,e,d){this.enabled(!1,a);x.enter(a,c,e);B.$$postDigest(function(){a=n(a);t("enter","ng-enter",a,c,e,w,d)})},leave:function(a,c){Y(a);this.enabled(!1,a);B.$$postDigest(function(){a=n(a);t("leave","ng-leave",a,null,null,function(){x.leave(a)},c)})},move:function(a,c,e,d){Y(a);this.enabled(!1,a);x.move(a,c,e);B.$$postDigest(function(){a=n(a);t("move","ng-move",a,c,e,w,d)})},addClass:function(a,c,d){a=n(a);t("addClass",c,a,null,null,function(){x.addClass(a,c)},d)},removeClass:function(a,c,d){a=n(a);
|
||||
t("removeClass",c,a,null,null,function(){x.removeClass(a,c)},d)},setClass:function(a,c,d,f){a=n(a);t("setClass",[c,d],a,null,null,function(){x.setClass(a,c,d)},f)},enabled:function(a,c){switch(arguments.length){case 2:if(a)M(c);else{var d=c.data(l)||{};d.disabled=!0;c.data(l,d)}break;case 1:s.disabled=!a;break;default:a=!s.disabled}return!!a}}}]);h.register("",["$window","$sniffer","$timeout","$$animateReflow",function(l,s,h,n){function J(b,g){I&&I();m.push(g);I=n(function(){D(m,function(b){b()});
|
||||
m=[];I=null;u={}})}function B(b,g){var a=Date.now()+1E3*g;if(!(a<=N)){h.cancel(L);var c=d(b);b=f.element(c);Q.push(b);N=a;L=h(function(){U(Q);Q=[]},g,!1)}}function U(b){D(b,function(b){(b=b.data(E))&&(b.closeAnimationFn||w)()})}function V(b,g){var a=g?u[g]:null;if(!a){var c=0,d=0,f=0,e=0,k,p,r,h;D(b,function(b){if(b.nodeType==da){b=l.getComputedStyle(b)||{};r=b[O+ea];c=Math.max(t(r),c);h=b[O+H];k=b[O+ha];d=Math.max(t(k),d);p=b[P+ha];e=Math.max(t(p),e);var g=t(b[P+ea]);0<g&&(g*=parseInt(b[P+K],10)||
|
||||
1);f=Math.max(g,f)}});a={total:0,transitionPropertyStyle:h,transitionDurationStyle:r,transitionDelayStyle:k,transitionDelay:d,transitionDuration:c,animationDelayStyle:p,animationDelay:e,animationDuration:f};g&&(u[g]=a)}return a}function t(b){var g=0;b=f.isString(b)?b.split(/\s*,\s*/):[];D(b,function(b){g=Math.max(parseFloat(b)||0,g)});return g}function Y(b){var g=b.parent(),a=g.data(G);a||(g.data(G,++q),a=q);return a+"-"+d(b).className}function X(b,g,a,c){var e=Y(g),k=e+" "+a,l=u[k]?++u[k].total:
|
||||
0,h={};if(0<l){var p=a+"-stagger",h=e+" "+p;(e=!u[h])&&g.addClass(p);h=V(g,h);e&&g.removeClass(p)}c=c||function(b){return b()};g.addClass(a);var p=g.data(E)||{},r=c(function(){return V(g,k)});c=r.transitionDuration;e=r.animationDuration;if(0===c&&0===e)return g.removeClass(a),!1;g.data(E,{running:p.running||0,itemIndex:l,stagger:h,timings:r,closeAnimationFn:f.noop});b=0<p.running||"setClass"==b;0<c&&M(g,a,b);0<e&&(d(g).style[P]="none 0s");return!0}function M(b,a,c){"ng-enter"!=a&&("ng-move"!=a&&"ng-leave"!=
|
||||
a)&&c?b.addClass(ga):d(b).style[O+H]="none"}function R(b,a){var c=O+H,e=d(b);e.style[c]&&0<e.style[c].length&&(e.style[c]="");b.removeClass(ga)}function S(b){var a=P;b=d(b);b.style[a]&&0<b.style[a].length&&(b.style[a]="")}function Z(b,a,c,e){function f(b){a.off(w,k);a.removeClass(l);A(a,c);b=d(a);for(var e in q)b.style.removeProperty(q[e])}function k(b){b.stopPropagation();var a=b.originalEvent||b;b=a.$manualTimeStamp||a.timeStamp||Date.now();a=parseFloat(a.elapsedTime.toFixed($));Math.max(b-x,0)>=
|
||||
u&&a>=s&&e()}var h=d(a);b=a.data(E);if(-1!=h.className.indexOf(c)&&b){var l="";D(c.split(" "),function(b,a){l+=(0<a?" ":"")+b+"-active"});var p=b.stagger,r=b.timings,n=b.itemIndex,s=Math.max(r.transitionDuration,r.animationDuration),t=Math.max(r.transitionDelay,r.animationDelay),u=t*y,x=Date.now(),w=ba+" "+aa,m="",q=[];if(0<r.transitionDuration){var z=r.transitionPropertyStyle;-1==z.indexOf("all")&&(m+=C+"transition-property: "+z+";",m+=C+"transition-duration: "+r.transitionDurationStyle+";",q.push(C+
|
||||
"transition-property"),q.push(C+"transition-duration"))}0<n&&(0<p.transitionDelay&&0===p.transitionDuration&&(m+=C+"transition-delay: "+W(r.transitionDelayStyle,p.transitionDelay,n)+"; ",q.push(C+"transition-delay")),0<p.animationDelay&&0===p.animationDuration&&(m+=C+"animation-delay: "+W(r.animationDelayStyle,p.animationDelay,n)+"; ",q.push(C+"animation-delay")));0<q.length&&(r=h.getAttribute("style")||"",h.setAttribute("style",r+" "+m));a.on(w,k);a.addClass(l);b.closeAnimationFn=function(){f();
|
||||
e()};h=(n*(Math.max(p.animationDelay,p.transitionDelay)||0)+(t+s)*v)*y;b.running++;B(a,h);return f}e()}function W(b,a,c){var d="";D(b.split(","),function(b,e){d+=(0<e?",":"")+(c*a+parseInt(b,10))+"s"});return d}function a(b,a,c,d){if(X(b,a,c,d))return function(b){b&&A(a,c)}}function c(b,a,c,d){if(a.data(E))return Z(b,a,c,d);A(a,c);d()}function e(b,g,d,e){var f=a(b,g,d);if(f){var h=f;J(g,function(){R(g,d);S(g);h=c(b,g,d,e)});return function(b){(h||w)(b)}}e()}function A(b,a){b.removeClass(a);var c=
|
||||
b.data(E);c&&(c.running&&c.running--,c.running&&0!==c.running||b.removeData(E))}function k(b,a){var c="";b=f.isArray(b)?b:b.split(/\s+/);D(b,function(b,d){b&&0<b.length&&(c+=(0<d?" ":"")+b+a)});return c}var C="",O,aa,P,ba;z.ontransitionend===T&&z.onwebkittransitionend!==T?(C="-webkit-",O="WebkitTransition",aa="webkitTransitionEnd transitionend"):(O="transition",aa="transitionend");z.onanimationend===T&&z.onwebkitanimationend!==T?(C="-webkit-",P="WebkitAnimation",ba="webkitAnimationEnd animationend"):
|
||||
(P="animation",ba="animationend");var ea="Duration",H="Property",ha="Delay",K="IterationCount",G="$$ngAnimateKey",E="$$ngAnimateCSS3Data",ga="ng-animate-block-transitions",$=3,v=1.5,y=1E3,u={},q=0,m=[],I,L=null,N=0,Q=[];return{enter:function(b,a){return e("enter",b,"ng-enter",a)},leave:function(b,a){return e("leave",b,"ng-leave",a)},move:function(a,c){return e("move",a,"ng-move",c)},beforeSetClass:function(b,c,d,e){var f=k(d,"-remove")+" "+k(c,"-add"),h=a("setClass",b,f,function(a){var e=b.attr("class");
|
||||
b.removeClass(d);b.addClass(c);a=a();b.attr("class",e);return a});if(h)return J(b,function(){R(b,f);S(b);e()}),h;e()},beforeAddClass:function(b,c,d){var e=a("addClass",b,k(c,"-add"),function(a){b.addClass(c);a=a();b.removeClass(c);return a});if(e)return J(b,function(){R(b,c);S(b);d()}),e;d()},setClass:function(a,d,e,f){e=k(e,"-remove");d=k(d,"-add");return c("setClass",a,e+" "+d,f)},addClass:function(a,d,e){return c("addClass",a,k(d,"-add"),e)},beforeRemoveClass:function(b,c,d){var e=a("removeClass",
|
||||
b,k(c,"-remove"),function(a){var d=b.attr("class");b.removeClass(c);a=a();b.attr("class",d);return a});if(e)return J(b,function(){R(b,c);S(b);d()}),e;d()},removeClass:function(a,d,e){return c("removeClass",a,k(d,"-remove"),e)}}}])}])})(window,window.angular);
|
||||
//# sourceMappingURL=angular-animate.min.js.map
|
@ -16,6 +16,7 @@
|
||||
angularRoute: 'angular/angular-route.min',
|
||||
angularTouch: 'angular/angular-touch.min',
|
||||
angularSanitize: 'angular/angular-sanitize.min',
|
||||
angularAnimate: 'angular/angular-animate.min',
|
||||
uuid: 'uuid/uuid',
|
||||
forge: 'forge/forge.min',
|
||||
punycode: 'punycode.min',
|
||||
@ -41,6 +42,10 @@
|
||||
exports: 'angular',
|
||||
deps: ['angular']
|
||||
},
|
||||
angularAnimate: {
|
||||
exports: 'angular',
|
||||
deps: ['angular']
|
||||
},
|
||||
iscroll: {
|
||||
exports: 'IScroll'
|
||||
},
|
||||
|
@ -4,6 +4,9 @@
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: border-box;
|
||||
|
||||
// remove flickering on item touch selection in ios
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
}
|
||||
|
||||
// Body reset
|
||||
@ -34,6 +37,24 @@ textarea {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
// Custom scrollbars in webkit
|
||||
// @see http://css-tricks.com/custom-scrollbars-in-webkit/
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: $color-grey-lighter;
|
||||
border: 3px solid transparent;
|
||||
background-clip: content-box;
|
||||
cursor: pointer !important;
|
||||
&:hover {
|
||||
background-color: $color-blue;
|
||||
}
|
||||
}
|
||||
|
||||
// add space at the top since ios7 apps are now fullscreen
|
||||
.ios-spacer {
|
||||
padding-top: 20px;
|
||||
@ -45,14 +66,4 @@ textarea {
|
||||
|
||||
// allow text selection
|
||||
user-select: none;
|
||||
|
||||
// make scrollbars invisible
|
||||
::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
}
|
||||
|
||||
// remove flickering on item touch selection in ios
|
||||
* {
|
||||
-webkit-tap-highlight-color: transparent !important;
|
||||
}
|
||||
}
|
@ -51,7 +51,6 @@ $lightbox-padding: 15px;
|
||||
$lightbox-max-width: 662px;
|
||||
$lightbox-width: 90%;
|
||||
$lightbox-min-height: 644px;
|
||||
$lightbox-top: 7.5%;
|
||||
|
||||
$btn-back-color: $color-blue;
|
||||
$btn-color: #fff;
|
||||
|
@ -3,6 +3,11 @@
|
||||
@import "functions";
|
||||
@import "grid";
|
||||
|
||||
// Third party libs
|
||||
@import "lib/angular-csp"; // use angular csp specific classes
|
||||
@import "lib/scut";
|
||||
|
||||
// Bootstrap
|
||||
@import "normalize";
|
||||
@import "variables"; // Modify this for custom colors, font-sizes, etc
|
||||
@import "fonts";
|
||||
@ -20,6 +25,8 @@
|
||||
@import "components/layout";
|
||||
@import "components/popover";
|
||||
@import "components/input";
|
||||
@import "components/mail-addresses";
|
||||
@import "components/spinner";
|
||||
|
||||
// Views
|
||||
@import "views/shared";
|
||||
@ -33,4 +40,4 @@
|
||||
@import "views/mail-list";
|
||||
@import "views/read";
|
||||
@import "views/write";
|
||||
@import "views/login";
|
||||
@import "views/login";
|
@ -46,6 +46,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.label-blank {
|
||||
background-color: transparent;
|
||||
color: $color-black;
|
||||
text-align: left;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.label-light {
|
||||
background-color: $label-light-back-color;
|
||||
color: $label-light-color;
|
||||
|
@ -5,22 +5,27 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2000;
|
||||
visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
|
||||
@include respond-to(desktop) {
|
||||
top: $lightbox-top;
|
||||
margin: 0 auto;
|
||||
width: $lightbox-width;
|
||||
max-width: $lightbox-max-width;
|
||||
max-height: $lightbox-min-height;
|
||||
height: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.lightbox-body {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
padding: $lightbox-padding;
|
||||
background: #fff;
|
||||
backface-visibility: hidden;
|
||||
|
||||
@include respond-to(desktop) {
|
||||
max-height: $lightbox-min-height;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
@ -52,36 +57,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
.lightbox-overlay.show .lightbox {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.lightbox-overlay {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
opacity: 0;
|
||||
background: $color-grey-dark-alpha;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.lightbox-overlay.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
@include respond-to(desktop) {
|
||||
@include scut-vcenter-ib(".lightbox");
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// effect
|
||||
.lightbox-effect .lightbox-body {
|
||||
transform: scale(0.7);
|
||||
opacity: 0;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
&.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.lightbox-overlay.show .lightbox-effect .lightbox-body {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
/* ngAnimate */
|
||||
&.show-add {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
.lightbox-body {
|
||||
transform: scale(0.7);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
}
|
||||
&.show-add-active {
|
||||
opacity: 1;
|
||||
.lightbox-body {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
&.show-remove {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s;
|
||||
.lightbox-body {
|
||||
transform: scale(1);
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
}
|
||||
&.show-remove-active {
|
||||
opacity: 0;
|
||||
.lightbox-body {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
}
|
||||
}
|
17
src/sass/components/_mail-addresses.scss
Normal file
17
src/sass/components/_mail-addresses.scss
Normal file
@ -0,0 +1,17 @@
|
||||
.mail-addresses {
|
||||
p {
|
||||
margin: 0.4em 0 0.2em;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-bottom: 0.2em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
width: 2.75em;
|
||||
color: $color-grey;
|
||||
}
|
||||
}
|
@ -19,6 +19,10 @@
|
||||
cursor: pointer;
|
||||
transition: background-color $time-li-fade, color $time-li-fade;
|
||||
|
||||
&.ng-animate {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@include text-overflow;
|
||||
|
||||
|
22
src/sass/components/_spinner.scss
Normal file
22
src/sass/components/_spinner.scss
Normal file
@ -0,0 +1,22 @@
|
||||
.spinner {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin-right: 0.2em;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
animation: spinner-rotation .6s linear infinite;
|
||||
border-left: 0.17em solid $color-grey-light;
|
||||
border-right: 0.17em solid $color-grey-light;
|
||||
border-bottom: 0.17em solid $color-grey-light;
|
||||
border-top: 0.17em solid $color-grey;
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
@keyframes spinner-rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
18
src/sass/lib/_angular-csp.scss
Executable file
18
src/sass/lib/_angular-csp.scss
Executable file
@ -0,0 +1,18 @@
|
||||
/* Include this file in your html if you are using the CSP mode. */
|
||||
|
||||
@charset "UTF-8";
|
||||
|
||||
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
|
||||
.ng-cloak, .x-ng-cloak,
|
||||
.ng-hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
ng\:form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ng-animate-block-transitions {
|
||||
transition:0s all!important;
|
||||
-webkit-transition:0s all!important;
|
||||
}
|
1485
src/sass/lib/_scut.scss
Normal file
1485
src/sass/lib/_scut.scss
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,9 +15,13 @@
|
||||
}
|
||||
|
||||
.key-list {
|
||||
max-height: 400px;
|
||||
position: relative;
|
||||
margin: 20px;
|
||||
overflow-y: scroll;
|
||||
|
||||
.key-list-scroll {
|
||||
max-height: 400px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
table {
|
||||
th, td {
|
||||
@ -37,6 +41,11 @@
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
// pull popover upwards to keep popup inside lightbox
|
||||
.popover {
|
||||
margin-top: -20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
|
||||
@include respond-to(desktop) {
|
||||
max-width: 350px;
|
||||
top: 30%;
|
||||
}
|
||||
|
||||
p {
|
||||
|
@ -63,32 +63,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display:none;
|
||||
}
|
||||
|
||||
&.syncing {
|
||||
.spinner {
|
||||
top: 6.5px;
|
||||
left: $padding-horizontal;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
position: absolute;
|
||||
animation: rotation .6s linear infinite;
|
||||
border-left: 2px solid $color-grey-light;
|
||||
border-right: 2px solid $color-grey-light;
|
||||
border-bottom: 2px solid $color-grey-light;
|
||||
border-top: 2px solid $color-grey;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.text {
|
||||
padding-left: 1.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
.view-read {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0px;
|
||||
padding: 10px 15px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
color: $color-grey-dark;
|
||||
|
||||
.headers {
|
||||
flex-shrink: 0;
|
||||
margin-bottom: 1em;
|
||||
|
||||
p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.subject {
|
||||
font-size: $font-size-bigger;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.date {
|
||||
@ -21,24 +21,31 @@
|
||||
font-size: $font-size-small;
|
||||
margin-top: 0.25em;
|
||||
margin-bottom: 1.5em;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.address {
|
||||
color: $color-grey;
|
||||
padding: 0.2em 0;
|
||||
|
||||
.mail-addresses {
|
||||
.label {
|
||||
margin-left: 0.3em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
p {
|
||||
margin-top: 0.2em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
float: right;
|
||||
margin: 0 15px 10px;
|
||||
|
||||
button {
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attachments {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: inherit;
|
||||
border: 1px;
|
||||
@ -72,54 +79,30 @@
|
||||
}
|
||||
|
||||
.seperator-line {
|
||||
flex-shrink: 0;
|
||||
height: 1px;
|
||||
color: $color-grey-lighter;
|
||||
background-color: $color-grey-lighter;
|
||||
}
|
||||
|
||||
.body {
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
margin-top: 1.75em;
|
||||
cursor: text;
|
||||
padding-bottom: 250px;
|
||||
line-height: 1.5em;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
user-select: text;
|
||||
|
||||
.working {
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
width: 230px;
|
||||
display: table;
|
||||
@include scut-vcenter-tt;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
|
||||
.container {
|
||||
display: table-cell;
|
||||
strong {
|
||||
color: $color-grey-input;
|
||||
vertical-align: middle;
|
||||
|
||||
.spinner {
|
||||
position: relative;
|
||||
|
||||
div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
animation: rotation .6s linear infinite;
|
||||
border-left: 5px solid $color-grey-light;
|
||||
border-right: 5px solid $color-grey-light;
|
||||
border-bottom: 5px solid $color-grey-light;
|
||||
border-top: 5px solid $color-grey;
|
||||
border-radius: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding-left: 40px;
|
||||
line-height: 30px;
|
||||
color: $color-grey-input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,6 +120,7 @@
|
||||
}
|
||||
|
||||
iframe {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -145,43 +129,39 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
border-bottom: 1px solid $color-grey-lighter;
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: block;
|
||||
background: none;
|
||||
width: 100%;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
padding: 0.5em 1em 0.5em 0.3em;
|
||||
color: $color-blue;
|
||||
user-select: none;
|
||||
transition: background-color 0.3s;
|
||||
text-align: left;
|
||||
|
||||
tr {
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: darken($color-white, 2%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.seperator {
|
||||
border-bottom: 1px solid $color-grey-lighter;
|
||||
}
|
||||
&:before {
|
||||
display: inline-block;
|
||||
width: 2.5em;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 7px 5px;
|
||||
|
||||
&.left {
|
||||
padding-left: 15px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
&.right {
|
||||
padding-right: 15px;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: darken($color-white, 2%);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
float: right;
|
||||
margin: 10px 15px;
|
||||
|
||||
button {
|
||||
margin-left: 7px;
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
.view-write {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
color: $color-grey-dark;
|
||||
@ -6,7 +8,8 @@
|
||||
|
||||
height: 100%;
|
||||
@include respond-to(desktop) {
|
||||
height: 600px;
|
||||
// this number depends on max-height set on .lightbox
|
||||
height: 590px; // magic number
|
||||
}
|
||||
|
||||
input {
|
||||
@ -18,26 +21,35 @@
|
||||
border: 0!important;
|
||||
}
|
||||
|
||||
.headers {
|
||||
.mail-addresses {
|
||||
flex-shrink: 0;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.2em 0;
|
||||
padding: 0.2em 0;
|
||||
cursor: text;
|
||||
}
|
||||
.mail-addresses-more {
|
||||
float: right;
|
||||
margin: 0.4em 0;
|
||||
|
||||
span {
|
||||
color: $color-grey;
|
||||
}
|
||||
button {
|
||||
display: inline-block;
|
||||
background: none;
|
||||
padding: 0 0.5em;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
color: $color-black;
|
||||
transition: color 0.3s;
|
||||
outline: 0;
|
||||
|
||||
input {
|
||||
margin-left: 0.3em;
|
||||
width: 80%;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $color-blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subject-box {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
margin: 20px 0 7px 0;
|
||||
width: inherit;
|
||||
@ -47,7 +59,6 @@
|
||||
height: em(44);
|
||||
|
||||
.subject-line {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
width: 80%;
|
||||
color: $color-grey;
|
||||
@ -82,6 +93,7 @@
|
||||
}
|
||||
|
||||
.attachments-box {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
margin: 0 0 5px 0;
|
||||
width: inherit;
|
||||
@ -126,13 +138,10 @@
|
||||
}
|
||||
|
||||
.body {
|
||||
flex-grow: 1;
|
||||
line-height: 1.5em;
|
||||
cursor: text;
|
||||
|
||||
@include respond-to(desktop) {
|
||||
height: 445px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
overflow-y: scroll;
|
||||
|
||||
*[contentEditable] {
|
||||
outline: 0px;
|
||||
|
@ -25,11 +25,6 @@
|
||||
|
||||
</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>
|
||||
|
@ -16,30 +16,34 @@
|
||||
</div>
|
||||
|
||||
<div class="key-list">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key ID</th>
|
||||
<th>Email</th>
|
||||
<th>Created</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
<tr ng-repeat="key in keys | orderBy:'userId' | filter:searchText">
|
||||
<td class="hover" ng-mouseover="getFingerprint(key)" popover="#fingerprint-contact">{{key._id.slice(8)}}</td>
|
||||
<td>{{key.userId}}</td>
|
||||
<td>{{key.created | date:'mediumDate'}}</td>
|
||||
<td>{{key.bitSize}} bit</td>
|
||||
<td><button class="remove" ng-click="removeKey(key)"></button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="key-list-scroll">
|
||||
<table>
|
||||
<tr>
|
||||
<th>Key ID</th>
|
||||
<th>Email</th>
|
||||
<th>Created</th>
|
||||
<th>Size</th>
|
||||
</tr>
|
||||
<tr ng-repeat="key in keys | orderBy:'userId' | filter:searchText">
|
||||
<td class="hover" ng-mouseover="getFingerprint(key)" popover="#fingerprint-contact">{{key._id.slice(8)}}</td>
|
||||
<td>{{key.userId}}</td>
|
||||
<td>{{key.created | date:'mediumDate'}}</td>
|
||||
<td>{{key.bitSize}} bit</td>
|
||||
<td><button class="remove" ng-click="removeKey(key)"></button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div><!--/.key-list-scroll-->
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="fingerprint-contact" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="popover-title"><b>Fingerprint</b></div>
|
||||
<div class="popover-content">{{fingerprint}}</div>
|
||||
</div><!--/.popover-->
|
||||
</div><!--/.key-list-->
|
||||
|
||||
</div><!-- /.view-contacts -->
|
||||
</div><!-- /.content -->
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="fingerprint-contact" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="popover-title"><b>Fingerprint</b></div>
|
||||
<div class="popover-content">{{fingerprint}}</div>
|
||||
</div><!--/.popover-->
|
||||
|
||||
|
||||
</div><!-- /.lightbox-body -->
|
@ -19,21 +19,22 @@
|
||||
</div><!--/.nav-container-->
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.writer.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/write.html'"></div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'write'}">
|
||||
<div class="lightbox" ng-include="'tpl/write.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.account.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/account.html'"></div>
|
||||
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'account'}">
|
||||
<div class="lightbox" ng-include="'tpl/account.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.setPassphrase.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/set-passphrase.html'"></div>
|
||||
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'set-passphrase'}">
|
||||
<div class="lightbox" ng-include="'tpl/set-passphrase.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.contacts.open}">
|
||||
<div class="lightbox lightbox-effect" ng-include="'tpl/contacts.html'"></div>
|
||||
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'contacts'}">
|
||||
<div class="lightbox" ng-include="'tpl/contacts.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.about.open}">
|
||||
<div class="lightbox lightbox-effect view-about" ng-include="'tpl/about.html'"></div>
|
||||
</div>
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.lightbox === 'about'}">
|
||||
<div class="lightbox view-about" ng-include="'tpl/about.html'"></div>
|
||||
</div>
|
@ -18,11 +18,6 @@
|
||||
</div><!--/content-->
|
||||
</div>
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div>
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="passphrase-info" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="arrow"></div>
|
||||
|
@ -33,11 +33,6 @@
|
||||
</div><!--/content-->
|
||||
</div>
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div>
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="passphrase-info" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="arrow"></div>
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
<div class="content">
|
||||
<p><b>Import keyfile.</b> To access your emails on this device, please import your existing key file.</p>
|
||||
|
||||
|
||||
<form>
|
||||
<div>
|
||||
<input type="file" accept=".asc" file-reader tabindex="1">
|
||||
@ -20,11 +20,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div>
|
||||
|
||||
<!-- popovers -->
|
||||
<div id="keyfile-info" class="popover right" ng-controller="PopoverCtrl">
|
||||
<div class="arrow"></div>
|
||||
|
@ -8,9 +8,4 @@
|
||||
<p><b>Login.</b> Authenticating with the mail server...</p>
|
||||
</div><!--/content-->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox-overlay" ng-class="{'show': state.dialog.open}">
|
||||
<div class="lightbox lightbox-effect dialog view-dialog" ng-include="'tpl/dialog.html'"></div>
|
||||
</div>
|
@ -8,7 +8,7 @@
|
||||
<input class="input-text input-search" type="search" results="5" ng-model="searchText" placeholder=" Filter..." focus-me="state.mailList.searching">
|
||||
</div>
|
||||
|
||||
<div class="list-wrapper" ng-iscroll="filteredMessages.length">
|
||||
<div class="list-wrapper" ng-iscroll="filteredMessages">
|
||||
<ul class="mail-list">
|
||||
<li ng-class="{'mail-list-active': email === state.mailList.selected, 'mail-list-attachment': email.attachments !== undefined && email.attachments.length > 0, 'mail-list-unread': email.unread, 'mail-list-replied': !email.unread && email.answered}" ng-click="select(email)" ng-repeat="email in (filteredMessages = (state.nav.currentFolder.messages | filter:searchText | orderBy:'uid':true | limitTo:100))">
|
||||
<h3>{{email.from[0].name || email.from[0].address}}</h3>
|
||||
|
@ -1,38 +1,43 @@
|
||||
<div class="controls">
|
||||
<button ng-click="state.mailList.remove(state.mailList.selected)" class="btn-icon" title="Delete mail"></button>
|
||||
<button class="btn-icon" title="Reply to" reply-selection></button>
|
||||
<button ng-click="state.writer.write()" class="btn-icon" title="New mail"></button>
|
||||
</div><!--/.controls-->
|
||||
|
||||
<div class="view-read" ng-controller="ReadCtrl">
|
||||
<div class="headers">
|
||||
<div class="controls">
|
||||
<button ng-click="state.mailList.remove(state.mailList.selected)" class="btn-icon" title="Delete mail"></button>
|
||||
<button class="btn-icon" title="Reply to" reply-selection></button>
|
||||
<button ng-click="state.writer.write()" class="btn-icon" title="New mail"></button>
|
||||
</div><!--/.controls-->
|
||||
|
||||
<p class="subject" ng-click="state.read.toggle(false)">{{(state.mailList.selected.subject) ? state.mailList.selected.subject : 'No subject'}}</p>
|
||||
<p class="date">{{state.mailList.selected.sentDate | date:'EEEE, MMM d, yyyy h:mm a'}}</p>
|
||||
<p class="address">
|
||||
From: <span ng-repeat="u in state.mailList.selected.from" class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
</p>
|
||||
<p class="address">
|
||||
To: <span ng-repeat="u in state.mailList.selected.to" class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
</p>
|
||||
<div ng-switch="state.mailList.selected.cc && state.mailList.selected.cc.length > 0">
|
||||
<p class="address" ng-switch-when="true">
|
||||
Cc: <span ng-repeat="u in state.mailList.selected.cc" class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
<div class="mail-addresses">
|
||||
<p>
|
||||
<label>From:</label>
|
||||
<span ng-repeat="u in state.mailList.selected.from">
|
||||
<span class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<label>To:</label>
|
||||
<span ng-repeat="u in state.mailList.selected.to">
|
||||
<span class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
</span>
|
||||
</p>
|
||||
<p ng-show="state.mailList.selected.cc && state.mailList.selected.cc.length > 0">
|
||||
<label>Cc:</label>
|
||||
<span ng-repeat="u in state.mailList.selected.cc">
|
||||
<span class="label" ng-class="{'label-primary': u.secure === false, 'label-primary-click': u.secure === false}" data-icon-append="{{(u.secure === false) ? '' : ''}}" ng-mouseover="getKeyId(u.address)" ng-click="invite(u)" popover="#fingerprint-info">{{u.name || u.address}}</span>
|
||||
</span>
|
||||
</p>
|
||||
</div><!--/.mail-addresses-->
|
||||
</div><!--/.headers-->
|
||||
|
||||
<div ng-switch="state.mailList.selected.attachments !== undefined && state.mailList.selected.attachments.length > 0">
|
||||
<div ng-switch-when="true">
|
||||
<div class="attachments">
|
||||
<span class="attachment" ng-repeat="attachment in state.mailList.selected.attachments" ng-click="download(attachment)">
|
||||
<span data-icon=""></span>
|
||||
{{attachment.filename}}
|
||||
</span><!--/.attachment-->
|
||||
</div><!--/.attachments-->
|
||||
</div>
|
||||
<div ng-switch-default>
|
||||
<div class="seperator-line"></div>
|
||||
</div>
|
||||
<div ng-switch-when="true" class="attachments">
|
||||
<span class="attachment" ng-repeat="attachment in state.mailList.selected.attachments" ng-click="download(attachment)">
|
||||
<span data-icon=""></span>
|
||||
{{attachment.filename}}
|
||||
</span><!--/.attachment-->
|
||||
</div><!--/.attachments-->
|
||||
<div ng-switch-default class="seperator-line"></div>
|
||||
</div><!--/.ng-switch-->
|
||||
|
||||
<div class="body" ng-switch="state.mailList.selected === undefined || (state.mailList.selected.encrypted === false && state.mailList.selected.body !== undefined) || (state.mailList.selected.encrypted === true && state.mailList.selected.decrypted === true)">
|
||||
@ -41,17 +46,12 @@
|
||||
<div class="line" ng-repeat="line in state.mailList.selected.body.split('\n') track by $index" ng-class="{'empty-line': lineEmpty(line)}">
|
||||
<span ng-bind-html="line | createAnchors"></span>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--/.line-->
|
||||
</div><!--/ng-switch-when-->
|
||||
<div class="working" ng-switch-default>
|
||||
<div class="container">
|
||||
<div class="spinner"><div></div></div>
|
||||
<span ng-switch="state.mailList.selected.loadingBody === true || state.mailList.selected.body === undefined || state.mailList.selected.body === null">
|
||||
<h1 ng-switch-when="true">Loading...</h1>
|
||||
<h1 ng-switch-default>Decrypting...</h1>
|
||||
</span>
|
||||
</div><!--/.container-->
|
||||
</div>
|
||||
<span class="spinner"></span>
|
||||
<strong ng-bind="(state.mailList.selected.loadingBody === true || state.mailList.selected.body === undefined || state.mailList.selected.body === null) ? 'Loading...' : 'Decrypting...'"></strong>
|
||||
</div><!--/.working-->
|
||||
</div><!--/.body-->
|
||||
|
||||
<!-- popovers -->
|
||||
@ -62,21 +62,10 @@
|
||||
|
||||
<div class="reply-selection popover bottom">
|
||||
<div class="arrow"></div>
|
||||
<div class="popover-content">
|
||||
<table>
|
||||
<tr class="seperator" ng-click="state.writer.write(state.mailList.selected)">
|
||||
<td class="left" data-icon=""></td>
|
||||
<td class="right">Reply</td>
|
||||
</tr>
|
||||
<tr class="seperator" ng-click="state.writer.write(state.mailList.selected, true)">
|
||||
<td class="left" data-icon=""></td>
|
||||
<td class="right">Reply All</td>
|
||||
</tr>
|
||||
<tr ng-click="state.writer.write(state.mailList.selected, null, true)">
|
||||
<td class="left" data-icon=""></td>
|
||||
<td class="right">Forward</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<ul class="popover-content">
|
||||
<li><button data-icon="" ng-click="state.writer.write(state.mailList.selected)">Reply</button></li>
|
||||
<li><button data-icon="" ng-click="state.writer.write(state.mailList.selected, true)">Reply All</button></li>
|
||||
<li><button data-icon="" ng-click="state.writer.write(state.mailList.selected, null, true)">Forward</button></li>
|
||||
</ul>
|
||||
</div><!--/.reply-selection-->
|
||||
</div><!--/.view-read-->
|
||||
|
@ -6,20 +6,30 @@
|
||||
<div class="content">
|
||||
|
||||
<div class="view-write">
|
||||
<div class="headers">
|
||||
<div class="mail-addresses">
|
||||
<div class="mail-addresses-more">
|
||||
<button ng-click="showCC = true;" ng-hide="showCC">Cc</button>
|
||||
<button ng-click="showBCC = true;" ng-hide="showBCC">Bcc</button>
|
||||
</div>
|
||||
<p field="to">
|
||||
<span>To:</span>
|
||||
<label>To:</label>
|
||||
<span ng-repeat="recipient in to track by $index">
|
||||
<input id="to{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(to, $index)" address-input="to" tabindex="1" ng-mouseover="getKeyId(recipient)" focus-me="state.writer.open && writerTitle !== 'Reply'">
|
||||
<input id="to{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" class="label" ng-class="{'label-blank': !recipient.address || recipient.secure === undefined, 'label-primary': recipient.secure === false}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(to, $index)" address-input="to" tabindex="1" ng-mouseover="getKeyId(recipient)" focus-me="state.lightbox === 'write' && writerTitle !== 'Reply'">
|
||||
</span>
|
||||
</p>
|
||||
<p field="cc">
|
||||
<span>Cc:</span>
|
||||
<p field="cc" ng-show="showCC === true">
|
||||
<label>Cc:</label>
|
||||
<span ng-repeat="recipient in cc track by $index">
|
||||
<input id="cc{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(cc, $index)" address-input="cc" tabindex="1" ng-mouseover="getKeyId(recipient)">
|
||||
<input id="cc{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" class="label" ng-class="{'label-blank': !recipient.address || recipient.secure === undefined, 'label-primary': recipient.secure === false}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(cc, $index)" address-input="cc" tabindex="1" ng-mouseover="getKeyId(recipient)">
|
||||
</span>
|
||||
</p>
|
||||
</div><!--/.address-headers-->
|
||||
<p field="bcc" ng-show="showBCC === true">
|
||||
<label>Bcc:</label>
|
||||
<span ng-repeat="recipient in bcc track by $index">
|
||||
<input id="bcc{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" class="label" ng-class="{'label-blank': !recipient.address || recipient.secure === undefined, 'label-primary': recipient.secure === false}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(bcc, $index)" address-input="bcc" tabindex="1" ng-mouseover="getKeyId(recipient)">
|
||||
</span>
|
||||
</p>
|
||||
</div><!--/.mail-addresses-->
|
||||
|
||||
<div class="subject-box">
|
||||
<div class="subject-line">
|
||||
@ -44,9 +54,9 @@
|
||||
</div><!--/ng-switch-->
|
||||
|
||||
<div class="body" focus-child>
|
||||
<p ng-model="body" contentEditable="true" spellcheck="false" ng-change="updatePreview()" tabindex="3" focus-me="state.writer.open && writerTitle === 'Reply'"></p>
|
||||
<p ng-model="body" contentEditable="true" spellcheck="false" ng-change="updatePreview()" tabindex="3" focus-me="state.lightbox === 'write' && writerTitle === 'Reply'"></p>
|
||||
|
||||
<div class="encrypt-preview" ng-class="{'invisible': !ciphertextPreview || !sendBtnSecure}">
|
||||
<div class="encrypt-preview" ng-show="ciphertextPreview && sendBtnSecure">
|
||||
<p>-----BEGIN ENCRYPTED PREVIEW-----<br>{{ciphertextPreview}}<br>-----END ENCRYPTED PREVIEW-----</p>
|
||||
</div><!--/.encrypt-preview-->
|
||||
</div><!--/.body-->
|
||||
|
@ -79,7 +79,7 @@ define(function(require) {
|
||||
})).yields();
|
||||
scope.onError = function(err) {
|
||||
expect(err.title).to.equal('Success');
|
||||
expect(scope.state.account.open).to.be.false;
|
||||
expect(scope.state.lightbox).to.equal(undefined);
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
expect(dl.createDownload.calledOnce).to.be.true;
|
||||
dl.createDownload.restore();
|
||||
|
@ -40,7 +40,6 @@ define(function(require) {
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.fingerprint).to.equal('XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX');
|
||||
expect(scope.state.contacts.open).to.be.false;
|
||||
expect(scope.state.contacts.toggle).to.exist;
|
||||
});
|
||||
});
|
||||
|
@ -97,10 +97,13 @@ define(function(require) {
|
||||
scope.passphrase = passphrase;
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields(new Error('asd'));
|
||||
|
||||
scope.confirmPassphrase();
|
||||
scope.onError = function(err) {
|
||||
expect(err.message).to.equal('asd');
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
done();
|
||||
};
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
done();
|
||||
scope.confirmPassphrase();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -176,10 +176,14 @@ define(function(require) {
|
||||
expect(state).to.equal(1);
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
scope.setState.restore();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err.message).to.equal('asd');
|
||||
done();
|
||||
};
|
||||
|
||||
scope.confirmPassphrase();
|
||||
});
|
||||
});
|
||||
|
@ -98,7 +98,7 @@ define(function(require) {
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when keypair upload fails', function() {
|
||||
it('should not work when keypair upload fails', function(done) {
|
||||
scope.passphrase = passphrase;
|
||||
scope.key = {
|
||||
privateKeyArmored: 'b'
|
||||
@ -113,6 +113,11 @@ define(function(require) {
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err.errMsg).to.equal('yo mamma.');
|
||||
done();
|
||||
};
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
@ -120,7 +125,7 @@ define(function(require) {
|
||||
expect(keychainMock.putUserKeyPair.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when unlock fails', function() {
|
||||
it('should not work when unlock fails', function(done) {
|
||||
scope.passphrase = passphrase;
|
||||
scope.key = {
|
||||
privateKeyArmored: 'b'
|
||||
@ -134,6 +139,11 @@ define(function(require) {
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err.errMsg).to.equal('yo mamma.');
|
||||
done();
|
||||
};
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(scope.incorrect).to.be.true;
|
||||
@ -141,13 +151,18 @@ define(function(require) {
|
||||
expect(emailDaoMock.unlock.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('should not work when keypair retrieval', function() {
|
||||
it('should not work when keypair retrieval', function(done) {
|
||||
scope.passphrase = passphrase;
|
||||
|
||||
keychainMock.getUserKeyPair.withArgs(emailAddress).yields({
|
||||
errMsg: 'yo mamma.'
|
||||
});
|
||||
|
||||
scope.onError = function(err) {
|
||||
expect(err.errMsg).to.equal('yo mamma.');
|
||||
done();
|
||||
};
|
||||
|
||||
scope.confirmPassphrase();
|
||||
|
||||
expect(keychainMock.getUserKeyPair.calledOnce).to.be.true;
|
||||
|
@ -63,10 +63,8 @@ define(function(require) {
|
||||
describe('initial state', function() {
|
||||
it('should be well defined', function() {
|
||||
expect(scope.state).to.exist;
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
expect(scope.state.lightbox).to.be.undefined;
|
||||
expect(scope.account.folders).to.not.be.empty;
|
||||
|
||||
expect(scope.onError).to.exist;
|
||||
expect(scope.openFolder).to.exist;
|
||||
});
|
||||
});
|
||||
|
@ -55,7 +55,7 @@ define(function(require) {
|
||||
describe('scope variables', function() {
|
||||
it('should be set correctly', function() {
|
||||
expect(scope.state.writer).to.exist;
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
expect(scope.state.lightbox).to.be.undefined;
|
||||
expect(scope.state.writer.write).to.exist;
|
||||
expect(scope.state.writer.close).to.exist;
|
||||
expect(scope.verify).to.exist;
|
||||
@ -68,11 +68,11 @@ define(function(require) {
|
||||
|
||||
describe('close', function() {
|
||||
it('should close the writer', function() {
|
||||
scope.state.writer.open = true;
|
||||
scope.state.lightbox = 'write';
|
||||
|
||||
scope.state.writer.close();
|
||||
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
expect(scope.state.lightbox).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
@ -200,7 +200,7 @@ define(function(require) {
|
||||
keychainMock.getReceiverPublicKey.yields(null, {
|
||||
userId: 'asdf@example.com'
|
||||
});
|
||||
scope.$apply = function() {
|
||||
scope.$digest = function() {
|
||||
expect(recipient.key).to.deep.equal({
|
||||
userId: 'asdf@example.com'
|
||||
});
|
||||
@ -311,8 +311,7 @@ define(function(require) {
|
||||
|
||||
expect(outboxMock.put.calledOnce).to.be.true;
|
||||
expect(emailDaoMock.sync.calledOnce).to.be.true;
|
||||
|
||||
expect(scope.state.writer.open).to.be.false;
|
||||
expect(scope.state.lightbox).to.be.undefined;
|
||||
expect(scope.replyTo.answered).to.be.true;
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user