item; }, init() { function setEventListener(id, eventType, callback) { document .getElementById(id) .addEventListener(eventType, callback.bind(gSiteDataSettings)); } this._absoluteTimeFormat = new Services.intl.DateTimeFormat(undefined, { dateStyle: "short", timeStyle: "short", }); this._relativeTimeFormat = new Services.intl.RelativeTimeFormat( undefined, {} ); this._list = document.getElementById("sitesList"); this._searchBox = document.getElementById("searchBox"); SiteDataManager.getSites().then(sites => { this._sites = sites; let sortCol = document.querySelector( "treecol[data-isCurrentSortCol=true]" ); this._sortSites(this._sites, sortCol); this._buildSitesList(this._sites); Services.obs.notifyObservers(null, "sitedata-settings-init"); }); setEventListener("sitesList", "select", this.onSelect); setEventListener("hostCol", "click", this.onClickTreeCol); setEventListener("usageCol", "click", this.onClickTreeCol); setEventListener("lastAccessedCol", "click", this.onClickTreeCol); setEventListener("cookiesCol", "click", this.onClickTreeCol); setEventListener("searchBox", "MozInputSearch:search", this.onInputSearch); setEventListener("removeAll", "command", this.onClickRemoveAll); setEventListener("removeSelected", "command", this.removeSelected); document.addEventListener("dialogaccept", e => this.saveChanges(e)); window.addEventListener("keypress", e => this.onKeyPress(e)); }, _updateButtonsState() { let items = this._list.getElementsByTagName("richlistitem"); let removeSelectedBtn = document.getElementById("removeSelected"); let removeAllBtn = document.getElementById("removeAll"); removeSelectedBtn.disabled = !this._list.selectedItems.length; removeAllBtn.disabled = !items.length; let l10nId = this._searchBox.value ? "site-data-remove-shown" : "site-data-remove-all"; document.l10n.setAttributes(removeAllBtn, l10nId); }, /** * @param sites {Array} * @param col {XULElement} the being sorted on */ _sortSites(sites, col) { let isCurrentSortCol = col.getAttribute("data-isCurrentSortCol"); let sortDirection = col.getAttribute("data-last-sortDirection") || "ascending"; if (isCurrentSortCol) { // Sort on the current column, flip the sorting direction sortDirection = sortDirection === "ascending" ? "descending" : "ascending"; } let sortFunc = null; switch (col.id) { case "hostCol": sortFunc = (a, b) => { let aHost = a.baseDomain.toLowerCase(); let bHost = b.baseDomain.toLowerCase(); return aHost.localeCompare(bHost); }; break; case "cookiesCol": sortFunc = (a, b) => a.cookies.length - b.cookies.length; break; case "usageCol": sortFunc = (a, b) => a.usage - b.usage; break; case "lastAccessedCol": sortFunc = (a, b) => a.lastAccessed - b.lastAccessed; break; } if (sortDirection === "descending") { sites.sort((a, b) => sortFunc(b, a)); } else { sites.sort(sortFunc); } let cols = this._list.previousElementSibling.querySelectorAll("treecol"); cols.forEach(c => { c.removeAttribute("sortDirection"); c.removeAttribute("data-isCurrentSortCol"); }); col.setAttribute("data-isCurrentSortCol", true); col.setAttribute("sortDirection", sortDirection); col.setAttribute("data-last-sortDirection", sortDirection); }, /** * @param sites {Array} array of metadata of sites */ _buildSitesList(sites) { // Clear old entries. let oldItems = this._list.querySelectorAll("richlistitem"); for (let item of oldItems) { item.remove(); } let keyword = this._searchBox.value.toLowerCase().trim(); let fragment = document.createDocumentFragment(); for (let site of sites) { if (keyword && !site.baseDomain.includes(keyword)) { continue; } if (site.userAction === "remove") { continue; } let item = this._createSiteListItem(site); fragment.appendChild(item); } this._list.appendChild(fragment); this._updateButtonsState(); }, _removeSiteItems(items) { for (let i = items.length - 1; i >= 0; --i) { let item = items[i]; let baseDomain = item.getAttribute("host"); let siteForBaseDomain = this._sites.find( site => site.baseDomain == baseDomain ); if (siteForBaseDomain) { siteForBaseDomain.userAction = "remove"; } item.remove(); } this._updateButtonsState(); }, async saveChanges(event) { let removals = this._sites .filter(site => site.userAction == "remove") .map(site => site.baseDomain); if (removals.length) { let removeAll = removals.length == this._sites.length; let promptArg = removeAll ? undefined : removals; if (!SiteDataManager.promptSiteDataRemoval(window, promptArg)) { // If the user cancelled the confirm dialog keep the site data window open, // they can still press cancel again to exit. event.preventDefault(); return; } try { if (removeAll) { await SiteDataManager.removeAll(); } else { await SiteDataManager.remove(removals); } } catch (e) { console.error(e); } } }, removeSelected() { let lastIndex = this._list.selectedItems.length - 1; let lastSelectedItem = this._list.selectedItems[lastIndex]; let lastSelectedItemPosition = this._list.getIndexOfItem(lastSelectedItem); let nextSelectedItem = this._list.getItemAtIndex( lastSelectedItemPosition + 1 ); this._removeSiteItems(this._list.selectedItems); this._list.clearSelection(); if (nextSelectedItem) { this._list.selectedItem = nextSelectedItem; } else { this._list.selectedIndex = this._list.itemCount - 1; } }, onClickTreeCol(e) { this._sortSites(this._sites, e.target); this._buildSitesList(this._sites); this._list.clearSelection(); }, onInputSearch() { this._buildSitesList(this._sites); this._list.clearSelection(); }, onClickRemoveAll() { let siteItems = this._list.getElementsByTagName("richlistitem"); if (siteItems.length) { this._removeSiteItems(siteItems); } }, onKeyPress(e) { if ( e.keyCode == KeyEvent.DOM_VK_DELETE || (AppConstants.platform == "macosx" && e.keyCode == KeyEvent.DOM_VK_BACK_SPACE) ) { if (!e.target.closest("#sitesList")) { // The user is typing or has not selected an item from the list to remove return; } // The users intention is to delete site data this.removeSelected(); } }, onSelect() { this._updateButtonsState(); }, }; window.addEventListener("load", () => gSiteDataSettings.init()); PK