Revision control

Other Tools

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
/**
6
* This file contains helper methods for dealing with nsIMsgFolders.
7
*/
8
9
this.EXPORTED_SYMBOLS = [
10
"getFolderProperties",
11
"getSpecialFolderString",
12
"allAccountsSorted",
13
"getMostRecentFolders",
14
"folderNameCompare",
15
];
16
17
const { MailServices } = ChromeUtils.import(
19
);
20
const { fixIterator, toArray } = ChromeUtils.import(
22
);
23
24
/**
25
* Returns a string representation of a folder's "special" type.
26
*
27
* @param aFolder the nsIMsgFolder whose special type should be returned
28
*/
29
function getSpecialFolderString(aFolder) {
30
let flags = aFolder.flags;
31
if (flags & Ci.nsMsgFolderFlags.Inbox) {
32
return "Inbox";
33
}
34
if (flags & Ci.nsMsgFolderFlags.Trash) {
35
return "Trash";
36
}
37
if (flags & Ci.nsMsgFolderFlags.Queue) {
38
return "Outbox";
39
}
40
if (flags & Ci.nsMsgFolderFlags.SentMail) {
41
return "Sent";
42
}
43
if (flags & Ci.nsMsgFolderFlags.Drafts) {
44
return "Drafts";
45
}
46
if (flags & Ci.nsMsgFolderFlags.Templates) {
47
return "Templates";
48
}
49
if (flags & Ci.nsMsgFolderFlags.Junk) {
50
return "Junk";
51
}
52
if (flags & Ci.nsMsgFolderFlags.Archive) {
53
return "Archive";
54
}
55
if (flags & Ci.nsMsgFolderFlags.Virtual) {
56
return "Virtual";
57
}
58
return "none";
59
}
60
61
/**
62
* This function is meant to be used with trees. It returns the property list
63
* for all of the common properties that css styling is based off of.
64
*
65
* @param nsIMsgFolder aFolder the folder whose properties should be returned
66
* as a string
67
* @param bool aOpen true if the folder is open/expanded
68
*
69
* @return A string of the property names, delimited by space.
70
*/
71
function getFolderProperties(aFolder, aOpen) {
72
const nsIMsgFolder = Ci.nsIMsgFolder;
73
let properties = [];
74
75
properties.push("folderNameCol");
76
77
properties.push("serverType-" + aFolder.server.type);
78
79
// set the SpecialFolder attribute
80
properties.push("specialFolder-" + getSpecialFolderString(aFolder));
81
82
// Now set the biffState
83
switch (aFolder.biffState) {
84
case nsIMsgFolder.nsMsgBiffState_NewMail:
85
properties.push("biffState-NewMail");
86
break;
87
case nsIMsgFolder.nsMsgBiffState_NoMail:
88
properties.push("biffState-NoMail");
89
break;
90
default:
91
properties.push("biffState-UnknownMail");
92
}
93
94
properties.push("isSecure-" + aFolder.server.isSecure);
95
96
// A folder has new messages, or a closed folder or any subfolder has new messages.
97
if (
98
aFolder.hasNewMessages ||
99
(!aOpen && aFolder.hasSubFolders && aFolder.hasFolderOrSubfolderNewMessages)
100
) {
101
properties.push("newMessages-true");
102
}
103
104
if (aFolder.isServer) {
105
properties.push("isServer-true");
106
} else {
107
// We only set this if we're not a server
108
let shallowUnread = aFolder.getNumUnread(false);
109
if (shallowUnread > 0) {
110
properties.push("hasUnreadMessages-true");
111
} else {
112
// Make sure that shallowUnread isn't negative
113
shallowUnread = 0;
114
}
115
let deepUnread = aFolder.getNumUnread(true);
116
if (deepUnread - shallowUnread > 0) {
117
properties.push("subfoldersHaveUnreadMessages-true");
118
}
119
}
120
121
properties.push("noSelect-" + aFolder.noSelect);
122
properties.push("imapShared-" + aFolder.imapShared);
123
124
return properties.join(" ");
125
}
126
127
/**
128
* Returns the sort order value based on the server type to be used for sorting.
129
* The servers (accounts) go in the following order:
130
* (0) default account, (1) other mail accounts, (2) Local Folders,
131
* (3) IM accounts, (4) RSS, (5) News, (9) others (no server)
132
* This ordering is encoded in the .sortOrder property of each server type.
133
*
134
* @param aServer the server object to be tested
135
*/
136
function getServerSortOrder(aServer) {
137
// If there is no server sort this object to the end.
138
if (!aServer) {
139
return 999999999;
140
}
141
142
// Otherwise get the server sort order from the Account manager.
143
return MailServices.accounts.getSortOrder(aServer);
144
}
145
146
/**
147
* Compares the passed in accounts according to their precedence.
148
*/
149
function compareAccounts(aAccount1, aAccount2) {
150
return (
151
getServerSortOrder(aAccount1.incomingServer) -
152
getServerSortOrder(aAccount2.incomingServer)
153
);
154
}
155
156
/**
157
* Returns a list of accounts sorted by server type.
158
*
159
* @param aExcludeIMAccounts Remove IM accounts from the list?
160
*/
161
function allAccountsSorted(aExcludeIMAccounts) {
162
// Get the account list, and add the proper items.
163
let accountList = toArray(
164
fixIterator(MailServices.accounts.accounts, Ci.nsIMsgAccount)
165
);
166
167
// This is a HACK to work around bug 41133. If we have one of the
168
// dummy "news" accounts there, that account won't have an
169
// incomingServer attached to it, and everything will blow up.
170
accountList = accountList.filter(a => a.incomingServer);
171
172
// Remove IM servers.
173
if (aExcludeIMAccounts) {
174
accountList = accountList.filter(a => a.incomingServer.type != "im");
175
}
176
177
return accountList.sort(compareAccounts);
178
}
179
180
/**
181
* Returns the most recently used/modified folders from the passed in list.
182
*
183
* @param aFolderList The array of nsIMsgFolders to search for recent folders.
184
* @param aMaxHits How many folders to return.
185
* @param aTimeProperty Which folder time property to use.
186
* Use "MRMTime" for most recently modified time.
187
* Use "MRUTime" for most recently used time.
188
*/
189
function getMostRecentFolders(aFolderList, aMaxHits, aTimeProperty) {
190
let recentFolders = [];
191
192
/**
193
* This sub-function will add a folder to the recentFolders array if it
194
* is among the aMaxHits most recent. If we exceed aMaxHits folders,
195
* it will pop the oldest folder, ensuring that we end up with the
196
* right number.
197
*
198
* @param aFolder The folder to check for recency.
199
*/
200
let oldestTime = 0;
201
function addIfRecent(aFolder) {
202
let time = 0;
203
try {
204
time = Number(aFolder.getStringProperty(aTimeProperty)) || 0;
205
} catch (e) {}
206
if (time <= oldestTime) {
207
return;
208
}
209
210
if (recentFolders.length == aMaxHits) {
211
recentFolders.sort((a, b) => a.time < b.time);
212
recentFolders.pop();
213
oldestTime = recentFolders[recentFolders.length - 1].time;
214
}
215
recentFolders.push({ folder: aFolder, time });
216
}
217
218
for (let folder of aFolderList) {
219
addIfRecent(folder);
220
}
221
222
return recentFolders.map(f => f.folder);
223
}
224
225
/**
226
* A locale dependent comparison function to produce a case-insensitive sort order
227
* used to sort folder names.
228
* Returns positive number if aString1 > aString2, negative number if aString1 > aString2,
229
* otherwise 0.
230
*
231
* @param aString1 first string to compare
232
* @param aString2 second string to compare
233
*/
234
function folderNameCompare(aString1, aString2) {
235
// TODO: improve this as described in bug 992651.
236
return aString1
237
.toLocaleLowerCase()
238
.localeCompare(aString2.toLocaleLowerCase());
239
}