Bug 1606584 - When listing accounts, return a tree of folders rather than a flattened list; r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net>
Thu, 09 Jan 2020 21:12:52 +1300
changeset 37960 446e3aafa9b9293168233e09a674e91dd33fcdc9
parent 37959 f1c1cd523798d8bc4c45bcfea083fbf66d7162ed
child 37961 35c3cd0f04a4e50ac05ca37b5b6c34306ef4da66
push id398
push userclokep@gmail.com
push dateMon, 09 Mar 2020 19:10:28 +0000
reviewersmkmelin
bugs1606584
Bug 1606584 - When listing accounts, return a tree of folders rather than a flattened list; r=mkmelin Original patch by Jonathan Protzenko <jonathan.protzenko@gmail.com>
mail/components/extensions/parent/ext-accounts.js
mail/components/extensions/schemas/folders.json
mail/components/extensions/test/browser/browser_ext_mailTabs.js
mail/components/extensions/test/xpcshell/test_ext_accounts.js
mail/components/extensions/test/xpcshell/test_ext_folders.js
mail/components/extensions/test/xpcshell/test_ext_messages.js
--- a/mail/components/extensions/parent/ext-accounts.js
+++ b/mail/components/extensions/parent/ext-accounts.js
@@ -20,24 +20,25 @@ ChromeUtils.defineModuleGetter(
 
 function convertAccount(account) {
   account = account.QueryInterface(Ci.nsIMsgAccount);
   let server = account.incomingServer;
   if (server.type == "im") {
     return null;
   }
 
-  let folders = [];
-  let traverse = function(folder, accountId) {
+  let traverse = function(folder) {
+    let f = convertFolder(folder, account.key);
+    f.subFolders = [];
     for (let subFolder of fixIterator(folder.subFolders, Ci.nsIMsgFolder)) {
-      folders.push(convertFolder(subFolder, accountId));
-      traverse(subFolder, accountId);
+      f.subFolders.push(traverse(subFolder));
     }
+    return f;
   };
-  traverse(account.incomingServer.rootFolder, account.key);
+  let folders = traverse(account.incomingServer.rootFolder).subFolders;
 
   return {
     id: account.key,
     name: account.incomingServer.prettyName,
     type: account.incomingServer.type,
     folders,
   };
 }
--- a/mail/components/extensions/schemas/folders.json
+++ b/mail/components/extensions/schemas/folders.json
@@ -34,16 +34,23 @@
             "type": "string",
             "optional": true,
             "description": "The human-friendly name of this folder."
           },
           "path": {
             "type": "string",
             "description": "Path to this folder in the account. Although paths look predictable, never guess a folder's path, as there are a number of reasons why it may not be what you think it is."
           },
+          "subFolders": {
+            "type": "array",
+            "items": {
+              "$ref": "MailFolder"
+            },
+            "optional": true
+          },
           "type": {
             "type": "string",
             "optional": true,
             "description": "The type of folder, for several common types.",
             "enum": ["inbox", "drafts", "sent", "trash", "templates", "archives", "junk", "outbox"]
           }
         }
       }
--- a/mail/components/extensions/test/browser/browser_ext_mailTabs.js
+++ b/mail/components/extensions/test/browser/browser_ext_mailTabs.js
@@ -88,16 +88,17 @@ add_task(async function test_update() {
     await awaitMessage("checkRealLayout", state);
 
     browser.mailTabs.update({ displayedFolder: folders[0] });
     state.sortType = "date";
     state.sortOrder = "ascending";
     state.folderPaneVisible = true;
     state.messagePaneVisible = true;
     state.displayedFolder = folders[0];
+    delete state.displayedFolder.subFolders;
     await checkCurrent(state);
     await awaitMessage("checkRealLayout", state);
     await awaitMessage("checkRealSort", state);
 
     state.sortOrder = "descending";
     for (let value of ["date", "subject", "author"]) {
       await browser.mailTabs.update({
         sortType: value,
--- a/mail/components/extensions/test/xpcshell/test_ext_accounts.js
+++ b/mail/components/extensions/test/xpcshell/test_ext_accounts.js
@@ -120,32 +120,34 @@ add_task(async function test_accounts() 
       let result5 = await browser.accounts.get(account1Id);
       let platformInfo = await browser.runtime.getPlatformInfo();
       assertDeepEqual(
         [
           {
             accountId: account1Id,
             name: "Trash",
             path: "/Trash",
+            subFolders: [
+              {
+                accountId: account1Id,
+                name: "foo 'bar'(!)",
+                path: "/Trash/foo 'bar'(!)",
+              },
+              {
+                accountId: account1Id,
+                name: "Ϟ",
+                // This character is not supported on Windows, so it gets hashed,
+                // by NS_MsgHashIfNecessary.
+                path: platformInfo.os == "win" ? "/Trash/b52bc214" : "/Trash/Ϟ",
+              },
+            ],
             type: "trash",
           },
           {
             accountId: account1Id,
-            name: "foo 'bar'(!)",
-            path: "/Trash/foo 'bar'(!)",
-          },
-          {
-            accountId: account1Id,
-            name: "Ϟ",
-            // This character is not supported on Windows, so it gets hashed,
-            // by NS_MsgHashIfNecessary.
-            path: platformInfo.os == "win" ? "/Trash/b52bc214" : "/Trash/Ϟ",
-          },
-          {
-            accountId: account1Id,
             name: "Outbox",
             path: "/Unsent Messages",
             type: "outbox",
           },
         ],
         result5.folders
       );
 
@@ -156,29 +158,31 @@ add_task(async function test_accounts() 
 
       let result6 = await browser.accounts.get(account2Id);
       assertDeepEqual(
         [
           {
             accountId: account2Id,
             name: "Inbox",
             path: "/INBOX",
+            subFolders: [
+              {
+                accountId: account2Id,
+                name: "foo 'bar'(!)",
+                path: "/INBOX/foo 'bar'(!)",
+              },
+              {
+                accountId: account2Id,
+                name: "Ϟ",
+                path: "/INBOX/&A94-",
+              },
+            ],
             type: "inbox",
           },
           {
-            accountId: account2Id,
-            name: "foo 'bar'(!)",
-            path: "/INBOX/foo 'bar'(!)",
-          },
-          {
-            accountId: account2Id,
-            name: "Ϟ",
-            path: "/INBOX/&A94-",
-          },
-          {
             // The trash folder magically appears at this point.
             // It wasn't here before.
             accountId: "account2",
             name: "Trash",
             path: "/Trash",
             type: "trash",
           },
         ],
--- a/mail/components/extensions/test/xpcshell/test_ext_folders.js
+++ b/mail/components/extensions/test/xpcshell/test_ext_folders.js
@@ -38,39 +38,51 @@ add_task(async function test_folders() {
         { accountId, path: "/folder1" },
         "folder2"
       );
       browser.test.assertEq(accountId, folder2.accountId);
       browser.test.assertEq("folder2", folder2.name);
       browser.test.assertEq("/folder1/folder2", folder2.path);
 
       account = await browser.accounts.get(accountId);
-      browser.test.assertEq(4, account.folders.length);
-      browser.test.assertEq("/folder1/folder2", account.folders[3].path);
+      browser.test.assertEq(3, account.folders.length);
+      browser.test.assertEq(1, account.folders[2].subFolders.length);
+      browser.test.assertEq(
+        "/folder1/folder2",
+        account.folders[2].subFolders[0].path
+      );
 
       let folder3 = await browser.folders.rename(
         { accountId, path: "/folder1/folder2" },
         "folder3"
       );
       browser.test.assertEq(accountId, folder3.accountId);
       browser.test.assertEq("folder3", folder3.name);
       browser.test.assertEq("/folder1/folder3", folder3.path);
 
       account = await browser.accounts.get(accountId);
-      browser.test.assertEq(4, account.folders.length);
-      browser.test.assertEq("/folder1/folder3", account.folders[3].path);
+      browser.test.assertEq(3, account.folders.length);
+      browser.test.assertEq(1, account.folders[2].subFolders.length);
+      browser.test.assertEq(
+        "/folder1/folder3",
+        account.folders[2].subFolders[0].path
+      );
 
       await browser.folders.delete({ accountId, path: "/folder1/folder3" });
 
       account = await browser.accounts.get(accountId);
-      browser.test.assertEq(4, account.folders.length);
+      browser.test.assertEq(3, account.folders.length);
       browser.test.assertEq("/Trash", account.folders[0].path);
-      browser.test.assertEq("/Trash/folder3", account.folders[1].path);
-      browser.test.assertEq("/Unsent Messages", account.folders[2].path);
-      browser.test.assertEq("/folder1", account.folders[3].path);
+      browser.test.assertEq(1, account.folders[0].subFolders.length);
+      browser.test.assertEq(
+        "/Trash/folder3",
+        account.folders[0].subFolders[0].path
+      );
+      browser.test.assertEq("/Unsent Messages", account.folders[1].path);
+      browser.test.assertEq("/folder1", account.folders[2].path);
 
       await browser.folders.delete({ accountId, path: "/Trash/folder3" });
 
       account = await browser.accounts.get(accountId);
       browser.test.assertEq(3, account.folders.length);
       browser.test.assertEq("/Trash", account.folders[0].path);
       browser.test.assertEq("/Unsent Messages", account.folders[1].path);
       browser.test.assertEq("/folder1", account.folders[2].path);
--- a/mail/components/extensions/test/xpcshell/test_ext_messages.js
+++ b/mail/components/extensions/test/xpcshell/test_ext_messages.js
@@ -400,33 +400,49 @@ add_task(async function test_archive() {
       browser.test.assertEq("/test", accountBefore.folders[2].path);
 
       let messagesBefore = await browser.messages.list(
         accountBefore.folders[2]
       );
       await browser.messages.archive(messagesBefore.messages.map(m => m.id));
 
       let accountAfter = await browser.accounts.get(accountId);
-      browser.test.assertEq(7, accountAfter.folders.length);
+      browser.test.assertEq(4, accountAfter.folders.length);
       browser.test.assertEq("/test", accountAfter.folders[2].path);
       browser.test.assertEq("/Archives", accountAfter.folders[3].path);
-      browser.test.assertEq("/Archives/2018", accountAfter.folders[4].path);
-      browser.test.assertEq("/Archives/2019", accountAfter.folders[5].path);
-      browser.test.assertEq("/Archives/2020", accountAfter.folders[6].path);
+      browser.test.assertEq(3, accountAfter.folders[3].subFolders.length);
+      browser.test.assertEq(
+        "/Archives/2018",
+        accountAfter.folders[3].subFolders[0].path
+      );
+      browser.test.assertEq(
+        "/Archives/2019",
+        accountAfter.folders[3].subFolders[1].path
+      );
+      browser.test.assertEq(
+        "/Archives/2020",
+        accountAfter.folders[3].subFolders[2].path
+      );
 
       let messagesAfter = await browser.messages.list(accountAfter.folders[2]);
       browser.test.assertEq(0, messagesAfter.messages.length);
 
-      let messages2018 = await browser.messages.list(accountAfter.folders[4]);
+      let messages2018 = await browser.messages.list(
+        accountAfter.folders[3].subFolders[0]
+      );
       browser.test.assertEq(2, messages2018.messages.length);
 
-      let messages2019 = await browser.messages.list(accountAfter.folders[5]);
+      let messages2019 = await browser.messages.list(
+        accountAfter.folders[3].subFolders[1]
+      );
       browser.test.assertEq(12, messages2019.messages.length);
 
-      let messages2020 = await browser.messages.list(accountAfter.folders[6]);
+      let messages2020 = await browser.messages.list(
+        accountAfter.folders[3].subFolders[2]
+      );
       browser.test.assertEq(1, messages2020.messages.length);
 
       browser.test.notifyPass("finished");
     },
     manifest: {
       permissions: ["accountsRead", "messagesMove", "messagesRead"],
     },
   });