diff options
Diffstat (limited to 'comm/mailnews/base/content/virtualFolderListEdit.js')
-rw-r--r-- | comm/mailnews/base/content/virtualFolderListEdit.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/comm/mailnews/base/content/virtualFolderListEdit.js b/comm/mailnews/base/content/virtualFolderListEdit.js new file mode 100644 index 0000000000..775d3ba1c7 --- /dev/null +++ b/comm/mailnews/base/content/virtualFolderListEdit.js @@ -0,0 +1,206 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* globals PROTO_TREE_VIEW */ + +var { XPCOMUtils } = ChromeUtils.import( + "resource://gre/modules/XPCOMUtils.jsm" +); +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +XPCOMUtils.defineLazyModuleGetters(this, { + FolderUtils: "resource:///modules/FolderUtils.jsm", + MailUtils: "resource:///modules/MailUtils.jsm", +}); + +window.addEventListener("DOMContentLoaded", () => { + gSelectVirtual.load(); +}); + +var gFolderTreeView = new PROTO_TREE_VIEW(); + +var gSelectVirtual = { + _treeElement: null, + _selectedList: new Set(), + + load() { + if (window.arguments[0].searchFolderURIs) { + let srchFolderUriArray = window.arguments[0].searchFolderURIs.split("|"); + for (let uri of srchFolderUriArray) { + this._selectedList.add(MailUtils.getOrCreateFolder(uri)); + } + } + + // Add the top level of the folder tree. + for (let account of FolderUtils.allAccountsSorted(true)) { + let server = account.incomingServer; + if ( + server instanceof Ci.nsIPop3IncomingServer && + server.deferredToAccount + ) { + continue; + } + + gFolderTreeView._rowMap.push(new FolderRow(server.rootFolder)); + } + + // Recursively expand the tree to show all selected folders. + function expandToSelected(row, i) { + hiddenFolders.delete(row._folder); + for (let folder of hiddenFolders) { + if (row._folder.isAncestorOf(folder)) { + gFolderTreeView.toggleOpenState(i); + for (let j = row.children.length - 1; j >= 0; j--) { + expandToSelected(row.children[j], i + j + 1); + } + break; + } + } + } + + let hiddenFolders = new Set(gSelectVirtual._selectedList); + for (let i = gFolderTreeView.rowCount - 1; i >= 0; i--) { + expandToSelected(gFolderTreeView._rowMap[i], i); + } + + this._treeElement = document.getElementById("folderPickerTree"); + this._treeElement.view = gFolderTreeView; + }, + + onKeyPress(aEvent) { + // For now, only do something on space key. + if (aEvent.charCode != aEvent.DOM_VK_SPACE) { + return; + } + + let selection = this._treeElement.view.selection; + let start = {}; + let end = {}; + let numRanges = selection.getRangeCount(); + + for (let range = 0; range < numRanges; range++) { + selection.getRangeAt(range, start, end); + for (let i = start.value; i <= end.value; i++) { + this._toggle(i); + } + } + }, + + onClick(aEvent) { + // We only care about button 0 (left click) events. + if (aEvent.button != 0) { + return; + } + + // We don't want to toggle when clicking on header or tree (scrollbar) or + // on treecol. + if (aEvent.target.nodeName != "treechildren") { + return; + } + + let treeCellInfo = this._treeElement.getCellAt( + aEvent.clientX, + aEvent.clientY + ); + if (treeCellInfo.row == -1 || treeCellInfo.col.id != "selectedCol") { + return; + } + + this._toggle(treeCellInfo.row); + }, + + _toggle(aRow) { + let folder = gFolderTreeView._rowMap[aRow]._folder; + if (this._selectedList.has(folder)) { + this._selectedList.delete(folder); + } else { + this._selectedList.add(folder); + } + + gFolderTreeView._tree.invalidateRow(aRow); + }, + + onAccept() { + // XXX We should just pass the folder objects around... + let uris = [...this._selectedList.values()] + .map(folder => folder.URI) + .join("|"); + + if (window.arguments[0].okCallback) { + window.arguments[0].okCallback(uris); + } + }, +}; + +document.addEventListener("dialogaccept", () => gSelectVirtual.onAccept()); + +/** + * A tree row representing a single folder. + */ +class FolderRow { + constructor(folder, parent = null) { + this._folder = folder; + this._open = false; + this._level = parent ? parent.level + 1 : 0; + this._parent = parent; + this._children = null; + } + + get id() { + return this._folder.URI; + } + + get text() { + return this.getText("folderNameCol"); + } + + getText(aColName) { + switch (aColName) { + case "folderNameCol": + return this._folder.abbreviatedName; + default: + return ""; + } + } + + get open() { + return this._open; + } + + get level() { + return this._level; + } + + getProperties(column) { + let properties = ""; + switch (column?.id) { + case "folderNameCol": + // From folderUtils.jsm. + properties = FolderUtils.getFolderProperties(this._folder, this.open); + break; + case "selectedCol": + properties = "selectedColumn"; + if (gSelectVirtual._selectedList.has(this._folder)) { + properties += " selected-true"; + } + break; + } + return properties; + } + + get children() { + if (this._children === null) { + this._children = []; + for (let subFolder of this._folder.subFolders) { + if (!subFolder.getFlag(Ci.nsMsgFolderFlags.Virtual)) { + this._children.push(new FolderRow(subFolder, this)); + } + } + this._children.sort((a, b) => a._folder.compareSortKeys(b._folder)); + } + return this._children; + } +} |