mirror of
https://github.com/moparisthebest/FireTray
synced 2024-12-22 05:48:49 -05:00
* refactor FiretrayMessaging
* add favorites to the "Included accounts" tree in preference UI
This commit is contained in:
parent
906e64d253
commit
934a67f93c
@ -20,6 +20,7 @@ var firetrayUIOptions = {
|
||||
this.strings = document.getElementById("firetray-options-strings");
|
||||
|
||||
if (firetray.Handler.inMailApp) {
|
||||
Cu.import("resource:///modules/mailServices.js");
|
||||
Cu.import("resource://firetray/FiretrayMessaging.jsm");
|
||||
this.initMailControls();
|
||||
} else {
|
||||
@ -405,7 +406,7 @@ var firetrayUIOptions = {
|
||||
|
||||
let subRows = firetray.Utils.XPath(
|
||||
checkboxCell,
|
||||
'ancestor::xul:treeitem[1]/descendant::xul:treechildren//xul:treerow');
|
||||
'ancestor::xul:treeitem[1]/child::xul:treechildren/xul:treeitem/xul:treerow');
|
||||
F.LOG("subRows="+subRows);
|
||||
for (let i=0, len=subRows.length; i<len; ++i) {
|
||||
firetrayUIOptions._disableTreeRow(
|
||||
@ -424,6 +425,7 @@ var firetrayUIOptions = {
|
||||
* preferences as excluded, but *shown* as "not included"
|
||||
*/
|
||||
// FIXME: this function is too long !
|
||||
// FIXME: tree not updated if accounts or favorite added/removed
|
||||
populateTreeAccountsOrServerTypes: function() {
|
||||
let that = this;
|
||||
let prefPane = document.getElementById("pane1");
|
||||
@ -451,37 +453,37 @@ var firetrayUIOptions = {
|
||||
for (let i=0, len=serverTypesSorted.length; i<len; ++i) {
|
||||
let serverTypeName = serverTypesSorted[i];
|
||||
|
||||
let item = document.createElement('treeitem');
|
||||
item.setAttribute("container",true);
|
||||
item.setAttribute("open",true);
|
||||
let typeItem = document.createElement('treeitem');
|
||||
typeItem.setAttribute("container",true);
|
||||
typeItem.setAttribute("open",true);
|
||||
|
||||
let row = document.createElement('treerow');
|
||||
item.appendChild(row);
|
||||
let typeRow = document.createElement('treerow');
|
||||
typeItem.appendChild(typeRow);
|
||||
|
||||
// account_or_server_type_name
|
||||
let cellName = document.createElement('treecell');
|
||||
cellName.setAttribute('label',serverTypeName);
|
||||
cellName.setAttribute('editable',false);
|
||||
row.appendChild(cellName);
|
||||
typeRow.appendChild(cellName);
|
||||
|
||||
// account_or_server_type_excluded => checkbox
|
||||
let cellExcluded = document.createElement('treecell');
|
||||
cellExcluded.setAttribute('value',!serverTypes[serverTypeName].excluded);
|
||||
cellExcluded.addEventListener( // CAUTION: removeEventListener in onQuit()
|
||||
'DOMAttrModified', that._userChangeValueTreeServerTypes, true);
|
||||
row.appendChild(cellExcluded);
|
||||
typeRow.appendChild(cellExcluded);
|
||||
|
||||
// account_or_server_type_order
|
||||
let cellOrder = document.createElement('treecell');
|
||||
cellOrder.setAttribute('label',serverTypes[serverTypeName].order);
|
||||
cellOrder.addEventListener( // CAUTION: removeEventListener in onQuit()
|
||||
'DOMAttrModified', that._userChangeValueTreeServerTypes, true);
|
||||
row.appendChild(cellOrder);
|
||||
typeRow.appendChild(cellOrder);
|
||||
|
||||
target.appendChild(item);
|
||||
target.appendChild(typeItem);
|
||||
|
||||
// add actual accounts as children
|
||||
let subChildren = document.createElement('treechildren');
|
||||
let accountChildren = document.createElement('treechildren');
|
||||
let typeAccounts = accountsByServerType[serverTypeName];
|
||||
F.LOG("type: "+serverTypeName+", Accounts: "+JSON.stringify(typeAccounts));
|
||||
if (typeof(typeAccounts) == "undefined")
|
||||
@ -489,46 +491,89 @@ var firetrayUIOptions = {
|
||||
|
||||
let rowDisabled = (cellExcluded.getAttribute("value") === "false");
|
||||
for (let i=0, len=typeAccounts.length; i<len; ++i) {
|
||||
let subItem = document.createElement('treeitem');
|
||||
let subRow = document.createElement('treerow');
|
||||
let account = typeAccounts[i];
|
||||
let accountItem = document.createElement('treeitem');
|
||||
accountItem.setAttribute("container",true);
|
||||
accountItem.setAttribute("open",true);
|
||||
|
||||
let accountRow = document.createElement('treerow');
|
||||
|
||||
// account_or_server_type_name
|
||||
cell = document.createElement('treecell');
|
||||
cell.setAttribute('id', typeAccounts[i].key);
|
||||
cell.setAttribute('label',typeAccounts[i].name);
|
||||
cell.setAttribute('editable',false);
|
||||
let accountCell = document.createElement('treecell');
|
||||
accountCell.setAttribute('id', account.key);
|
||||
accountCell.setAttribute('label',account.name);
|
||||
accountCell.setAttribute('editable',false);
|
||||
if (rowDisabled === true)
|
||||
cell.setAttribute('properties', "disabled");
|
||||
subRow.appendChild(cell);
|
||||
accountCell.setAttribute('properties', "disabled");
|
||||
accountRow.appendChild(accountCell);
|
||||
|
||||
// account_or_server_type_excluded => checkbox
|
||||
let cell = document.createElement('treecell');
|
||||
cell.setAttribute('value',(accountsExcluded.indexOf(typeAccounts[i].key) < 0));
|
||||
accountCell = document.createElement('treecell');
|
||||
accountCell.setAttribute('value',(accountsExcluded.indexOf(account.key) < 0));
|
||||
if (rowDisabled === true) {
|
||||
cell.setAttribute('properties', "disabled");
|
||||
cell.setAttribute('editable', "false");
|
||||
accountCell.setAttribute('properties', "disabled");
|
||||
accountCell.setAttribute('editable', "false");
|
||||
} else {
|
||||
cell.addEventListener( // CAUTION: removeEventListener in onQuit()
|
||||
accountCell.addEventListener( // CAUTION: removeEventListener in onQuit()
|
||||
'DOMAttrModified', that._userChangeValueTree, true);
|
||||
}
|
||||
subRow.appendChild(cell);
|
||||
accountRow.appendChild(accountCell);
|
||||
|
||||
// account_or_server_type_order - UNUSED (added for consistency)
|
||||
cell = document.createElement('treecell');
|
||||
cell.setAttribute('editable',false);
|
||||
accountCell = document.createElement('treecell');
|
||||
accountCell.setAttribute('editable',false);
|
||||
if (rowDisabled === true)
|
||||
cell.setAttribute('properties', "disabled");
|
||||
subRow.appendChild(cell);
|
||||
accountCell.setAttribute('properties', "disabled");
|
||||
accountRow.appendChild(accountCell);
|
||||
|
||||
// we must initialize sub-cells correctly to prevent prefsync at a
|
||||
// stage where the pref will be incomplete
|
||||
/* this._disableTreeRow(
|
||||
subRow, (cellExcluded.getAttribute("value") === "false")); */
|
||||
subItem.appendChild(subRow);
|
||||
subChildren.appendChild(subItem);
|
||||
}
|
||||
item.appendChild(subChildren);
|
||||
accountRow, (cellExcluded.getAttribute("value") === "false")); */
|
||||
accountItem.appendChild(accountRow);
|
||||
accountChildren.appendChild(accountItem);
|
||||
|
||||
// add favorite folders
|
||||
let folderChildren = document.createElement('treechildren');
|
||||
let folderChildrenCount = 0;
|
||||
let msgAccount = MailServices.accounts.getIncomingServer(account.key);
|
||||
firetray.Messaging.applyToSubfolders(msgAccount.rootFolder, true, function(folder) {
|
||||
if (!(folder.flags & Ci.nsMsgFolderFlags.Favorite)) return;
|
||||
|
||||
F.LOG("adding folder favorite="+folder.prettyName);
|
||||
let folderItem = document.createElement('treeitem');
|
||||
let folderRow = document.createElement('treerow');
|
||||
|
||||
// folder name
|
||||
let folderCell = document.createElement('treecell');
|
||||
folderCell.setAttribute('id', folder.name);
|
||||
folderCell.setAttribute('label',folder.prettyName);
|
||||
folderCell.setAttribute('editable',false);
|
||||
folderCell.setAttribute('properties', "disabled");
|
||||
folderRow.appendChild(folderCell);
|
||||
|
||||
// checkbox
|
||||
folderCell = document.createElement('treecell');
|
||||
folderCell.setAttribute('editable', "false");
|
||||
folderCell.setAttribute('properties', "disabled");
|
||||
folderRow.appendChild(folderCell);
|
||||
|
||||
// order - UNUSED
|
||||
folderCell = document.createElement('treecell');
|
||||
folderCell.setAttribute('editable', "false");
|
||||
folderCell.setAttribute('properties', "disabled");
|
||||
folderRow.appendChild(folderCell);
|
||||
|
||||
folderItem.appendChild(folderRow);
|
||||
folderChildren.appendChild(folderItem);
|
||||
++folderChildrenCount;
|
||||
});
|
||||
|
||||
if (folderChildrenCount)
|
||||
accountItem.appendChild(folderChildren);
|
||||
}
|
||||
|
||||
typeItem.appendChild(accountChildren);
|
||||
}
|
||||
|
||||
let tree = document.getElementById("ui_tree_mail_accounts");
|
||||
|
@ -157,12 +157,6 @@
|
||||
preference="pref_folder_count_recursive"
|
||||
observes="broadcaster-notification-disabled"/>
|
||||
|
||||
<checkbox id="ui_only_favorite_folders"
|
||||
label="&only_favorite_folders.label;"
|
||||
accesskey="&only_favorite_folders.accesskey;"
|
||||
preference="pref_only_favorite_folders"
|
||||
observes="broadcaster-notification-disabled"/>
|
||||
|
||||
<groupbox id="ui_mail_notification" flex="1">
|
||||
<caption>
|
||||
<label id="ui_mail_notification_type_label"
|
||||
@ -257,6 +251,13 @@
|
||||
observes="broadcaster-notification-disabled" />
|
||||
</caption>
|
||||
|
||||
<checkbox id="ui_only_favorite_folders"
|
||||
label="&only_favorite_folders.label;"
|
||||
accesskey="&only_favorite_folders.accesskey;"
|
||||
preference="pref_only_favorite_folders"
|
||||
tooltiptext="&only_favorite_folders.tooltip;"
|
||||
observes="broadcaster-notification-disabled"/>
|
||||
|
||||
<tree id="ui_tree_mail_accounts" flex="1" rows="10" minwidth="400"
|
||||
seltype="single" editable="true" hidecolumnpicker="false"
|
||||
observes="broadcaster-notification-disabled"
|
||||
|
@ -48,8 +48,6 @@
|
||||
<!ENTITY mail_notification_enabled.accesskey "a">
|
||||
<!ENTITY folder_count_recursive.label "Include subfolders">
|
||||
<!ENTITY folder_count_recursive.accesskey "f">
|
||||
<!ENTITY only_favorite_folders.label "Only favorite folders">
|
||||
<!ENTITY only_favorite_folders.accesskey "v">
|
||||
<!ENTITY mail_notification_type.label "Mail notification type">
|
||||
<!ENTITY mail_notification_type.tooltip "aka. Biff">
|
||||
<!ENTITY mail_notification_unread_count.label "display new message count">
|
||||
@ -70,8 +68,12 @@
|
||||
<!ENTITY unread_count_folder_exceptions.label "Included special folders">
|
||||
<!ENTITY unread_count_folder_exceptions.tooltip "Included special folders for unread message count">
|
||||
<!ENTITY excluded_folders_list.tooltip "Use CTRL + left click to select/deselect folders for unread message count">
|
||||
|
||||
<!ENTITY unread_count_account_exceptions.label "Included accounts">
|
||||
<!ENTITY unread_count_account_exceptions.tooltip "Included accounts for unread message count">
|
||||
<!ENTITY only_favorite_folders.label "Only favorite folders">
|
||||
<!ENTITY only_favorite_folders.accesskey "v">
|
||||
<!ENTITY only_favorite_folders.tooltip "Within included folder types and included accounts, only count messages in favorite folders">
|
||||
|
||||
<!ENTITY account_or_server_type_name "Account">
|
||||
<!ENTITY account_or_server_type_name.tooltip "Account name or type">
|
||||
|
@ -26,6 +26,7 @@ firetray.Messaging = {
|
||||
initialized: false,
|
||||
cleaningTimer: null,
|
||||
currentMsgCount: null,
|
||||
newMsgCount: null,
|
||||
|
||||
init: function() {
|
||||
if (this.initialized) {
|
||||
@ -114,7 +115,7 @@ firetray.Messaging = {
|
||||
|
||||
OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) {
|
||||
F.LOG("OnItemPropertyFlagChanged"+property+" for "+item+" was "+oldFlag+" became "+newFlag);
|
||||
this.onMsgCountChange(item, property, oldValue, newValue);
|
||||
this.onMsgCountChange(item, property, oldFlag, newFlag);
|
||||
},
|
||||
|
||||
OnItemEvent: function(item, event) {
|
||||
@ -123,20 +124,19 @@ firetray.Messaging = {
|
||||
|
||||
onMsgCountChange: function(item, property, oldValue, newValue) {
|
||||
let excludedFoldersFlags = firetray.Utils.prefService.getIntPref("excluded_folders_flags");
|
||||
let msgCountType = firetray.Utils.prefService.getIntPref("message_count_type");
|
||||
let onlyFavorites = firetray.Utils.prefService.getBoolPref("only_favorite_folders");
|
||||
let msgCountType = firetray.Utils.prefService.getIntPref("message_count_type");
|
||||
|
||||
if (!(item.flags & excludedFoldersFlags)) {
|
||||
let prop = property.toString();
|
||||
if (prop === "FolderFlag") {
|
||||
if (onlyFavorites && (oldValue ^ newValue) & Ci.nsMsgFolderFlags.Favorite) {
|
||||
if (prop === "FolderFlag" && onlyFavorites) {
|
||||
if ((oldValue ^ newValue) & Ci.nsMsgFolderFlags.Favorite)
|
||||
firetray.Messaging.updateMsgCountWithCb();
|
||||
}
|
||||
} else if (msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD &&
|
||||
prop === "TotalUnreadMessages") {
|
||||
} else if (prop === "TotalUnreadMessages" &&
|
||||
msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD) {
|
||||
firetray.Messaging.updateMsgCountWithCb();
|
||||
} else if (msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_NEW &&
|
||||
prop === "NewMessages") {
|
||||
} else if (prop === "NewMessages" &&
|
||||
msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_NEW) {
|
||||
if (oldValue === true && newValue === false)
|
||||
item.setNumNewMessages(0); // https://bugzilla.mozilla.org/show_bug.cgi?id=727460
|
||||
firetray.Messaging.updateMsgCountWithCb();
|
||||
@ -153,30 +153,28 @@ firetray.Messaging = {
|
||||
if (!this.initialized) return;
|
||||
|
||||
if ("undefined" === typeof(callback) || !callback) callback = function() { // default
|
||||
firetray.Messaging.updateIcon(msgCount);
|
||||
firetray.Messaging.updateIcon(this.newMsgCount);
|
||||
|
||||
let mailChangeTriggerFile = firetray.Utils.prefService.getCharPref("mail_change_trigger");
|
||||
if (mailChangeTriggerFile)
|
||||
firetray.Messaging.runProcess(mailChangeTriggerFile, [msgCount.toString()]);
|
||||
firetray.Messaging.runProcess(mailChangeTriggerFile, [this.newMsgCount.toString()]);
|
||||
};
|
||||
|
||||
let msgCount;
|
||||
let msgCountType = firetray.Utils.prefService.getIntPref("message_count_type");
|
||||
F.LOG("msgCountType="+msgCountType);
|
||||
if (msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_UNREAD) {
|
||||
msgCount = this.countMessages(this.unreadMsgCountIterate);
|
||||
this.countMessages("UnreadMessages");
|
||||
} else if (msgCountType === FIRETRAY_MESSAGE_COUNT_TYPE_NEW) {
|
||||
msgCount = this.countMessages(this.newMsgCountIterate);
|
||||
this.countMessages("HasNewMessages");
|
||||
} else
|
||||
F.ERROR('unknown message count type');
|
||||
|
||||
if (msgCount !== this.currentMsgCount) {
|
||||
if (this.newMsgCount !== this.currentMsgCount) {
|
||||
callback.call(this);
|
||||
this.currentMsgCount = msgCount;
|
||||
this.currentMsgCount = this.newMsgCount;
|
||||
} else {
|
||||
F.LOG("message count unchanged");
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
updateIcon: function(msgCount) {
|
||||
@ -227,87 +225,80 @@ firetray.Messaging = {
|
||||
/**
|
||||
* computes total unread or new message count.
|
||||
*/
|
||||
countMessages: function(folderCountFunction) {
|
||||
countMessages: function(countType) {
|
||||
let mailAccounts = firetray.Utils.getObjPref('mail_accounts');
|
||||
F.LOG("mail accounts from pref: "+JSON.stringify(mailAccounts));
|
||||
let serverTypes = mailAccounts["serverTypes"];
|
||||
let excludedAccounts = mailAccounts["excludedAccounts"];
|
||||
|
||||
let msgCount = 0;
|
||||
try {
|
||||
let accounts = new this.Accounts();
|
||||
for (let accountServer in accounts) {
|
||||
F.LOG("is servertype excluded: "+serverTypes[accountServer.type].excluded+", account exclusion index: "+excludedAccounts.indexOf(accountServer.key));
|
||||
if ( (serverTypes[accountServer.type].excluded)
|
||||
|| (excludedAccounts.indexOf(accountServer.key) >= 0) )
|
||||
continue;
|
||||
|
||||
let rootFolder = accountServer.rootFolder; // nsIMsgFolder
|
||||
if (rootFolder.hasSubFolders) {
|
||||
let subFolders = rootFolder.subFolders;
|
||||
while(subFolders.hasMoreElements()) {
|
||||
let folder = subFolders.getNext().QueryInterface(Ci.nsIMsgFolder);
|
||||
msgCount = folderCountFunction(folder, msgCount);
|
||||
}
|
||||
}
|
||||
this.newMsgCount = 0;
|
||||
let accounts = new this.Accounts();
|
||||
for (let accountServer in accounts) { // nsIMsgAccount
|
||||
if (!serverTypes[accountServer.type]) {
|
||||
F.WARN("'"+accountServer.type+"' server type is not handled");
|
||||
continue;
|
||||
}
|
||||
} catch (x) {
|
||||
F.ERROR(x);
|
||||
F.LOG("is servertype excluded: "+serverTypes[accountServer.type].excluded+", account exclusion index: "+excludedAccounts.indexOf(accountServer.key));
|
||||
if ((serverTypes[accountServer.type].excluded) ||
|
||||
(excludedAccounts.indexOf(accountServer.key) >= 0))
|
||||
continue;
|
||||
|
||||
this.applyToSubfolders(
|
||||
accountServer.rootFolder,
|
||||
firetray.Utils.prefService.getBoolPref("folder_count_recursive"),
|
||||
function(folder){this.msgCountIterate(countType, folder);}
|
||||
);
|
||||
|
||||
}
|
||||
F.LOG("Total New="+msgCount);
|
||||
return msgCount;
|
||||
F.LOG("Total "+countType+"="+this.newMsgCount);
|
||||
},
|
||||
|
||||
unreadMsgCountIterate: function(folder, accumulator) {
|
||||
let folderCountFunctionName = 'getNumUnread';
|
||||
let onlyFavorites = firetray.Utils.prefService.getBoolPref("only_favorite_folders");
|
||||
let excludedFoldersFlags = firetray.Utils.prefService.getIntPref("excluded_folders_flags");
|
||||
|
||||
if (folder.hasSubFolders && firetray.Utils.prefService.getBoolPref("folder_count_recursive")) {
|
||||
// need to handle each folder on it's own to respect folder flags
|
||||
/**
|
||||
* @param folder: a nsIMsgFolder
|
||||
* @param recursive: if we should look into nested folders
|
||||
* @param fun: a function to apply to all folders
|
||||
*/
|
||||
applyToSubfolders: function(folder, recursive, fun) {
|
||||
if (folder.hasSubFolders) {
|
||||
let subFolders = folder.subFolders;
|
||||
while(subFolders.hasMoreElements()) {
|
||||
let subFolder = subFolders.getNext().QueryInterface(Ci.nsIMsgFolder);
|
||||
accumulator = firetray.Messaging.unreadMsgCountIterate(subFolder, accumulator);
|
||||
if (recursive && subFolder.hasSubFolders)
|
||||
firetray.Messaging.applyToSubfoldersRecursive(subFolder, recursive, fun);
|
||||
else
|
||||
fun.call(this, subFolder);
|
||||
}
|
||||
}
|
||||
|
||||
let folderUnreadMsgCount = 0;
|
||||
if (!(folder.flags & excludedFoldersFlags)) {
|
||||
if (!onlyFavorites || folder.flags & Ci.nsMsgFolderFlags.Favorite) {
|
||||
folderUnreadMsgCount = folder[folderCountFunctionName](false);
|
||||
}
|
||||
}
|
||||
|
||||
F.LOG(folder.prettyName+" "+folderCountFunctionName+"="+folderUnreadMsgCount);
|
||||
return accumulator + folderUnreadMsgCount;
|
||||
},
|
||||
applyToSubfoldersRecursive: function(folder, recursive, fun) {
|
||||
fun.call(this, folder);
|
||||
this.applyToSubfolders(folder, recursive, fun);
|
||||
},
|
||||
|
||||
newMsgCountIterate: function(folder, accumulator) {
|
||||
if (folder.hasSubFolders && firetray.Utils.prefService.getBoolPref("folder_count_recursive")) {
|
||||
F.LOG("hasSubFolders");
|
||||
let subFolders = folder.subFolders;
|
||||
while(subFolders.hasMoreElements()) {
|
||||
let subFolder = subFolders.getNext().QueryInterface(Ci.nsIMsgFolder);
|
||||
accumulator = firetray.Messaging.newMsgCountIterate(subFolder, accumulator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type: one of 'UnreadMessages', 'HasNewMessages'
|
||||
*/
|
||||
msgCountIterate: function(type, folder) {
|
||||
let onlyFavorites = firetray.Utils.prefService.getBoolPref("only_favorite_folders");
|
||||
let excludedFoldersFlags = firetray.Utils.prefService.getIntPref("excluded_folders_flags");
|
||||
if (!(folder.flags & excludedFoldersFlags)) {
|
||||
if (!onlyFavorites || folder.flags & Ci.nsMsgFolderFlags.Favorite) {
|
||||
accumulator = firetray.Messaging.addHasNewMessages(folder, accumulator);
|
||||
firetray.Messaging["add"+type](folder);
|
||||
}
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
F.LOG("newMsgCount="+this.newMsgCount);
|
||||
},
|
||||
|
||||
addHasNewMessages: function(folder, accumulator) {
|
||||
let folderNewMsgCount = folder.hasNewMessages;
|
||||
F.LOG(folder.prettyName+" hasNewMessages="+folderNewMsgCount);
|
||||
return accumulator || folderNewMsgCount;
|
||||
addUnreadMessages: function(folder) {
|
||||
let folderUnreadMsgCount = folder['getNumUnread'](false);
|
||||
F.LOG("folder: "+folder.prettyName+" folderUnreadMsgCount="+folderUnreadMsgCount);
|
||||
this.newMsgCount += folderUnreadMsgCount;
|
||||
},
|
||||
|
||||
addHasNewMessages: function(folder) {
|
||||
let folderNewMsgCount = folder.hasNewMessages;
|
||||
F.LOG("folder: "+folder.prettyName+" hasNewMessages="+folderNewMsgCount);
|
||||
this.newMsgCount = this.newMsgCount || folderNewMsgCount;
|
||||
},
|
||||
|
||||
runProcess: function(filepath, args) {
|
||||
|
Loading…
Reference in New Issue
Block a user