Bug 1545199 - Persist calendar-task-tree column state across restarts. r=darktrojan
authorPaul Morris <paul@paulwmorris.com>
Tue, 02 Jul 2019 16:51:14 -0400
changeset 36037 091a75e4e8ccd8396deb5f9c1aef85d54e43d57e
parent 36036 ee2fd60f9f9fefe3fd6aee789498f4463b8045f5
child 36038 63616633fa865cdf7ce749bc003a0e01f0eb0f31
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersdarktrojan
bugs1545199
Bug 1545199 - Persist calendar-task-tree column state across restarts. r=darktrojan
calendar/base/content/calendar-task-tree.js
--- a/calendar/base/content/calendar-task-tree.js
+++ b/calendar/base/content/calendar-task-tree.js
@@ -297,16 +297,18 @@
                     col.width = Number(widths.shift());
                 }
                 if (sorted && sorted == itemProperty) {
                     this.mTreeView.sortDirection = sortDirection;
                     this.mTreeView.selectedColumn = col;
                 }
             });
 
+            window.addEventListener("unload", this.persistColumnState.bind(this));
+
             this.dispatchEvent(new CustomEvent("bindingattached", { bubbles: false }));
         }
 
         get currentTask() {
             const index = this.currentIndex;
 
             const isSelected = this.view && this.view.selection &&
                 this.view.selection.isSelected(index);
@@ -349,16 +351,49 @@
             this.mTextFilterField = val;
         }
 
         get textFilterField() {
             return this.mTextFilterField;
         }
 
         /**
+         * We want to make several attributes of the calendar-task-tree column elements persist
+         * across restarts. Unfortunately there's no reliable way by using the XUL 'persist'
+         * attribute on the column elements. So instead we store the data on the calendar-task-tree
+         * element before Thunderbird quits (using `persistColumnState`), and then restore the
+         * attributes on the columns when Thunderbird starts up again (using `restoreColumnState`).
+         *
+         * This function reads data from column attributes and sets it on several attributes on the
+         * task tree element, which are persisted because they are in the "persist" attribute of
+         * the task tree element.
+         * (E.g. `persist="visible-columns ordinals widths sort-active sort-direction"`.)
+         */
+        persistColumnState() {
+            const columns = Array.from(this.querySelectorAll("treecol"));
+            const widths = columns.map(col => col.width || 0);
+            const ordinals = columns.map(col => col.ordinal);
+            const visibleColumns = columns.filter(col => col.getAttribute("hidden") != "true")
+                .map(col => col.getAttribute("itemproperty"));
+
+            this.setAttribute("widths", widths.join(" "));
+            this.setAttribute("ordinals", ordinals.join(" "));
+            this.setAttribute("visible-columns", visibleColumns.join(" "));
+
+            const sorted = this.mTreeView.selectedColumn;
+            if (sorted) {
+                this.setAttribute("sort-active", sorted.getAttribute("itemproperty"));
+                this.setAttribute("sort-direction", this.mTreeView.sortDirection);
+            } else {
+                this.removeAttribute("sort-active");
+                this.removeAttribute("sort-direction");
+            }
+        }
+
+        /**
          * Calculates the text to display in the "Due In" column for the given task,
          * the amount of time between now and when the task is due.
          *
          * @param {Object} task    A task object.
          * @return {string}        A formatted string for the "Due In" column for the task.
          */
         duration(task) {
             const noValidDueDate = !(task && task.dueDate && task.dueDate.isValid);
@@ -586,48 +621,18 @@
             let focused = (document.activeElement == this) || menuOpen;
 
             calendarController.onSelectionChanged({ detail: focused ? this.selectedTasks : [] });
             calendarController.todo_tasktree_focused = focused;
         }
 
         disconnectedCallback() {
             super.disconnectedCallback();
-
+            this.persistColumnState();
             this.mTreeView = null;
-
-            let widths = "";
-            let ordinals = "";
-            let visible = "";
-            let sorted = this.mTreeView.selectedColumn;
-
-            this.querySelectorAll("treecol").forEach((col) => {
-                if (col.getAttribute("hidden") != "true") {
-                    let content = col.getAttribute("itemproperty");
-                    visible += visible.length > 0 ? " " + content : content;
-                }
-                if (ordinals.length > 0) {
-                    ordinals += " ";
-                }
-                ordinals += col.ordinal;
-                if (widths.length > 0) {
-                    widths += " ";
-                }
-                widths += col.width || 0;
-            });
-            this.setAttribute("visible-columns", visible);
-            this.setAttribute("ordinals", ordinals);
-            this.setAttribute("widths", widths);
-            if (sorted) {
-                this.setAttribute("sort-active", sorted.getAttribute("itemproperty"));
-                this.setAttribute("sort-direction", this.mTreeView.sortDirection);
-            } else {
-                this.removeAttribute("sort-active");
-                this.removeAttribute("sort-direction");
-            }
         }
     }
 
     customElements.define("calendar-task-tree", CalendarTaskTree, { "extends": "tree" });
 
     /**
      * Custom element for the task tree that appears in the todaypane.
      */