in mail/base/content/about3Pane.js [3275:3483]
_onDrop(event) {
this._timedExpand();
this._clearDropTarget();
this._autoExpandedRows.length = 0;
if (event.dataTransfer.dropEffect == "none") {
// Somehow this is possible. It should not be possible.
return;
}
const row = event.target.closest("li");
if (!row) {
return;
}
const targetFolder = MailServices.folderLookup.getFolderForURL(row.uri);
const types = Array.from(event.dataTransfer.mozTypesAt(0));
if (types.includes("text/x-moz-message")) {
const array = [];
let sourceFolder;
for (let i = 0; i < event.dataTransfer.mozItemCount; i++) {
const msgHdr = top.messenger.msgHdrFromURI(
event.dataTransfer.mozGetDataAt("text/x-moz-message", i)
);
if (!i) {
sourceFolder = msgHdr.folder;
}
array.push(msgHdr);
}
let isMove = event.dataTransfer.dropEffect == "move";
const isNews = sourceFolder.flags & Ci.nsMsgFolderFlags.Newsgroup;
if (!sourceFolder.canDeleteMessages || isNews) {
isMove = false;
}
Services.prefs.setStringPref(
"mail.last_msg_movecopy_target_uri",
targetFolder.URI
);
Services.prefs.setBoolPref("mail.last_msg_movecopy_was_move", isMove);
// ### ugh, so this won't work with cross-folder views. We would
// really need to partition the messages by folder.
if (isMove) {
dbViewWrapperListener.threadPaneCommandUpdater.updateNextMessageAfterDelete();
}
MailServices.copy.copyMessages(
sourceFolder,
array,
targetFolder,
isMove,
null,
top.msgWindow,
true
);
} else if (types.includes("text/x-moz-folder")) {
const rows = [];
let isMove = event.dataTransfer.dropEffect == "move";
if (event.dataTransfer.mozItemCount == 1) {
// Only one folder was dragged and dropped.
// If the dropped Y-coordinate is near the center of the targetFolder,
// simply move it into the targetFolder. Otherwise, reorder the dropped
// folder above or below the targetFolder.
const sourceFolder = event.dataTransfer
.mozGetDataAt("text/x-moz-folder", 0)
.QueryInterface(Ci.nsIMsgFolder);
let destinationFolder = targetFolder;
let isReordering = false;
let insertAfter = false;
// Only allow moving a folder in "all" mode, otherwise it would be
// impossible to reorder folders unambiguously.
if (
isMove &&
targetFolder.parent &&
sourceFolder.server == targetFolder.server &&
!targetFolder.isServer &&
row.modeName == "all"
) {
const { center, quarterOfHeight } = this._calculateElementHeight(row);
const upperElementEnd = event.clientY < center - quarterOfHeight;
const lowerElementEndWithoutChildren =
event.clientY > center + quarterOfHeight &&
(!row.classList.contains("children") ||
row.classList.contains("collapsed"));
isReordering = upperElementEnd || lowerElementEndWithoutChildren;
insertAfter = lowerElementEndWithoutChildren;
if (isReordering) {
// To insert the sourceFolder before or after the targetFolder,
// we have to transfer sourceFolder to the parent of targetFolder
// as a sibling of targetFolder. If it is the same as the current
// parent, there is no need to perform the transferFolder, so let
// destinationFolder be null.
destinationFolder =
targetFolder.parent != sourceFolder.parent
? targetFolder.parent
: null;
}
}
if (destinationFolder) {
// Move sourceFolder to a different parent.
// Reset the sort order of sourceFolder before moving it.
sourceFolder.userSortOrder = Ci.nsIMsgFolder.NO_SORT_VALUE;
// Start the move. This is done in an asynchronous process, so order
// them in the listener that will be called when the move is complete.
isMove = folderPaneContextMenu.transferFolder(
isMove,
sourceFolder,
destinationFolder,
isReordering
? new ReorderFolderListener(
sourceFolder,
targetFolder,
insertAfter
)
: null
);
// Save in prefs the destination folder URI and if this was a move
// or copy.
// This is to fill in the next folder or message context menu item
// "Move|Copy to <DestinationFolderName> Again".
Services.prefs.setStringPref(
"mail.last_msg_movecopy_target_uri",
destinationFolder.URI
);
} else if (isReordering) {
// Reorder within current siblings.
this.insertFolder(sourceFolder, targetFolder, insertAfter);
if (folderTree.selection.has(folderTree.rows.indexOf(row))) {
rows.push(this.getRowForFolder(sourceFolder.URI, row.modeName));
}
}
Services.prefs.setBoolPref("mail.last_msg_movecopy_was_move", isMove);
} else {
// FIXME! Bug 1896531.
console.warn(
"Bug 1896531. Copy and move for multiselection is only partially supported and it might fail."
);
for (let i = 0; i < event.dataTransfer.mozItemCount; i++) {
const sourceFolder = event.dataTransfer
.mozGetDataAt("text/x-moz-folder", i)
.QueryInterface(Ci.nsIMsgFolder);
isMove = folderPaneContextMenu.transferFolder(
isMove,
sourceFolder,
targetFolder
);
rows.push(this.getRowForFolder(sourceFolder.URI, row.modeName));
}
// Save in prefs the target folder URI and if this was a move or copy.
// This is to fill in the next folder or message context menu item
// "Move|Copy to <TargetFolderName> Again".
Services.prefs.setStringPref(
"mail.last_msg_movecopy_target_uri",
targetFolder.URI
);
Services.prefs.setBoolPref("mail.last_msg_movecopy_was_move", isMove);
}
this.swapFolderSelection(rows);
} else if (types.includes("application/x-moz-file")) {
for (let i = 0; i < event.dataTransfer.mozItemCount; i++) {
const extFile = event.dataTransfer
.mozGetDataAt("application/x-moz-file", i)
.QueryInterface(Ci.nsIFile);
if (extFile.isFile() && /\.eml$/i.test(extFile.leafName)) {
MailServices.copy.copyFileMessage(
extFile,
targetFolder,
null,
false,
1,
"",
null,
top.msgWindow
);
}
}
} else if (types.includes("text/x-moz-newsfolder")) {
const rows = [];
for (let i = 0; i < event.dataTransfer.mozItemCount; i++) {
const folder = event.dataTransfer
.mozGetDataAt("text/x-moz-newsfolder", i)
.QueryInterface(Ci.nsIMsgFolder);
const newsRoot = targetFolder.rootFolder.QueryInterface(
Ci.nsIMsgNewsFolder
);
newsRoot.reorderGroup(folder, targetFolder);
rows.push(this.getRowForFolder(folder, row.modeName));
}
this.swapFolderSelection(rows);
} else if (
types.includes("text/x-moz-url-data") ||
types.includes("text/x-moz-url")
) {
// This is a potential rss feed. A link image as well as link text url
// should be handled; try to extract a url from non moz apps as well.
const feedURI = FeedUtils.getFeedUriFromDataTransfer(event.dataTransfer);
FeedUtils.subscribeToFeed(feedURI.spec, targetFolder);
}
event.preventDefault();
},