Bug 1524779 - Use a separate button to show all preferences. r=mconley,flod

This allows interacting with the page without using the keyboard in the rare cases where this may be necessary. The button is ghosted because search is the preferred interaction.

Pressing ESC allows resetting the input field without the performance impact of showing all preferences.

Differential Revision: https://phabricator.services.mozilla.com/D19162

--HG--
extra : rebase_source : 276e682c2fbfd2cbaa855134b3431ff0d7f33f89
extra : amend_source : 55656fcbf550753988036d48a9820a9e3319065f
extra : source : 1f5e185b778f4de4ebb3942d495c8ce61b65addc
This commit is contained in:
Paolo Amadini 2019-02-18 13:30:31 +00:00
Родитель a8a53fe9a5
Коммит c968f98386
9 изменённых файлов: 94 добавлений и 31 удалений

Просмотреть файл

@ -6,6 +6,10 @@ html {
height: 100%;
}
.hidden {
display: none;
}
body.config-background {
min-height: 100%;
background-image: url("chrome://browser/content/aboutconfig/background.svg");
@ -50,6 +54,17 @@ body.config-warning {
background-position-x: right 9px;
}
#show-all:not(.hidden) {
display: block;
margin: 10px auto;
}
/* Ghost the button when it's not selected. */
#show-all:not(:focus):not(:hover):not(:active) {
background-color: transparent;
opacity: .7;
}
#prefs {
background-color: var(--in-content-box-background);
color: var(--in-content-text-color);
@ -61,10 +76,6 @@ body.config-warning {
border-spacing: 0;
}
#prefs > tr.hidden {
display: none;
}
#prefs > tr.odd {
background-color: var(--in-content-box-background-odd);
}

Просмотреть файл

@ -47,10 +47,12 @@
<!-- Use a unique ID to prevent showing autocomplete results from other
browser pages with similarly named fields. -->
<input type="text" id="about-config-search"
data-l10n-id="about-config-search">
data-l10n-id="about-config-search-input">
</div>
<table id="prefs"></table>
<button id="show-all" data-l10n-id="about-config-show-all"></button>
</template>
</body>
</html>

Просмотреть файл

@ -48,6 +48,11 @@ let gPrefInEdit = null;
*/
let gFilterString = null;
/**
* True if we were requested to show all preferences.
*/
let gFilterShowAll = false;
class PrefRow {
constructor(name) {
this.name = name;
@ -114,7 +119,8 @@ class PrefRow {
}
get matchesFilter() {
return !gFilterString || this.name.toLowerCase().includes(gFilterString);
return gFilterShowAll ||
(gFilterString && this.name.toLowerCase().includes(gFilterString));
}
/**
@ -367,6 +373,7 @@ function loadPrefs() {
let search = gSearchInput = document.getElementById("about-config-search");
let prefs = gPrefsTable = document.getElementById("prefs");
let showAll = document.getElementById("show-all");
search.focus();
for (let name of Services.prefs.getChildList("")) {
@ -387,7 +394,19 @@ function loadPrefs() {
search.addEventListener("input", () => {
// We call "disarm" to restart the timer at every input.
gFilterPrefsTask.disarm();
if (!search.value.trim().length) {
// Return immediately to the empty page if the search string is empty.
filterPrefs();
} else {
gFilterPrefsTask.arm();
}
});
showAll.addEventListener("click", event => {
search.focus();
search.value = "";
gFilterPrefsTask.disarm();
filterPrefs({ showAll: true });
});
prefs.addEventListener("click", event => {
@ -416,7 +435,7 @@ function loadPrefs() {
});
}
function filterPrefs() {
function filterPrefs(options = {}) {
if (gPrefInEdit) {
gPrefInEdit.endEdit();
}
@ -424,11 +443,19 @@ function filterPrefs() {
let searchName = gSearchInput.value.trim();
gFilterString = searchName.toLowerCase();
gFilterShowAll = !!options.showAll;
let showResults = gFilterString || gFilterShowAll;
document.getElementById("show-all").classList.toggle("hidden", showResults);
let prefArray = [];
if (showResults) {
if (!gSortedExistingPrefs) {
gSortedExistingPrefs = [...gExistingPrefs.values()];
gSortedExistingPrefs.sort((a, b) => a.name > b.name);
}
prefArray = gSortedExistingPrefs;
}
// The slowest operations tend to be the addition and removal of DOM nodes, so
// this algorithm tries to reduce removals by hiding nodes instead. This
@ -439,9 +466,9 @@ function filterPrefs() {
let indexInArray = 0;
let elementInTable = gPrefsTable.firstElementChild;
let odd = false;
while (indexInArray < gSortedExistingPrefs.length || elementInTable) {
while (indexInArray < prefArray.length || elementInTable) {
// For efficiency, filter the array while we are iterating.
let prefInArray = gSortedExistingPrefs[indexInArray];
let prefInArray = prefArray[indexInArray];
if (prefInArray) {
if (!prefInArray.matchesFilter) {
indexInArray++;

Просмотреть файл

@ -77,9 +77,9 @@ add_task(async function test_delete_user_pref() {
Assert.ok(!row.hasClass("deleted"));
Assert.ok(Preferences.get(PREF_NEW) === testValue);
// Searching again after deleting should remove the row.
// Filtering again after deleting should remove the row.
row.resetColumnButton.click();
this.search();
this.showAll();
Assert.ok(!this.getRow(PREF_NEW));
});
}
@ -103,8 +103,8 @@ add_task(async function test_reset_user_pref() {
Assert.ok(!Services.prefs.prefHasUserValue(PREF_BOOLEAN_DEFAULT_TRUE));
Assert.equal(this.getRow(PREF_BOOLEAN_DEFAULT_TRUE).value, "true");
// Search for nothing to test gPrefArray
this.search();
// Filter again to test the preference cache.
this.showAll();
row = this.getRow(PREF_BOOLEAN_DEFAULT_TRUE);
Assert.ok(!row.hasClass("has-user-value"));
Assert.ok(!row.resetColumnButton);

Просмотреть файл

@ -56,9 +56,9 @@ add_task(async function test_observe_add_user_pref() {
Assert.equal(row.value, "" + value);
Assert.ok(Preferences.get(PREF_NEW) === value);
// Searching again after deleting should remove the row.
// Filtering again after deleting should remove the row.
Preferences.reset(PREF_NEW);
this.search();
this.showAll();
Assert.ok(!this.getRow(PREF_NEW));
// Searching for the preference name should give the ability to add it.
@ -79,12 +79,12 @@ add_task(async function test_observe_add_user_pref() {
Assert.ok(!this.getRow(PREF_NEW));
// Resetting the filter should display the new preference.
this.search("");
this.showAll();
Assert.equal(this.getRow(PREF_NEW).value, "" + value);
// Reset the preference, then continue by adding a different value.
Preferences.reset(PREF_NEW);
this.search("");
this.showAll();
}
});
});
@ -98,8 +98,8 @@ add_task(async function test_observe_delete_user_pref() {
Preferences.reset(PREF_NEW);
Assert.ok(row.hasClass("deleted"));
// Searching again should remove the row.
this.search();
// Filtering again should remove the row.
this.showAll();
Assert.ok(!this.getRow(PREF_NEW));
});
}

Просмотреть файл

@ -34,8 +34,9 @@ add_task(async function test_search() {
// new button preference if desired
Assert.equal(this.rows.length, filteredPrefArray.length + 1);
// Test empty search returns all preferences.
this.search();
// Show all preferences again after filtering.
this.showAll();
Assert.equal(this.searchInput.value, "");
// The total number of preferences may change at any time because of
// operations running in the background, so we only test approximately.
@ -44,11 +45,20 @@ add_task(async function test_search() {
// We want thousands of prefs instead of a few dozen that are filtered.
Assert.greater(this.rows.length, prefArray.length - 50);
// Pressing ESC while showing all preferences returns to the initial page.
EventUtils.sendKey("escape");
Assert.equal(this.rows.length, 0);
// Test invalid search returns no preferences.
// Expecting 1 row to be returned since it offers the ability to add.
this.search("aJunkValueasdf");
Assert.equal(this.rows.length, 1);
// Pressing ESC clears the field and returns to the initial page.
EventUtils.sendKey("escape");
Assert.equal(this.searchInput.value, "");
Assert.equal(this.rows.length, 0);
// Two preferences match this filter, and one of those matches exactly.
this.search("test.aboutconfig.a");
Assert.equal(this.rows.length, 2);
@ -57,6 +67,10 @@ add_task(async function test_search() {
// new preference with the same name but a different case.
this.search("TEST.aboutconfig.a");
Assert.equal(this.rows.length, 3);
// Entering an empty string returns to the initial page.
this.search("");
Assert.equal(this.rows.length, 0);
});
});

Просмотреть файл

@ -30,8 +30,8 @@ add_task(async function test_showWarningNextTime() {
Assert.ok(!this.prefsTable.firstElementChild);
Assert.equal(this.document.activeElement, this.searchInput);
// Pressing ESC shows all results immediately.
EventUtils.sendKey("escape");
// The show all button should be present and show all results immediately.
this.showAll();
Assert.ok(this.prefsTable.firstElementChild);
}, { dontBypassWarning: true });
}

Просмотреть файл

@ -98,7 +98,7 @@ class AboutConfigTest {
await this.document.l10n.ready;
if (!options.dontBypassWarning) {
this.bypassWarningButton.click();
this.search();
this.showAll();
}
}
@ -134,11 +134,19 @@ class AboutConfigTest {
return this.rows.find(row => row.name == name);
}
/**
* Shows all preferences using the dedicated button.
*/
showAll() {
this.search("");
this.document.getElementById("show-all").click();
}
/**
* Performs a new search using the dedicated textbox. This also makes sure
* that the list of preferences displayed is up to date.
*/
search(value = "") {
search(value) {
this.searchInput.value = value;
this.searchInput.focus();
EventUtils.sendKey("return");

Просмотреть файл

@ -10,8 +10,9 @@ about-config-warning-button = I accept the risk
about-config-title = about:config
about-config-search =
.placeholder = Search or press ESC to show all
about-config-search-input =
.placeholder = Search
about-config-show-all = Show All
about-config-pref-add = Add
about-config-pref-toggle = Toggle