mirror of
https://github.com/moparisthebest/mail
synced 2024-11-26 19:02:20 -05:00
refactor mail list
This commit is contained in:
parent
a82c2ca20a
commit
342105cb4c
@ -14,6 +14,10 @@ define(function(require) {
|
|||||||
num = 100,
|
num = 100,
|
||||||
firstSelect = true;
|
firstSelect = true;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init
|
||||||
|
//
|
||||||
|
|
||||||
emailDao = appController._emailDao;
|
emailDao = appController._emailDao;
|
||||||
if (emailDao) {
|
if (emailDao) {
|
||||||
emailDao.onIncomingMessage = function(email) {
|
emailDao.onIncomingMessage = function(email) {
|
||||||
@ -50,7 +54,7 @@ define(function(require) {
|
|||||||
// scope functions
|
// scope functions
|
||||||
//
|
//
|
||||||
|
|
||||||
$scope.$parent.select = $scope.select = function(email) {
|
$scope.select = function(email) {
|
||||||
if (!email) {
|
if (!email) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -64,15 +68,14 @@ define(function(require) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$scope.selected = email;
|
|
||||||
// set selected in parent scope ro it can be displayed in the read view
|
$scope.state.mailList.selected = email;
|
||||||
$scope.$parent.selected = $scope.selected;
|
|
||||||
|
|
||||||
// mark selected message as 'read'
|
// mark selected message as 'read'
|
||||||
markAsRead(email);
|
markAsRead(email);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$parent.synchronize = $scope.synchronize = function(callback) {
|
$scope.synchronize = function(callback) {
|
||||||
updateStatus('Syncing ...');
|
updateStatus('Syncing ...');
|
||||||
// sync from imap to local db
|
// sync from imap to local db
|
||||||
syncImapFolder({
|
syncImapFolder({
|
||||||
@ -94,7 +97,60 @@ define(function(require) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$watch('currentFolder', function() {
|
$scope.remove = function(email) {
|
||||||
|
if (!email) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index;
|
||||||
|
removeLocalAndShowNext();
|
||||||
|
removeRemote();
|
||||||
|
|
||||||
|
function removeLocalAndShowNext() {
|
||||||
|
index = $scope.emails.indexOf(email);
|
||||||
|
// show the next mail
|
||||||
|
if ($scope.emails.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),
|
||||||
|
// otherwise show the next one (i.e. the one above in the list)
|
||||||
|
$scope.select(_.last($scope.emails) === email ? $scope.emails[index - 1] : $scope.emails[index + 1]);
|
||||||
|
} else {
|
||||||
|
// if we have only one email in the array, show nothing
|
||||||
|
$scope.select();
|
||||||
|
$scope.state.mailList.selected = undefined;
|
||||||
|
}
|
||||||
|
$scope.emails.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeRemote() {
|
||||||
|
var trashFolder = _.findWhere($scope.folders, {
|
||||||
|
type: 'Trash'
|
||||||
|
});
|
||||||
|
if (getFolder() === trashFolder) {
|
||||||
|
emailDao.imapDeleteMessage({
|
||||||
|
folder: getFolder().path,
|
||||||
|
uid: email.uid
|
||||||
|
}, moved);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emailDao.imapMoveMessage({
|
||||||
|
folder: getFolder().path,
|
||||||
|
uid: email.uid,
|
||||||
|
destination: trashFolder.path
|
||||||
|
}, moved);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moved(err) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
$scope.emails.splice(index, 0, email);
|
||||||
|
$scope.$apply();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watch('state.nav.currentFolder', function() {
|
||||||
if (!getFolder()) {
|
if (!getFolder()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,10 +164,16 @@ define(function(require) {
|
|||||||
// development... display dummy mail objects
|
// development... display dummy mail objects
|
||||||
firstSelect = true;
|
firstSelect = true;
|
||||||
updateStatus('Last update: ', new Date());
|
updateStatus('Last update: ', new Date());
|
||||||
$scope.$parent.emails = $scope.emails = createDummyMails();
|
$scope.emails = createDummyMails();
|
||||||
$scope.select($scope.emails[0]);
|
$scope.select($scope.emails[0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// share local scope functions with root state
|
||||||
|
$scope.state.mailList = {
|
||||||
|
remove: $scope.remove,
|
||||||
|
synchronize: $scope.synchronize
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// helper functions
|
// helper functions
|
||||||
//
|
//
|
||||||
@ -185,8 +247,6 @@ define(function(require) {
|
|||||||
function updateStatus(lbl, time) {
|
function updateStatus(lbl, time) {
|
||||||
$scope.lastUpdateLbl = lbl;
|
$scope.lastUpdateLbl = lbl;
|
||||||
$scope.lastUpdate = (time) ? time : '';
|
$scope.lastUpdate = (time) ? time : '';
|
||||||
$scope.$parent.lastUpdateLbl = $scope.lastUpdateLbl;
|
|
||||||
$scope.$parent.lastUpdate = $scope.lastUpdate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayEmails(emails) {
|
function displayEmails(emails) {
|
||||||
@ -202,13 +262,13 @@ define(function(require) {
|
|||||||
return -e.uid;
|
return -e.uid;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$parent.emails = $scope.emails = emails;
|
$scope.emails = emails;
|
||||||
$scope.select($scope.emails[0]);
|
$scope.select($scope.emails[0]);
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFolder() {
|
function getFolder() {
|
||||||
return $scope.$parent.currentFolder;
|
return $scope.state.nav.currentFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
function markAsRead(email) {
|
function markAsRead(email) {
|
||||||
|
@ -39,7 +39,7 @@ define(function(require) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.openFolder = function(folder) {
|
$scope.openFolder = function(folder) {
|
||||||
$scope.currentFolder = folder;
|
$scope.state.nav.currentFolder = folder;
|
||||||
$scope.state.nav.toggle(false);
|
$scope.state.nav.toggle(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,59 +50,6 @@ define(function(require) {
|
|||||||
$scope.accountOpen = false;
|
$scope.accountOpen = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.remove = function(email) {
|
|
||||||
if (!email) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var index;
|
|
||||||
removeLocalAndShowNext();
|
|
||||||
removeRemote();
|
|
||||||
|
|
||||||
function removeLocalAndShowNext() {
|
|
||||||
index = $scope.emails.indexOf(email);
|
|
||||||
// show the next mail
|
|
||||||
if ($scope.emails.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),
|
|
||||||
// otherwise show the next one (i.e. the one above in the list)
|
|
||||||
$scope.select(_.last($scope.emails) === email ? $scope.emails[index - 1] : $scope.emails[index + 1]);
|
|
||||||
} else {
|
|
||||||
// if we have only one email in the array, show nothing
|
|
||||||
$scope.select();
|
|
||||||
$scope.selected = undefined;
|
|
||||||
}
|
|
||||||
$scope.emails.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeRemote() {
|
|
||||||
var trashFolder = _.findWhere($scope.folders, {
|
|
||||||
type: 'Trash'
|
|
||||||
});
|
|
||||||
if ($scope.currentFolder === trashFolder) {
|
|
||||||
emailDao.imapDeleteMessage({
|
|
||||||
folder: $scope.currentFolder.path,
|
|
||||||
uid: email.uid
|
|
||||||
}, moved);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emailDao.imapMoveMessage({
|
|
||||||
folder: $scope.currentFolder.path,
|
|
||||||
uid: email.uid,
|
|
||||||
destination: trashFolder.path
|
|
||||||
}, moved);
|
|
||||||
}
|
|
||||||
|
|
||||||
function moved(err) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
$scope.emails.splice(index, 0, email);
|
|
||||||
$scope.$apply();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.emptyOutbox = function() {
|
$scope.emptyOutbox = function() {
|
||||||
var dbType = 'email_OUTBOX',
|
var dbType = 'email_OUTBOX',
|
||||||
outbox = _.findWhere($scope.folders, {
|
outbox = _.findWhere($scope.folders, {
|
||||||
@ -267,15 +214,20 @@ define(function(require) {
|
|||||||
elm.bind('keydown', function(e) {
|
elm.bind('keydown', function(e) {
|
||||||
var cs = scope.$$childTail;
|
var cs = scope.$$childTail;
|
||||||
|
|
||||||
if (e.keyCode === 78 && !scope.state.writer.open) {
|
// global state is not yet set, ignore keybaord shortcuts
|
||||||
|
if (!scope.state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.keyCode === 78 && scope.state.writer && !scope.state.writer.open) {
|
||||||
// n -> new mail
|
// n -> new mail
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
scope.state.writer.write();
|
scope.state.writer.write();
|
||||||
|
|
||||||
} else if (e.keyCode === 82 && !scope.state.writer.open && cs.selected) {
|
} else if (e.keyCode === 82 && scope.state.writer && !scope.state.writer.open && scope.state.mailList.selected) {
|
||||||
// r -> reply
|
// r -> reply
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
scope.state.writer.write(cs.selected);
|
scope.state.writer.write(scope.state.mailList.selected);
|
||||||
|
|
||||||
} else if (e.keyCode === 27 && scope.state.writer.open) {
|
} else if (e.keyCode === 27 && scope.state.writer.open) {
|
||||||
// escape -> close writer
|
// escape -> close writer
|
||||||
@ -287,10 +239,10 @@ define(function(require) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
cs.closeAccount();
|
cs.closeAccount();
|
||||||
|
|
||||||
} else if (e.keyCode === 83 && !scope.state.writer.open && cs.synchronize) {
|
} else if (e.keyCode === 83 && scope.state.writer && !scope.state.writer.open && scope.state.mailList.synchronize) {
|
||||||
// s -> sync folder
|
// s -> sync folder
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
cs.synchronize();
|
scope.state.mailList.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.$apply();
|
scope.$apply();
|
||||||
|
@ -166,7 +166,7 @@ define(function(require) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.closeWriter();
|
$scope.state.writer.close();
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
$scope.emptyOutbox();
|
$scope.emptyOutbox();
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<section class="content main-content" ng-class="{'shift-right': state.read.open}">
|
<section class="content main-content" ng-class="{'shift-right': state.read.open}">
|
||||||
|
|
||||||
<!-- left column: containing list view and navigation header -->
|
<!-- left column: containing list view and navigation header -->
|
||||||
<div class="column column-left" ng-include="'tpl/mail-list.html'" ng-controller="MailListCtrl"></div>
|
<div class="column column-left" ng-include="'tpl/mail-list.html'"></div>
|
||||||
|
|
||||||
<!-- right column: containing list read view -->
|
<!-- right column: containing list read view -->
|
||||||
<div class="column" ng-include="'tpl/read.html'"></div>
|
<div class="column" ng-include="'tpl/read.html'"></div>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<div class="view-mail-list">
|
<div class="view-mail-list" ng-controller="MailListCtrl">
|
||||||
<!-- nav controll and section headline -->
|
<!-- nav controll and section headline -->
|
||||||
<header data-icon="" ng-click="state.nav.toggle(true); $event.stopPropagation()">
|
<header data-icon="" ng-click="state.nav.toggle(true); $event.stopPropagation()">
|
||||||
<h2>{{currentFolder.type}}</h2>
|
<h2>{{state.nav.currentFolder.type}}</h2>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="list-wrapper" ng-iscroll>
|
<div class="list-wrapper" ng-iscroll>
|
||||||
<ul class="mail-list">
|
<ul class="mail-list">
|
||||||
<li ng-class="{'mail-list-active': email === selected, 'mail-list-attachment': email.attachments !== undefined && email.attachments.length > 0, 'mail-list-unread': email.unread, 'mail-list-replied': email.answered}" ng-click="select(email)" ng-repeat="email in emails">
|
<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.answered}" ng-click="select(email)" ng-repeat="email in emails">
|
||||||
<h3>{{email.from[0].name || email.from[0].address}}</h3>
|
<h3>{{email.from[0].name || email.from[0].address}}</h3>
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<p class="subject">{{email.subject || 'No subject'}}</p>
|
<p class="subject">{{email.subject || 'No subject'}}</p>
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
<div class="controls">
|
<div class="controls">
|
||||||
<button ng-click="remove(selected)" class="btn-icon" title="Delete mail"></button>
|
<button ng-click="state.mailList.remove(state.mailList.selected)" class="btn-icon" title="Delete mail"></button>
|
||||||
<button ng-click="state.writer.write(selected)" class="btn-icon" title="Reply to"></button>
|
<button ng-click="state.writer.write(state.mailList.selected)" class="btn-icon" title="Reply to"></button>
|
||||||
<button ng-click="state.writer.write()" class="btn-icon" title="New mail"></button>
|
<button ng-click="state.writer.write()" class="btn-icon" title="New mail"></button>
|
||||||
</div><!--/.controls-->
|
</div><!--/.controls-->
|
||||||
|
|
||||||
<div class="view-read" ng-controller="ReadCtrl">
|
<div class="view-read" ng-controller="ReadCtrl">
|
||||||
<div class="headers">
|
<div class="headers">
|
||||||
<p class="subject" ng-click="state.read.toggle(false)">{{selected.subject || 'No subject'}}</p>
|
<p class="subject" ng-click="state.read.toggle(false)">{{state.mailList.selected.subject || 'No subject'}}</p>
|
||||||
<p class="date">{{selected.sentDate | date:'EEEE, MMM d, yyyy h:mm a'}}</p>
|
<p class="date">{{state.mailList.selected.sentDate | date:'EEEE, MMM d, yyyy h:mm a'}}</p>
|
||||||
<p class="address">From: <span class="label" data-icon-append="">{{selected.from[0].name || selected.from[0].address}}</span></p>
|
<p class="address">From: <span class="label" data-icon-append="">{{state.mailList.selected.from[0].name || state.mailList.selected.from[0].address}}</span></p>
|
||||||
<p class="address">To: <span class="label" data-icon-append="" ng-repeat="t in selected.to">{{t.address}} </span></p>
|
<p class="address">To: <span class="label" data-icon-append="" ng-repeat="t in state.mailList.selected.to">{{t.address}} </span></p>
|
||||||
<div ng-switch="selected.cc !== undefined">
|
<div ng-switch="state.mailList.selected.cc !== undefined">
|
||||||
<p class="address" ng-switch-when="true">
|
<p class="address" ng-switch-when="true">
|
||||||
CC: <span class="label" ng-repeat="t in selected.cc">{{t.address}} </span>
|
CC: <span class="label" ng-repeat="t in state.mailList.selected.cc">{{t.address}} </span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div><!--/.headers-->
|
</div><!--/.headers-->
|
||||||
|
|
||||||
<div class="seperator-line"></div>
|
<div class="seperator-line"></div>
|
||||||
|
|
||||||
<div class="body" ng-switch="selected.html === true">
|
<div class="body" ng-switch="state.mailList.selected.html === true">
|
||||||
<!-- sandbox untrusted markup from html emails in an iframe. The "allow-same-origin" attribute is required to dynamically adjust the height of the iframe. Script execution is not allowed. -->
|
<!-- sandbox untrusted markup from html emails in an iframe. The "allow-same-origin" attribute is required to dynamically adjust the height of the iframe. Script execution is not allowed. -->
|
||||||
<iframe ng-switch-when="true" sandbox="allow-same-origin" srcdoc="{{selected.body}}" seamless frame-load></iframe>
|
<iframe ng-switch-when="true" sandbox="allow-same-origin" srcdoc="{{state.mailList.selected.body}}" seamless frame-load></iframe>
|
||||||
|
|
||||||
<!-- Render parts of a text only email in paragraphs for easier styling -->
|
<!-- Render parts of a text only email in paragraphs for easier styling -->
|
||||||
<p ng-repeat="part in selected.bodyDisplayParts track by $index">{{part}}</p>
|
<p ng-repeat="part in state.mailList.selected.bodyDisplayParts track by $index">{{part}}</p>
|
||||||
</div><!--/.body-->
|
</div><!--/.body-->
|
||||||
</div><!--/.view-read-->
|
</div><!--/.view-read-->
|
@ -9,7 +9,7 @@
|
|||||||
<div class="headers">
|
<div class="headers">
|
||||||
<p>
|
<p>
|
||||||
<span>To:</span>
|
<span>To:</span>
|
||||||
<input type="email" ng-model="to" ng-change="verifyTo()" ng-class="{'label': toSecure === true, 'label label-primary': toSecure === false}" tabindex="1" focus-me="writerOpen && !writerReply" auto-size="to" spellcheck="false">
|
<input type="email" ng-model="to" ng-change="verifyTo()" ng-class="{'label': toSecure === true, 'label label-primary': toSecure === false}" tabindex="1" focus-me="state.writer.open && writerTitle !== 'Reply'" auto-size="to" spellcheck="false">
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span>Cc:</span>
|
<span>Cc:</span>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
</div><!--/.subject-box-->
|
</div><!--/.subject-box-->
|
||||||
|
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<p ng-model="body" contentEditable="true" ng-change="updatePreview()" tabindex="4" focus-me="writerOpen && writerReply"></p>
|
<p ng-model="body" contentEditable="true" ng-change="updatePreview()" tabindex="4" focus-me="state.writer.open && writerTitle === 'Reply'"></p>
|
||||||
|
|
||||||
<div class="encrypt-preview">
|
<div class="encrypt-preview">
|
||||||
<p>-----BEGIN ENCRYPTED PREVIEW-----<br>{{ciphertextPreview}}<br>-----END ENCRYPTED PREVIEW-----</p>
|
<p>-----BEGIN ENCRYPTED PREVIEW-----<br>{{ciphertextPreview}}<br>-----END ENCRYPTED PREVIEW-----</p>
|
||||||
|
Loading…
Reference in New Issue
Block a user