Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: new-options.js

Issue 29445590: Issue 5255 - Advanced tab (HTML, strings and functionality) (Closed)
Patch Set: Addressed Thomas comments Created July 12, 2017, 1:03 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: new-options.js
===================================================================
--- a/new-options.js
+++ b/new-options.js
@@ -27,6 +27,7 @@
let acceptableAdsUrl = null;
let isCustomFiltersLoaded = false;
let {getMessage} = ext.i18n;
+ let customFiltersArray = [];
Thomas Greiner 2017/07/14 12:26:13 Detail: I'd recommend not to include the value typ
saroyanm 2017/07/14 16:17:25 Acknowledged.
saroyanm 2017/07/14 17:11:06 Done.
let filterErrors = new Map([
["synchronize_invalid_url",
"options_filterList_lastDownload_invalidURL"],
@@ -38,6 +39,12 @@
"options_filterList_lastDownload_checksumMismatch"]
]);
+ const whitelistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/;
+ // Period of time in milliseconds
+ const minuteInMs = 60000;
+ const hourInMs = 3600000;
+ const fullDayInMs = 86400000;
+
function Collection(details)
{
this.details = details;
@@ -100,7 +107,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));
@@ -126,13 +134,11 @@
}
this._setEmpty(table, null);
- if (table.hasChildNodes())
- {
- table.insertBefore(listItem,
- table.childNodes[this.items.indexOf(item)]);
- }
+ if (table.children.length > 0)
+ table.insertBefore(listItem, table.children[this.items.indexOf(item)]);
else
table.appendChild(listItem);
+
this.updateItem(item);
}
return length;
@@ -200,9 +206,8 @@
control.setAttribute("disabled", true);
}
- let dateElement = element.querySelector(".date");
- let timeElement = element.querySelector(".time");
- if (dateElement && timeElement)
+ let lastUpdateElement = element.querySelector(".last-update");
+ if (lastUpdateElement)
{
let message = element.querySelector(".message");
if (item.isDownloading)
@@ -222,9 +227,39 @@
}
else if (item.lastDownload > 0)
{
- let dateTime = i18nFormatDateTime(item.lastDownload * 1000);
- dateElement.textContent = dateTime[0];
- timeElement.textContent = dateTime[1];
+ let lastUpdate = item.lastDownload * 1000;
+ let lastUpdateLive = function()
+ {
+ let sinceUpdate = Date.now() - lastUpdate;
+ if (sinceUpdate > fullDayInMs)
+ {
+ let lastUpdateDate = new Date(item.lastDownload * 1000);
+ let monthName = lastUpdateDate.toLocaleString(undefined,
+ {month: "short"});
+ let day = lastUpdateDate.getDate();
+ day = day < 10 ? "0" + day : day;
+ lastUpdateElement.textContent = day + " " + monthName + " " +
+ lastUpdateDate.getFullYear();
+ }
+ else if (sinceUpdate > hourInMs)
+ {
+ let placeholder = [Math.round(sinceUpdate / hourInMs)];
+ lastUpdateElement.textContent =
+ getMessage("options_filterList_hours", placeholder);
Thomas Greiner 2017/07/14 12:26:12 This placeholder isn't defined in new-options.json
saroyanm 2017/07/14 16:17:24 Well spotted, will remove it.
saroyanm 2017/07/14 17:11:06 Done.
+ }
+ else if (sinceUpdate > minuteInMs)
+ {
+ let placeholder = [Math.round(sinceUpdate / minuteInMs)];
+ lastUpdateElement.textContent =
+ getMessage("options_filterList_minutes", placeholder);
+ }
+ else
+ {
+ lastUpdateElement.textContent =
+ getMessage("options_filterList_now");
+ }
+ };
+ lastUpdateLive();
element.classList.remove("show-message");
}
}
@@ -315,12 +350,6 @@
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",
@@ -378,18 +407,38 @@
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);
+ {
+ customFiltersArray.push(filter.text);
+ if (isCustomFiltersLoaded)
Thomas Greiner 2017/07/14 12:26:12 Detail: What is this check for? It seems that `upd
saroyanm 2017/07/14 16:17:25 Shouldn't we wait only for the time when all filte
Thomas Greiner 2017/07/14 16:37:42 Right, I remember and I see that this has actually
saroyanm 2017/07/14 16:41:34 I agree, I'll create a separate issue for that, wh
+ updateCustomFiltersUi();
+ }
filtersMap[filter.text] = filter;
}
+ function removeCustomFilter(text)
+ {
+ let index = customFiltersArray.indexOf(text);
+ if (index >= 0)
+ customFiltersArray.splice(index, 1);
Thomas Greiner 2017/07/14 12:26:12 What if there are multiple instances of the same f
saroyanm 2017/07/14 16:17:25 There shouldn't be multiple instances of same filt
Thomas Greiner 2017/07/14 16:37:42 My thinking was that a pre-existing filter could a
saroyanm 2017/07/14 16:41:34 Acknowledged.
+
+ updateCustomFiltersUi();
+ }
+
+ function updateCustomFiltersUi()
+ {
+ let customFiltersListElement = E("custom-filters-raw");
+ customFiltersListElement.value = "";
Thomas Greiner 2017/07/14 12:26:12 Detail: This is redundant because the line below w
saroyanm 2017/07/14 16:17:24 Thanks for noticing. Will update.
saroyanm 2017/07/14 17:11:06 Done.
+ customFiltersListElement.value = customFiltersArray.join("\n");
+ }
+
function loadRecommendations()
{
fetch("subscriptions.xml")
@@ -474,7 +523,7 @@
location.hash = id;
}
- function execAction(action, element)
+ function execAction(action, element, event)
{
switch (action)
{
@@ -493,7 +542,8 @@
break;
}
case "cancel-custom-filters":
- E("custom-filters").classList.remove("mode-edit");
+ updateCustomFiltersUi();
+ setCustomFiltersView("read");
break;
case "cancel-domain-exception":
E("whitelisting-textbox").value = "";
@@ -504,7 +554,7 @@
closeDialog();
break;
case "edit-custom-filters":
- editCustomFilters();
+ setCustomFiltersView("write");
break;
case "edit-domain-exception":
document.querySelector("#whitelisting .controls").classList
@@ -553,7 +603,7 @@
},
() =>
{
- E("custom-filters").classList.remove("mode-edit");
+ setCustomFiltersView("read");
});
break;
case "switch-tab":
@@ -599,6 +649,28 @@
}
}
+ function setCustomFiltersView(mode)
+ {
+ let customFilters = E("custom-filters");
+ let customFiltersListElement = E("custom-filters-raw");
+ if (mode == "read")
+ {
+ customFiltersListElement.disabled = true;
+ if (!customFiltersListElement.value)
+ {
+ setCustomFiltersView("empty");
+ return;
+ }
+ }
+ else if (mode == "write")
+ {
+ updateCustomFiltersUi();
Thomas Greiner 2017/07/14 12:26:13 Interesting that you're calling `updateCustomFilte
saroyanm 2017/07/14 16:17:25 You are right, I'm not sure why I did this.. I'll
saroyanm 2017/07/14 17:11:06 Done.
+ customFiltersListElement.disabled = false;
+ }
+
+ customFilters.dataset.mode = mode;
+ }
+
function onClick(e)
{
let context = document.querySelector(".show-context-menu");
@@ -612,7 +684,7 @@
actions = actions.split(",");
for (let action of actions)
{
- execAction(action, e.target);
+ execAction(action, e.target, e);
}
}
@@ -659,7 +731,7 @@
let actions = container.getAttribute("data-action").split(",");
for (let action of actions)
{
- execAction(action, element);
+ execAction(action, element, e);
}
}
@@ -684,10 +756,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 +825,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 +846,18 @@
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("link-filters").setAttribute("href", link);
+ });
+
+ getDocLink("subscriptions", (link) =>
{
- e.preventDefault();
- addCustomFilters();
- }, false);
+ setLinks("filter-lists-description", link);
+ });
+
+ E("custom-filters-raw").setAttribute("placeholder",
+ getMessage("options_customFilters_edit_placeholder", ["/ads/track/*"]));
// Help tab
getDocLink("faq", (link) =>
@@ -930,6 +990,8 @@
updateFilter(filter);
isCustomFiltersLoaded = true;
+ updateCustomFiltersUi();
+ setCustomFiltersView("read");
});
}
});
@@ -975,21 +1037,6 @@
.classList.remove("mode-edit");
}
- function editCustomFilters()
- {
- if (!isCustomFiltersLoaded)
- {
- console.error("Custom filters are not loaded");
- return;
- }
-
- E("custom-filters").classList.add("mode-edit");
- let filterTexts = [];
- for (let customFilterItem of collections.customFilters.items)
- filterTexts.push(customFilterItem.text);
- E("custom-filters-raw").value = filterTexts.join("\n");
- }
-
function addEnableSubscription(url, title, homepage)
{
let messageType = null;
@@ -1024,8 +1071,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;
« locale/en-US/new-options.json ('K') | « new-options.html ('k') | skin/new-options.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld