Bug 977814 - Control the number of tiles displayed in each about:start compartment using prefs. r=sfoster

This commit is contained in:
Jim Mathies 2014-03-06 08:32:55 -06:00
parent 3c125ad52e
commit 674036ab16
10 changed files with 130 additions and 67 deletions

View File

@ -9,15 +9,17 @@
* fills it with the user's bookmarks.
*
* @param aSet Control implementing nsIDOMXULSelectControlElement.
* @param {Number} aLimit Maximum number of items to show in the view.
* @param aRoot Bookmark root to show in the view.
*/
function BookmarksView(aSet, aLimit, aRoot, aFilterUnpinned) {
function BookmarksView(aSet, aRoot, aFilterUnpinned) {
View.call(this, aSet);
this._inBatch = false; // batch up grid updates to avoid redundant arrangeItems calls
this._limit = aLimit;
// View monitors this for maximum tile display counts
this.tilePrefName = "browser.display.startUI.bookmarks.maxresults";
this.showing = this.maxTiles > 0;
this._filterUnpinned = aFilterUnpinned;
this._bookmarkService = PlacesUtils.bookmarks;
this._navHistoryService = gHistSvc;
@ -33,13 +35,17 @@ function BookmarksView(aSet, aLimit, aRoot, aFilterUnpinned) {
}
BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
_limit: null,
_set: null,
_changes: null,
_root: null,
_sort: 0, // Natural bookmark order.
_toRemove: null,
// For View's showing property
get vbox() {
return document.getElementById("start-bookmarks");
},
get sort() {
return this._sort;
},
@ -67,6 +73,11 @@ BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
View.prototype.destruct.call(this);
},
refreshView: function () {
this.clearBookmarks();
this.getBookmarks();
},
handleItemClick: function bv_handleItemClick(aItem) {
let url = aItem.getAttribute("value");
StartUI.goToURI(url);
@ -91,7 +102,7 @@ BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
options.excludeQueries = true; // Don't include "smart folders"
options.sortingMode = this._sort;
let limit = this._limit || Infinity;
let limit = this.maxTiles;
let query = this._navHistoryService.getNewQuery();
query.setFolders([Bookmarks.metroRoot], 1);
@ -305,7 +316,7 @@ let BookmarksStartView = {
get _grid() { return document.getElementById("start-bookmarks-grid"); },
init: function init() {
this._view = new BookmarksView(this._grid, StartUI.maxResultsPerSection, Bookmarks.metroRoot, true);
this._view = new BookmarksView(this._grid, Bookmarks.metroRoot, true);
this._view.getBookmarks();
this._grid.removeAttribute("fade");
},

View File

@ -4,12 +4,15 @@
'use strict';
function HistoryView(aSet, aLimit, aFilterUnpinned) {
function HistoryView(aSet, aFilterUnpinned) {
View.call(this, aSet);
this._inBatch = 0;
this._limit = aLimit;
// View monitors this for maximum tile display counts
this.tilePrefName = "browser.display.startUI.history.maxresults";
this.showing = this.maxTiles > 0;
this._filterUnpinned = aFilterUnpinned;
this._historyService = PlacesUtils.history;
this._navHistoryService = gHistSvc;
@ -25,6 +28,11 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
_set: null,
_toRemove: null,
// For View's showing property
get vbox() {
return document.getElementById("start-history");
},
destruct: function destruct() {
this._historyService.removeObserver(this);
if (StartUI.chromeWin) {
@ -34,6 +42,11 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
View.prototype.destruct.call(this);
},
refreshView: function () {
this.onClearHistory();
this.populateGrid();
},
handleItemClick: function tabview_handleItemClick(aItem) {
let url = aItem.getAttribute("value");
StartUI.goToURI(url);
@ -48,7 +61,7 @@ HistoryView.prototype = Util.extend(Object.create(View.prototype), {
options.resultType = options.RESULTS_AS_URI;
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
let limit = this._limit || Infinity;
let limit = this.maxTiles;
let result = this._navHistoryService.executeQuery(query, options);
let rootNode = result.root;
rootNode.containerOpen = true;
@ -297,7 +310,7 @@ let HistoryStartView = {
get _grid() { return document.getElementById("start-history-grid"); },
init: function init() {
this._view = new HistoryView(this._grid, StartUI.maxResultsPerSection, true);
this._view = new HistoryView(this._grid, true);
this._view.populateGrid();
this._grid.removeAttribute("fade");
},

View File

@ -9,10 +9,6 @@ Cu.import("resource://gre/modules/Services.jsm");
var StartUI = {
get startUI() { return document.getElementById("start-container"); },
get maxResultsPerSection() {
return Services.prefs.getIntPref("browser.display.startUI.maxresults");
},
get chromeWin() {
// XXX Not e10s friendly. We use this in a few places.
return Services.wm.getMostRecentWindow('navigator:browser');

View File

@ -4,15 +4,13 @@
"use strict"
let prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
Cu.import("resource://gre/modules/PageThumbs.jsm");
function TopSitesView(aGrid, aMaxSites) {
function TopSitesView(aGrid) {
View.call(this, aGrid);
this._topSitesMax = aMaxSites;
// View monitors this for maximum tile display counts
this.tilePrefName = "browser.display.startUI.topsites.maxresults";
this.showing = this.maxTiles > 0 && !this.isFirstRun();
// clean up state when the appbar closes
StartUI.chromeWin.addEventListener('MozAppbarDismissing', this, false);
@ -30,12 +28,16 @@ function TopSitesView(aGrid, aMaxSites) {
TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
_set:null,
_topSitesMax: null,
// _lastSelectedSites used to temporarily store blocked/removed sites for undo/restore-ing
_lastSelectedSites: null,
// isUpdating used only for testing currently
isUpdating: false,
// For View's showing property
get vbox() {
return document.getElementById("start-topsites");
},
destruct: function destruct() {
Services.obs.removeObserver(this, "Metro:RefreshTopsiteThumbnail");
NewTabUtils.allPages.unregister(this);
@ -190,12 +192,17 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
this.isUpdating = true;
let sites = TopSites.getSites();
if (this._topSitesMax) {
sites = sites.slice(0, this._topSitesMax);
}
let tileset = this._set;
tileset.clearAll(true);
if (!this.maxTiles) {
this.isUpdating = false;
return;
} else {
sites = sites.slice(0, this.maxTiles);
}
for (let site of sites) {
let slot = tileset.nextSlot();
this.updateTile(slot, site);
@ -214,7 +221,7 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
},
isFirstRun: function isFirstRun() {
return prefs.getBoolPref("browser.firstrun.show.localepicker");
return Services.prefs.getBoolPref("browser.firstrun.show.localepicker");
},
_adjustDOMforViewState: function _adjustDOMforViewState(aState) {
@ -243,6 +250,10 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
}
},
refreshView: function () {
this.populateGrid();
},
// nsIObservers
observe: function (aSubject, aTopic, aState) {
switch (aTopic) {
@ -250,6 +261,8 @@ TopSitesView.prototype = Util.extend(Object.create(View.prototype), {
this.forceReloadOfThumbnail(aState);
break;
}
View.prototype.observe.call(this, aSubject, aTopic, aState);
this.showing = this.maxTiles > 0 && !this.isFirstRun();
},
// nsINavHistoryObserver
@ -295,11 +308,7 @@ let TopSitesStartView = {
get _grid() { return document.getElementById("start-topsites-grid"); },
init: function init() {
this._view = new TopSitesView(this._grid, 8);
if (this._view.isFirstRun()) {
let topsitesVbox = document.getElementById("start-topsites");
topsitesVbox.setAttribute("hidden", "true");
}
this._view = new TopSitesView(this._grid);
this._grid.removeAttribute("fade");
},

View File

@ -56,7 +56,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(!gStartView._pinHelper.isPinned(2), "Item hidden");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
// --------- hide multiple items
@ -82,7 +82,7 @@ gTests.push({
ok(!item1 && !item2 && !item3, "Items are not in grid");
ok(!gStartView._pinHelper.isPinned(0) && !gStartView._pinHelper.isPinned(5) && !gStartView._pinHelper.isPinned(12) , "Items hidden");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
}
});
@ -114,7 +114,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(BookmarksTestHelper._nodes[2], "Item not deleted yet");
ok(!restoreButton.hidden, "Restore button is visible.");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
EventUtils.synthesizeMouse(restoreButton, 10, 10, {}, window);
@ -152,7 +152,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(!BookmarksTestHelper._nodes[2], "Item RIP");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
// --------- delete multiple items and restore
@ -184,7 +184,7 @@ gTests.push({
ok(BookmarksTestHelper._nodes[0] && BookmarksTestHelper._nodes[5] && BookmarksTestHelper._nodes[12],
"Items not deleted yet");
ok(!restoreButton.hidden, "Restore button is visible.");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
EventUtils.synthesizeMouse(restoreButton, 10, 10, {}, window);
@ -198,7 +198,7 @@ gTests.push({
ok(gStartView._set.getIndexOfItem(item1) === initialLocation1 &&
gStartView._set.getIndexOfItem(item2) === initialLocation2 &&
gStartView._set.getIndexOfItem(item3) === initialLocation3, "Items back in the same position.");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
// --------- delete multiple items for good
@ -240,6 +240,6 @@ gTests.push({
ok(!item1 && !item2 && !item3, "Items are not in grid");
ok(!BookmarksTestHelper._nodes[0] && !BookmarksTestHelper._nodes[5] && !BookmarksTestHelper._nodes[12],
"Items are gone");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
}
});

View File

@ -67,7 +67,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(!gStartView._pinHelper.isPinned(uriFromIndex(2)), "Item hidden");
is(gStartView._set.itemCount, gStartView._limit, "Grid repopulated");
is(gStartView._set.itemCount, gStartView.maxTiles, "Grid repopulated");
// --------- hide multiple items
@ -94,7 +94,7 @@ gTests.push({
ok(!item1 && !item2 && !item3, "Items are not in grid");
ok(!gStartView._pinHelper.isPinned(uriFromIndex(0)) && !gStartView._pinHelper.isPinned(uriFromIndex(5)) && !gStartView._pinHelper.isPinned(uriFromIndex(12)) , "Items hidden");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
}
});
@ -126,7 +126,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(HistoryTestHelper._nodes[uriFromIndex(2)], "Item not actually deleted yet");
ok(!restoreButton.hidden, "Restore button is visible.");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
EventUtils.synthesizeMouse(restoreButton, 10, 10, {}, window);
@ -135,7 +135,7 @@ gTests.push({
item = gStartView._set.getItemsByUrl(uriFromIndex(2))[0];
ok(item, "Item back in grid");
ok(gStartView._set.getIndexOfItem(item) === initialLocation, "Back in same position.");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
// --------- delete item 2 for realz
@ -174,7 +174,7 @@ gTests.push({
ok(!item, "Item not in grid");
ok(!HistoryTestHelper._nodes[uriFromIndex(2)], "Item RIP");
is(gStartView._set.itemCount, gStartView._limit, "Grid repopulated");
is(gStartView._set.itemCount, gStartView.maxTiles, "Grid repopulated");
// --------- delete multiple items and restore
@ -209,7 +209,7 @@ gTests.push({
ok(HistoryTestHelper._nodes[uriFromIndex(0)] && HistoryTestHelper._nodes[uriFromIndex(5)] && HistoryTestHelper._nodes[uriFromIndex(12)],
"Items not deleted yet");
ok(!restoreButton.hidden, "Restore button is visible.");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
EventUtils.synthesizeMouse(restoreButton, 10, 10, {}, window);
@ -223,7 +223,7 @@ gTests.push({
ok(gStartView._set.getIndexOfItem(item1) === initialLocation1 &&
gStartView._set.getIndexOfItem(item2) === initialLocation2 &&
gStartView._set.getIndexOfItem(item3) === initialLocation3, "Items back in the same position.");
ok(gStartView._set.itemCount === gStartView._limit, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles, "Grid repopulated");
// --------- delete multiple items for good
@ -254,7 +254,7 @@ gTests.push({
ok(HistoryTestHelper._nodes[uriFromIndex(0)] && HistoryTestHelper._nodes[uriFromIndex(5)] && HistoryTestHelper._nodes[uriFromIndex(12)],
"Items not deleted yet");
ok(!restoreButton.hidden, "Restore button is visible.");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
let promise = waitForEvent(Elements.contextappbar, "transitionend", null, Elements.contextappbar);
Elements.contextappbar.dismiss();
@ -267,6 +267,6 @@ gTests.push({
ok(!item1 && !item2 && !item3, "Items are not in grid");
ok(!HistoryTestHelper._nodes[uriFromIndex(0)] && !HistoryTestHelper._nodes[uriFromIndex(5)] && !HistoryTestHelper._nodes[uriFromIndex(12)],
"Items are gone");
ok(gStartView._set.itemCount === gStartView._limit - 1, "Grid repopulated");
ok(gStartView._set.itemCount === gStartView.maxTiles - 1, "Grid repopulated");
}
});

View File

@ -71,7 +71,7 @@ var BookmarksTestHelper = {
// Just enough items so that there will be one less then the limit
// after removing 4 items.
this.createNodes(this._startView._limit + 3);
this.createNodes(this._startView.maxTiles + 3);
this._originalNavHistoryService = this._startView._navHistoryService;
this._startView._navHistoryService = this.MockNavHistoryService;

View File

@ -68,7 +68,7 @@ var HistoryTestHelper = {
// Just enough items so that there will be one less then the limit
// after removing 4 items.
this.createNodes(this._startView._limit + 3);
this.createNodes(this._startView.maxTiles + 3);
this._originalNavHistoryService = this._startView._navHistoryService;
this._startView._navHistoryService = this.MockNavHistoryService;

View File

@ -28,6 +28,8 @@ function View(aSet) {
this._set = aSet;
this._set.controller = this;
this._window = aSet.ownerDocument.defaultView;
this._maxTiles = 8;
this._tilePrefName = "unknown";
this.onResize = () => this._adjustDOMforViewState();
this._window.addEventListener("resize", this.onResize);
@ -37,8 +39,31 @@ function View(aSet) {
}
View.prototype = {
set maxTiles(aVal) {
this._maxTiles = aVal;
},
get maxTiles() {
return this._maxTiles;
},
set showing(aFlag) {
// 'vbox' must be defined on objects that inherit from us
this.vbox.setAttribute("hidden", aFlag ? "false" : "true");
},
set tilePrefName(aStr) {
// Should be called once on init by objects that inherit from us
this._tilePrefName = aStr;
this._maxTiles = Services.prefs.getIntPref(this._tilePrefName);
Services.prefs.addObserver(this._tilePrefName, this, false);
},
destruct: function () {
this._window.removeEventListener("resize", this.onResize);
if (this._tilePrefName != "unknown") {
Services.prefs.removeObserver(this._tilePrefName, this);
}
},
_adjustDOMforViewState: function _adjustDOMforViewState(aState) {
@ -111,6 +136,22 @@ View.prototype = {
aItem.color = background;
}
});
}
},
refreshView: function () {
},
observe: function (aSubject, aTopic, aState) {
switch (aTopic) {
case "nsPref:changed": {
if (aState == this._tilePrefName) {
let count = Services.prefs.getIntPref(this._tilePrefName);
this.maxTiles = count;
this.showing = this.maxTiles > 0;
this.refreshView();
}
break;
}
}
}
};

View File

@ -112,28 +112,28 @@ pref("toolkit.zoomManager.zoomValues", "1");
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
pref("browser.viewport.scaleRatio", -1);
/* use long press to display a context menu */
// use long press to display a context menu
pref("ui.click_hold_context_menus", false);
/* offline cache prefs */
// offline cache prefs
pref("browser.offline-apps.notify", true);
/* protocol warning prefs */
// protocol warning prefs
pref("network.protocol-handler.warn-external.tel", false);
pref("network.protocol-handler.warn-external.mailto", false);
pref("network.protocol-handler.warn-external.vnd.youtube", false);
pref("network.protocol-handler.warn-external.ms-windows-store", false);
pref("network.protocol-handler.external.ms-windows-store", true);
/* startui prefs */
// display the overlay nav buttons
pref("browser.display.overlaynavbuttons", true);
/* history max results display */
pref("browser.display.history.maxresults", 100);
/* max items per section of the startui */
pref("browser.display.startUI.maxresults", 16);
// max number of top site tiles to display in the startui
pref("browser.display.startUI.topsites.maxresults", 8);
// max items for the bookmarks compartment in the startui
pref("browser.display.startUI.bookmarks.maxresults", 16);
// max items for the history compartment in the startui
pref("browser.display.startUI.history.maxresults", 16);
// Number of times to display firstrun instructions on new tab page
pref("browser.firstrun.count", 3);
// Has the content first run been dismissed
@ -145,7 +145,7 @@ pref("browser.firstrun-content.dismissed", false);
// 2 and other values, nothing
pref("browser.backspace_action", 0);
/* session history */
// session history
pref("browser.sessionhistory.max_entries", 50);
// On startup, don't automatically restore tabs
@ -641,13 +641,6 @@ pref("browser.safebrowsing.malware.reportURL", "https://safebrowsing.google.com/
pref("browser.firstrun.show.localepicker", false);
// True if you always want dump() to work
//
// On Android, you also need to do the following for the output
// to show up in logcat:
//
// $ adb shell stop
// $ adb shell setprop log.redirect-stdio true
// $ adb shell start
pref("javascript.options.showInConsole", true);
pref("browser.dom.window.dump.enabled", true);