mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 851130 - Part 1 - Code reshuffle to move StartUI to a tab. r=sfoster
This commit is contained in:
parent
75bff57542
commit
1c1df0b142
@ -3,10 +3,6 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
'use strict';
|
'use strict';
|
||||||
let prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
|
||||||
getService(Components.interfaces.nsIPrefBranch);
|
|
||||||
Cu.import("resource://gre/modules/PageThumbs.jsm");
|
|
||||||
Cu.import("resource:///modules/colorUtils.jsm");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* singleton to provide data-level functionality to the views
|
* singleton to provide data-level functionality to the views
|
||||||
@ -163,290 +159,3 @@ let TopSites = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function TopSitesView(aGrid, aMaxSites) {
|
|
||||||
this._set = aGrid;
|
|
||||||
this._set.controller = this;
|
|
||||||
this._topSitesMax = aMaxSites;
|
|
||||||
|
|
||||||
// clean up state when the appbar closes
|
|
||||||
window.addEventListener('MozAppbarDismissing', this, false);
|
|
||||||
let history = Cc["@mozilla.org/browser/nav-history-service;1"].
|
|
||||||
getService(Ci.nsINavHistoryService);
|
|
||||||
history.addObserver(this, false);
|
|
||||||
|
|
||||||
PageThumbs.addExpirationFilter(this);
|
|
||||||
Services.obs.addObserver(this, "Metro:RefreshTopsiteThumbnail", false);
|
|
||||||
Services.obs.addObserver(this, "metro_viewstate_changed", false);
|
|
||||||
|
|
||||||
NewTabUtils.allPages.register(this);
|
|
||||||
TopSites.prepareCache().then(function(){
|
|
||||||
this.populateGrid();
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
|
|
||||||
handleItemClick: function tabview_handleItemClick(aItem) {
|
|
||||||
let url = aItem.getAttribute("value");
|
|
||||||
BrowserUI.goToURI(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
doActionOnSelectedTiles: function(aActionName, aEvent) {
|
|
||||||
let tileGroup = this._set;
|
|
||||||
let selectedTiles = tileGroup.selectedItems;
|
|
||||||
let sites = Array.map(selectedTiles, TopSites._linkFromNode);
|
|
||||||
let nextContextActions = new Set();
|
|
||||||
|
|
||||||
switch (aActionName){
|
|
||||||
case "delete":
|
|
||||||
for (let aNode of selectedTiles) {
|
|
||||||
// add some class to transition element before deletion?
|
|
||||||
aNode.contextActions.delete('delete');
|
|
||||||
// we need new context buttons to show (the tile node will go away though)
|
|
||||||
}
|
|
||||||
this._lastSelectedSites = (this._lastSelectedSites || []).concat(sites);
|
|
||||||
// stop the appbar from dismissing
|
|
||||||
aEvent.preventDefault();
|
|
||||||
nextContextActions.add('restore');
|
|
||||||
TopSites.hideSites(sites);
|
|
||||||
break;
|
|
||||||
case "restore":
|
|
||||||
// usually restore is an undo action, so we have to recreate the tiles and grid selection
|
|
||||||
if (this._lastSelectedSites) {
|
|
||||||
let selectedUrls = this._lastSelectedSites.map((site) => site.url);
|
|
||||||
// re-select the tiles once the tileGroup is done populating and arranging
|
|
||||||
tileGroup.addEventListener("arranged", function _onArranged(aEvent){
|
|
||||||
for (let url of selectedUrls) {
|
|
||||||
let tileNode = tileGroup.querySelector("richgriditem[value='"+url+"']");
|
|
||||||
if (tileNode) {
|
|
||||||
tileNode.setAttribute("selected", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tileGroup.removeEventListener("arranged", _onArranged, false);
|
|
||||||
// <sfoster> we can't just call selectItem n times on tileGroup as selecting means trigger the default action
|
|
||||||
// for seltype="single" grids.
|
|
||||||
// so we toggle the attributes and raise the selectionchange "manually"
|
|
||||||
let event = tileGroup.ownerDocument.createEvent("Events");
|
|
||||||
event.initEvent("selectionchange", true, true);
|
|
||||||
tileGroup.dispatchEvent(event);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
TopSites.restoreSites(this._lastSelectedSites);
|
|
||||||
// stop the appbar from dismissing,
|
|
||||||
// the selectionchange event will trigger re-population of the context appbar
|
|
||||||
aEvent.preventDefault();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "pin":
|
|
||||||
let pinIndices = [];
|
|
||||||
Array.forEach(selectedTiles, function(aNode) {
|
|
||||||
pinIndices.push( Array.indexOf(aNode.control.children, aNode) );
|
|
||||||
aNode.contextActions.delete('pin');
|
|
||||||
aNode.contextActions.add('unpin');
|
|
||||||
});
|
|
||||||
TopSites.pinSites(sites, pinIndices);
|
|
||||||
break;
|
|
||||||
case "unpin":
|
|
||||||
Array.forEach(selectedTiles, function(aNode) {
|
|
||||||
aNode.contextActions.delete('unpin');
|
|
||||||
aNode.contextActions.add('pin');
|
|
||||||
});
|
|
||||||
TopSites.unpinSites(sites);
|
|
||||||
break;
|
|
||||||
// default: no action
|
|
||||||
}
|
|
||||||
if (nextContextActions.size) {
|
|
||||||
// at next tick, re-populate the context appbar
|
|
||||||
setTimeout(function(){
|
|
||||||
// fire a MozContextActionsChange event to update the context appbar
|
|
||||||
let event = document.createEvent("Events");
|
|
||||||
event.actions = [...nextContextActions];
|
|
||||||
event.initEvent("MozContextActionsChange", true, false);
|
|
||||||
tileGroup.dispatchEvent(event);
|
|
||||||
},0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function(aEvent) {
|
|
||||||
switch (aEvent.type){
|
|
||||||
case "MozAppbarDismissing":
|
|
||||||
// clean up when the context appbar is dismissed - we don't remember selections
|
|
||||||
this._lastSelectedSites = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
update: function() {
|
|
||||||
// called by the NewTabUtils.allPages.update, notifying us of data-change in topsites
|
|
||||||
let grid = this._set,
|
|
||||||
dirtySites = TopSites.dirty();
|
|
||||||
|
|
||||||
if (dirtySites.size) {
|
|
||||||
// we can just do a partial update and refresh the node representing each dirty tile
|
|
||||||
for (let site of dirtySites) {
|
|
||||||
let tileNode = grid.querySelector("[value='"+site.url+"']");
|
|
||||||
if (tileNode) {
|
|
||||||
this.updateTile(tileNode, new Site(site));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// flush, recreate all
|
|
||||||
this.isUpdating = true;
|
|
||||||
// destroy and recreate all item nodes, skip calling arrangeItems
|
|
||||||
grid.clearAll(true);
|
|
||||||
this.populateGrid();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateTile: function(aTileNode, aSite, aArrangeGrid) {
|
|
||||||
this._updateFavicon(aTileNode, Util.makeURI(aSite.url));
|
|
||||||
|
|
||||||
Task.spawn(function() {
|
|
||||||
let filepath = PageThumbsStorage.getFilePathForURL(aSite.url);
|
|
||||||
if (yield OS.File.exists(filepath)) {
|
|
||||||
aSite.backgroundImage = 'url("'+PageThumbs.getThumbnailURL(aSite.url)+'")';
|
|
||||||
aTileNode.setAttribute("customImage", aSite.backgroundImage);
|
|
||||||
if (aTileNode.refresh) {
|
|
||||||
aTileNode.refresh()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
aSite.applyToTileNode(aTileNode);
|
|
||||||
if (aArrangeGrid) {
|
|
||||||
this._set.arrangeItems();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
populateGrid: function populateGrid() {
|
|
||||||
this.isUpdating = true;
|
|
||||||
|
|
||||||
let sites = TopSites.getSites();
|
|
||||||
let length = Math.min(sites.length, this._topSitesMax || Infinity);
|
|
||||||
let tileset = this._set;
|
|
||||||
|
|
||||||
// if we're updating with a collection that is smaller than previous
|
|
||||||
// remove any extra tiles
|
|
||||||
while (tileset.children.length > length) {
|
|
||||||
tileset.removeChild(tileset.children[tileset.children.length -1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let idx=0; idx < length; idx++) {
|
|
||||||
let isNew = !tileset.children[idx],
|
|
||||||
site = sites[idx];
|
|
||||||
let item = isNew ? tileset.createItemElement(site.title, site.url) : tileset.children[idx];
|
|
||||||
|
|
||||||
this.updateTile(item, site);
|
|
||||||
if (isNew) {
|
|
||||||
tileset.appendChild(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tileset.arrangeItems();
|
|
||||||
this.isUpdating = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
forceReloadOfThumbnail: function forceReloadOfThumbnail(url) {
|
|
||||||
let nodes = this._set.querySelectorAll('richgriditem[value="'+url+'"]');
|
|
||||||
for (let item of nodes) {
|
|
||||||
if ("isBound" in item && item.isBound) {
|
|
||||||
item.refreshBackgroundImage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
filterForThumbnailExpiration: function filterForThumbnailExpiration(aCallback) {
|
|
||||||
aCallback([item.getAttribute("value") for (item of this._set.children)]);
|
|
||||||
},
|
|
||||||
|
|
||||||
isFirstRun: function isFirstRun() {
|
|
||||||
return prefs.getBoolPref("browser.firstrun.show.localepicker");
|
|
||||||
},
|
|
||||||
|
|
||||||
destruct: function destruct() {
|
|
||||||
Services.obs.removeObserver(this, "Metro:RefreshTopsiteThumbnail");
|
|
||||||
Services.obs.removeObserver(this, "metro_viewstate_changed");
|
|
||||||
PageThumbs.removeExpirationFilter(this);
|
|
||||||
window.removeEventListener('MozAppbarDismissing', this, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIObservers
|
|
||||||
observe: function (aSubject, aTopic, aState) {
|
|
||||||
switch(aTopic) {
|
|
||||||
case "Metro:RefreshTopsiteThumbnail":
|
|
||||||
this.forceReloadOfThumbnail(aState);
|
|
||||||
break;
|
|
||||||
case "metro_viewstate_changed":
|
|
||||||
this.onViewStateChange(aState);
|
|
||||||
for (let item of this._set.children) {
|
|
||||||
if (aState == "snapped") {
|
|
||||||
item.removeAttribute("tiletype");
|
|
||||||
} else {
|
|
||||||
item.setAttribute("tiletype", "thumbnail");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsINavHistoryObserver
|
|
||||||
onBeginUpdateBatch: function() {
|
|
||||||
},
|
|
||||||
|
|
||||||
onEndUpdateBatch: function() {
|
|
||||||
},
|
|
||||||
|
|
||||||
onVisit: function(aURI, aVisitID, aTime, aSessionID,
|
|
||||||
aReferringID, aTransitionType) {
|
|
||||||
},
|
|
||||||
|
|
||||||
onTitleChanged: function(aURI, aPageTitle) {
|
|
||||||
},
|
|
||||||
|
|
||||||
onDeleteURI: function(aURI) {
|
|
||||||
},
|
|
||||||
|
|
||||||
onClearHistory: function() {
|
|
||||||
this._set.clearAll();
|
|
||||||
},
|
|
||||||
|
|
||||||
onPageChanged: function(aURI, aWhat, aValue) {
|
|
||||||
},
|
|
||||||
|
|
||||||
onDeleteVisits: function (aURI, aVisitTime, aGUID, aReason, aTransitionType) {
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: function(iid) {
|
|
||||||
if (iid.equals(Components.interfaces.nsINavHistoryObserver) ||
|
|
||||||
iid.equals(Components.interfaces.nsISupports)) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
let TopSitesStartView = {
|
|
||||||
_view: null,
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function uninit() {
|
|
||||||
this._view.destruct();
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function show() {
|
|
||||||
this._grid.arrangeItems();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -65,372 +65,3 @@ var Bookmarks = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps a list/grid control implementing nsIDOMXULSelectControlElement and
|
|
||||||
* 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) {
|
|
||||||
this._set = aSet;
|
|
||||||
this._set.controller = this;
|
|
||||||
this._inBatch = false; // batch up grid updates to avoid redundant arrangeItems calls
|
|
||||||
|
|
||||||
this._limit = aLimit;
|
|
||||||
this._filterUnpinned = aFilterUnpinned;
|
|
||||||
this._bookmarkService = PlacesUtils.bookmarks;
|
|
||||||
this._navHistoryService = gHistSvc;
|
|
||||||
|
|
||||||
this._changes = new BookmarkChangeListener(this);
|
|
||||||
this._pinHelper = new ItemPinHelper("metro.bookmarks.unpinned");
|
|
||||||
this._bookmarkService.addObserver(this._changes, false);
|
|
||||||
Services.obs.addObserver(this, "metro_viewstate_changed", false);
|
|
||||||
window.addEventListener('MozAppbarDismissing', this, false);
|
|
||||||
window.addEventListener('BookmarksNeedsRefresh', this, false);
|
|
||||||
|
|
||||||
this.root = aRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
|
|
||||||
_limit: null,
|
|
||||||
_set: null,
|
|
||||||
_changes: null,
|
|
||||||
_root: null,
|
|
||||||
_sort: 0, // Natural bookmark order.
|
|
||||||
_toRemove: null,
|
|
||||||
|
|
||||||
get sort() {
|
|
||||||
return this._sort;
|
|
||||||
},
|
|
||||||
|
|
||||||
set sort(aSort) {
|
|
||||||
this._sort = aSort;
|
|
||||||
this.clearBookmarks();
|
|
||||||
this.getBookmarks();
|
|
||||||
},
|
|
||||||
|
|
||||||
get root() {
|
|
||||||
return this._root;
|
|
||||||
},
|
|
||||||
|
|
||||||
set root(aRoot) {
|
|
||||||
this._root = aRoot;
|
|
||||||
},
|
|
||||||
|
|
||||||
handleItemClick: function bv_handleItemClick(aItem) {
|
|
||||||
let url = aItem.getAttribute("value");
|
|
||||||
BrowserUI.goToURI(url);
|
|
||||||
},
|
|
||||||
|
|
||||||
_getItemForBookmarkId: function bv__getItemForBookmark(aBookmarkId) {
|
|
||||||
return this._set.querySelector("richgriditem[bookmarkId='" + aBookmarkId + "']");
|
|
||||||
},
|
|
||||||
|
|
||||||
_getBookmarkIdForItem: function bv__getBookmarkForItem(aItem) {
|
|
||||||
return +aItem.getAttribute("bookmarkId");
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateItemWithAttrs: function dv__updateItemWithAttrs(anItem, aAttrs) {
|
|
||||||
for (let name in aAttrs)
|
|
||||||
anItem.setAttribute(name, aAttrs[name]);
|
|
||||||
},
|
|
||||||
|
|
||||||
getBookmarks: function bv_getBookmarks(aRefresh) {
|
|
||||||
let options = this._navHistoryService.getNewQueryOptions();
|
|
||||||
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
|
||||||
options.excludeQueries = true; // Don't include "smart folders"
|
|
||||||
options.sortingMode = this._sort;
|
|
||||||
|
|
||||||
let limit = this._limit || Infinity;
|
|
||||||
|
|
||||||
let query = this._navHistoryService.getNewQuery();
|
|
||||||
query.setFolders([Bookmarks.metroRoot], 1);
|
|
||||||
|
|
||||||
let result = this._navHistoryService.executeQuery(query, options);
|
|
||||||
let rootNode = result.root;
|
|
||||||
rootNode.containerOpen = true;
|
|
||||||
let childCount = rootNode.childCount;
|
|
||||||
|
|
||||||
this._inBatch = true; // batch up grid updates to avoid redundant arrangeItems calls
|
|
||||||
|
|
||||||
for (let i = 0, addedCount = 0; i < childCount && addedCount < limit; i++) {
|
|
||||||
let node = rootNode.getChild(i);
|
|
||||||
|
|
||||||
// Ignore folders, separators, undefined item types, etc.
|
|
||||||
if (node.type != node.RESULT_TYPE_URI)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If item is marked for deletion, skip it.
|
|
||||||
if (this._toRemove && this._toRemove.indexOf(node.itemId) !== -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let item = this._getItemForBookmarkId(node.itemId);
|
|
||||||
|
|
||||||
// Item has been unpinned.
|
|
||||||
if (this._filterUnpinned && !this._pinHelper.isPinned(node.itemId)) {
|
|
||||||
if (item)
|
|
||||||
this.removeBookmark(node.itemId);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aRefresh || !item) {
|
|
||||||
// If we're not refreshing or the item is not in the grid, add it.
|
|
||||||
this.addBookmark(node.itemId, addedCount);
|
|
||||||
} else if (aRefresh && item) {
|
|
||||||
// Update context action in case it changed in another view.
|
|
||||||
this._setContextActions(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
addedCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove extra items in case a refresh added more than the limit.
|
|
||||||
// This can happen when undoing a delete.
|
|
||||||
if (aRefresh) {
|
|
||||||
while (this._set.itemCount > limit)
|
|
||||||
this._set.removeItemAt(this._set.itemCount - 1, true);
|
|
||||||
}
|
|
||||||
this._set.arrangeItems();
|
|
||||||
this._inBatch = false;
|
|
||||||
rootNode.containerOpen = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
inCurrentView: function bv_inCurrentView(aParentId, aItemId) {
|
|
||||||
if (this._root && aParentId != this._root)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !!this._getItemForBookmarkId(aItemId);
|
|
||||||
},
|
|
||||||
|
|
||||||
clearBookmarks: function bv_clearBookmarks() {
|
|
||||||
this._set.clearAll();
|
|
||||||
},
|
|
||||||
|
|
||||||
addBookmark: function bv_addBookmark(aBookmarkId, aPos) {
|
|
||||||
let index = this._bookmarkService.getItemIndex(aBookmarkId);
|
|
||||||
let uri = this._bookmarkService.getBookmarkURI(aBookmarkId);
|
|
||||||
let title = this._bookmarkService.getItemTitle(aBookmarkId) || uri.spec;
|
|
||||||
let item = this._set.insertItemAt(aPos || index, title, uri.spec, this._inBatch);
|
|
||||||
item.setAttribute("bookmarkId", aBookmarkId);
|
|
||||||
this._setContextActions(item);
|
|
||||||
this._updateFavicon(item, uri);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setContextActions: function bv__setContextActions(aItem) {
|
|
||||||
let itemId = this._getBookmarkIdForItem(aItem);
|
|
||||||
aItem.setAttribute("data-contextactions", "delete," + (this._pinHelper.isPinned(itemId) ? "unpin" : "pin"));
|
|
||||||
if (aItem.refresh) aItem.refresh();
|
|
||||||
},
|
|
||||||
|
|
||||||
_sendNeedsRefresh: function bv__sendNeedsRefresh(){
|
|
||||||
// Event sent when all view instances need to refresh.
|
|
||||||
let event = document.createEvent("Events");
|
|
||||||
event.initEvent("BookmarksNeedsRefresh", true, false);
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
updateBookmark: function bv_updateBookmark(aBookmarkId) {
|
|
||||||
let item = this._getItemForBookmarkId(aBookmarkId);
|
|
||||||
|
|
||||||
if (!item)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let oldIndex = this._set.getIndexOfItem(item);
|
|
||||||
let index = this._bookmarkService.getItemIndex(aBookmarkId);
|
|
||||||
|
|
||||||
if (oldIndex != index) {
|
|
||||||
this.removeBookmark(aBookmarkId);
|
|
||||||
this.addBookmark(aBookmarkId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uri = this._bookmarkService.getBookmarkURI(aBookmarkId);
|
|
||||||
let title = this._bookmarkService.getItemTitle(aBookmarkId) || uri.spec;
|
|
||||||
|
|
||||||
item.setAttribute("value", uri.spec);
|
|
||||||
item.setAttribute("label", title);
|
|
||||||
|
|
||||||
this._updateFavicon(item, uri);
|
|
||||||
},
|
|
||||||
|
|
||||||
removeBookmark: function bv_removeBookmark(aBookmarkId) {
|
|
||||||
let item = this._getItemForBookmarkId(aBookmarkId);
|
|
||||||
let index = this._set.getIndexOfItem(item);
|
|
||||||
this._set.removeItemAt(index, this._inBatch);
|
|
||||||
},
|
|
||||||
|
|
||||||
destruct: function bv_destruct() {
|
|
||||||
this._bookmarkService.removeObserver(this._changes);
|
|
||||||
Services.obs.removeObserver(this, "metro_viewstate_changed");
|
|
||||||
window.removeEventListener('MozAppbarDismissing', this, false);
|
|
||||||
window.removeEventListener('BookmarksNeedsRefresh', this, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
doActionOnSelectedTiles: function bv_doActionOnSelectedTiles(aActionName, aEvent) {
|
|
||||||
let tileGroup = this._set;
|
|
||||||
let selectedTiles = tileGroup.selectedItems;
|
|
||||||
|
|
||||||
switch (aActionName){
|
|
||||||
case "delete":
|
|
||||||
Array.forEach(selectedTiles, function(aNode) {
|
|
||||||
if (!this._toRemove) {
|
|
||||||
this._toRemove = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
let itemId = this._getBookmarkIdForItem(aNode);
|
|
||||||
|
|
||||||
this._toRemove.push(itemId);
|
|
||||||
this.removeBookmark(itemId);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
// stop the appbar from dismissing
|
|
||||||
aEvent.preventDefault();
|
|
||||||
|
|
||||||
// at next tick, re-populate the context appbar.
|
|
||||||
setTimeout(function(){
|
|
||||||
// fire a MozContextActionsChange event to update the context appbar
|
|
||||||
let event = document.createEvent("Events");
|
|
||||||
// we need the restore button to show (the tile node will go away though)
|
|
||||||
event.actions = ["restore"];
|
|
||||||
event.initEvent("MozContextActionsChange", true, false);
|
|
||||||
tileGroup.dispatchEvent(event);
|
|
||||||
}, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "restore":
|
|
||||||
// clear toRemove and let _sendNeedsRefresh update the items.
|
|
||||||
this._toRemove = null;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "unpin":
|
|
||||||
Array.forEach(selectedTiles, function(aNode) {
|
|
||||||
let itemId = this._getBookmarkIdForItem(aNode);
|
|
||||||
|
|
||||||
if (this._filterUnpinned)
|
|
||||||
this.removeBookmark(itemId);
|
|
||||||
|
|
||||||
this._pinHelper.setUnpinned(itemId);
|
|
||||||
}, this);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "pin":
|
|
||||||
Array.forEach(selectedTiles, function(aNode) {
|
|
||||||
let itemId = this._getBookmarkIdForItem(aNode);
|
|
||||||
|
|
||||||
this._pinHelper.setPinned(itemId);
|
|
||||||
}, this);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send refresh event so all view are in sync.
|
|
||||||
this._sendNeedsRefresh();
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIObservers
|
|
||||||
observe: function (aSubject, aTopic, aState) {
|
|
||||||
switch(aTopic) {
|
|
||||||
case "metro_viewstate_changed":
|
|
||||||
this.onViewStateChange(aState);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function bv_handleEvent(aEvent) {
|
|
||||||
switch (aEvent.type){
|
|
||||||
case "MozAppbarDismissing":
|
|
||||||
// If undo wasn't pressed, time to do definitive actions.
|
|
||||||
if (this._toRemove) {
|
|
||||||
for (let bookmarkId of this._toRemove) {
|
|
||||||
this._bookmarkService.removeItem(bookmarkId);
|
|
||||||
}
|
|
||||||
this._toRemove = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "BookmarksNeedsRefresh":
|
|
||||||
this.getBookmarks(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var BookmarksStartView = {
|
|
||||||
_view: null,
|
|
||||||
get _grid() { return document.getElementById("start-bookmarks-grid"); },
|
|
||||||
|
|
||||||
init: function init() {
|
|
||||||
this._view = new BookmarksView(this._grid, StartUI.maxResultsPerSection, Bookmarks.metroRoot, true);
|
|
||||||
this._view.getBookmarks();
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function uninit() {
|
|
||||||
this._view.destruct();
|
|
||||||
},
|
|
||||||
|
|
||||||
show: function show() {
|
|
||||||
this._grid.arrangeItems();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Observes bookmark changes and keeps a linked BookmarksView updated.
|
|
||||||
*
|
|
||||||
* @param aView An instance of BookmarksView.
|
|
||||||
*/
|
|
||||||
function BookmarkChangeListener(aView) {
|
|
||||||
this._view = aView;
|
|
||||||
}
|
|
||||||
|
|
||||||
BookmarkChangeListener.prototype = {
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//// nsINavBookmarkObserver
|
|
||||||
onBeginUpdateBatch: function () { },
|
|
||||||
onEndUpdateBatch: function () { },
|
|
||||||
|
|
||||||
onItemAdded: function bCL_onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle, aDateAdded, aGUID, aParentGUID) {
|
|
||||||
this._view.getBookmarks(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemChanged: function bCL_onItemChanged(aItemId, aProperty, aIsAnnotationProperty, aNewValue, aLastModified, aItemType, aParentId, aGUID, aParentGUID) {
|
|
||||||
let itemIndex = PlacesUtils.bookmarks.getItemIndex(aItemId);
|
|
||||||
if (!this._view.inCurrentView(aParentId, aItemId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._view.updateBookmark(aItemId);
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemMoved: function bCL_onItemMoved(aItemId, aOldParentId, aOldIndex, aNewParentId, aNewIndex, aItemType, aGUID, aOldParentGUID, aNewParentGUID) {
|
|
||||||
let wasInView = this._view.inCurrentView(aOldParentId, aItemId);
|
|
||||||
let nowInView = this._view.inCurrentView(aNewParentId, aItemId);
|
|
||||||
|
|
||||||
if (!wasInView && nowInView)
|
|
||||||
this._view.addBookmark(aItemId);
|
|
||||||
|
|
||||||
if (wasInView && !nowInView)
|
|
||||||
this._view.removeBookmark(aItemId);
|
|
||||||
|
|
||||||
this._view.getBookmarks(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onBeforeItemRemoved: function (aItemId, aItemType, aParentId, aGUID, aParentGUID) { },
|
|
||||||
onItemRemoved: function bCL_onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGUID, aParentGUID) {
|
|
||||||
if (!this._view.inCurrentView(aParentId, aItemId))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this._view.removeBookmark(aItemId);
|
|
||||||
this._view.getBookmarks(true);
|
|
||||||
},
|
|
||||||
|
|
||||||
onItemVisited: function(aItemId, aVisitId, aTime, aTransitionType, aURI, aParentId, aGUID, aParentGUID) { },
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//// nsISupports
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
|
|
||||||
};
|
|
||||||
|
@ -34,13 +34,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
|||||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||||
"resource://gre/modules/Task.jsm");
|
"resource://gre/modules/Task.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "CrossSlide",
|
|
||||||
"resource:///modules/CrossSlide.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||||
"resource://gre/modules/osfile.jsm");
|
"resource://gre/modules/osfile.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "View",
|
|
||||||
"resource:///modules/View.jsm");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Services
|
* Services
|
||||||
@ -123,13 +118,8 @@ let ScriptContexts = {};
|
|||||||
["Bookmarks", "chrome://browser/content/bookmarks.js"],
|
["Bookmarks", "chrome://browser/content/bookmarks.js"],
|
||||||
["Downloads", "chrome://browser/content/downloads.js"],
|
["Downloads", "chrome://browser/content/downloads.js"],
|
||||||
["ConsolePanelView", "chrome://browser/content/console.js"],
|
["ConsolePanelView", "chrome://browser/content/console.js"],
|
||||||
["BookmarksStartView", "chrome://browser/content/bookmarks.js"],
|
|
||||||
["HistoryView", "chrome://browser/content/history.js"],
|
|
||||||
["HistoryStartView", "chrome://browser/content/history.js"],
|
|
||||||
["Site", "chrome://browser/content/Site.js"],
|
["Site", "chrome://browser/content/Site.js"],
|
||||||
["TopSites", "chrome://browser/content/TopSites.js"],
|
["TopSites", "chrome://browser/content/TopSites.js"],
|
||||||
["TopSitesView", "chrome://browser/content/TopSites.js"],
|
|
||||||
["TopSitesStartView", "chrome://browser/content/TopSites.js"],
|
|
||||||
["Sanitizer", "chrome://browser/content/sanitize.js"],
|
["Sanitizer", "chrome://browser/content/sanitize.js"],
|
||||||
["SanitizeUI", "chrome://browser/content/sanitizeUI.js"],
|
["SanitizeUI", "chrome://browser/content/sanitizeUI.js"],
|
||||||
["SSLExceptions", "chrome://browser/content/exceptions.js"],
|
["SSLExceptions", "chrome://browser/content/exceptions.js"],
|
||||||
@ -137,10 +127,6 @@ let ScriptContexts = {};
|
|||||||
["NavButtonSlider", "chrome://browser/content/NavButtonSlider.js"],
|
["NavButtonSlider", "chrome://browser/content/NavButtonSlider.js"],
|
||||||
["ContextUI", "chrome://browser/content/ContextUI.js"],
|
["ContextUI", "chrome://browser/content/ContextUI.js"],
|
||||||
["FlyoutPanelsUI", "chrome://browser/content/flyoutpanels/FlyoutPanelsUI.js"],
|
["FlyoutPanelsUI", "chrome://browser/content/flyoutpanels/FlyoutPanelsUI.js"],
|
||||||
#ifdef MOZ_SERVICES_SYNC
|
|
||||||
["RemoteTabsView", "chrome://browser/content/RemoteTabs.js"],
|
|
||||||
["RemoteTabsStartView", "chrome://browser/content/RemoteTabs.js"],
|
|
||||||
#endif
|
|
||||||
].forEach(function (aScript) {
|
].forEach(function (aScript) {
|
||||||
let [name, script] = aScript;
|
let [name, script] = aScript;
|
||||||
XPCOMUtils.defineLazyGetter(window, name, function() {
|
XPCOMUtils.defineLazyGetter(window, name, function() {
|
||||||
|
@ -1113,139 +1113,6 @@ var BrowserUI = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var StartUI = {
|
|
||||||
get isVisible() { return this.isStartPageVisible; },
|
|
||||||
get isStartPageVisible() { return Elements.windowState.hasAttribute("startpage"); },
|
|
||||||
|
|
||||||
get maxResultsPerSection() {
|
|
||||||
return Services.prefs.getIntPref("browser.display.startUI.maxresults");
|
|
||||||
},
|
|
||||||
|
|
||||||
sections: [
|
|
||||||
"TopSitesStartView",
|
|
||||||
"BookmarksStartView",
|
|
||||||
"HistoryStartView",
|
|
||||||
"RemoteTabsStartView"
|
|
||||||
],
|
|
||||||
|
|
||||||
init: function init() {
|
|
||||||
Elements.startUI.addEventListener("contextmenu", this, false);
|
|
||||||
Elements.startUI.addEventListener("click", this, false);
|
|
||||||
Elements.startUI.addEventListener("MozMousePixelScroll", this, false);
|
|
||||||
|
|
||||||
this.sections.forEach(function (sectionName) {
|
|
||||||
let section = window[sectionName];
|
|
||||||
if (section.init)
|
|
||||||
section.init();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function() {
|
|
||||||
this.sections.forEach(function (sectionName) {
|
|
||||||
let section = window[sectionName];
|
|
||||||
if (section.uninit)
|
|
||||||
section.uninit();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Show the Firefox start page / "new tab" page */
|
|
||||||
show: function show() {
|
|
||||||
if (this.isStartPageVisible)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ContextUI.displayNavbar();
|
|
||||||
|
|
||||||
Elements.contentShowing.setAttribute("disabled", "true");
|
|
||||||
Elements.windowState.setAttribute("startpage", "true");
|
|
||||||
|
|
||||||
this.sections.forEach(function (sectionName) {
|
|
||||||
let section = window[sectionName];
|
|
||||||
if (section.show)
|
|
||||||
section.show();
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Hide the Firefox start page */
|
|
||||||
hide: function hide(aURI) {
|
|
||||||
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
|
||||||
if (!this.isStartPageVisible || this.isStartURI(aURI))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Elements.contentShowing.removeAttribute("disabled");
|
|
||||||
Elements.windowState.removeAttribute("startpage");
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Is the current tab supposed to show the Firefox start page? */
|
|
||||||
isStartURI: function isStartURI(aURI) {
|
|
||||||
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
|
||||||
return aURI == kStartOverlayURI || aURI == "about:home";
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Call this to show or hide the start page when switching tabs or pages */
|
|
||||||
update: function update(aURI) {
|
|
||||||
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
|
||||||
if (this.isStartURI(aURI)) {
|
|
||||||
this.show();
|
|
||||||
} else if (aURI != "about:blank") { // about:blank is loaded briefly for new tabs; ignore it
|
|
||||||
this.hide(aURI);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onClick: function onClick(aEvent) {
|
|
||||||
// If someone clicks / taps in empty grid space, take away
|
|
||||||
// focus from the nav bar edit so the soft keyboard will hide.
|
|
||||||
if (BrowserUI.blurNavBar()) {
|
|
||||||
// Advanced notice to CAO, so we can shuffle the nav bar in advance
|
|
||||||
// of the keyboard transition.
|
|
||||||
ContentAreaObserver.navBarWillBlur();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aEvent.button == 0)
|
|
||||||
ContextUI.dismissTabs();
|
|
||||||
},
|
|
||||||
|
|
||||||
onNarrowTitleClick: function onNarrowTitleClick(sectionId) {
|
|
||||||
let section = document.getElementById(sectionId);
|
|
||||||
|
|
||||||
if (section.hasAttribute("expanded"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let expandedSection of Elements.startUI.querySelectorAll(".meta-section[expanded]"))
|
|
||||||
expandedSection.removeAttribute("expanded")
|
|
||||||
|
|
||||||
section.setAttribute("expanded", "true");
|
|
||||||
},
|
|
||||||
|
|
||||||
handleEvent: function handleEvent(aEvent) {
|
|
||||||
switch (aEvent.type) {
|
|
||||||
case "contextmenu":
|
|
||||||
let event = document.createEvent("Events");
|
|
||||||
event.initEvent("MozEdgeUICompleted", true, false);
|
|
||||||
window.dispatchEvent(event);
|
|
||||||
break;
|
|
||||||
case "click":
|
|
||||||
this.onClick(aEvent);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "MozMousePixelScroll":
|
|
||||||
let startBox = document.getElementById("start-scrollbox");
|
|
||||||
let [, scrollInterface] = ScrollUtils.getScrollboxFromElement(startBox);
|
|
||||||
|
|
||||||
if (Elements.windowState.getAttribute("viewstate") == "snapped") {
|
|
||||||
scrollInterface.scrollBy(0, aEvent.detail);
|
|
||||||
} else {
|
|
||||||
scrollInterface.scrollBy(aEvent.detail, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
aEvent.preventDefault();
|
|
||||||
aEvent.stopPropagation();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var PanelUI = {
|
var PanelUI = {
|
||||||
get _panels() { return document.getElementById("panel-items"); },
|
get _panels() { return document.getElementById("panel-items"); },
|
||||||
|
|
||||||
|
@ -190,46 +190,6 @@
|
|||||||
<toolbarbutton id="newtab-button" command="cmd_newTab" label="&newtab.label;"/>
|
<toolbarbutton id="newtab-button" command="cmd_newTab" label="&newtab.label;"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
||||||
<!-- Start UI -->
|
|
||||||
<hbox id="start-container" flex="1" observes="bcast_windowState" class="meta content-height content-width">
|
|
||||||
<!-- portrait/landscape/filled view -->
|
|
||||||
|
|
||||||
<scrollbox id="start-scrollbox" observes="bcast_preciseInput" flex="1">
|
|
||||||
<vbox id="start-topsites" class="meta-section" expanded="true">
|
|
||||||
<label class="meta-section-title wide-title" value="&topSitesHeader.label;"/>
|
|
||||||
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-topsites')">
|
|
||||||
&narrowTopSitesHeader.label;
|
|
||||||
</html:div>
|
|
||||||
<richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
<vbox id="start-bookmarks" class="meta-section">
|
|
||||||
<label class="meta-section-title wide-title" value="&bookmarksHeader.label;"/>
|
|
||||||
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-bookmarks')">
|
|
||||||
&narrowBookmarksHeader.label;
|
|
||||||
</html:div>
|
|
||||||
<richgrid id="start-bookmarks-grid" set-name="bookmarks" seltype="multiple" flex="1"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
<vbox id="start-history" class="meta-section">
|
|
||||||
<label class="meta-section-title wide-title" value="&recentHistoryHeader.label;"/>
|
|
||||||
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-history')">
|
|
||||||
&narrowRecentHistoryHeader.label;
|
|
||||||
</html:div>
|
|
||||||
<richgrid id="start-history-grid" set-name="recentHistory" seltype="multiple" flex="1"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
<vbox id="start-remotetabs" class="meta-section">
|
|
||||||
<label class="meta-section-title wide-title" value="&remoteTabsHeader.label;"/>
|
|
||||||
<html:div id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-remotetabs')">
|
|
||||||
&narrowRemoteTabsHeader.label;
|
|
||||||
</html:div>
|
|
||||||
<richgrid id="start-remotetabs-grid" set-name="remoteTabs" seltype="multiple" flex="1"/>
|
|
||||||
</vbox>
|
|
||||||
|
|
||||||
</scrollbox>
|
|
||||||
</hbox>
|
|
||||||
</vbox> <!-- end tray -->
|
</vbox> <!-- end tray -->
|
||||||
|
|
||||||
<!-- Content viewport -->
|
<!-- Content viewport -->
|
||||||
|
374
browser/metro/base/content/startui/BookmarksView.js
Normal file
374
browser/metro/base/content/startui/BookmarksView.js
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a list/grid control implementing nsIDOMXULSelectControlElement and
|
||||||
|
* 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) {
|
||||||
|
this._set = aSet;
|
||||||
|
this._set.controller = this;
|
||||||
|
this._inBatch = false; // batch up grid updates to avoid redundant arrangeItems calls
|
||||||
|
|
||||||
|
this._limit = aLimit;
|
||||||
|
this._filterUnpinned = aFilterUnpinned;
|
||||||
|
this._bookmarkService = PlacesUtils.bookmarks;
|
||||||
|
this._navHistoryService = gHistSvc;
|
||||||
|
|
||||||
|
this._changes = new BookmarkChangeListener(this);
|
||||||
|
this._pinHelper = new ItemPinHelper("metro.bookmarks.unpinned");
|
||||||
|
this._bookmarkService.addObserver(this._changes, false);
|
||||||
|
Services.obs.addObserver(this, "metro_viewstate_changed", false);
|
||||||
|
window.addEventListener('MozAppbarDismissing', this, false);
|
||||||
|
window.addEventListener('BookmarksNeedsRefresh', this, false);
|
||||||
|
|
||||||
|
this.root = aRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
|
||||||
|
_limit: null,
|
||||||
|
_set: null,
|
||||||
|
_changes: null,
|
||||||
|
_root: null,
|
||||||
|
_sort: 0, // Natural bookmark order.
|
||||||
|
_toRemove: null,
|
||||||
|
|
||||||
|
get sort() {
|
||||||
|
return this._sort;
|
||||||
|
},
|
||||||
|
|
||||||
|
set sort(aSort) {
|
||||||
|
this._sort = aSort;
|
||||||
|
this.clearBookmarks();
|
||||||
|
this.getBookmarks();
|
||||||
|
},
|
||||||
|
|
||||||
|
get root() {
|
||||||
|
return this._root;
|
||||||
|
},
|
||||||
|
|
||||||
|
set root(aRoot) {
|
||||||
|
this._root = aRoot;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleItemClick: function bv_handleItemClick(aItem) {
|
||||||
|
let url = aItem.getAttribute("value");
|
||||||
|
BrowserUI.goToURI(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
_getItemForBookmarkId: function bv__getItemForBookmark(aBookmarkId) {
|
||||||
|
return this._set.querySelector("richgriditem[bookmarkId='" + aBookmarkId + "']");
|
||||||
|
},
|
||||||
|
|
||||||
|
_getBookmarkIdForItem: function bv__getBookmarkForItem(aItem) {
|
||||||
|
return +aItem.getAttribute("bookmarkId");
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateItemWithAttrs: function dv__updateItemWithAttrs(anItem, aAttrs) {
|
||||||
|
for (let name in aAttrs)
|
||||||
|
anItem.setAttribute(name, aAttrs[name]);
|
||||||
|
},
|
||||||
|
|
||||||
|
getBookmarks: function bv_getBookmarks(aRefresh) {
|
||||||
|
let options = this._navHistoryService.getNewQueryOptions();
|
||||||
|
options.queryType = options.QUERY_TYPE_BOOKMARKS;
|
||||||
|
options.excludeQueries = true; // Don't include "smart folders"
|
||||||
|
options.sortingMode = this._sort;
|
||||||
|
|
||||||
|
let limit = this._limit || Infinity;
|
||||||
|
|
||||||
|
let query = this._navHistoryService.getNewQuery();
|
||||||
|
query.setFolders([Bookmarks.metroRoot], 1);
|
||||||
|
|
||||||
|
let result = this._navHistoryService.executeQuery(query, options);
|
||||||
|
let rootNode = result.root;
|
||||||
|
rootNode.containerOpen = true;
|
||||||
|
let childCount = rootNode.childCount;
|
||||||
|
|
||||||
|
this._inBatch = true; // batch up grid updates to avoid redundant arrangeItems calls
|
||||||
|
|
||||||
|
for (let i = 0, addedCount = 0; i < childCount && addedCount < limit; i++) {
|
||||||
|
let node = rootNode.getChild(i);
|
||||||
|
|
||||||
|
// Ignore folders, separators, undefined item types, etc.
|
||||||
|
if (node.type != node.RESULT_TYPE_URI)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If item is marked for deletion, skip it.
|
||||||
|
if (this._toRemove && this._toRemove.indexOf(node.itemId) !== -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let item = this._getItemForBookmarkId(node.itemId);
|
||||||
|
|
||||||
|
// Item has been unpinned.
|
||||||
|
if (this._filterUnpinned && !this._pinHelper.isPinned(node.itemId)) {
|
||||||
|
if (item)
|
||||||
|
this.removeBookmark(node.itemId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aRefresh || !item) {
|
||||||
|
// If we're not refreshing or the item is not in the grid, add it.
|
||||||
|
this.addBookmark(node.itemId, addedCount);
|
||||||
|
} else if (aRefresh && item) {
|
||||||
|
// Update context action in case it changed in another view.
|
||||||
|
this._setContextActions(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
addedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove extra items in case a refresh added more than the limit.
|
||||||
|
// This can happen when undoing a delete.
|
||||||
|
if (aRefresh) {
|
||||||
|
while (this._set.itemCount > limit)
|
||||||
|
this._set.removeItemAt(this._set.itemCount - 1, true);
|
||||||
|
}
|
||||||
|
this._set.arrangeItems();
|
||||||
|
this._inBatch = false;
|
||||||
|
rootNode.containerOpen = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
inCurrentView: function bv_inCurrentView(aParentId, aItemId) {
|
||||||
|
if (this._root && aParentId != this._root)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !!this._getItemForBookmarkId(aItemId);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearBookmarks: function bv_clearBookmarks() {
|
||||||
|
this._set.clearAll();
|
||||||
|
},
|
||||||
|
|
||||||
|
addBookmark: function bv_addBookmark(aBookmarkId, aPos) {
|
||||||
|
let index = this._bookmarkService.getItemIndex(aBookmarkId);
|
||||||
|
let uri = this._bookmarkService.getBookmarkURI(aBookmarkId);
|
||||||
|
let title = this._bookmarkService.getItemTitle(aBookmarkId) || uri.spec;
|
||||||
|
let item = this._set.insertItemAt(aPos || index, title, uri.spec, this._inBatch);
|
||||||
|
item.setAttribute("bookmarkId", aBookmarkId);
|
||||||
|
this._setContextActions(item);
|
||||||
|
this._updateFavicon(item, uri);
|
||||||
|
},
|
||||||
|
|
||||||
|
_setContextActions: function bv__setContextActions(aItem) {
|
||||||
|
let itemId = this._getBookmarkIdForItem(aItem);
|
||||||
|
aItem.setAttribute("data-contextactions", "delete," + (this._pinHelper.isPinned(itemId) ? "unpin" : "pin"));
|
||||||
|
if (aItem.refresh) aItem.refresh();
|
||||||
|
},
|
||||||
|
|
||||||
|
_sendNeedsRefresh: function bv__sendNeedsRefresh(){
|
||||||
|
// Event sent when all view instances need to refresh.
|
||||||
|
let event = document.createEvent("Events");
|
||||||
|
event.initEvent("BookmarksNeedsRefresh", true, false);
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
updateBookmark: function bv_updateBookmark(aBookmarkId) {
|
||||||
|
let item = this._getItemForBookmarkId(aBookmarkId);
|
||||||
|
|
||||||
|
if (!item)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let oldIndex = this._set.getIndexOfItem(item);
|
||||||
|
let index = this._bookmarkService.getItemIndex(aBookmarkId);
|
||||||
|
|
||||||
|
if (oldIndex != index) {
|
||||||
|
this.removeBookmark(aBookmarkId);
|
||||||
|
this.addBookmark(aBookmarkId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uri = this._bookmarkService.getBookmarkURI(aBookmarkId);
|
||||||
|
let title = this._bookmarkService.getItemTitle(aBookmarkId) || uri.spec;
|
||||||
|
|
||||||
|
item.setAttribute("value", uri.spec);
|
||||||
|
item.setAttribute("label", title);
|
||||||
|
|
||||||
|
this._updateFavicon(item, uri);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeBookmark: function bv_removeBookmark(aBookmarkId) {
|
||||||
|
let item = this._getItemForBookmarkId(aBookmarkId);
|
||||||
|
let index = this._set.getIndexOfItem(item);
|
||||||
|
this._set.removeItemAt(index, this._inBatch);
|
||||||
|
},
|
||||||
|
|
||||||
|
destruct: function bv_destruct() {
|
||||||
|
this._bookmarkService.removeObserver(this._changes);
|
||||||
|
Services.obs.removeObserver(this, "metro_viewstate_changed");
|
||||||
|
window.removeEventListener('MozAppbarDismissing', this, false);
|
||||||
|
window.removeEventListener('BookmarksNeedsRefresh', this, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
doActionOnSelectedTiles: function bv_doActionOnSelectedTiles(aActionName, aEvent) {
|
||||||
|
let tileGroup = this._set;
|
||||||
|
let selectedTiles = tileGroup.selectedItems;
|
||||||
|
|
||||||
|
switch (aActionName){
|
||||||
|
case "delete":
|
||||||
|
Array.forEach(selectedTiles, function(aNode) {
|
||||||
|
if (!this._toRemove) {
|
||||||
|
this._toRemove = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let itemId = this._getBookmarkIdForItem(aNode);
|
||||||
|
|
||||||
|
this._toRemove.push(itemId);
|
||||||
|
this.removeBookmark(itemId);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
// stop the appbar from dismissing
|
||||||
|
aEvent.preventDefault();
|
||||||
|
|
||||||
|
// at next tick, re-populate the context appbar.
|
||||||
|
setTimeout(function(){
|
||||||
|
// fire a MozContextActionsChange event to update the context appbar
|
||||||
|
let event = document.createEvent("Events");
|
||||||
|
// we need the restore button to show (the tile node will go away though)
|
||||||
|
event.actions = ["restore"];
|
||||||
|
event.initEvent("MozContextActionsChange", true, false);
|
||||||
|
tileGroup.dispatchEvent(event);
|
||||||
|
}, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "restore":
|
||||||
|
// clear toRemove and let _sendNeedsRefresh update the items.
|
||||||
|
this._toRemove = null;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "unpin":
|
||||||
|
Array.forEach(selectedTiles, function(aNode) {
|
||||||
|
let itemId = this._getBookmarkIdForItem(aNode);
|
||||||
|
|
||||||
|
if (this._filterUnpinned)
|
||||||
|
this.removeBookmark(itemId);
|
||||||
|
|
||||||
|
this._pinHelper.setUnpinned(itemId);
|
||||||
|
}, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "pin":
|
||||||
|
Array.forEach(selectedTiles, function(aNode) {
|
||||||
|
let itemId = this._getBookmarkIdForItem(aNode);
|
||||||
|
|
||||||
|
this._pinHelper.setPinned(itemId);
|
||||||
|
}, this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send refresh event so all view are in sync.
|
||||||
|
this._sendNeedsRefresh();
|
||||||
|
},
|
||||||
|
|
||||||
|
// nsIObservers
|
||||||
|
observe: function (aSubject, aTopic, aState) {
|
||||||
|
switch(aTopic) {
|
||||||
|
case "metro_viewstate_changed":
|
||||||
|
this.onViewStateChange(aState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent: function bv_handleEvent(aEvent) {
|
||||||
|
switch (aEvent.type){
|
||||||
|
case "MozAppbarDismissing":
|
||||||
|
// If undo wasn't pressed, time to do definitive actions.
|
||||||
|
if (this._toRemove) {
|
||||||
|
for (let bookmarkId of this._toRemove) {
|
||||||
|
this._bookmarkService.removeItem(bookmarkId);
|
||||||
|
}
|
||||||
|
this._toRemove = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "BookmarksNeedsRefresh":
|
||||||
|
this.getBookmarks(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let BookmarksStartView = {
|
||||||
|
_view: null,
|
||||||
|
get _grid() { return document.getElementById("start-bookmarks-grid"); },
|
||||||
|
|
||||||
|
init: function init() {
|
||||||
|
this._view = new BookmarksView(this._grid, StartUI.maxResultsPerSection, Bookmarks.metroRoot, true);
|
||||||
|
this._view.getBookmarks();
|
||||||
|
},
|
||||||
|
|
||||||
|
uninit: function uninit() {
|
||||||
|
this._view.destruct();
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function show() {
|
||||||
|
this._grid.arrangeItems();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observes bookmark changes and keeps a linked BookmarksView updated.
|
||||||
|
*
|
||||||
|
* @param aView An instance of BookmarksView.
|
||||||
|
*/
|
||||||
|
function BookmarkChangeListener(aView) {
|
||||||
|
this._view = aView;
|
||||||
|
}
|
||||||
|
|
||||||
|
BookmarkChangeListener.prototype = {
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//// nsINavBookmarkObserver
|
||||||
|
onBeginUpdateBatch: function () { },
|
||||||
|
onEndUpdateBatch: function () { },
|
||||||
|
|
||||||
|
onItemAdded: function bCL_onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle, aDateAdded, aGUID, aParentGUID) {
|
||||||
|
this._view.getBookmarks(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
onItemChanged: function bCL_onItemChanged(aItemId, aProperty, aIsAnnotationProperty, aNewValue, aLastModified, aItemType, aParentId, aGUID, aParentGUID) {
|
||||||
|
let itemIndex = PlacesUtils.bookmarks.getItemIndex(aItemId);
|
||||||
|
if (!this._view.inCurrentView(aParentId, aItemId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._view.updateBookmark(aItemId);
|
||||||
|
},
|
||||||
|
|
||||||
|
onItemMoved: function bCL_onItemMoved(aItemId, aOldParentId, aOldIndex, aNewParentId, aNewIndex, aItemType, aGUID, aOldParentGUID, aNewParentGUID) {
|
||||||
|
let wasInView = this._view.inCurrentView(aOldParentId, aItemId);
|
||||||
|
let nowInView = this._view.inCurrentView(aNewParentId, aItemId);
|
||||||
|
|
||||||
|
if (!wasInView && nowInView)
|
||||||
|
this._view.addBookmark(aItemId);
|
||||||
|
|
||||||
|
if (wasInView && !nowInView)
|
||||||
|
this._view.removeBookmark(aItemId);
|
||||||
|
|
||||||
|
this._view.getBookmarks(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
onBeforeItemRemoved: function (aItemId, aItemType, aParentId, aGUID, aParentGUID) { },
|
||||||
|
onItemRemoved: function bCL_onItemRemoved(aItemId, aParentId, aIndex, aItemType, aURI, aGUID, aParentGUID) {
|
||||||
|
if (!this._view.inCurrentView(aParentId, aItemId))
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._view.removeBookmark(aItemId);
|
||||||
|
this._view.getBookmarks(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
onItemVisited: function(aItemId, aVisitId, aTime, aTransitionType, aURI, aParentId, aGUID, aParentGUID) { },
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//// nsISupports
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
|
||||||
|
};
|
72
browser/metro/base/content/startui/Start.xul
Normal file
72
browser/metro/base/content/startui/Start.xul
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
|
||||||
|
<?xml-stylesheet href="chrome://browser/skin/platform.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/skin/browser.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://browser/skin/tiles.css" type="text/css"?>
|
||||||
|
|
||||||
|
<!DOCTYPE window [
|
||||||
|
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
|
||||||
|
%globalDTD;
|
||||||
|
<!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
|
||||||
|
%browserDTD;
|
||||||
|
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||||
|
%brandDTD;
|
||||||
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
|
<!ENTITY % syncBrandDTD SYSTEM "chrome://browser/locale/syncBrand.dtd">
|
||||||
|
%syncBrandDTD;
|
||||||
|
<!ENTITY % syncDTD SYSTEM "chrome://browser/locale/sync.dtd">
|
||||||
|
%syncDTD;
|
||||||
|
#endif
|
||||||
|
]>
|
||||||
|
|
||||||
|
<page id="startui-page"
|
||||||
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
onload="StartUI.init();"
|
||||||
|
onunload="StartUI.uninit();">
|
||||||
|
|
||||||
|
<script type="application/javascript" src="chrome://browser/content/startui-scripts.js"/>
|
||||||
|
|
||||||
|
<hbox id="start-container" flex="1" observes="bcast_windowState" class="meta content-height content-width">
|
||||||
|
<scrollbox id="start-scrollbox" observes="bcast_preciseInput" flex="1">
|
||||||
|
<vbox id="start-topsites" class="meta-section" expanded="true">
|
||||||
|
<label class="meta-section-title wide-title" value="&topSitesHeader.label;"/>
|
||||||
|
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-topsites')">
|
||||||
|
&narrowTopSitesHeader.label;
|
||||||
|
</html:div>
|
||||||
|
<richgrid id="start-topsites-grid" set-name="topSites" rows="3" columns="3" tiletype="thumbnail" seltype="multiple" flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
|
||||||
|
<vbox id="start-bookmarks" class="meta-section">
|
||||||
|
<label class="meta-section-title wide-title" value="&bookmarksHeader.label;"/>
|
||||||
|
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-bookmarks')">
|
||||||
|
&narrowBookmarksHeader.label;
|
||||||
|
</html:div>
|
||||||
|
<richgrid id="start-bookmarks-grid" set-name="bookmarks" seltype="multiple" flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
|
||||||
|
<vbox id="start-history" class="meta-section">
|
||||||
|
<label class="meta-section-title wide-title" value="&recentHistoryHeader.label;"/>
|
||||||
|
<html:div class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-history')">
|
||||||
|
&narrowRecentHistoryHeader.label;
|
||||||
|
</html:div>
|
||||||
|
<richgrid id="start-history-grid" set-name="recentHistory" seltype="multiple" flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
|
||||||
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
|
<vbox id="start-remotetabs" class="meta-section">
|
||||||
|
<label class="meta-section-title wide-title" value="&remoteTabsHeader.label;"/>
|
||||||
|
<html:div id="snappedRemoteTabsLabel" class="meta-section-title narrow-title" onclick="StartUI.onNarrowTitleClick('start-remotetabs')">
|
||||||
|
&narrowRemoteTabsHeader.label;
|
||||||
|
</html:div>
|
||||||
|
<richgrid id="start-remotetabs-grid" set-name="remoteTabs" seltype="multiple" flex="1"/>
|
||||||
|
</vbox>
|
||||||
|
#endif
|
||||||
|
</scrollbox>
|
||||||
|
</hbox>
|
||||||
|
</page>
|
139
browser/metro/base/content/startui/StartUI.js
Normal file
139
browser/metro/base/content/startui/StartUI.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var StartUI = {
|
||||||
|
get isVisible() { return this.isStartPageVisible; },
|
||||||
|
get isStartPageVisible() { return true; /*return Elements.windowState.hasAttribute("startpage");*/ },
|
||||||
|
|
||||||
|
get maxResultsPerSection() {
|
||||||
|
return Services.prefs.getIntPref("browser.display.startUI.maxresults");
|
||||||
|
},
|
||||||
|
|
||||||
|
sections: [
|
||||||
|
"TopSitesStartView",
|
||||||
|
"BookmarksStartView",
|
||||||
|
"HistoryStartView",
|
||||||
|
"RemoteTabsStartView"
|
||||||
|
],
|
||||||
|
|
||||||
|
init: function init() {
|
||||||
|
Elements.startUI.addEventListener("contextmenu", this, false);
|
||||||
|
Elements.startUI.addEventListener("click", this, false);
|
||||||
|
Elements.startUI.addEventListener("MozMousePixelScroll", this, false);
|
||||||
|
|
||||||
|
this.sections.forEach(function (sectionName) {
|
||||||
|
let section = window[sectionName];
|
||||||
|
if (section.init)
|
||||||
|
section.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
uninit: function() {
|
||||||
|
this.sections.forEach(function (sectionName) {
|
||||||
|
let section = window[sectionName];
|
||||||
|
if (section.uninit)
|
||||||
|
section.uninit();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Show the Firefox start page / "new tab" page */
|
||||||
|
show: function show() {
|
||||||
|
if (this.isStartPageVisible)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ContextUI.displayNavbar();
|
||||||
|
|
||||||
|
Elements.contentShowing.setAttribute("disabled", "true");
|
||||||
|
Elements.windowState.setAttribute("startpage", "true");
|
||||||
|
|
||||||
|
this.sections.forEach(function (sectionName) {
|
||||||
|
let section = window[sectionName];
|
||||||
|
if (section.show)
|
||||||
|
section.show();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Hide the Firefox start page */
|
||||||
|
hide: function hide(aURI) {
|
||||||
|
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
||||||
|
if (!this.isStartPageVisible || this.isStartURI(aURI))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Elements.contentShowing.removeAttribute("disabled");
|
||||||
|
Elements.windowState.removeAttribute("startpage");
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Is the current tab supposed to show the Firefox start page? */
|
||||||
|
isStartURI: function isStartURI(aURI) {
|
||||||
|
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
||||||
|
return aURI == kStartOverlayURI || aURI == "about:home";
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Call this to show or hide the start page when switching tabs or pages */
|
||||||
|
update: function update(aURI) {
|
||||||
|
aURI = aURI || Browser.selectedBrowser.currentURI.spec;
|
||||||
|
if (this.isStartURI(aURI)) {
|
||||||
|
this.show();
|
||||||
|
} else if (aURI != "about:blank") { // about:blank is loaded briefly for new tabs; ignore it
|
||||||
|
this.hide(aURI);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onClick: function onClick(aEvent) {
|
||||||
|
// If someone clicks / taps in empty grid space, take away
|
||||||
|
// focus from the nav bar edit so the soft keyboard will hide.
|
||||||
|
if (BrowserUI.blurNavBar()) {
|
||||||
|
// Advanced notice to CAO, so we can shuffle the nav bar in advance
|
||||||
|
// of the keyboard transition.
|
||||||
|
ContentAreaObserver.navBarWillBlur();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aEvent.button == 0)
|
||||||
|
ContextUI.dismissTabs();
|
||||||
|
},
|
||||||
|
|
||||||
|
onNarrowTitleClick: function onNarrowTitleClick(sectionId) {
|
||||||
|
let section = document.getElementById(sectionId);
|
||||||
|
|
||||||
|
if (section.hasAttribute("expanded"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let expandedSection of Elements.startUI.querySelectorAll(".meta-section[expanded]"))
|
||||||
|
expandedSection.removeAttribute("expanded")
|
||||||
|
|
||||||
|
section.setAttribute("expanded", "true");
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent: function handleEvent(aEvent) {
|
||||||
|
switch (aEvent.type) {
|
||||||
|
case "contextmenu":
|
||||||
|
let event = document.createEvent("Events");
|
||||||
|
event.initEvent("MozEdgeUICompleted", true, false);
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
break;
|
||||||
|
case "click":
|
||||||
|
this.onClick(aEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "MozMousePixelScroll":
|
||||||
|
let startBox = document.getElementById("start-scrollbox");
|
||||||
|
let [, scrollInterface] = ScrollUtils.getScrollboxFromElement(startBox);
|
||||||
|
|
||||||
|
if (Elements.windowState.getAttribute("viewstate") == "snapped") {
|
||||||
|
scrollInterface.scrollBy(0, aEvent.detail);
|
||||||
|
} else {
|
||||||
|
scrollInterface.scrollBy(aEvent.detail, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
aEvent.preventDefault();
|
||||||
|
aEvent.stopPropagation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
299
browser/metro/base/content/startui/TopSitesView.js
Normal file
299
browser/metro/base/content/startui/TopSitesView.js
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
let prefs = Components.classes["@mozilla.org/preferences-service;1"].
|
||||||
|
getService(Components.interfaces.nsIPrefBranch);
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/PageThumbs.jsm");
|
||||||
|
Cu.import("resource:///modules/colorUtils.jsm");
|
||||||
|
|
||||||
|
function TopSitesView(aGrid, aMaxSites) {
|
||||||
|
this._set = aGrid;
|
||||||
|
this._set.controller = this;
|
||||||
|
this._topSitesMax = aMaxSites;
|
||||||
|
|
||||||
|
// clean up state when the appbar closes
|
||||||
|
window.addEventListener('MozAppbarDismissing', this, false);
|
||||||
|
let history = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||||
|
getService(Ci.nsINavHistoryService);
|
||||||
|
history.addObserver(this, false);
|
||||||
|
|
||||||
|
PageThumbs.addExpirationFilter(this);
|
||||||
|
Services.obs.addObserver(this, "Metro:RefreshTopsiteThumbnail", false);
|
||||||
|
Services.obs.addObserver(this, "metro_viewstate_changed", false);
|
||||||
|
|
||||||
|
NewTabUtils.allPages.register(this);
|
||||||
|
TopSites.prepareCache().then(function(){
|
||||||
|
this.populateGrid();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
|
handleItemClick: function tabview_handleItemClick(aItem) {
|
||||||
|
let url = aItem.getAttribute("value");
|
||||||
|
StartUI.goToURI(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
doActionOnSelectedTiles: function(aActionName, aEvent) {
|
||||||
|
let tileGroup = this._set;
|
||||||
|
let selectedTiles = tileGroup.selectedItems;
|
||||||
|
let sites = Array.map(selectedTiles, TopSites._linkFromNode);
|
||||||
|
let nextContextActions = new Set();
|
||||||
|
|
||||||
|
switch (aActionName){
|
||||||
|
case "delete":
|
||||||
|
for (let aNode of selectedTiles) {
|
||||||
|
// add some class to transition element before deletion?
|
||||||
|
aNode.contextActions.delete('delete');
|
||||||
|
// we need new context buttons to show (the tile node will go away though)
|
||||||
|
}
|
||||||
|
this._lastSelectedSites = (this._lastSelectedSites || []).concat(sites);
|
||||||
|
// stop the appbar from dismissing
|
||||||
|
aEvent.preventDefault();
|
||||||
|
nextContextActions.add('restore');
|
||||||
|
TopSites.hideSites(sites);
|
||||||
|
break;
|
||||||
|
case "restore":
|
||||||
|
// usually restore is an undo action, so we have to recreate the tiles and grid selection
|
||||||
|
if (this._lastSelectedSites) {
|
||||||
|
let selectedUrls = this._lastSelectedSites.map((site) => site.url);
|
||||||
|
// re-select the tiles once the tileGroup is done populating and arranging
|
||||||
|
tileGroup.addEventListener("arranged", function _onArranged(aEvent){
|
||||||
|
for (let url of selectedUrls) {
|
||||||
|
let tileNode = tileGroup.querySelector("richgriditem[value='"+url+"']");
|
||||||
|
if (tileNode) {
|
||||||
|
tileNode.setAttribute("selected", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tileGroup.removeEventListener("arranged", _onArranged, false);
|
||||||
|
// <sfoster> we can't just call selectItem n times on tileGroup as selecting means trigger the default action
|
||||||
|
// for seltype="single" grids.
|
||||||
|
// so we toggle the attributes and raise the selectionchange "manually"
|
||||||
|
let event = tileGroup.ownerDocument.createEvent("Events");
|
||||||
|
event.initEvent("selectionchange", true, true);
|
||||||
|
tileGroup.dispatchEvent(event);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
TopSites.restoreSites(this._lastSelectedSites);
|
||||||
|
// stop the appbar from dismissing,
|
||||||
|
// the selectionchange event will trigger re-population of the context appbar
|
||||||
|
aEvent.preventDefault();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "pin":
|
||||||
|
let pinIndices = [];
|
||||||
|
Array.forEach(selectedTiles, function(aNode) {
|
||||||
|
pinIndices.push( Array.indexOf(aNode.control.children, aNode) );
|
||||||
|
aNode.contextActions.delete('pin');
|
||||||
|
aNode.contextActions.add('unpin');
|
||||||
|
});
|
||||||
|
TopSites.pinSites(sites, pinIndices);
|
||||||
|
break;
|
||||||
|
case "unpin":
|
||||||
|
Array.forEach(selectedTiles, function(aNode) {
|
||||||
|
aNode.contextActions.delete('unpin');
|
||||||
|
aNode.contextActions.add('pin');
|
||||||
|
});
|
||||||
|
TopSites.unpinSites(sites);
|
||||||
|
break;
|
||||||
|
// default: no action
|
||||||
|
}
|
||||||
|
if (nextContextActions.size) {
|
||||||
|
// at next tick, re-populate the context appbar
|
||||||
|
setTimeout(function(){
|
||||||
|
// fire a MozContextActionsChange event to update the context appbar
|
||||||
|
let event = document.createEvent("Events");
|
||||||
|
event.actions = [...nextContextActions];
|
||||||
|
event.initEvent("MozContextActionsChange", true, false);
|
||||||
|
tileGroup.dispatchEvent(event);
|
||||||
|
},0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent: function(aEvent) {
|
||||||
|
switch (aEvent.type){
|
||||||
|
case "MozAppbarDismissing":
|
||||||
|
// clean up when the context appbar is dismissed - we don't remember selections
|
||||||
|
this._lastSelectedSites = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function() {
|
||||||
|
// called by the NewTabUtils.allPages.update, notifying us of data-change in topsites
|
||||||
|
let grid = this._set,
|
||||||
|
dirtySites = TopSites.dirty();
|
||||||
|
|
||||||
|
if (dirtySites.size) {
|
||||||
|
// we can just do a partial update and refresh the node representing each dirty tile
|
||||||
|
for (let site of dirtySites) {
|
||||||
|
let tileNode = grid.querySelector("[value='"+site.url+"']");
|
||||||
|
if (tileNode) {
|
||||||
|
this.updateTile(tileNode, new Site(site));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// flush, recreate all
|
||||||
|
this.isUpdating = true;
|
||||||
|
// destroy and recreate all item nodes, skip calling arrangeItems
|
||||||
|
grid.clearAll(true);
|
||||||
|
this.populateGrid();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTile: function(aTileNode, aSite, aArrangeGrid) {
|
||||||
|
this._updateFavicon(aTileNode, Util.makeURI(aSite.url));
|
||||||
|
|
||||||
|
Task.spawn(function() {
|
||||||
|
let filepath = PageThumbsStorage.getFilePathForURL(aSite.url);
|
||||||
|
if (yield OS.File.exists(filepath)) {
|
||||||
|
aSite.backgroundImage = 'url("'+PageThumbs.getThumbnailURL(aSite.url)+'")';
|
||||||
|
aTileNode.setAttribute("customImage", aSite.backgroundImage);
|
||||||
|
if (aTileNode.refresh) {
|
||||||
|
aTileNode.refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
aSite.applyToTileNode(aTileNode);
|
||||||
|
if (aArrangeGrid) {
|
||||||
|
this._set.arrangeItems();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
populateGrid: function populateGrid() {
|
||||||
|
this.isUpdating = true;
|
||||||
|
|
||||||
|
let sites = TopSites.getSites();
|
||||||
|
let length = Math.min(sites.length, this._topSitesMax || Infinity);
|
||||||
|
let tileset = this._set;
|
||||||
|
|
||||||
|
// if we're updating with a collection that is smaller than previous
|
||||||
|
// remove any extra tiles
|
||||||
|
while (tileset.children.length > length) {
|
||||||
|
tileset.removeChild(tileset.children[tileset.children.length -1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let idx=0; idx < length; idx++) {
|
||||||
|
let isNew = !tileset.children[idx],
|
||||||
|
site = sites[idx];
|
||||||
|
let item = isNew ? tileset.createItemElement(site.title, site.url) : tileset.children[idx];
|
||||||
|
|
||||||
|
this.updateTile(item, site);
|
||||||
|
if (isNew) {
|
||||||
|
tileset.appendChild(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tileset.arrangeItems();
|
||||||
|
this.isUpdating = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
forceReloadOfThumbnail: function forceReloadOfThumbnail(url) {
|
||||||
|
let nodes = this._set.querySelectorAll('richgriditem[value="'+url+'"]');
|
||||||
|
for (let item of nodes) {
|
||||||
|
if ("isBound" in item && item.isBound) {
|
||||||
|
item.refreshBackgroundImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
filterForThumbnailExpiration: function filterForThumbnailExpiration(aCallback) {
|
||||||
|
aCallback([item.getAttribute("value") for (item of this._set.children)]);
|
||||||
|
},
|
||||||
|
|
||||||
|
isFirstRun: function isFirstRun() {
|
||||||
|
return prefs.getBoolPref("browser.firstrun.show.localepicker");
|
||||||
|
},
|
||||||
|
|
||||||
|
destruct: function destruct() {
|
||||||
|
Services.obs.removeObserver(this, "Metro:RefreshTopsiteThumbnail");
|
||||||
|
Services.obs.removeObserver(this, "metro_viewstate_changed");
|
||||||
|
PageThumbs.removeExpirationFilter(this);
|
||||||
|
window.removeEventListener('MozAppbarDismissing', this, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// nsIObservers
|
||||||
|
observe: function (aSubject, aTopic, aState) {
|
||||||
|
switch(aTopic) {
|
||||||
|
case "Metro:RefreshTopsiteThumbnail":
|
||||||
|
this.forceReloadOfThumbnail(aState);
|
||||||
|
break;
|
||||||
|
case "metro_viewstate_changed":
|
||||||
|
this.onViewStateChange(aState);
|
||||||
|
for (let item of this._set.children) {
|
||||||
|
if (aState == "snapped") {
|
||||||
|
item.removeAttribute("tiletype");
|
||||||
|
} else {
|
||||||
|
item.setAttribute("tiletype", "thumbnail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// nsINavHistoryObserver
|
||||||
|
onBeginUpdateBatch: function() {
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndUpdateBatch: function() {
|
||||||
|
},
|
||||||
|
|
||||||
|
onVisit: function(aURI, aVisitID, aTime, aSessionID,
|
||||||
|
aReferringID, aTransitionType) {
|
||||||
|
},
|
||||||
|
|
||||||
|
onTitleChanged: function(aURI, aPageTitle) {
|
||||||
|
},
|
||||||
|
|
||||||
|
onDeleteURI: function(aURI) {
|
||||||
|
},
|
||||||
|
|
||||||
|
onClearHistory: function() {
|
||||||
|
this._set.clearAll();
|
||||||
|
},
|
||||||
|
|
||||||
|
onPageChanged: function(aURI, aWhat, aValue) {
|
||||||
|
},
|
||||||
|
|
||||||
|
onDeleteVisits: function (aURI, aVisitTime, aGUID, aReason, aTransitionType) {
|
||||||
|
},
|
||||||
|
|
||||||
|
QueryInterface: function(iid) {
|
||||||
|
if (iid.equals(Components.interfaces.nsINavHistoryObserver) ||
|
||||||
|
iid.equals(Components.interfaces.nsISupports)) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
let TopSitesStartView = {
|
||||||
|
_view: null,
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uninit: function uninit() {
|
||||||
|
this._view.destruct();
|
||||||
|
},
|
||||||
|
|
||||||
|
show: function show() {
|
||||||
|
this._grid.arrangeItems();
|
||||||
|
}
|
||||||
|
};
|
83
browser/metro/base/content/startui/startui-scripts.js
Normal file
83
browser/metro/base/content/startui/startui-scripts.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let Cc = Components.classes;
|
||||||
|
let Ci = Components.interfaces;
|
||||||
|
let Cu = Components.utils;
|
||||||
|
let Cr = Components.results;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
|
||||||
|
"resource://gre/modules/PlacesUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||||
|
"resource://gre/modules/NetUtil.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
|
||||||
|
"resource://gre/modules/NewTabUtils.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
|
||||||
|
"resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
||||||
|
"resource://gre/modules/Task.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "CrossSlide",
|
||||||
|
"resource:///modules/CrossSlide.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||||
|
"resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "View",
|
||||||
|
"resource:///modules/View.jsm");
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(window, "gHistSvc",
|
||||||
|
"@mozilla.org/browser/nav-history-service;1",
|
||||||
|
"nsINavHistoryService",
|
||||||
|
"nsIBrowserHistory");
|
||||||
|
|
||||||
|
let ScriptContexts = {};
|
||||||
|
[
|
||||||
|
["Util", "chrome://browser/content/Util.js"],
|
||||||
|
["Site", "chrome://browser/content/Site.js"],
|
||||||
|
["StartUI", "chrome://browser/content/StartUI.js"],
|
||||||
|
["Bookmarks", "chrome://browser/content/bookmarks.js"],
|
||||||
|
["BookmarksView", "chrome://browser/content/BookmarksView.js"],
|
||||||
|
["HistoryView", "chrome://browser/content/HistoryView.js"],
|
||||||
|
["TopSitesView", "chrome://browser/content/TopSitesView.js"],
|
||||||
|
["RemoteTabsView", "chrome://browser/content/RemoteTabsView.js"],
|
||||||
|
["BookmarksStartView", "chrome://browser/content/BookmarksView.js"],
|
||||||
|
["HistoryStartView", "chrome://browser/content/HistoryView.js"],
|
||||||
|
["TopSitesStartView", "chrome://browser/content/TopSitesView.js"],
|
||||||
|
["RemoteTabsStartView", "chrome://browser/content/RemoteTabsView.js"],
|
||||||
|
["ItemPinHelper", "chrome://browser/content/helperui/ItemPinHelper.js"],
|
||||||
|
].forEach(function (aScript) {
|
||||||
|
let [name, script] = aScript;
|
||||||
|
XPCOMUtils.defineLazyGetter(window, name, function() {
|
||||||
|
let sandbox;
|
||||||
|
if (script in ScriptContexts) {
|
||||||
|
sandbox = ScriptContexts[script];
|
||||||
|
} else {
|
||||||
|
sandbox = ScriptContexts[script] = {};
|
||||||
|
Services.scriptloader.loadSubScript(script, sandbox);
|
||||||
|
}
|
||||||
|
return sandbox[name];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// singleton
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "TopSites", function() {
|
||||||
|
return StartUI.chromeWin.TopSites;
|
||||||
|
});
|
||||||
|
|
||||||
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
|
XPCOMUtils.defineLazyGetter(this, "Weave", function() {
|
||||||
|
Components.utils.import("resource://services-sync/main.js");
|
||||||
|
return Weave;
|
||||||
|
});
|
||||||
|
#endif
|
@ -78,7 +78,6 @@ chrome.jar:
|
|||||||
content/bookmarks.js (content/bookmarks.js)
|
content/bookmarks.js (content/bookmarks.js)
|
||||||
content/exceptions.js (content/exceptions.js)
|
content/exceptions.js (content/exceptions.js)
|
||||||
content/downloads.js (content/downloads.js)
|
content/downloads.js (content/downloads.js)
|
||||||
content/history.js (content/history.js)
|
|
||||||
content/Site.js (content/Site.js)
|
content/Site.js (content/Site.js)
|
||||||
content/TopSites.js (content/TopSites.js)
|
content/TopSites.js (content/TopSites.js)
|
||||||
content/console.js (content/console.js)
|
content/console.js (content/console.js)
|
||||||
@ -86,12 +85,21 @@ chrome.jar:
|
|||||||
content/dbg-metro-actors.js (content/dbg-metro-actors.js)
|
content/dbg-metro-actors.js (content/dbg-metro-actors.js)
|
||||||
#ifdef MOZ_SERVICES_SYNC
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
content/flyoutpanels/SyncFlyoutPanel.js (content/flyoutpanels/SyncFlyoutPanel.js)
|
content/flyoutpanels/SyncFlyoutPanel.js (content/flyoutpanels/SyncFlyoutPanel.js)
|
||||||
content/RemoteTabs.js (content/RemoteTabs.js)
|
|
||||||
#endif
|
#endif
|
||||||
content/NavButtonSlider.js (content/NavButtonSlider.js)
|
content/NavButtonSlider.js (content/NavButtonSlider.js)
|
||||||
content/ContextUI.js (content/ContextUI.js)
|
content/ContextUI.js (content/ContextUI.js)
|
||||||
content/apzc.js (content/apzc.js)
|
content/apzc.js (content/apzc.js)
|
||||||
|
|
||||||
|
* content/Start.xul (content/startui/Start.xul)
|
||||||
|
* content/startui-scripts.js (content/startui/startui-scripts.js)
|
||||||
|
content/StartUI.js (content/startui/StartUI.js)
|
||||||
|
content/BookmarksView.js (content/startui/BookmarksView.js)
|
||||||
|
content/HistoryView.js (content/startui/HistoryView.js)
|
||||||
|
content/TopSitesView.js (content/startui/TopSitesView.js)
|
||||||
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
|
content/RemoteTabsView.js (content/startui/RemoteTabsView.js)
|
||||||
|
#endif
|
||||||
|
|
||||||
% override chrome://global/content/config.xul chrome://browser/content/config.xul
|
% override chrome://global/content/config.xul chrome://browser/content/config.xul
|
||||||
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
|
||||||
% override chrome://mozapps/content/extensions/extensions.xul chrome://browser/content/aboutAddons.xhtml
|
% override chrome://mozapps/content/extensions/extensions.xul chrome://browser/content/aboutAddons.xhtml
|
||||||
|
Loading…
Reference in New Issue
Block a user