| Index: new-options.js |
| =================================================================== |
| --- a/new-options.js |
| +++ b/new-options.js |
| @@ -38,6 +38,8 @@ |
| "options_filterList_lastDownload_checksumMismatch"] |
| ]); |
| + const whitelistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/; |
| + |
| function Collection(details) |
| { |
| this.details = details; |
| @@ -100,7 +102,8 @@ |
| for (let j = 0; j < this.details.length; j++) |
| { |
| - let table = E(this.details[j].id); |
| + let detail = this.details[j]; |
| + let table = E(detail.id); |
| let template = table.querySelector("template"); |
| let listItem = document.createElement("li"); |
| listItem.appendChild(document.importNode(template.content, true)); |
| @@ -128,11 +131,13 @@ |
| this._setEmpty(table, null); |
| if (table.hasChildNodes()) |
| { |
| - table.insertBefore(listItem, |
| - table.childNodes[this.items.indexOf(item)]); |
| + let beforeIndex = this.items.indexOf(item) + (detail.useHeader == true); |
| + table.insertBefore(listItem, table.children[beforeIndex]); |
| } |
| else |
| + { |
| table.appendChild(listItem); |
| + } |
| this.updateItem(item); |
| } |
| return length; |
| @@ -200,9 +205,8 @@ |
| control.setAttribute("disabled", true); |
| } |
| - let dateElement = element.querySelector(".date"); |
| - let timeElement = element.querySelector(".time"); |
| - if (dateElement && timeElement) |
| + let lastUpdateElem = element.querySelector(".last-update"); |
| + if (lastUpdateElem) |
| { |
| let message = element.querySelector(".message"); |
| if (item.isDownloading) |
| @@ -222,9 +226,40 @@ |
| } |
| else if (item.lastDownload > 0) |
| { |
| - let dateTime = i18nFormatDateTime(item.lastDownload * 1000); |
| - dateElement.textContent = dateTime[0]; |
| - timeElement.textContent = dateTime[1]; |
| + let timer = setInterval(lastUpdateLive, 60000); |
| + let lastUpdate = item.lastDownload * 1000; |
| + function lastUpdateLive() |
| + { |
| + let sinceUpdate = Date.now() - lastUpdate; |
| + if(sinceUpdate > 86400000) |
| + { |
| + let lastUpdateDate = new Date(item.lastDownload * 1000); |
| + let monthName = lastUpdateDate.toLocaleString("en-US", |
|
saroyanm
2017/06/11 15:40:12
For reference: Make sense to find a way to pass th
saroyanm
2017/06/12 16:44:42
Create a function in i18n, that returns month: "sh
saroyanm
2017/06/14 10:59:00
I used different approach while we do have the val
Thomas Greiner
2017/07/07 13:01:07
This looks like a race condition because the "lang
|
| + { month: "short" }); |
| + let day = lastUpdateDate.getDate(); |
| + day = day < 10 ? "0" + day : day; |
| + lastUpdateElem.textContent = day + " " + monthName + " " + |
|
saroyanm
2017/06/12 16:44:42
Note: Make sense to discuss if we need to localize
|
| + lastUpdateDate.getFullYear(); |
| + clearInterval(timer); |
| + return; |
| + } |
| + else if (sinceUpdate > 3600000) |
| + { |
| + lastUpdateElem.textContent = Math.round(sinceUpdate / 3600000) + |
| + " " + getMessage("options_filterList_hours"); |
| + } |
| + else if (sinceUpdate > 60000) |
| + { |
| + lastUpdateElem.textContent = Math.round(sinceUpdate / 60000) + |
| + " " + getMessage("options_filterList_minutes"); |
| + } |
| + else |
| + { |
| + lastUpdateElem.textContent = |
| + getMessage("options_filterList_just"); |
| + } |
| + } |
| + lastUpdateLive(); |
| element.classList.remove("show-message"); |
| } |
| } |
| @@ -315,16 +350,11 @@ |
| emptyText: "options_whitelisted_empty" |
| } |
| ]); |
| - collections.customFilters = new Collection([ |
| - { |
| - id: "custom-filters-table", |
| - emptyText: "options_customFilters_empty" |
| - } |
| - ]); |
| collections.filterLists = new Collection([ |
| { |
| id: "all-filter-lists-table", |
| - useOriginalTitle: true |
| + useOriginalTitle: true, |
| + useHeader: true |
| } |
| ]); |
| @@ -378,18 +408,50 @@ |
| function updateFilter(filter) |
| { |
| - let match = filter.text.match(/^@@\|\|([^/:]+)\^\$document$/); |
| + let match = filter.text.match(whitelistedDomainRegexp); |
| if (match && !filtersMap[filter.text]) |
| { |
| filter.title = match[1]; |
| collections.whitelist.addItem(filter); |
| } |
| else |
| - collections.customFilters.addItem(filter); |
| + addCustomFilter(filter); |
| filtersMap[filter.text] = filter; |
| } |
| + function addCustomFilter(filter) |
| + { |
| + customFiltersView("read"); |
| + |
| + // Note: document.createElement("option") is unreliable in Opera |
|
saroyanm
2017/06/11 15:40:12
I'm not sure if this still true, I took this from
saroyanm
2017/06/12 16:44:42
Check if it's still an issue in the supported Oper
saroyanm
2017/06/14 10:59:00
Done.
This was added back in 2012 -> https://hg.a
Thomas Greiner
2017/07/07 13:01:08
Acknowledged.
|
| + let elt = new Option(); |
| + elt.text = filter.text; |
| + elt.value = filter.text; |
| + E("custom-filters-box").appendChild(elt); |
| + } |
| + |
| + function removeCustomFilter(text) |
| + { |
| + let list = E("custom-filters-box"); |
| + let selector = "option[value=" + CSS.escape(text) + "]"; |
| + for (let option of list.querySelectorAll(selector)) |
| + list.removeChild(option); |
| + |
| + if (E("custom-filters-box").options.length == 0) |
| + customFiltersView("empty") |
| + } |
| + |
| + function convertToRawFormat(event) |
| + { |
| + let filters = []; |
| + |
| + for (let option of E("custom-filters-box").options) |
| + filters.push(option.value); |
| + |
| + document.getElementById("custom-filters-raw").value = filters.join("\n"); |
| + } |
| + |
| function loadRecommendations() |
| { |
| fetch("subscriptions.xml") |
| @@ -493,7 +555,7 @@ |
| break; |
| } |
| case "cancel-custom-filters": |
| - E("custom-filters").classList.remove("mode-edit"); |
| + customFiltersView("read"); |
| break; |
| case "cancel-domain-exception": |
| E("whitelisting-textbox").value = ""; |
| @@ -504,7 +566,7 @@ |
| closeDialog(); |
| break; |
| case "edit-custom-filters": |
| - editCustomFilters(); |
| + customFiltersView("write"); |
| break; |
| case "edit-domain-exception": |
| document.querySelector("#whitelisting .controls").classList |
| @@ -553,7 +615,7 @@ |
| }, |
| () => |
| { |
| - E("custom-filters").classList.remove("mode-edit"); |
| + customFiltersView("read"); |
| }); |
| break; |
| case "switch-tab": |
| @@ -599,6 +661,36 @@ |
| } |
| } |
| + function customFiltersView(mode) |
| + { |
| + switch (mode) |
| + { |
| + case "read": |
| + if (E("custom-filters-box").options.length == 0) |
| + { |
| + customFiltersView("empty"); |
| + } |
| + else |
| + { |
| + E("custom-filters").classList.add("mode-view"); |
| + E("custom-filters").classList.remove("mode-edit"); |
| + E("custom-filters").classList.remove("mode-empty"); |
| + } |
| + break; |
| + case "write": |
| + convertToRawFormat(); |
| + E("custom-filters").classList.remove("mode-view"); |
| + E("custom-filters").classList.add("mode-edit"); |
| + E("custom-filters").classList.remove("mode-empty"); |
| + break; |
| + case "empty": |
| + E("custom-filters").classList.remove("mode-view"); |
| + E("custom-filters").classList.remove("mode-edit"); |
| + E("custom-filters").classList.add("mode-empty"); |
| + break; |
| + } |
| + } |
| + |
| function onClick(e) |
| { |
| let context = document.querySelector(".show-context-menu"); |
| @@ -684,10 +776,6 @@ |
| let tabContentId = tab.getAttribute("aria-controls"); |
| let tabContent = document.getElementById(tabContentId); |
| - // Select sub tabs |
| - if (tab.hasAttribute("data-subtab")) |
| - selectTabItem(tab.getAttribute("data-subtab"), tabContent, false); |
| - |
| if (tab && focus) |
| tab.focus(); |
| @@ -757,12 +845,12 @@ |
| }, false); |
| // Advanced tab |
| - let tweaks = document.querySelectorAll("#tweaks li[data-pref]"); |
| - tweaks = Array.prototype.map.call(tweaks, (checkbox) => |
| + let customize = document.querySelectorAll("#customize li[data-pref]"); |
| + customize = Array.prototype.map.call(customize, (checkbox) => |
| { |
| return checkbox.getAttribute("data-pref"); |
| }); |
| - for (let key of tweaks) |
| + for (let key of customize) |
| { |
| getPref(key, (value) => |
| { |
| @@ -778,26 +866,10 @@ |
| hidePref("show_devtools_panel", !features.devToolsPanel); |
| }); |
| - let filterTextbox = document.querySelector("#custom-filters-add input"); |
| - placeholderValue = getMessage("options_customFilters_textbox_placeholder"); |
| - filterTextbox.setAttribute("placeholder", placeholderValue); |
| - function addCustomFilters() |
| + getDocLink("filterdoc", (link) => |
| { |
| - let filterText = filterTextbox.value; |
| - sendMessageHandleErrors({ |
| - type: "filters.add", |
| - text: filterText |
| - }, |
| - () => |
| - { |
| - filterTextbox.value = ""; |
| - }); |
| - } |
| - E("custom-filters-add").addEventListener("submit", (e) => |
| - { |
| - e.preventDefault(); |
| - addCustomFilters(); |
| - }, false); |
| + E("link-filters").setAttribute("href", link); |
| + }); |
| // Help tab |
| getDocLink("faq", (link) => |
| @@ -1024,8 +1096,11 @@ |
| break; |
| case "removed": |
| let knownFilter = filtersMap[filter.text]; |
| - collections.whitelist.removeItem(knownFilter); |
| - collections.customFilters.removeItem(knownFilter); |
| + if (whitelistedDomainRegexp.test(knownFilter.text)) |
| + collections.whitelist.removeItem(knownFilter); |
| + else |
| + removeCustomFilter(filter.text); |
| + |
| delete filtersMap[filter.text]; |
| updateShareLink(); |
| break; |