historySidebar.js (7175B)
1 /* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 /* Shared Places Import - change other consumers if you change this: */ 7 var { XPCOMUtils } = ChromeUtils.importESModule( 8 "resource://gre/modules/XPCOMUtils.sys.mjs" 9 ); 10 11 ChromeUtils.defineESModuleGetters(this, { 12 PlacesTransactions: "resource://gre/modules/PlacesTransactions.sys.mjs", 13 PlacesUIUtils: "moz-src:///browser/components/places/PlacesUIUtils.sys.mjs", 14 PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", 15 PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.sys.mjs", 16 }); 17 18 XPCOMUtils.defineLazyScriptGetter( 19 this, 20 "PlacesTreeView", 21 "chrome://browser/content/places/treeView.js" 22 ); 23 XPCOMUtils.defineLazyScriptGetter( 24 this, 25 ["PlacesInsertionPoint", "PlacesController", "PlacesControllerDragHelper"], 26 "chrome://browser/content/places/controller.js" 27 ); 28 /* End Shared Places Import */ 29 30 var gHistoryTree; 31 var gSearchBox; 32 var gHistoryGrouping = ""; 33 var gCumulativeSearches = 0; 34 var gCumulativeFilterCount = 0; 35 36 window.addEventListener("load", () => { 37 let uidensity = window.top.document.documentElement.getAttribute("uidensity"); 38 if (uidensity) { 39 document.documentElement.setAttribute("uidensity", uidensity); 40 } 41 42 gHistoryTree = document.getElementById("historyTree"); 43 gHistoryTree.addEventListener("click", event => 44 PlacesUIUtils.onSidebarTreeClick(event) 45 ); 46 gHistoryTree.addEventListener("keypress", event => 47 PlacesUIUtils.onSidebarTreeKeyPress(event) 48 ); 49 gHistoryTree.addEventListener("mousemove", event => 50 PlacesUIUtils.onSidebarTreeMouseMove(event) 51 ); 52 gHistoryTree.addEventListener("mouseout", () => 53 PlacesUIUtils.setMouseoverURL("", window) 54 ); 55 56 gSearchBox = document.getElementById("search-box"); 57 gSearchBox.addEventListener("MozInputSearch:search", () => 58 searchHistory(gSearchBox.value) 59 ); 60 61 let viewButton = document.getElementById("viewButton"); 62 gHistoryGrouping = viewButton.getAttribute("selectedsort"); 63 64 Glean.historySidebar.filterType[gHistoryGrouping].add(1); 65 66 if (gHistoryGrouping == "site") { 67 document.getElementById("bysite").setAttribute("checked", "true"); 68 } else if (gHistoryGrouping == "visited") { 69 document.getElementById("byvisited").setAttribute("checked", "true"); 70 } else if (gHistoryGrouping == "lastvisited") { 71 document.getElementById("bylastvisited").setAttribute("checked", "true"); 72 } else if (gHistoryGrouping == "dayandsite") { 73 document.getElementById("bydayandsite").setAttribute("checked", "true"); 74 } else { 75 document.getElementById("byday").setAttribute("checked", "true"); 76 } 77 78 document 79 .querySelector("#viewButton > menupopup") 80 .addEventListener("command", event => { 81 let by = event.target.id.slice(2); 82 viewButton.setAttribute("selectedsort", by); 83 GroupBy(by); 84 }); 85 86 let bhTooltip = document.getElementById("bhTooltip"); 87 bhTooltip.addEventListener("popupshowing", event => { 88 window.top.BookmarksEventHandler.fillInBHTooltip(bhTooltip, event); 89 }); 90 bhTooltip.addEventListener("popuphiding", () => 91 bhTooltip.removeAttribute("position") 92 ); 93 94 // Add a button to close the history sidebar. This should only be visible when 95 // this document is used for the revamped sidebar. See tor-browser#44108. 96 document 97 .getElementById("sidebar-panel-close") 98 .addEventListener("click", () => { 99 window.browsingContext.embedderWindowGlobal.browsingContext.window.SidebarController.toggle( 100 "viewHistorySidebar" 101 ); 102 }); 103 // Hack to convert the sidebar-menu-history Fluent string's label attribute 104 // into text content. 105 const headingEl = document.getElementById("sidebar-panel-header-history"); 106 const updateHeadingText = () => { 107 const label = headingEl.getAttribute("label"); 108 if (!label) { 109 return; 110 } 111 headingEl.textContent = label; 112 headingEl.removeAttribute("label"); 113 }; 114 const headingElObserver = new MutationObserver(updateHeadingText); 115 headingElObserver.observe(headingEl, { 116 attributes: true, 117 attributeFilter: ["label"], 118 }); 119 updateHeadingText(); 120 121 searchHistory(""); 122 }); 123 124 function GroupBy(groupingType) { 125 if (groupingType != gHistoryGrouping) { 126 Glean.historySidebar.filterType[groupingType].add(1); 127 } 128 gHistoryGrouping = groupingType; 129 gCumulativeFilterCount++; 130 searchHistory(gSearchBox.value); 131 } 132 133 function updateTelemetry(urlsOpened = []) { 134 Glean.historySidebar.cumulativeSearches.accumulateSingleSample( 135 gCumulativeSearches 136 ); 137 Glean.historySidebar.cumulativeFilterCount.accumulateSingleSample( 138 gCumulativeFilterCount 139 ); 140 clearCumulativeCounters(); 141 142 Glean.sidebar.link.history.add(urlsOpened.length); 143 } 144 145 function searchHistory(aInput) { 146 var query = PlacesUtils.history.getNewQuery(); 147 var options = PlacesUtils.history.getNewQueryOptions(); 148 149 const NHQO = Ci.nsINavHistoryQueryOptions; 150 var sortingMode; 151 var resultType; 152 153 switch (gHistoryGrouping) { 154 case "visited": 155 resultType = NHQO.RESULTS_AS_URI; 156 sortingMode = NHQO.SORT_BY_VISITCOUNT_DESCENDING; 157 break; 158 case "lastvisited": 159 resultType = NHQO.RESULTS_AS_URI; 160 sortingMode = NHQO.SORT_BY_DATE_DESCENDING; 161 break; 162 case "dayandsite": 163 resultType = NHQO.RESULTS_AS_DATE_SITE_QUERY; 164 break; 165 case "site": 166 resultType = NHQO.RESULTS_AS_SITE_QUERY; 167 sortingMode = NHQO.SORT_BY_TITLE_ASCENDING; 168 break; 169 case "day": 170 default: 171 resultType = NHQO.RESULTS_AS_DATE_QUERY; 172 break; 173 } 174 175 if (aInput) { 176 query.searchTerms = aInput; 177 if (gHistoryGrouping != "visited" && gHistoryGrouping != "lastvisited") { 178 sortingMode = NHQO.SORT_BY_FRECENCY_DESCENDING; 179 resultType = NHQO.RESULTS_AS_URI; 180 } 181 } 182 183 options.sortingMode = sortingMode; 184 options.resultType = resultType; 185 options.includeHidden = !!aInput; 186 187 let timerId; 188 if (gHistoryGrouping == "lastvisited") { 189 timerId = Glean.historySidebar.lastvisitedTreeQueryTime.start(); 190 } 191 192 // call load() on the tree manually 193 // instead of setting the place attribute in historySidebar.xhtml 194 // otherwise, we will end up calling load() twice 195 gHistoryTree.load(query, options); 196 197 // Sometimes search is activated without an input string. For example, when 198 // the history sidbar is first opened or when a search filter is selected. 199 // Since we're trying to measure how often the searchbar was used, we should first 200 // check if there's an input string before collecting telemetry. 201 if (aInput) { 202 Glean.sidebar.search.history.add(1); 203 gCumulativeSearches++; 204 } 205 206 if (gHistoryGrouping == "lastvisited") { 207 Glean.historySidebar.lastvisitedTreeQueryTime.stopAndAccumulate(timerId); 208 } 209 } 210 211 function clearCumulativeCounters() { 212 gCumulativeSearches = 0; 213 gCumulativeFilterCount = 0; 214 } 215 216 window.addEventListener("unload", () => { 217 clearCumulativeCounters(); 218 PlacesUIUtils.setMouseoverURL("", window); 219 }); 220 221 window.addEventListener("SidebarFocused", () => gSearchBox.focus());