зеркало из https://github.com/mozilla/snowl.git
more message deletion work; implement concept of 'trash' (though it will not be called that and have so such thing as a folder), handle 'current' flag cases to prevent dupes, add 'show deleted' and 'purge deleted' buttons. remaining: contextmenu purge and undelete of deleted items.
This commit is contained in:
Родитель
2abbeb4e9c
Коммит
f41ae66e23
|
@ -111,6 +111,7 @@ let CollectionsView = {
|
|||
|
||||
Filters: {
|
||||
unread: false,
|
||||
deleted: false,
|
||||
searchterms: null
|
||||
},
|
||||
|
||||
|
@ -129,6 +130,12 @@ let CollectionsView = {
|
|||
|
||||
this.Filters["unread"] = document.getElementById("snowlUnreadButton").
|
||||
checked ? true : false;
|
||||
this.Filters["deleted"] = document.getElementById("snowlShowDeletedButton").
|
||||
checked ? true : false;
|
||||
if (this.Filters["deleted"])
|
||||
document.getElementById("snowlPurgeDeletedButton").removeAttribute("disabled");
|
||||
else
|
||||
document.getElementById("snowlPurgeDeletedButton").setAttribute("disabled", true);
|
||||
|
||||
// Restore persisted view selection (need to build the menulist) or init.
|
||||
let selIndex = parseInt(this._collectionsViewMenu.getAttribute("selectedindex"));
|
||||
|
@ -370,14 +377,29 @@ this._log.info("onClick: START itemIds - " +this.itemIds.toSource());
|
|||
},
|
||||
|
||||
onCommandUnreadButton: function(aEvent) {
|
||||
// XXX Instead of rebuilding from scratch each time, when going from
|
||||
// all to unread, simply hide the ones that are read (f.e. by setting a CSS
|
||||
// class on read items and then using a CSS rule to hide them)?
|
||||
// Unfortunately, css cannot be used to hide a treechildren row using
|
||||
// properties and pseudo element selectors.
|
||||
aEvent.target.checked = !aEvent.target.checked;
|
||||
this.Filters["unread"] = aEvent.target.checked ? true : false;
|
||||
gMessageViewWindow.SnowlMessageView.onFilter(this.Filters);
|
||||
},
|
||||
|
||||
onCommandShowDeletedButton: function(aEvent) {
|
||||
aEvent.target.checked = !aEvent.target.checked;
|
||||
this.Filters["deleted"] = aEvent.target.checked ? true : false;
|
||||
|
||||
if (this.Filters["deleted"])
|
||||
document.getElementById("snowlPurgeDeletedButton").removeAttribute("disabled");
|
||||
else
|
||||
document.getElementById("snowlPurgeDeletedButton").setAttribute("disabled", true);
|
||||
|
||||
gMessageViewWindow.SnowlMessageView.onFilter(this.Filters);
|
||||
},
|
||||
|
||||
onCommandPurgeDeletedButton: function(aEvent) {
|
||||
gMessageViewWindow.SnowlMessageView.onDeleteMessages();
|
||||
},
|
||||
|
||||
_resetCollectionsView: true,
|
||||
onPopupshowingCollectionsView: function(event) {
|
||||
// Build dynamic Views list.
|
||||
|
@ -809,6 +831,10 @@ this._log.info("removeAuthor: Removing author - " + query.queryName + " : " + se
|
|||
let query, uri, rangeFirst = { }, rangeLast = { }, refreshFlag = false;
|
||||
let numRanges = this._tree.view.selection.getRangeCount();
|
||||
|
||||
if (this.Filters["deleted"])
|
||||
// Don't refresh if showing deleted for selected collection.
|
||||
return refreshFlag;
|
||||
|
||||
for (let i = 0; i < numRanges && !refreshFlag; i++) {
|
||||
this._tree.view.selection.getRangeAt(i, rangeFirst, rangeLast);
|
||||
for (let index = rangeFirst.value; index <= rangeLast.value; index++) {
|
||||
|
|
|
@ -144,6 +144,17 @@
|
|||
type="checkbox"
|
||||
oncommand="ListSidebar.onToggleWrite(event)"
|
||||
tooltiptext="&writeButton.tooltip;"/>
|
||||
<toolbarbutton id="snowlShowDeletedButton"
|
||||
class="tabbable"
|
||||
type="checkbox"
|
||||
autoCheck="false"
|
||||
persist="checked"
|
||||
oncommand="CollectionsView.onCommandShowDeletedButton(event)"
|
||||
tooltiptext="&showDeletedButton.tooltip;"/>
|
||||
<toolbarbutton id="snowlPurgeDeletedButton"
|
||||
class="tabbable"
|
||||
oncommand="CollectionsView.onCommandPurgeDeletedButton(event)"
|
||||
tooltiptext="&purgeDeletedButton.tooltip;"/>
|
||||
</toolbar>
|
||||
|
||||
</page>
|
||||
|
|
|
@ -34,10 +34,14 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
treechildren::-moz-tree-cell-text(unread) {
|
||||
#snowlView > treechildren::-moz-tree-cell-text(unread) {
|
||||
font-weight: bold !important
|
||||
}
|
||||
|
||||
#snowlView > treechildren::-moz-tree-cell-text(deleted) {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/* XXX: these 2 rules were used by only the unread button, are they needed still?
|
||||
/* Don't style the buttons natively because they look ugly on Linux.
|
||||
* FIXME: test on other platforms and style conditionally as appropriate,
|
||||
|
|
|
@ -48,6 +48,7 @@ Cu.import("resource://snowl/modules/URI.js");
|
|||
|
||||
// modules that are Snowl-specific
|
||||
Cu.import("resource://snowl/modules/collection.js");
|
||||
Cu.import("resource://snowl/modules/constants.js");
|
||||
Cu.import("resource://snowl/modules/datastore.js");
|
||||
Cu.import("resource://snowl/modules/message.js");
|
||||
Cu.import("resource://snowl/modules/service.js");
|
||||
|
@ -149,11 +150,15 @@ let SnowlMessageView = {
|
|||
|
||||
getCellProperties: function (aRow, aColumn, aProperties) {
|
||||
// We have to set this on each cell rather than on the row as a whole
|
||||
// because the styling we apply to unread messages (bold text) has to be
|
||||
// because the text styling we apply to unread/deleted messages has to be
|
||||
// specified by the ::-moz-tree-cell-text pseudo-element, which inherits
|
||||
// only the cell's properties.
|
||||
if (!this._collection.messages[aRow].read)
|
||||
aProperties.AppendElement(this._atomSvc.getAtom("unread"));
|
||||
|
||||
if (this._collection.messages[aRow].current == MESSAGE_NON_CURRENT_DELETED ||
|
||||
this._collection.messages[aRow].current == MESSAGE_CURRENT_DELETED)
|
||||
aProperties.AppendElement(this._atomSvc.getAtom("deleted"));
|
||||
},
|
||||
|
||||
getColumnProperties: function(aColumnID, aColumn, aProperties) {},
|
||||
|
@ -233,6 +238,15 @@ let SnowlMessageView = {
|
|||
if (this.Filters["unread"])
|
||||
filters.push({ expression: "read = 0", parameters: {} });
|
||||
|
||||
if (this.Filters["deleted"])
|
||||
filters.push({ expression: "(current = " + MESSAGE_NON_CURRENT_DELETED + " OR" +
|
||||
" current = " + MESSAGE_CURRENT_DELETED + ")",
|
||||
parameters: {} });
|
||||
else
|
||||
filters.push({ expression: "(current = " + MESSAGE_NON_CURRENT + " OR" +
|
||||
" current = " + MESSAGE_CURRENT + ")",
|
||||
parameters: {} });
|
||||
|
||||
// FIXME: use a left join here once the SQLite bug breaking left joins to
|
||||
// virtual tables has been fixed (i.e. after we upgrade to SQLite 3.5.7+).
|
||||
if (this.Filters["searchterms"])
|
||||
|
@ -619,8 +633,12 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
// Create an array of messages and list rows to pass on.
|
||||
let messages = [], selectedRows = [];
|
||||
let rangeFirst = { }, rangeLast = { };
|
||||
let numRanges = this._tree.view.selection.getRangeCount();
|
||||
|
||||
if (this.Filters["deleted"])
|
||||
// Showing deleted messages, thus a purge is requested. Select the whole list.
|
||||
this._tree.view.selection.selectAll();
|
||||
|
||||
let numRanges = this._tree.view.selection.getRangeCount();
|
||||
for (let i = 0; i < numRanges; i++) {
|
||||
this._tree.view.selection.getRangeAt(i, rangeFirst, rangeLast);
|
||||
for (let index = rangeFirst.value; index <= rangeLast.value; index++) {
|
||||
|
@ -639,7 +657,7 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
_deleteMessages: function(aMessages, aRows) {
|
||||
//this._log.info("_deleteMessages: START #ids - "+aMessages.length);
|
||||
// Delete messages. Delete author if deleting author's only remaining message.
|
||||
let message, messageID, authorID;
|
||||
let message, messageID, current;
|
||||
let messageIDs = [];
|
||||
let refreshList = false, sessionHistoryEmpty = false;
|
||||
|
||||
|
@ -647,59 +665,25 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
for (let i = 0; i < aMessages.length; ++i) {
|
||||
message = aMessages[i];
|
||||
messageID = message.id;
|
||||
messageIDs.push(messageID)
|
||||
authorID = message.authorID;
|
||||
authorPlaceID = message.author.placeID;
|
||||
messageIDs.push(messageID);
|
||||
current = message.current;
|
||||
|
||||
if (!SnowlMessage.get(messageID))
|
||||
//this._log.info("_deleteMessages: Delete messages NOTFOUND - "+messageID);
|
||||
continue;
|
||||
|
||||
if (!refreshList && this.CollectionsView.isMessageForSelectedCollection(message))
|
||||
if (!refreshList && (this.Filters["deleted"] ||
|
||||
this.CollectionsView.isMessageForSelectedCollection(message)))
|
||||
// Message being deleted in a selected collection? Don't repeat call if
|
||||
// at least one is true.
|
||||
// XXX: is this call worth doing, based on likely deletion usage.
|
||||
// at least one is true. Also refresh if showing deleted list.
|
||||
// XXX: is this call worth doing, based on likely deletion usage, or just
|
||||
// always refresh..
|
||||
refreshList = true;
|
||||
|
||||
SnowlDatastore.dbConnection.beginTransaction();
|
||||
try {
|
||||
// Delete messages
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM metadata " +
|
||||
"WHERE messageID = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages METADATA DONE");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM partsText " +
|
||||
"WHERE docid IN " +
|
||||
"(SELECT id FROM parts WHERE messageID = " + messageID + ")");
|
||||
//this._log.info("_deleteMessages: Delete messages PARTSTEXT DONE");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM parts " +
|
||||
"WHERE messageID = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages PARTS DONE");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM messages " +
|
||||
"WHERE id = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages DONE");
|
||||
if (!SnowlService.hasAuthorMessage(authorID)) {
|
||||
// Delete people/identities; author's only message has been deleted.
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM people " +
|
||||
"WHERE id IN " +
|
||||
"(SELECT personID FROM identities WHERE id = " + authorID + ")");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM identities " +
|
||||
"WHERE id = " + authorID);
|
||||
// Finally, clean up Places bookmark by author's placeID. A collections
|
||||
// tree rebuild is triggered by Places on removeItem of a visible item,
|
||||
// triggering a select event. Need to bypass in onSelect.
|
||||
this.CollectionsView.noSelect = true;
|
||||
PlacesUtils.bookmarks.removeItem(authorPlaceID);
|
||||
//this._log.info("_deleteMessages: Delete DONE authorID - "+authorID);
|
||||
}
|
||||
// PlacesUtils.history.removePage(URI(this.MESSAGE_URI + messageID));
|
||||
//this._log.info("_deleteMessages: Delete DONE messageID - "+messageID);
|
||||
|
||||
SnowlDatastore.dbConnection.commitTransaction();
|
||||
}
|
||||
catch(ex) {
|
||||
SnowlDatastore.dbConnection.rollbackTransaction();
|
||||
throw ex;
|
||||
}
|
||||
if (current == MESSAGE_NON_CURRENT || current == MESSAGE_CURRENT)
|
||||
SnowlMessage.markDeleted(message);
|
||||
else
|
||||
SnowlMessage.delete(message);
|
||||
}
|
||||
|
||||
sessionHistoryEmpty = this._cleanSessionHistory(messageIDs);
|
||||
|
@ -713,7 +697,7 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
// Refresh list; if the currently deleted message is selected, then select
|
||||
// the next message (same row post refresh) or prior message (if deleted
|
||||
// message is last row). In a multiselection, this means the row
|
||||
// of the first message in the selection.
|
||||
// of the first message in the selection. Refresh deleted list if purged.
|
||||
let currRow, rowCount, selIndex;
|
||||
|
||||
if (aRows) {
|
||||
|
@ -750,13 +734,14 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
// deletion. Return true if last message in history is deleted, else false.
|
||||
|
||||
// XXX: clean across all tabs' history, not just current tab?
|
||||
//this._log.info("_cleanSessionHistory: messageIDs - "+aMessageIDs);
|
||||
let shEntry, uri, msgUri, msgId;
|
||||
let newCount = 0, restoreIndex = 0, historyChanged = false;
|
||||
let newCount = 0, historyChanged = false;
|
||||
let newHistory = [];
|
||||
|
||||
let sh = getBrowser().webNavigation.sessionHistory;
|
||||
let currIndex = sh.index;
|
||||
let restoreIndex = currIndex;
|
||||
//this._log.info("_cleanSessionHistory: messageIDs:currIndex - "+aMessageIDs+" : "+currIndex);
|
||||
|
||||
for (i = 0; i < sh.count; i++){
|
||||
shEntry = sh.getEntryAtIndex(i, false).QueryInterface(Ci.nsISHEntry);
|
||||
|
@ -768,8 +753,8 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
if (msgUri == this.MESSAGE_URI && aMessageIDs.indexOf(msgId) != -1) {
|
||||
//this._log.info("_cleanSessionHistory: Delete from HISTORY - "+uri);
|
||||
historyChanged = true;
|
||||
if (currIndex == i)
|
||||
restoreIndex = newCount > 0 ? --newCount : newCount;
|
||||
if (i <= currIndex)
|
||||
restoreIndex = restoreIndex <= 0 ? 0 : --restoreIndex;
|
||||
continue;
|
||||
}
|
||||
//this._log.info("_cleanSessionHistory: Add to HISTORY - "+uri);
|
||||
|
@ -794,8 +779,8 @@ this._log.info("_toggleRead: all? " + aAll);
|
|||
sh.addEntry(shEntry, true);
|
||||
})
|
||||
|
||||
sh.QueryInterface(Ci.nsIWebNavigation).gotoIndex(restoreIndex);
|
||||
//this._log.info("_cleanSessionHistory: restoreIndex - "+restoreIndex);
|
||||
sh.QueryInterface(Ci.nsIWebNavigation).gotoIndex(restoreIndex);
|
||||
return false;
|
||||
},
|
||||
|
||||
|
|
|
@ -120,6 +120,10 @@ td {
|
|||
padding-top: 6px;
|
||||
}
|
||||
|
||||
#headerDeck[deleted] > #briefHeaderRow > .headerDataSubject > #subject{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.fullHeaderRowSeparator {
|
||||
border-bottom: 1px solid threedshadow;
|
||||
margin: 0 10px;
|
||||
|
|
|
@ -135,6 +135,10 @@ var messageContent = {
|
|||
appendChild(document.createTextNode(SnowlDateUtils._formatDate(message.timestamp)));
|
||||
|
||||
headerDeck.removeAttribute("notfound");
|
||||
|
||||
if (message.current == MESSAGE_NON_CURRENT_DELETED ||
|
||||
message.current == MESSAGE_CURRENT_DELETED)
|
||||
headerDeck.setAttribute("deleted", true);
|
||||
}
|
||||
else {
|
||||
// Message no longer exists (removed source/author/message) but is in history.
|
||||
|
|
|
@ -42,13 +42,19 @@
|
|||
#snowlToolbar > toolbarbutton > .toolbarbutton-icon {
|
||||
-moz-margin-end: 0;
|
||||
}
|
||||
|
||||
#snowlToolbar > toolbarbutton > .toolbarbutton-text {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#snowlToolbar > toolbarbutton[disabled] {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
#snowlSubscribeButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/add.png");
|
||||
}
|
||||
|
||||
#snowlRefreshButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/arrow_refresh_small.png");
|
||||
}
|
||||
|
@ -61,6 +67,15 @@
|
|||
#snowlUnreadButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/new.png");
|
||||
}
|
||||
|
||||
#writeButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/email_add.png");
|
||||
}
|
||||
|
||||
#snowlShowDeletedButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/bin_closed.png");
|
||||
}
|
||||
|
||||
#snowlPurgeDeletedButton {
|
||||
list-style-image: url("chrome://snowl/content/icons/bin_empty.png");
|
||||
}
|
||||
|
|
|
@ -5,3 +5,5 @@
|
|||
<!ENTITY unreadButton.tooltip "Only show unread messages.">
|
||||
<!ENTITY listToolbarButton.tooltip "Toggle View toolbar.">
|
||||
<!ENTITY writeButton.tooltip "Write a message.">
|
||||
<!ENTITY showDeletedButton.tooltip "Show deleted messages for selected Collections.">
|
||||
<!ENTITY purgeDeletedButton.tooltip "Purge all deleted messages from selected Collections.">
|
||||
|
|
|
@ -265,10 +265,11 @@ this._log.info("got " + groups.length + " groups");
|
|||
sourceID: statement.row.sourceID,
|
||||
subject: statement.row.subject,
|
||||
authorID: statement.row.authorID,
|
||||
link: statement.row.link,
|
||||
timestamp: SnowlDateUtils.julianToJSDate(statement.row.timestamp),
|
||||
_read: (statement.row.read ? true : false),
|
||||
received: SnowlDateUtils.julianToJSDate(statement.row.received),
|
||||
link: statement.row.link,
|
||||
current: statement.row.current,
|
||||
_read: (statement.row.read ? true : false),
|
||||
content: content
|
||||
});
|
||||
|
||||
|
@ -298,12 +299,13 @@ this._log.info("got " + groups.length + " groups");
|
|||
let columns = [
|
||||
"messages.id AS messageID",
|
||||
"messages.sourceID",
|
||||
"messages.authorID",
|
||||
"messages.subject",
|
||||
"messages.link",
|
||||
"messages.authorID",
|
||||
"messages.timestamp",
|
||||
"messages.read",
|
||||
"messages.received",
|
||||
"messages.link",
|
||||
"messages.current",
|
||||
"messages.read",
|
||||
"parts.id AS partID",
|
||||
"parts.content",
|
||||
"parts.mediaType",
|
||||
|
|
|
@ -40,7 +40,12 @@ const EXPORTED_SYMBOLS = ["TEXT_CONSTRUCT_TYPES",
|
|||
"PART_TYPE_SUMMARY",
|
||||
"XML_NS",
|
||||
"XUL_NS",
|
||||
"HTML_NS"];
|
||||
"HTML_NS",
|
||||
"MESSAGE_NON_CURRENT",
|
||||
"MESSAGE_CURRENT",
|
||||
"MESSAGE_NON_CURRENT_DELETED",
|
||||
"MESSAGE_CURRENT_DELETED",
|
||||
"MESSAGE_CURRENT_PENDING_PURGE"];
|
||||
|
||||
// Internet media type to nsIFeedTextConstruct::type mappings.
|
||||
const TEXT_CONSTRUCT_TYPES = {
|
||||
|
@ -60,6 +65,13 @@ const INTERNET_MEDIA_TYPES = {
|
|||
const PART_TYPE_CONTENT = 1;
|
||||
const PART_TYPE_SUMMARY = 2;
|
||||
|
||||
const XML_NS = "http://www.w3.org/XML/1998/namespace"
|
||||
const XML_NS = "http://www.w3.org/XML/1998/namespace";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
// Message statuses
|
||||
const MESSAGE_NON_CURRENT = 0;
|
||||
const MESSAGE_CURRENT = 1;
|
||||
const MESSAGE_NON_CURRENT_DELETED = 2;
|
||||
const MESSAGE_CURRENT_DELETED = 3;
|
||||
const MESSAGE_CURRENT_PENDING_PURGE = 4;
|
||||
|
|
|
@ -772,7 +772,9 @@ let SnowlDatastore = {
|
|||
|
||||
get _selectHasAuthorMessageStatement() {
|
||||
let statement = this.createStatement(
|
||||
"SELECT 1 FROM messages WHERE authorID = :authorID"
|
||||
"SELECT 1 FROM messages" +
|
||||
" WHERE authorID = :authorID AND" +
|
||||
" current <> " + MESSAGE_CURRENT_PENDING_PURGE
|
||||
);
|
||||
this.__defineGetter__("_selectHasAuthorMessageStatement", function() { return statement });
|
||||
return this._selectHasAuthorMessageStatement;
|
||||
|
|
|
@ -41,6 +41,9 @@ const Ci = Components.interfaces;
|
|||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
// modules that come with Firefox
|
||||
Cu.import("resource://gre/modules/utils.js"); // Places
|
||||
|
||||
// modules that are generic
|
||||
Cu.import("resource://snowl/modules/URI.js");
|
||||
|
||||
|
@ -65,7 +68,7 @@ SnowlMessage.get = function(id) {
|
|||
let message;
|
||||
|
||||
let statement = SnowlDatastore.createStatement(
|
||||
"SELECT sourceID, subject, link, timestamp, read, received, authorID " +
|
||||
"SELECT sourceID, subject, authorID, timestamp, received, link, current, read " +
|
||||
"FROM messages WHERE messages.id = :id"
|
||||
);
|
||||
|
||||
|
@ -77,10 +80,11 @@ SnowlMessage.get = function(id) {
|
|||
sourceID: statement.row.sourceID,
|
||||
subject: statement.row.subject,
|
||||
authorID: statement.row.authorID,
|
||||
link: statement.row.link,
|
||||
timestamp: SnowlDateUtils.julianToJSDate(statement.row.timestamp),
|
||||
_read: (statement.row.read ? true : false),
|
||||
received: SnowlDateUtils.julianToJSDate(statement.row.received)
|
||||
received: SnowlDateUtils.julianToJSDate(statement.row.received),
|
||||
link: statement.row.link,
|
||||
current: statement.row.current,
|
||||
_read: (statement.row.read ? true : false)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +95,87 @@ SnowlMessage.get = function(id) {
|
|||
return message;
|
||||
};
|
||||
|
||||
SnowlMessage.delete = function(aMessage) {
|
||||
let message = aMessage;
|
||||
let messageID = message.id;
|
||||
let authorID = message.authorID;
|
||||
let authorPlaceID = message.author.placeID;
|
||||
let current = message.current;
|
||||
|
||||
SnowlDatastore.dbConnection.beginTransaction();
|
||||
try {
|
||||
// Delete messages
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM metadata " +
|
||||
"WHERE messageID = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages METADATA DONE");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM partsText " +
|
||||
"WHERE docid IN " +
|
||||
"(SELECT id FROM parts WHERE messageID = " + messageID + ")");
|
||||
//this._log.info("_deleteMessages: Delete messages PARTSTEXT DONE");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM parts " +
|
||||
"WHERE messageID = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages PARTS DONE");
|
||||
// If a message is current and marked deleted, need to keep the record so
|
||||
// duplicates are not re added upon refresh. So we move to a pending purge
|
||||
// state and delete the rest of the message.
|
||||
if (current == MESSAGE_CURRENT_DELETED)
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("UPDATE messages " +
|
||||
"SET current = " + MESSAGE_CURRENT_PENDING_PURGE +
|
||||
" WHERE id = " + messageID);
|
||||
else
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM messages " +
|
||||
"WHERE id = " + messageID);
|
||||
//this._log.info("_deleteMessages: Delete messages DONE");
|
||||
if (!SnowlService.hasAuthorMessage(authorID)) {
|
||||
// Delete people/identities; author's only message has been deleted.
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM people " +
|
||||
"WHERE id IN " +
|
||||
"(SELECT personID FROM identities WHERE id = " + authorID + ")");
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL("DELETE FROM identities " +
|
||||
"WHERE id = " + authorID);
|
||||
// Finally, clean up Places bookmark by author's placeID. A collections
|
||||
// tree rebuild is triggered by Places on removeItem of a visible item,
|
||||
// triggering a select event. Need to bypass in onSelect.
|
||||
SnowlMessage.prototype.CollectionsView.noSelect = true;
|
||||
PlacesUtils.bookmarks.removeItem(authorPlaceID);
|
||||
//this._log.info("_deleteMessages: Delete DONE authorID - "+authorID);
|
||||
}
|
||||
// PlacesUtils.history.removePage(URI(this.MESSAGE_URI + messageID));
|
||||
//SnowlPlaces._log.info("_deleteMessages: Delete DONE messageID - "+messageID);
|
||||
|
||||
SnowlDatastore.dbConnection.commitTransaction();
|
||||
}
|
||||
catch(ex) {
|
||||
SnowlDatastore.dbConnection.rollbackTransaction();
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
|
||||
SnowlMessage.markDeleted = function(aMessage) {
|
||||
let message = aMessage;
|
||||
let messageID = message.id;
|
||||
|
||||
SnowlDatastore.dbConnection.beginTransaction();
|
||||
try {
|
||||
// Mark message deleted, make sure this caller checks for non delete status first.
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL(
|
||||
"UPDATE messages SET current =" +
|
||||
" (CASE WHEN current = " + MESSAGE_NON_CURRENT +
|
||||
" THEN " + MESSAGE_NON_CURRENT_DELETED +
|
||||
" WHEN current = " + MESSAGE_CURRENT +
|
||||
" THEN " + MESSAGE_CURRENT_DELETED +
|
||||
" END)" +
|
||||
" WHERE id = " + messageID
|
||||
);
|
||||
|
||||
SnowlDatastore.dbConnection.commitTransaction();
|
||||
}
|
||||
catch(ex) {
|
||||
SnowlDatastore.dbConnection.rollbackTransaction();
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
|
||||
SnowlMessage.prototype = {
|
||||
id: null,
|
||||
subject: null,
|
||||
|
@ -287,6 +372,13 @@ SnowlMessage.prototype = {
|
|||
|
||||
get source() {
|
||||
return SnowlService.sourcesByID[this.sourceID];
|
||||
},
|
||||
|
||||
get CollectionsView() {
|
||||
delete this._CollectionsView;
|
||||
return this._CollectionsView = SnowlService.gBrowserWindow.document.
|
||||
getElementById("sidebar").
|
||||
contentWindow.CollectionsView;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -486,19 +486,26 @@ this._log.info("persist placeID:sources.id - " + placeID + " : " + this.id);
|
|||
/**
|
||||
* Update the current flag for messages in a source, after a refresh.
|
||||
* If message's current flag = 1 set to 0, then set current flag for messages
|
||||
* in the current refresh list to 1.
|
||||
* in the current refresh list to 1. Purge current and marked deleted
|
||||
* placeholder message records if no longer current.
|
||||
*
|
||||
* @param aCurrentMessageIDs {array} messages table ids of the current list
|
||||
*/
|
||||
updateCurrentMessages: function(aCurrentMessageIDs) {
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL(
|
||||
"UPDATE messages SET current = 0" +
|
||||
" WHERE sourceID = " + this.id + " AND current = 1"
|
||||
"UPDATE messages SET current = " + MESSAGE_NON_CURRENT +
|
||||
" WHERE sourceID = " + this.id + " AND current = " + MESSAGE_CURRENT
|
||||
);
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL(
|
||||
"UPDATE messages SET current = 1" +
|
||||
"UPDATE messages SET current = " + MESSAGE_CURRENT +
|
||||
" WHERE sourceID = " + this.id + " AND id IN" +
|
||||
"(" + aCurrentMessageIDs.join(", ") + ")"
|
||||
" (" + aCurrentMessageIDs.join(", ") + ") AND current = " + MESSAGE_NON_CURRENT
|
||||
);
|
||||
SnowlDatastore.dbConnection.executeSimpleSQL(
|
||||
"DELETE FROM messages" +
|
||||
" WHERE sourceID = " + this.id + " AND" +
|
||||
" current = " + MESSAGE_CURRENT_PENDING_PURGE + " AND" +
|
||||
" id NOT IN (" + aCurrentMessageIDs.join(", ") + ")"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче