зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to central, a=merge
MozReview-Commit-ID: LJgJXsmBQcx
This commit is contained in:
Коммит
1b5b528b2e
|
@ -144,17 +144,7 @@ var BrowserPageActions = {
|
|||
this.multiViewNode.appendChild(panelViewNode);
|
||||
}
|
||||
buttonNode.addEventListener("command", event => {
|
||||
if (panelViewNode) {
|
||||
action.subview.onShowing(panelViewNode);
|
||||
this.multiViewNode.showSubView(panelViewNode, buttonNode);
|
||||
return;
|
||||
}
|
||||
if (action.wantsIframe) {
|
||||
this._toggleActivatedActionPanelForAction(action);
|
||||
return;
|
||||
}
|
||||
this.panelNode.hidePopup();
|
||||
action.onCommand(event, buttonNode);
|
||||
this.doCommandForAction(action, event, buttonNode);
|
||||
});
|
||||
return [buttonNode, panelViewNode];
|
||||
},
|
||||
|
@ -381,14 +371,7 @@ var BrowserPageActions = {
|
|||
}
|
||||
}
|
||||
buttonNode.addEventListener("click", event => {
|
||||
if (event.button != 0) {
|
||||
return;
|
||||
}
|
||||
if (action.subview || action.wantsIframe) {
|
||||
this._toggleActivatedActionPanelForAction(action);
|
||||
return;
|
||||
}
|
||||
action.onCommand(event, buttonNode);
|
||||
this.doCommandForAction(action, event, buttonNode);
|
||||
});
|
||||
return buttonNode;
|
||||
},
|
||||
|
@ -477,12 +460,32 @@ var BrowserPageActions = {
|
|||
}
|
||||
},
|
||||
|
||||
doCommandForAction(action) {
|
||||
doCommandForAction(action, event, buttonNode) {
|
||||
if (event.type == "click" && event.button != 0) {
|
||||
return;
|
||||
}
|
||||
PageActions.logTelemetry("used", action, buttonNode);
|
||||
// If we're in the panel, open a subview inside the panel:
|
||||
// Note that we can't use this.panelNode.contains(buttonNode) here
|
||||
// because of XBL boundaries breaking ELement.contains.
|
||||
if (action.subview && buttonNode && buttonNode.closest("panel") == this.panelNode) {
|
||||
let panelViewNodeID = this._panelViewNodeIDForActionID(action.id, false);
|
||||
let panelViewNode = document.getElementById(panelViewNodeID);
|
||||
action.subview.onShowing(panelViewNode);
|
||||
this.multiViewNode.showSubView(panelViewNode, buttonNode);
|
||||
return;
|
||||
}
|
||||
// Otherwise, hide the main popup in case it was open:
|
||||
this.panelNode.hidePopup();
|
||||
|
||||
// Toggle the activated action's panel if necessary
|
||||
if (action.subview || action.wantsIframe) {
|
||||
this._toggleActivatedActionPanelForAction(action);
|
||||
return;
|
||||
}
|
||||
action.onCommand();
|
||||
|
||||
// Otherwise, run the action.
|
||||
action.onCommand(event, buttonNode);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -666,6 +669,8 @@ var BrowserPageActions = {
|
|||
if (!this._contextAction) {
|
||||
return;
|
||||
}
|
||||
let telemetryType = this._contextAction.shownInUrlbar ? "removed" : "added";
|
||||
PageActions.logTelemetry(telemetryType, this._contextAction);
|
||||
this._contextAction.shownInUrlbar = !this._contextAction.shownInUrlbar;
|
||||
},
|
||||
|
||||
|
@ -761,13 +766,6 @@ BrowserPageActions.bookmark = {
|
|||
BrowserPageActions.panelNode.hidePopup();
|
||||
BookmarkingUI.onStarCommand(event);
|
||||
},
|
||||
|
||||
onUrlbarNodeClicked(event) {
|
||||
if (event.type == "click" && event.button != 0) {
|
||||
return;
|
||||
}
|
||||
BookmarkingUI.onStarCommand(event);
|
||||
},
|
||||
};
|
||||
|
||||
// copy URL
|
||||
|
|
|
@ -288,26 +288,11 @@ var TabsInTitlebar = {
|
|||
|
||||
function updateTitlebarDisplay() {
|
||||
if (AppConstants.platform == "macosx") {
|
||||
// OS X and the other platforms differ enough to necessitate this kind of
|
||||
// special-casing. Like the other platforms where we CAN_DRAW_IN_TITLEBAR,
|
||||
// we draw in the OS X titlebar when putting the tabs up there. However, OS X
|
||||
// also draws in the titlebar when a lightweight theme is applied, regardless
|
||||
// of whether or not the tabs are drawn in the titlebar.
|
||||
if (TabsInTitlebar.enabled) {
|
||||
document.documentElement.setAttribute("chromemargin-nonlwtheme", "0,-1,-1,-1");
|
||||
document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1");
|
||||
document.documentElement.removeAttribute("drawtitle");
|
||||
} else {
|
||||
// We set chromemargin-nonlwtheme to "" instead of removing it as a way of
|
||||
// making sure that LightweightThemeConsumer doesn't take it upon itself to
|
||||
// detect this value again if and when we do a lwtheme state change.
|
||||
document.documentElement.setAttribute("chromemargin-nonlwtheme", "");
|
||||
let isCustomizing = document.documentElement.hasAttribute("customizing");
|
||||
let hasLWTheme = document.documentElement.hasAttribute("lwtheme");
|
||||
let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
|
||||
if ((!hasLWTheme || isCustomizing) && !isPrivate) {
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
}
|
||||
document.documentElement.removeAttribute("chromemargin");
|
||||
document.documentElement.setAttribute("drawtitle", "true");
|
||||
}
|
||||
} else if (TabsInTitlebar.enabled) {
|
||||
|
|
|
@ -90,12 +90,12 @@ panel[hidden] panelview {
|
|||
transition: transform var(--panelui-subview-transition-duration);
|
||||
}
|
||||
|
||||
panelview:not([mainview]):not([current]) {
|
||||
panelview:not([mainview]):not([current]):not([in-transition]) {
|
||||
transition: visibility 0s linear var(--panelui-subview-transition-duration);
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
photonpanelmultiview panelview:not([current]) {
|
||||
photonpanelmultiview panelview:not([current]):not([in-transition]) {
|
||||
transition: none;
|
||||
visibility: collapse;
|
||||
}
|
||||
|
@ -243,6 +243,10 @@ window:not([chromehidden~="toolbar"]) #nav-bar[nonemptyoverflow] > .overflow-but
|
|||
%ifdef MENUBAR_CAN_AUTOHIDE
|
||||
#toolbar-menubar:not([autohide=true]) ~ #TabsToolbar > .titlebar-placeholder,
|
||||
%endif
|
||||
%ifndef MOZ_WIDGET_COCOA
|
||||
#main-window:not([sizemode=normal]) .titlebar-placeholder[type="pre-tabs"],
|
||||
#main-window:not([sizemode=normal]) .titlebar-placeholder[type="post-tabs"],
|
||||
%endif
|
||||
#main-window:not([chromemargin]) > #titlebar,
|
||||
#main-window[inFullscreen] > #titlebar,
|
||||
#main-window[inFullscreen] .titlebar-placeholder,
|
||||
|
|
|
@ -4944,6 +4944,18 @@ var CombinedStopReload = {
|
|||
if (XULBrowserWindow.stopCommand.getAttribute("disabled") != "true")
|
||||
reload.setAttribute("displaystop", "true");
|
||||
stop.addEventListener("click", this);
|
||||
|
||||
// Removing attributes based on the observed command doesn't happen if the button
|
||||
// is in the palette when the command's attribute is removed (cf. bug 309953)
|
||||
for (let button of [stop, reload]) {
|
||||
if (button.hasAttribute("disabled")) {
|
||||
let command = document.getElementById(button.getAttribute("command"));
|
||||
if (!command.hasAttribute("disabled")) {
|
||||
button.removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.reload = reload;
|
||||
this.stop = stop;
|
||||
this.stopReloadContainer = this.reload.parentNode;
|
||||
|
|
|
@ -900,7 +900,7 @@
|
|||
class="urlbar-icon-wrapper urlbar-page-action"
|
||||
context="pageActionPanelContextMenu"
|
||||
oncontextmenu="BrowserPageActions.onContextMenu(event);"
|
||||
onclick="BrowserPageActions.bookmark.onUrlbarNodeClicked(event);">
|
||||
onclick="BrowserPageActions.doCommandForAction(PageActions.actionForID('bookmark'), event, this);">
|
||||
<image id="star-button"
|
||||
class="urlbar-icon"
|
||||
role="button"
|
||||
|
|
|
@ -68,7 +68,7 @@ const EXPECTED_APPMENU_SUBVIEW_REFLOWS = [
|
|||
{
|
||||
stack: [
|
||||
"descriptionHeightWorkaround@resource:///modules/PanelMultiView.jsm",
|
||||
"_cleanupTransitionPhase@resource:///modules/PanelMultiView.jsm",
|
||||
"hideAllViewsExcept@resource:///modules/PanelMultiView.jsm",
|
||||
],
|
||||
|
||||
times: 2, // This number should only ever go down - never up.
|
||||
|
|
|
@ -1311,7 +1311,9 @@ CustomizeMode.prototype = {
|
|||
|
||||
onLWThemesMenuShowing(aEvent) {
|
||||
const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
|
||||
const RECENT_LWT_COUNT = 5;
|
||||
const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
|
||||
const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
|
||||
const MAX_THEME_COUNT = 6;
|
||||
|
||||
this._clearLWThemesMenu(aEvent.target);
|
||||
|
||||
|
@ -1366,20 +1368,28 @@ CustomizeMode.prototype = {
|
|||
let themes = [aDefaultTheme];
|
||||
let lwts = LightweightThemeManager.usedThemes;
|
||||
let currentLwt = LightweightThemeManager.currentTheme;
|
||||
let currentLwtIndex = lwts.indexOf(currentLwt);
|
||||
if (currentLwtIndex > -1) {
|
||||
// Make sure that the current lightweight theme
|
||||
// is at the beginning of the array to avoid truncation
|
||||
// in the next step.
|
||||
lwts = lwts.splice(currentLwtIndex, 1).concat(lwts);
|
||||
}
|
||||
if (lwts.length > RECENT_LWT_COUNT)
|
||||
lwts.length = RECENT_LWT_COUNT;
|
||||
// The lwts besides the builtin themes don't have an isActive property:
|
||||
for (let lwt of lwts) {
|
||||
lwt.isActive = !!currentLwt && (lwt.id == currentLwt.id);
|
||||
themes.push(lwt);
|
||||
if (!lwt.hasOwnProperty("isActive")) {
|
||||
lwt.isActive = !!currentLwt && (lwt.id == currentLwt.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Move the current theme (if any) and the light/dark themes to the start:
|
||||
let importantThemes = [LIGHT_THEME_ID, DARK_THEME_ID];
|
||||
if (currentLwt && !importantThemes.includes(currentLwt.id)) {
|
||||
importantThemes.push(currentLwt.id);
|
||||
}
|
||||
for (let importantTheme of importantThemes) {
|
||||
let themeIndex = lwts.findIndex(theme => theme.id == importantTheme);
|
||||
if (themeIndex > -1) {
|
||||
themes.push(...lwts.splice(themeIndex, 1));
|
||||
}
|
||||
}
|
||||
themes = themes.concat(lwts);
|
||||
if (themes.length > MAX_THEME_COUNT)
|
||||
themes.length = MAX_THEME_COUNT;
|
||||
|
||||
let footer = doc.getElementById("customization-lwtheme-menu-footer");
|
||||
let panel = footer.parentNode;
|
||||
let recommendedLabel = doc.getElementById("customization-lwtheme-menu-recommended");
|
||||
|
@ -1400,8 +1410,15 @@ CustomizeMode.prototype = {
|
|||
recommendedThemes = JSON.parse(recommendedThemes);
|
||||
let sb = Services.strings.createBundle("chrome://browser/locale/lightweightThemes.properties");
|
||||
for (let theme of recommendedThemes) {
|
||||
theme.name = sb.GetStringFromName("lightweightThemes." + theme.id + ".name");
|
||||
theme.description = sb.GetStringFromName("lightweightThemes." + theme.id + ".description");
|
||||
try {
|
||||
theme.name = sb.GetStringFromName("lightweightThemes." + theme.id + ".name");
|
||||
theme.description = sb.GetStringFromName("lightweightThemes." + theme.id + ".description");
|
||||
} catch (ex) {
|
||||
// If finding strings for this failed, just don't build it. This can
|
||||
// happen for users with 'older' recommended themes lists, some of which
|
||||
// have since been removed from Firefox.
|
||||
continue;
|
||||
}
|
||||
let button = buildToolbarButton(theme);
|
||||
button.addEventListener("command", () => {
|
||||
LightweightThemeManager.setLocalTheme(button.theme);
|
||||
|
|
|
@ -191,6 +191,15 @@ this.PanelMultiView = class {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Boolean} |true| when the 'ephemeral' attribute is set, which means
|
||||
* that this instance should be ready to be thrown away at
|
||||
* any time.
|
||||
*/
|
||||
get _ephemeral() {
|
||||
return this.node.hasAttribute("ephemeral");
|
||||
}
|
||||
|
||||
get panelViews() {
|
||||
// If there's a dedicated subViews container, we're not in the right binding
|
||||
// to use SlidingPanelViews.
|
||||
|
@ -217,10 +226,9 @@ this.PanelMultiView = class {
|
|||
.getService(Ci.nsIScreenManager);
|
||||
}
|
||||
/**
|
||||
* Getter that returns the currently visible subview OR the subview that is
|
||||
* about to be shown whilst a 'ViewShowing' event is being dispatched.
|
||||
*
|
||||
* @return {panelview}
|
||||
* @return {panelview} the currently visible subview OR the subview that is
|
||||
* about to be shown whilst a 'ViewShowing' event is being
|
||||
* dispatched.
|
||||
*/
|
||||
get current() {
|
||||
return this._viewShowing || this._currentSubView
|
||||
|
@ -235,6 +243,13 @@ this.PanelMultiView = class {
|
|||
this.__currentSubView = panel;
|
||||
return panel;
|
||||
}
|
||||
/**
|
||||
* @return {Promise} showSubView() returns a promise, which is kept here for
|
||||
* random access.
|
||||
*/
|
||||
get currentShowPromise() {
|
||||
return this._currentShowPromise || Promise.resolve();
|
||||
}
|
||||
get _keyNavigationMap() {
|
||||
if (!this.__keyNavigationMap)
|
||||
this.__keyNavigationMap = new Map();
|
||||
|
@ -316,9 +331,11 @@ this.PanelMultiView = class {
|
|||
value: (...args) => this[method](...args)
|
||||
});
|
||||
});
|
||||
Object.defineProperty(this.node, "current", {
|
||||
enumerable: true,
|
||||
get: () => this.current
|
||||
["current", "currentShowPromise"].forEach(property => {
|
||||
Object.defineProperty(this.node, property, {
|
||||
enumerable: true,
|
||||
get: () => this[property]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -327,8 +344,10 @@ this.PanelMultiView = class {
|
|||
if (!this.node)
|
||||
return;
|
||||
|
||||
if (this._mainView) {
|
||||
let mainView = this._mainView;
|
||||
if (this._ephemeral)
|
||||
this.hideAllViewsExcept(null);
|
||||
let mainView = this._mainView;
|
||||
if (mainView) {
|
||||
if (this._panelViewCache)
|
||||
this._panelViewCache.appendChild(mainView);
|
||||
mainView.removeAttribute("mainview");
|
||||
|
@ -395,10 +414,13 @@ this.PanelMultiView = class {
|
|||
* @return {Boolean}
|
||||
*/
|
||||
_canGoBack(view = this._currentSubView) {
|
||||
return view != this._mainView;
|
||||
return view.id != this._mainViewId;
|
||||
}
|
||||
|
||||
setMainView(aNewMainView) {
|
||||
if (!aNewMainView)
|
||||
return;
|
||||
|
||||
if (this._mainView) {
|
||||
if (!this.panelViews)
|
||||
this._subViews.appendChild(this._mainView);
|
||||
|
@ -418,38 +440,59 @@ this.PanelMultiView = class {
|
|||
}
|
||||
|
||||
showMainView() {
|
||||
if (!this._mainViewId)
|
||||
return Promise.resolve();
|
||||
|
||||
if (this.panelViews)
|
||||
return this.showSubView(this._mainView);
|
||||
|
||||
if (this.showingSubView) {
|
||||
let viewNode = this._currentSubView;
|
||||
this._dispatchViewEvent(viewNode, "ViewHiding");
|
||||
if (this.panelViews) {
|
||||
this._transitionHeight(() => {
|
||||
viewNode.removeAttribute("current");
|
||||
this.showSubView(this._mainViewId);
|
||||
} else {
|
||||
this._transitionHeight(() => {
|
||||
viewNode.removeAttribute("current");
|
||||
this._currentSubView = null;
|
||||
this.node.setAttribute("viewtype", "main");
|
||||
});
|
||||
}
|
||||
} else if (this.panelViews) {
|
||||
// Make sure to hide all subviews, except for the mainView.
|
||||
let mainView = this._mainView;
|
||||
for (let panelview of this._panelViews) {
|
||||
if (panelview == mainView)
|
||||
panelview.setAttribute("current", true);
|
||||
else
|
||||
panelview.removeAttribute("current");
|
||||
}
|
||||
this.node.setAttribute("viewtype", "main");
|
||||
this._currentSubView = null;
|
||||
this.node.setAttribute("viewtype", "main");
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.panelViews) {
|
||||
this._shiftMainView();
|
||||
this._shiftMainView();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that all the panelviews, that are currently part of this instance,
|
||||
* are hidden, except one specifically.
|
||||
*
|
||||
* @param {panelview} [theOne] The panelview DOM node to ensure is visible.
|
||||
* Optional.
|
||||
*/
|
||||
hideAllViewsExcept(theOne = null) {
|
||||
for (let panelview of this._panelViews) {
|
||||
// When the panelview was already reparented, don't interfere any more.
|
||||
if (panelview == theOne || !this.node || panelview.panelMultiView != this.node)
|
||||
continue;
|
||||
if (panelview.hasAttribute("current"))
|
||||
this._dispatchViewEvent(panelview, "ViewHiding");
|
||||
panelview.removeAttribute("current");
|
||||
}
|
||||
|
||||
this._viewShowing = null;
|
||||
|
||||
if (!this.node || !theOne)
|
||||
return;
|
||||
|
||||
this._currentSubView = theOne;
|
||||
if (!theOne.hasAttribute("current")) {
|
||||
theOne.setAttribute("current", true);
|
||||
this.descriptionHeightWorkaround(theOne);
|
||||
this._dispatchViewEvent(theOne, "ViewShown");
|
||||
}
|
||||
this.node.setAttribute("viewtype", (theOne.id == this._mainViewId) ? "main" : "subview");
|
||||
}
|
||||
|
||||
showSubView(aViewId, aAnchor, aPreviousView) {
|
||||
return (async () => {
|
||||
this._currentShowPromise = (async () => {
|
||||
// Support passing in the node directly.
|
||||
let viewNode = typeof aViewId == "string" ? this.node.querySelector("#" + aViewId) : aViewId;
|
||||
if (!viewNode) {
|
||||
|
@ -465,8 +508,10 @@ this.PanelMultiView = class {
|
|||
|
||||
let reverse = !!aPreviousView;
|
||||
let previousViewNode = aPreviousView || this._currentSubView;
|
||||
let playTransition = (!!previousViewNode && previousViewNode != viewNode &&
|
||||
this._panel.state == "open");
|
||||
// If the panelview to show is the same as the previous one, the 'ViewShowing'
|
||||
// event has already been dispatched. Don't do it twice.
|
||||
let showingSameView = viewNode == previousViewNode;
|
||||
let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
|
||||
|
||||
let dwu, previousRect;
|
||||
if (playTransition || this.panelViews) {
|
||||
|
@ -492,6 +537,13 @@ this.PanelMultiView = class {
|
|||
}
|
||||
|
||||
this._viewShowing = viewNode;
|
||||
// Because the 'mainview' attribute may be out-of-sync, due to view node
|
||||
// reparenting in combination with ephemeral PanelMultiView instances,
|
||||
// this is the best place to correct it (just before showing).
|
||||
if (viewNode.id == this._mainViewId)
|
||||
viewNode.setAttribute("mainview", true);
|
||||
else
|
||||
viewNode.removeAttribute("mainview");
|
||||
|
||||
// Make sure that new panels always have a title set.
|
||||
if (this.panelViews && aAnchor) {
|
||||
|
@ -502,53 +554,45 @@ this.PanelMultiView = class {
|
|||
if (this.panelViews && this._mainViewWidth)
|
||||
viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
|
||||
|
||||
// Emit the ViewShowing event so that the widget definition has a chance
|
||||
// to lazily populate the subview with things or perhaps even cancel this
|
||||
// whole operation.
|
||||
let detail = {
|
||||
blockers: new Set(),
|
||||
addBlocker(promise) {
|
||||
this.blockers.add(promise);
|
||||
if (!showingSameView || !viewNode.hasAttribute("current")) {
|
||||
// Emit the ViewShowing event so that the widget definition has a chance
|
||||
// to lazily populate the subview with things or perhaps even cancel this
|
||||
// whole operation.
|
||||
let detail = {
|
||||
blockers: new Set(),
|
||||
addBlocker(promise) {
|
||||
this.blockers.add(promise);
|
||||
}
|
||||
};
|
||||
let cancel = this._dispatchViewEvent(viewNode, "ViewShowing", aAnchor, detail);
|
||||
if (detail.blockers.size) {
|
||||
try {
|
||||
let results = await Promise.all(detail.blockers);
|
||||
cancel = cancel || results.some(val => val === false);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
let cancel = this._dispatchViewEvent(viewNode, "ViewShowing", aAnchor, detail);
|
||||
if (detail.blockers.size) {
|
||||
try {
|
||||
let results = await Promise.all(detail.blockers);
|
||||
cancel = cancel || results.some(val => val === false);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
this._viewShowing = null;
|
||||
if (cancel) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._currentSubView = viewNode;
|
||||
if (this.panelViews) {
|
||||
if (viewNode.id == this._mainViewId) {
|
||||
this.node.setAttribute("viewtype", "main");
|
||||
} else {
|
||||
this.node.setAttribute("viewtype", "subview");
|
||||
}
|
||||
// If we've got an older transition still running, make sure to clean it up.
|
||||
await this._cleanupTransitionPhase();
|
||||
if (!playTransition) {
|
||||
viewNode.setAttribute("current", true);
|
||||
this.descriptionHeightWorkaround(viewNode);
|
||||
if (cancel) {
|
||||
this._viewShowing = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we have to transition the panel.
|
||||
if (this.panelViews && playTransition) {
|
||||
await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
|
||||
|
||||
this._dispatchViewEvent(viewNode, "ViewShown");
|
||||
this._updateKeyboardFocus(viewNode);
|
||||
} else if (!this.panelViews) {
|
||||
if (this.panelViews) {
|
||||
// If we've got an older transition still running, make sure to clean it up.
|
||||
await this._cleanupTransitionPhase();
|
||||
if (playTransition) {
|
||||
await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
|
||||
this._updateKeyboardFocus(viewNode);
|
||||
} else {
|
||||
this.hideAllViewsExcept(viewNode);
|
||||
}
|
||||
} else {
|
||||
this._currentSubView = viewNode;
|
||||
this._transitionHeight(() => {
|
||||
viewNode.setAttribute("current", true);
|
||||
if (viewNode.id == this._mainViewId) {
|
||||
|
@ -564,6 +608,7 @@ this.PanelMultiView = class {
|
|||
this._shiftMainView(aAnchor);
|
||||
}
|
||||
})().catch(e => Cu.reportError(e));
|
||||
return this._currentShowPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -596,7 +641,7 @@ this.PanelMultiView = class {
|
|||
if (this._autoResizeWorkaroundTimer)
|
||||
window.clearTimeout(this._autoResizeWorkaroundTimer);
|
||||
|
||||
this._transitionDetails = {
|
||||
let details = this._transitionDetails = {
|
||||
phase: TRANSITION_PHASES.START,
|
||||
previousViewNode, viewNode, reverse, anchor
|
||||
};
|
||||
|
@ -604,6 +649,10 @@ this.PanelMultiView = class {
|
|||
if (anchor)
|
||||
anchor.setAttribute("open", "true");
|
||||
|
||||
// Since we're going to show two subview at the same time, don't abuse the
|
||||
// 'current' attribute, since it's needed for other state-keeping, but use
|
||||
// a separate 'in-transition' attribute instead.
|
||||
previousViewNode.setAttribute("in-transition", true);
|
||||
// Set the viewContainer dimensions to make sure only the current view is
|
||||
// visible.
|
||||
this._viewContainer.style.height = Math.max(previousRect.height, this._mainViewHeight) + "px";
|
||||
|
@ -616,7 +665,7 @@ this.PanelMultiView = class {
|
|||
let viewRect;
|
||||
if (viewNode.__lastKnownBoundingRect) {
|
||||
viewRect = viewNode.__lastKnownBoundingRect;
|
||||
viewNode.setAttribute("current", true);
|
||||
viewNode.setAttribute("in-transition", true);
|
||||
} else if (viewNode.customRectGetter) {
|
||||
// Can't use Object.assign directly with a DOM Rect object because its properties
|
||||
// aren't enumerable.
|
||||
|
@ -626,11 +675,11 @@ this.PanelMultiView = class {
|
|||
if (header) {
|
||||
viewRect.height += this._dwu.getBoundsWithoutFlushing(header).height;
|
||||
}
|
||||
viewNode.setAttribute("current", true);
|
||||
viewNode.setAttribute("in-transition", true);
|
||||
} else {
|
||||
let oldSibling = viewNode.nextSibling || null;
|
||||
this._offscreenViewStack.appendChild(viewNode);
|
||||
viewNode.setAttribute("current", true);
|
||||
viewNode.setAttribute("in-transition", true);
|
||||
|
||||
viewRect = await BrowserUtils.promiseLayoutFlushed(this.document, "layout", () => {
|
||||
return this._dwu.getBoundsWithoutFlushing(viewNode);
|
||||
|
@ -644,7 +693,7 @@ this.PanelMultiView = class {
|
|||
}
|
||||
|
||||
this._transitioning = true;
|
||||
this._transitionDetails.phase = TRANSITION_PHASES.PREPARE;
|
||||
details.phase = TRANSITION_PHASES.PREPARE;
|
||||
|
||||
// The 'magic' part: build up the amount of pixels to move right or left.
|
||||
let moveToLeft = (this._dir == "rtl" && !reverse) || (this._dir == "ltr" && reverse);
|
||||
|
@ -679,26 +728,26 @@ this.PanelMultiView = class {
|
|||
await BrowserUtils.promiseLayoutFlushed(document, "layout", () => {});
|
||||
|
||||
// Kick off the transition!
|
||||
this._transitionDetails.phase = TRANSITION_PHASES.TRANSITION;
|
||||
details.phase = TRANSITION_PHASES.TRANSITION;
|
||||
this._viewStack.style.transform = "translateX(" + (moveToLeft ? "" : "-") + deltaX + "px)";
|
||||
|
||||
await new Promise(resolve => {
|
||||
this._transitionDetails.resolve = resolve;
|
||||
this._viewContainer.addEventListener("transitionend", this._transitionDetails.listener = ev => {
|
||||
details.resolve = resolve;
|
||||
this._viewContainer.addEventListener("transitionend", details.listener = ev => {
|
||||
// It's quite common that `height` on the view container doesn't need
|
||||
// to transition, so we make sure to do all the work on the transform
|
||||
// transition-end, because that is guaranteed to happen.
|
||||
if (ev.target != this._viewStack || ev.propertyName != "transform")
|
||||
return;
|
||||
this._viewContainer.removeEventListener("transitionend", this._transitionDetails.listener);
|
||||
delete this._transitionDetails.listener;
|
||||
this._viewContainer.removeEventListener("transitionend", details.listener);
|
||||
delete details.listener;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
this._transitionDetails.phase = TRANSITION_PHASES.END;
|
||||
details.phase = TRANSITION_PHASES.END;
|
||||
|
||||
await this._cleanupTransitionPhase();
|
||||
await this._cleanupTransitionPhase(details);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -706,8 +755,9 @@ this.PanelMultiView = class {
|
|||
* above. Which attributes and properties depends on the phase the transition
|
||||
* was left from - normally that'd be `TRANSITION_PHASES.END`.
|
||||
*/
|
||||
async _cleanupTransitionPhase() {
|
||||
if (!this._transitionDetails)
|
||||
async _cleanupTransitionPhase(details = this._transitionDetails) {
|
||||
// Make sure to only clean up a phase from the most recent transition.
|
||||
if (!this._transitionDetails || details != this._transitionDetails)
|
||||
return;
|
||||
|
||||
let {phase, previousViewNode, viewNode, reverse, resolve, listener, anchor} = this._transitionDetails;
|
||||
|
@ -715,11 +765,11 @@ this.PanelMultiView = class {
|
|||
|
||||
// Do the things we _always_ need to do whenever the transition ends or is
|
||||
// interrupted.
|
||||
this._dispatchViewEvent(previousViewNode, "ViewHiding");
|
||||
previousViewNode.removeAttribute("current");
|
||||
this.hideAllViewsExcept(viewNode);
|
||||
previousViewNode.removeAttribute("in-transition");
|
||||
viewNode.removeAttribute("in-transition");
|
||||
if (reverse)
|
||||
this._resetKeyNavigation(previousViewNode);
|
||||
this.descriptionHeightWorkaround(viewNode);
|
||||
|
||||
if (anchor)
|
||||
anchor.removeAttribute("open");
|
||||
|
@ -915,7 +965,7 @@ this.PanelMultiView = class {
|
|||
case "mousemove":
|
||||
this._resetKeyNavigation();
|
||||
break;
|
||||
case "popupshowing":
|
||||
case "popupshowing": {
|
||||
this.node.setAttribute("panelopen", "true");
|
||||
// Bug 941196 - The panel can get taller when opening a subview. Disabling
|
||||
// autoPositioning means that the panel won't jump around if an opened
|
||||
|
@ -971,13 +1021,14 @@ this.PanelMultiView = class {
|
|||
// without any scrolling (using "display: flex;"), and only if the view
|
||||
// exceeds the available space we set the height explicitly and enable
|
||||
// scrolling.
|
||||
if (this._mainView.hasAttribute("blockinboxworkaround")) {
|
||||
let mainView = this._mainView;
|
||||
if (mainView && mainView.hasAttribute("blockinboxworkaround")) {
|
||||
let blockInBoxWorkaround = () => {
|
||||
let mainViewHeight =
|
||||
this._dwu.getBoundsWithoutFlushing(this._mainView).height;
|
||||
this._dwu.getBoundsWithoutFlushing(mainView).height;
|
||||
if (mainViewHeight > maxHeight) {
|
||||
this._mainView.style.height = maxHeight + "px";
|
||||
this._mainView.setAttribute("exceeding", "true");
|
||||
mainView.style.height = maxHeight + "px";
|
||||
mainView.setAttribute("exceeding", "true");
|
||||
}
|
||||
};
|
||||
// On Windows, we cannot measure the full height of the main view
|
||||
|
@ -993,12 +1044,14 @@ this.PanelMultiView = class {
|
|||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "popupshown":
|
||||
// Now that the main view is visible, we can check the height of the
|
||||
// description elements it contains.
|
||||
this.descriptionHeightWorkaround();
|
||||
if (!this.panelViews)
|
||||
this.descriptionHeightWorkaround();
|
||||
break;
|
||||
case "popuphidden":
|
||||
case "popuphidden": {
|
||||
// WebExtensions consumers can hide the popup from viewshowing, or
|
||||
// mid-transition, which disrupts our state:
|
||||
this._viewShowing = null;
|
||||
|
@ -1029,12 +1082,14 @@ this.PanelMultiView = class {
|
|||
|
||||
// Always try to layout the panel normally when reopening it. This is
|
||||
// also the layout that will be used in customize mode.
|
||||
if (this._mainView.hasAttribute("blockinboxworkaround")) {
|
||||
this._mainView.style.removeProperty("height");
|
||||
this._mainView.removeAttribute("exceeding");
|
||||
let mainView = this._mainView;
|
||||
if (mainView && mainView.hasAttribute("blockinboxworkaround")) {
|
||||
mainView.style.removeProperty("height");
|
||||
mainView.removeAttribute("exceeding");
|
||||
}
|
||||
this._dispatchViewEvent(this.node, "PanelMultiViewHidden");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,7 +1312,7 @@ this.PanelMultiView = class {
|
|||
* view if omitted.
|
||||
*/
|
||||
descriptionHeightWorkaround(viewNode = this._mainView) {
|
||||
if (!viewNode.hasAttribute("descriptionheightworkaround")) {
|
||||
if (!viewNode || !viewNode.hasAttribute("descriptionheightworkaround")) {
|
||||
// This view does not require the workaround.
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -419,31 +419,37 @@ const PanelUI = {
|
|||
tempPanel.setAttribute("animate", "false");
|
||||
}
|
||||
tempPanel.setAttribute("context", "");
|
||||
tempPanel.setAttribute("photon", true);
|
||||
document.getElementById(CustomizableUI.AREA_NAVBAR).appendChild(tempPanel);
|
||||
// If the view has a footer, set a convenience class on the panel.
|
||||
tempPanel.classList.toggle("cui-widget-panelWithFooter",
|
||||
viewNode.querySelector(".panel-subview-footer"));
|
||||
|
||||
// If the panelview is already selected in another PanelMultiView instance
|
||||
// as a subview, make sure to properly hide it there.
|
||||
let oldMultiView = viewNode.panelMultiView;
|
||||
if (oldMultiView && oldMultiView.current == viewNode) {
|
||||
await oldMultiView.showMainView();
|
||||
}
|
||||
|
||||
let viewShown = false;
|
||||
let listener = () => viewShown = true;
|
||||
viewNode.addEventListener("ViewShown", listener, {once: true});
|
||||
|
||||
let multiView = document.createElement("photonpanelmultiview");
|
||||
multiView.setAttribute("id", "customizationui-widget-multiview");
|
||||
multiView.setAttribute("nosubviews", "true");
|
||||
multiView.setAttribute("viewCacheId", "appMenu-viewCache");
|
||||
tempPanel.setAttribute("photon", true);
|
||||
multiView.setAttribute("mainViewId", viewNode.id);
|
||||
multiView.appendChild(viewNode);
|
||||
multiView.setAttribute("ephemeral", true);
|
||||
document.getElementById("appMenu-viewCache").appendChild(viewNode);
|
||||
tempPanel.appendChild(multiView);
|
||||
viewNode.classList.add("cui-widget-panelview");
|
||||
|
||||
let viewShown = false;
|
||||
let panelRemover = () => {
|
||||
viewNode.classList.remove("cui-widget-panelview");
|
||||
if (viewShown) {
|
||||
CustomizableUI.removePanelCloseListeners(tempPanel);
|
||||
tempPanel.removeEventListener("popuphidden", panelRemover);
|
||||
|
||||
let currentView = multiView.current || viewNode;
|
||||
let evt = new CustomEvent("ViewHiding", {detail: currentView});
|
||||
currentView.dispatchEvent(evt);
|
||||
}
|
||||
aAnchor.open = false;
|
||||
|
||||
|
@ -453,35 +459,15 @@ const PanelUI = {
|
|||
tempPanel.remove();
|
||||
};
|
||||
|
||||
// Emit the ViewShowing event so that the widget definition has a chance
|
||||
// to lazily populate the subview with things.
|
||||
let detail = {
|
||||
blockers: new Set(),
|
||||
addBlocker(aPromise) {
|
||||
this.blockers.add(aPromise);
|
||||
},
|
||||
};
|
||||
// Wait until all the tasks needed to show a view are done.
|
||||
await multiView.currentShowPromise;
|
||||
|
||||
let evt = new CustomEvent("ViewShowing", { bubbles: true, cancelable: true, detail });
|
||||
viewNode.dispatchEvent(evt);
|
||||
|
||||
let cancel = evt.defaultPrevented;
|
||||
if (detail.blockers.size) {
|
||||
try {
|
||||
let results = await Promise.all(detail.blockers);
|
||||
cancel = cancel || results.some(val => val === false);
|
||||
} catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (cancel) {
|
||||
if (!viewShown) {
|
||||
viewNode.removeEventListener("ViewShown", listener);
|
||||
panelRemover();
|
||||
return;
|
||||
}
|
||||
|
||||
viewShown = true;
|
||||
CustomizableUI.addPanelCloseListeners(tempPanel);
|
||||
tempPanel.addEventListener("popuphidden", panelRemover);
|
||||
|
||||
|
@ -539,7 +525,8 @@ const PanelUI = {
|
|||
withFavicons: true
|
||||
});
|
||||
// If there's nothing to display, or the panel is already hidden, get out.
|
||||
if (!highlights.length || viewNode.panelMultiView.getAttribute("panelopen") != "true") {
|
||||
let multiView = viewNode.panelMultiView;
|
||||
if (!highlights.length || (multiView && multiView.getAttribute("panelopen") != "true")) {
|
||||
this._loadingRecentHighlights = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
"use strict";
|
||||
|
||||
const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
|
||||
const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
|
||||
const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
|
||||
const {LightweightThemeManager} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
|
||||
|
||||
add_task(async function() {
|
||||
Services.prefs.clearUserPref("lightweightThemes.usedThemes");
|
||||
Services.prefs.clearUserPref("lightweightThemes.recommendedThemes");
|
||||
LightweightThemeManager.clearBuiltInThemes();
|
||||
|
||||
await startCustomizing();
|
||||
|
||||
|
@ -35,9 +36,14 @@ add_task(async function() {
|
|||
let header = document.getElementById("customization-lwtheme-menu-header");
|
||||
let recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended");
|
||||
|
||||
is(header.nextSibling.nextSibling, recommendedHeader,
|
||||
"There should only be one theme (default) in the 'My Themes' section by default");
|
||||
is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "That theme should be the default theme");
|
||||
is(header.nextSibling.nextSibling.nextSibling.nextSibling, recommendedHeader,
|
||||
"There should only be three themes (default, light, dark) in the 'My Themes' section by default");
|
||||
is(header.nextSibling.theme.id, DEFAULT_THEME_ID,
|
||||
"The first theme should be the default theme");
|
||||
is(header.nextSibling.nextSibling.theme.id, LIGHT_THEME_ID,
|
||||
"The second theme should be the light theme");
|
||||
is(header.nextSibling.nextSibling.nextSibling.theme.id, DARK_THEME_ID,
|
||||
"The third theme should be the dark theme");
|
||||
|
||||
let firstLWTheme = recommendedHeader.nextSibling;
|
||||
let firstLWThemeId = firstLWTheme.theme.id;
|
||||
|
@ -52,12 +58,18 @@ add_task(async function() {
|
|||
await popupShownPromise;
|
||||
|
||||
is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
|
||||
let installedThemeId = header.nextSibling.nextSibling.theme.id;
|
||||
let installedThemeId = header.nextSibling.nextSibling.nextSibling.nextSibling.theme.id;
|
||||
ok(installedThemeId.startsWith(firstLWThemeId),
|
||||
"The second theme in the 'My Themes' section should be the newly installed theme: " +
|
||||
"Installed theme id: " + installedThemeId + "; First theme ID: " + firstLWThemeId);
|
||||
is(header.nextSibling.nextSibling.nextSibling, recommendedHeader,
|
||||
"There should be two themes in the 'My Themes' section");
|
||||
let themeCount = 0;
|
||||
let iterNode = header;
|
||||
while (iterNode.nextSibling && iterNode.nextSibling.theme) {
|
||||
themeCount++;
|
||||
iterNode = iterNode.nextSibling;
|
||||
}
|
||||
is(themeCount, 4,
|
||||
"There should be four themes in the 'My Themes' section");
|
||||
|
||||
let defaultTheme = header.nextSibling;
|
||||
defaultTheme.doCommand();
|
||||
|
@ -90,11 +102,21 @@ add_task(async function() {
|
|||
await popupShownPromise;
|
||||
header = document.getElementById("customization-lwtheme-menu-header");
|
||||
is(header.hidden, false, "Header should never be hidden");
|
||||
is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
|
||||
is(header.nextSibling.hidden, false, "The default theme should never be hidden");
|
||||
let themeNode = header.nextSibling;
|
||||
is(themeNode.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
|
||||
is(themeNode.hidden, false, "The default theme should never be hidden");
|
||||
|
||||
themeNode = themeNode.nextSibling;
|
||||
is(themeNode.theme.id, LIGHT_THEME_ID, "The second theme should be the Light theme");
|
||||
is(themeNode.hidden, false, "The light theme should never be hidden");
|
||||
|
||||
themeNode = themeNode.nextSibling;
|
||||
is(themeNode.theme.id, DARK_THEME_ID, "The third theme should be the Dark theme");
|
||||
is(themeNode.hidden, false, "The dark theme should never be hidden");
|
||||
|
||||
recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended");
|
||||
is(header.nextSibling.nextSibling, recommendedHeader,
|
||||
"There should only be one theme (default) in the 'My Themes' section by default");
|
||||
is(themeNode.nextSibling, recommendedHeader,
|
||||
"There should only be three themes (default, light, dark) in the 'My Themes' section now");
|
||||
let footer = document.getElementById("customization-lwtheme-menu-footer");
|
||||
is(recommendedHeader.nextSibling.id, footer.id, "There should be no recommended themes in the menu");
|
||||
is(recommendedHeader.hidden, true, "The recommendedHeader should be hidden since there are no recommended themes");
|
||||
|
|
|
@ -35,15 +35,16 @@ function checkSeparatorInsertion(menuId, buttonId, subviewId) {
|
|||
|
||||
await document.getElementById("nav-bar").overflowable.show();
|
||||
|
||||
let subview = document.getElementById(subviewId);
|
||||
let button = document.getElementById(buttonId);
|
||||
button.click();
|
||||
await BrowserTestUtils.waitForEvent(subview, "ViewShown");
|
||||
|
||||
await BrowserTestUtils.waitForEvent(PanelUI.overflowPanel, "ViewShown");
|
||||
let subview = document.getElementById(subviewId);
|
||||
ok(subview.firstChild, "Subview should have a kid");
|
||||
is(subview.firstChild.localName, "toolbarbutton", "There should be no separators to start with");
|
||||
let subviewBody = subview.firstChild;
|
||||
ok(subviewBody.firstChild, "Subview should have a kid");
|
||||
is(subviewBody.firstChild.localName, "toolbarbutton", "There should be no separators to start with");
|
||||
|
||||
for (let kid of subview.children) {
|
||||
for (let kid of subviewBody.children) {
|
||||
if (kid.localName == "menuseparator") {
|
||||
ok(kid.previousSibling && kid.previousSibling.localName != "menuseparator",
|
||||
"Separators should never have another separator next to them, and should never be the first node.");
|
||||
|
@ -58,7 +59,7 @@ function checkSeparatorInsertion(menuId, buttonId, subviewId) {
|
|||
};
|
||||
}
|
||||
|
||||
add_task(checkSeparatorInsertion("menuWebDeveloperPopup", "developer-button", "PanelUI-developerItems"));
|
||||
add_task(checkSeparatorInsertion("menuWebDeveloperPopup", "developer-button", "PanelUI-developer"));
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
for (let el of tempElements) {
|
||||
|
|
|
@ -8,7 +8,6 @@ const kWidgetId = "test-981418-widget-onbeforecreated";
|
|||
|
||||
// Should be able to add broken view widget
|
||||
add_task(async function testAddOnBeforeCreatedWidget() {
|
||||
let viewShownDeferred = Promise.defer();
|
||||
let onBeforeCreatedCalled = false;
|
||||
let widgetSpec = {
|
||||
id: kWidgetId,
|
||||
|
@ -17,73 +16,47 @@ add_task(async function testAddOnBeforeCreatedWidget() {
|
|||
onBeforeCreated(doc) {
|
||||
let view = doc.createElement("panelview");
|
||||
view.id = kWidgetId + "idontexistyet";
|
||||
document.getElementById("PanelUI-multiView").appendChild(view);
|
||||
document.getElementById("appMenu-viewCache").appendChild(view);
|
||||
onBeforeCreatedCalled = true;
|
||||
},
|
||||
onViewShowing() {
|
||||
viewShownDeferred.resolve();
|
||||
}
|
||||
};
|
||||
|
||||
let noError = true;
|
||||
try {
|
||||
CustomizableUI.createWidget(widgetSpec);
|
||||
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_NAVBAR);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
noError = false;
|
||||
}
|
||||
ok(noError, "Should not throw an exception trying to add the widget.");
|
||||
CustomizableUI.createWidget(widgetSpec);
|
||||
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_NAVBAR);
|
||||
|
||||
ok(onBeforeCreatedCalled, "onBeforeCreated should have been called");
|
||||
|
||||
let widgetNode = document.getElementById(kWidgetId);
|
||||
let viewNode = document.getElementById(kWidgetId + "idontexistyet");
|
||||
ok(widgetNode, "Widget should exist");
|
||||
if (widgetNode) {
|
||||
try {
|
||||
widgetNode.click();
|
||||
ok(viewNode, "Panelview should exist");
|
||||
widgetNode.click();
|
||||
|
||||
let tempPanel = document.getElementById("customizationui-widget-panel");
|
||||
let panelShownPromise = promisePanelElementShown(window, tempPanel);
|
||||
let tempPanel = document.getElementById("customizationui-widget-panel");
|
||||
let panelShownPromise = promisePanelElementShown(window, tempPanel);
|
||||
|
||||
let shownTimeout = setTimeout(() => viewShownDeferred.reject("Panel not shown within 20s"), 20000);
|
||||
await viewShownDeferred.promise;
|
||||
await panelShownPromise;
|
||||
clearTimeout(shownTimeout);
|
||||
ok(true, "Found view shown");
|
||||
await Promise.all([
|
||||
BrowserTestUtils.waitForEvent(viewNode, "ViewShown"),
|
||||
panelShownPromise
|
||||
]);
|
||||
|
||||
let panelHiddenPromise = promisePanelElementHidden(window, tempPanel);
|
||||
tempPanel.hidePopup();
|
||||
await panelHiddenPromise;
|
||||
let panelHiddenPromise = promisePanelElementHidden(window, tempPanel);
|
||||
tempPanel.hidePopup();
|
||||
await panelHiddenPromise;
|
||||
|
||||
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
await waitForOverflowButtonShown();
|
||||
await document.getElementById("nav-bar").overflowable.show();
|
||||
CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
|
||||
await waitForOverflowButtonShown();
|
||||
await document.getElementById("nav-bar").overflowable.show();
|
||||
|
||||
viewShownDeferred = Promise.defer();
|
||||
widgetNode.click();
|
||||
widgetNode.click();
|
||||
|
||||
shownTimeout = setTimeout(() => viewShownDeferred.reject("Panel not shown within 20s"), 20000);
|
||||
await viewShownDeferred.promise;
|
||||
clearTimeout(shownTimeout);
|
||||
ok(true, "Found view shown");
|
||||
await BrowserTestUtils.waitForEvent(viewNode, "ViewShown");
|
||||
|
||||
let panelHidden = promiseOverflowHidden(window);
|
||||
PanelUI.overflowPanel.hidePopup();
|
||||
await panelHidden;
|
||||
} catch (ex) {
|
||||
ok(false, "Unexpected exception (like a timeout for one of the yields) " +
|
||||
"when testing view widget.");
|
||||
}
|
||||
}
|
||||
let panelHidden = promiseOverflowHidden(window);
|
||||
PanelUI.overflowPanel.hidePopup();
|
||||
await panelHidden;
|
||||
|
||||
noError = true;
|
||||
try {
|
||||
CustomizableUI.destroyWidget(kWidgetId);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
noError = false;
|
||||
}
|
||||
ok(noError, "Should not throw an exception trying to remove the broken view widget.");
|
||||
CustomizableUI.destroyWidget(kWidgetId);
|
||||
});
|
||||
|
||||
add_task(async function asyncCleanup() {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
let syncService = {};
|
||||
Components.utils.import("resource://services-sync/service.js", syncService);
|
||||
const service = syncService.Service;
|
||||
Components.utils.import("resource://services-sync/UIState.jsm");
|
||||
const {UIState} = Components.utils.import("resource://services-sync/UIState.jsm", {});
|
||||
|
||||
let getState;
|
||||
let originalSync;
|
||||
|
|
|
@ -316,12 +316,12 @@ function subviewShown(aSubview) {
|
|||
let timeoutId = win.setTimeout(() => {
|
||||
reject("Subview (" + aSubview.id + ") did not show within 20 seconds.");
|
||||
}, 20000);
|
||||
function onViewShowing(e) {
|
||||
aSubview.removeEventListener("ViewShowing", onViewShowing);
|
||||
function onViewShown(e) {
|
||||
aSubview.removeEventListener("ViewShown", onViewShown);
|
||||
win.clearTimeout(timeoutId);
|
||||
resolve();
|
||||
}
|
||||
aSubview.addEventListener("ViewShowing", onViewShowing);
|
||||
aSubview.addEventListener("ViewShown", onViewShown);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -214,26 +214,32 @@ richlistitem.download button {
|
|||
-moz-binding: url("chrome://browser/content/downloads/download.xml#download-subview-toolbarbutton");
|
||||
}
|
||||
|
||||
/* When a Download is hovered that has an [openLabel] attribute set, which means
|
||||
that the file exists and can be opened, hide the status label.
|
||||
When a Download is hovered - specifically on the secondary action button - that
|
||||
has a [retryLabel] attribute set, which means that the file does not exist and
|
||||
the download failed earlier, hide the status label. */
|
||||
.subviewbutton.download:hover:-moz-any([openLabel],[retryLabel][buttonover]) > .toolbarbutton-text > .status-full,
|
||||
/* When a Download is not hovered at all or the secondary action button is hovered,
|
||||
hide the 'Open File' status label. */
|
||||
.subviewbutton.download:-moz-any(:not(:hover),[buttonover]) > .toolbarbutton-text > .status-open,
|
||||
/* When a Download is not hovered at all, or when it's hovered but specifically
|
||||
not the secondary action button or when the [retryLabel] is not set, hide the
|
||||
'Retry Downloads' label. */
|
||||
.subviewbutton.download:-moz-any(:not(:hover),:hover:not([buttonover]),:not([retryLabel])) > .toolbarbutton-text > .status-retry,
|
||||
/* When a Download is not hovered at all, or when it's hovered but specifically
|
||||
not the secondary action button or when the file does not exist, hide the
|
||||
'Open Containing Folder' label. */
|
||||
.subviewbutton.download:-moz-any(:not(:hover),:hover:not([buttonover]),:not([exists])) > .toolbarbutton-text > .status-show,
|
||||
/* Hide all status labels by default and selectively display one at a time,
|
||||
depending on the state of the Download. */
|
||||
.subviewbutton.download > .toolbarbutton-text > .status-text,
|
||||
/* When a Download is not hovered at all, hide the secondary action button. */
|
||||
.subviewbutton.download:not(:hover) > .action-button,
|
||||
/* Always hide the label of the secondary action button. */
|
||||
.subviewbutton.download > .action-button > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* When a Download is _not_ hovered, display the full status message. */
|
||||
.subviewbutton.download:not(:hover) > .toolbarbutton-text > .status-full,
|
||||
/* When a Download is hovered when the file doesn't exist and cannot be retried,
|
||||
keep showing the full status message. */
|
||||
.subviewbutton.download:hover:-moz-any(:not([openLabel]),:not([exists])):not([retryLabel]) > .toolbarbutton-text > .status-full,
|
||||
/* When a Download is hovered and the it can be retried, but the action button
|
||||
is _not_ hovered, keep showing the full status message. */
|
||||
.subviewbutton.download:hover[retryLabel]:not([buttonover]) > .toolbarbutton-text > .status-full,
|
||||
/* When a Download is hovered and the file can be opened, but the action button
|
||||
is _not_ hovered, show the 'Open File' status label. */
|
||||
.subviewbutton.download:hover[openLabel][exists]:not([buttonover]) > .toolbarbutton-text > .status-open,
|
||||
/* When a Download is hovered - its action button explicitly - and it can be
|
||||
retried, show the 'Retry Download' label. */
|
||||
.subviewbutton.download:hover[retryLabel][buttonover] > .toolbarbutton-text > .status-retry,
|
||||
/* When a Download is hovered - its action button explicitly - and the file can
|
||||
be shown in the OS's shell, show the 'Open Containing Folder' label. */
|
||||
.subviewbutton.download:hover[openLabel][exists][buttonover] > .toolbarbutton-text > .status-show {
|
||||
display: inline;
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ this.browserAction = class extends ExtensionAPI {
|
|||
view.setAttribute("flex", "1");
|
||||
view.setAttribute("extension", true);
|
||||
|
||||
document.getElementById("PanelUI-multiView").appendChild(view);
|
||||
document.getElementById("appMenu-viewCache").appendChild(view);
|
||||
|
||||
if (this.extension.hasPermission("menus") ||
|
||||
this.extension.hasPermission("contextMenus")) {
|
||||
|
|
|
@ -40,6 +40,8 @@ const FAVICON_REQUEST_TIMEOUT = 60 * 1000;
|
|||
// Map from windows to arrays of data about pending favicon loads.
|
||||
let gFaviconLoadDataMap = new Map();
|
||||
|
||||
const ITEM_CHANGED_BATCH_NOTIFICATION_THRESHOLD = 10;
|
||||
|
||||
// copied from utilityOverlay.js
|
||||
const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
|
||||
const PREF_LOAD_BOOKMARKS_IN_BACKGROUND = "browser.tabs.loadBookmarksInBackground";
|
||||
|
@ -1539,7 +1541,41 @@ this.PlacesUIUtils = {
|
|||
if (!info)
|
||||
return null;
|
||||
return this.promiseNodeLikeFromFetchInfo(info);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This function wraps potentially large places transaction operations
|
||||
* with batch notifications to the result node, hence switching the views
|
||||
* to batch mode.
|
||||
*
|
||||
* @param {nsINavHistoryResult} resultNode The result node to turn on batching.
|
||||
* @note If resultNode is not supplied, the function will pass-through to
|
||||
* functionToWrap.
|
||||
* @param {Integer} itemsBeingChanged The count of items being changed. If the
|
||||
* count is lower than a threshold, then
|
||||
* batching won't be set.
|
||||
* @param {Function} functionToWrap The function to
|
||||
*/
|
||||
async batchUpdatesForNode(resultNode, itemsBeingChanged, functionToWrap) {
|
||||
if (!resultNode) {
|
||||
await functionToWrap();
|
||||
return;
|
||||
}
|
||||
|
||||
resultNode = resultNode.QueryInterface(Ci.nsINavBookmarkObserver);
|
||||
|
||||
if (itemsBeingChanged > ITEM_CHANGED_BATCH_NOTIFICATION_THRESHOLD) {
|
||||
resultNode.onBeginUpdateBatch();
|
||||
}
|
||||
|
||||
try {
|
||||
await functionToWrap();
|
||||
} finally {
|
||||
if (itemsBeingChanged > ITEM_CHANGED_BATCH_NOTIFICATION_THRESHOLD) {
|
||||
resultNode.onEndUpdateBatch();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -808,7 +808,9 @@ PlacesController.prototype = {
|
|||
}
|
||||
|
||||
if (transactions.length) {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
await PlacesUIUtils.batchUpdatesForNode(this._view.result, transactions.length, async () => {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -966,7 +968,9 @@ PlacesController.prototype = {
|
|||
|
||||
if (transactions.length > 0) {
|
||||
if (PlacesUIUtils.useAsyncTransactions) {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
await PlacesUIUtils.batchUpdatesForNode(this._view.result, transactions.length, async () => {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
});
|
||||
} else {
|
||||
var txn = new PlacesAggregatedTransaction(txnName, transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
|
@ -1304,30 +1308,39 @@ PlacesController.prototype = {
|
|||
let urls = items.filter(item => "uri" in item).map(item => Services.io.newURI(item.uri));
|
||||
await PlacesTransactions.Tag({ urls, tag: ip.tagName }).transact();
|
||||
} else {
|
||||
await PlacesTransactions.batch(async function() {
|
||||
let insertionIndex = await ip.getIndex();
|
||||
let parent = ip.guid;
|
||||
let transactionData = [];
|
||||
|
||||
for (let item of items) {
|
||||
let doCopy = action == "copy";
|
||||
let insertionIndex = await ip.getIndex();
|
||||
let parent = ip.guid;
|
||||
|
||||
// If this is not a copy, check for safety that we can move the
|
||||
// source, otherwise report an error and fallback to a copy.
|
||||
if (!doCopy &&
|
||||
!PlacesControllerDragHelper.canMoveUnwrappedNode(item)) {
|
||||
Components.utils.reportError("Tried to move an unmovable " +
|
||||
"Places node, reverting to a copy operation.");
|
||||
doCopy = true;
|
||||
}
|
||||
let guid = await PlacesUIUtils.getTransactionForData(
|
||||
item, type, parent, insertionIndex, doCopy).transact();
|
||||
itemsToSelect.push(await PlacesUtils.promiseItemId(guid));
|
||||
for (let item of items) {
|
||||
let doCopy = action == "copy";
|
||||
|
||||
// Adjust index to make sure items are pasted in the correct
|
||||
// position. If index is DEFAULT_INDEX, items are just appended.
|
||||
if (insertionIndex != PlacesUtils.bookmarks.DEFAULT_INDEX)
|
||||
insertionIndex++;
|
||||
// If this is not a copy, check for safety that we can move the
|
||||
// source, otherwise report an error and fallback to a copy.
|
||||
if (!doCopy &&
|
||||
!PlacesControllerDragHelper.canMoveUnwrappedNode(item)) {
|
||||
Components.utils.reportError("Tried to move an unmovable " +
|
||||
"Places node, reverting to a copy operation.");
|
||||
doCopy = true;
|
||||
}
|
||||
|
||||
transactionData.push([item, type, parent, insertionIndex, doCopy]);
|
||||
|
||||
// Adjust index to make sure items are pasted in the correct
|
||||
// position. If index is DEFAULT_INDEX, items are just appended.
|
||||
if (insertionIndex != PlacesUtils.bookmarks.DEFAULT_INDEX)
|
||||
insertionIndex++;
|
||||
}
|
||||
|
||||
await PlacesUIUtils.batchUpdatesForNode(this._view.result, transactionData.length, async () => {
|
||||
await PlacesTransactions.batch(async () => {
|
||||
for (let item of transactionData) {
|
||||
let guid = await PlacesUIUtils.getTransactionForData(
|
||||
...item).transact();
|
||||
itemsToSelect.push(await PlacesUtils.promiseItemId(guid));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
@ -1581,10 +1594,15 @@ var PlacesControllerDragHelper = {
|
|||
|
||||
/**
|
||||
* Handles the drop of one or more items onto a view.
|
||||
* @param insertionPoint
|
||||
* The insertion point where the items should be dropped
|
||||
*
|
||||
* @param {Object} insertionPoint The insertion point where the items should
|
||||
* be dropped.
|
||||
* @param {Object} dt The dataTransfer information for the drop.
|
||||
* @param {Object} view The tree view where this object is being
|
||||
* dropped to. This allows batching to take
|
||||
* place.
|
||||
*/
|
||||
async onDrop(insertionPoint, dt) {
|
||||
async onDrop(insertionPoint, dt, view) {
|
||||
let doCopy = ["copy", "link"].includes(dt.dropEffect);
|
||||
|
||||
let transactions = [];
|
||||
|
@ -1707,7 +1725,9 @@ var PlacesControllerDragHelper = {
|
|||
return;
|
||||
}
|
||||
if (PlacesUIUtils.useAsyncTransactions) {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
await PlacesUIUtils.batchUpdatesForNode(view && view.result, transactions.length, async () => {
|
||||
await PlacesTransactions.batch(transactions);
|
||||
});
|
||||
} else {
|
||||
let txn = new PlacesAggregatedTransaction("DropItems", transactions);
|
||||
PlacesUtils.transactionManager.doTransaction(txn);
|
||||
|
|
|
@ -1453,11 +1453,14 @@ PlacesTreeView.prototype = {
|
|||
// since this information is specific to the tree view.
|
||||
let ip = this._getInsertionPoint(aRow, aOrientation);
|
||||
if (ip) {
|
||||
PlacesControllerDragHelper.onDrop(ip, aDataTransfer)
|
||||
.catch(Components.utils.reportError);
|
||||
PlacesControllerDragHelper.onDrop(ip, aDataTransfer, this)
|
||||
.catch(Components.utils.reportError)
|
||||
.then(() => {
|
||||
// We should only clear the drop target once
|
||||
// the onDrop is complete, as it is an async function.
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
});
|
||||
}
|
||||
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
},
|
||||
|
||||
getParentIndex: function PTV_getParentIndex(aRow) {
|
||||
|
|
|
@ -1078,15 +1078,16 @@ this.UITour = {
|
|||
shouldOpenAppMenu = true;
|
||||
} else if (this.targetIsInPageActionPanel(aTarget)) {
|
||||
shouldOpenPageActionPanel = true;
|
||||
// Ensure the panel visibility so as to ensure the visibility of
|
||||
// the target element inside the panel otherwise
|
||||
// we would be rejected in the below `isElementVisible` checking.
|
||||
// Ensure the panel visibility so as to ensure the visibility of the target
|
||||
// element inside the panel otherwise we would be rejected in the below
|
||||
// `isElementVisible` checking.
|
||||
aChromeWindow.BrowserPageActions.panelNode.hidden = false;
|
||||
}
|
||||
|
||||
// Prevent showing a panel at an undefined position.
|
||||
if (!this.isElementVisible(aTarget.node)) {
|
||||
return Promise.reject(`_ensureTarget: Reject the ${aTarget.name} target since it isn't visible.`);
|
||||
// Prevent showing a panel at an undefined position, but when it's tucked
|
||||
// away inside a panel, we skip this check.
|
||||
if (!aTarget.node.closest("panelview") && !this.isElementVisible(aTarget.node)) {
|
||||
return Promise.reject(`_ensureTarget: Reject the ${aTarget.name || aTarget.targetName} target since it isn't visible.`);
|
||||
}
|
||||
|
||||
let menuToOpen = null;
|
||||
|
|
|
@ -64,6 +64,8 @@ for (const type of [
|
|||
"SECTION_REGISTER",
|
||||
"SECTION_UPDATE",
|
||||
"SECTION_UPDATE_CARD",
|
||||
"SETTINGS_CLOSE",
|
||||
"SETTINGS_OPEN",
|
||||
"SET_PREF",
|
||||
"SHOW_FIREFOX_ACCOUNTS",
|
||||
"SNIPPETS_DATA",
|
||||
|
|
|
@ -45,7 +45,8 @@ const INITIAL_STATE = {
|
|||
visible: false,
|
||||
data: {}
|
||||
},
|
||||
Sections: []
|
||||
Sections: [],
|
||||
PreferencesPane: {visible: false}
|
||||
};
|
||||
|
||||
function App(prevState = INITIAL_STATE.App, action) {
|
||||
|
@ -310,11 +311,22 @@ function Snippets(prevState = INITIAL_STATE.Snippets, action) {
|
|||
}
|
||||
}
|
||||
|
||||
function PreferencesPane(prevState = INITIAL_STATE.PreferencesPane, action) {
|
||||
switch (action.type) {
|
||||
case at.SETTINGS_OPEN:
|
||||
return Object.assign({}, prevState, {visible: true});
|
||||
case at.SETTINGS_CLOSE:
|
||||
return Object.assign({}, prevState, {visible: false});
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
}
|
||||
|
||||
this.INITIAL_STATE = INITIAL_STATE;
|
||||
this.TOP_SITES_DEFAULT_LENGTH = TOP_SITES_DEFAULT_LENGTH;
|
||||
this.TOP_SITES_SHOWMORE_LENGTH = TOP_SITES_SHOWMORE_LENGTH;
|
||||
|
||||
this.reducers = {TopSites, App, Snippets, Prefs, Dialog, Sections};
|
||||
this.reducers = {TopSites, App, Snippets, Prefs, Dialog, Sections, PreferencesPane};
|
||||
this.insertPinned = insertPinned;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["reducers", "INITIAL_STATE", "insertPinned", "TOP_SITES_DEFAULT_LENGTH", "TOP_SITES_SHOWMORE_LENGTH"];
|
||||
|
|
|
@ -151,5 +151,8 @@
|
|||
"icon": "highlights",
|
||||
"initialized": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"PreferencesPane": {
|
||||
"visible": false
|
||||
}
|
||||
};
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -418,8 +418,12 @@ main {
|
|||
|
||||
.edit-topsites-wrapper .edit-topsites-button {
|
||||
position: absolute;
|
||||
offset-inline-end: 0;
|
||||
top: -2px; }
|
||||
offset-inline-end: 21px;
|
||||
top: -2px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
|
||||
.edit-topsites-wrapper .edit-topsites-button:focus, .edit-topsites-wrapper .edit-topsites-button:active {
|
||||
opacity: 1; }
|
||||
.edit-topsites-wrapper .edit-topsites-button button {
|
||||
background: none;
|
||||
border: 0;
|
||||
|
@ -457,6 +461,9 @@ main {
|
|||
.edit-topsites-wrapper .show-less span {
|
||||
padding-inline-start: 3px; }
|
||||
|
||||
section.top-sites:hover .edit-topsites-button {
|
||||
opacity: 1; }
|
||||
|
||||
.topsite-form .form-wrapper {
|
||||
margin: auto;
|
||||
max-width: 350px;
|
||||
|
@ -517,13 +524,13 @@ main {
|
|||
opacity: 1;
|
||||
transform: translateY(0); } }
|
||||
|
||||
.sections-list .section-top-bar {
|
||||
.section-top-bar {
|
||||
position: relative; }
|
||||
.sections-list .section-top-bar .section-info-option {
|
||||
.section-top-bar .section-info-option {
|
||||
offset-inline-end: 0;
|
||||
position: absolute;
|
||||
top: 0; }
|
||||
.sections-list .section-top-bar .info-option-icon {
|
||||
.section-top-bar .info-option-icon {
|
||||
background-image: url("assets/glyph-info-option-12.svg");
|
||||
background-size: 12px 12px;
|
||||
background-repeat: no-repeat;
|
||||
|
@ -533,19 +540,30 @@ main {
|
|||
height: 16px;
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
margin-bottom: -2px; }
|
||||
.sections-list .section-top-bar .info-option-icon[aria-expanded="true"] {
|
||||
margin-bottom: -2px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
|
||||
.section-top-bar .info-option-icon:focus, .section-top-bar .info-option-icon:active {
|
||||
opacity: 1; }
|
||||
.section-top-bar .info-option-icon[aria-expanded="true"] {
|
||||
fill: rgba(12, 12, 13, 0.8); }
|
||||
.sections-list .section-top-bar .section-info-option .info-option {
|
||||
.section-top-bar .section-info-option .info-option {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 0.2s, opacity 0.2s ease-out;
|
||||
transition-delay: 0.5s; }
|
||||
.sections-list .section-top-bar .info-option-icon[aria-expanded="true"] + .info-option {
|
||||
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
|
||||
.section-top-bar .section-info-option .info-option::before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 32px;
|
||||
left: 50%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: -32px; }
|
||||
.section-top-bar .info-option-icon[aria-expanded="true"] + .info-option {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: visibility 0.2s, opacity 0.2s ease-out; }
|
||||
.sections-list .section-top-bar .info-option {
|
||||
transition: visibility 0.2s, opacity 0.2s cubic-bezier(0.07, 0.95, 0, 1); }
|
||||
.section-top-bar .info-option {
|
||||
z-index: 9999;
|
||||
position: absolute;
|
||||
background: #FFF;
|
||||
|
@ -553,23 +571,45 @@ main {
|
|||
border-radius: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 120%;
|
||||
margin-inline-end: -13px;
|
||||
margin-inline-end: -9px;
|
||||
offset-inline-end: 0;
|
||||
top: 20px;
|
||||
width: 320px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.1);
|
||||
-moz-user-select: none; }
|
||||
.sections-list .section-top-bar .info-option-header {
|
||||
.section-top-bar .info-option-header {
|
||||
font-size: 15px;
|
||||
font-weight: 600; }
|
||||
.sections-list .section-top-bar .info-option-body {
|
||||
.section-top-bar .info-option-body {
|
||||
margin: 0;
|
||||
margin-top: 12px; }
|
||||
.sections-list .section-top-bar .info-option-link {
|
||||
display: block;
|
||||
margin-top: 12px;
|
||||
color: #0060DF; }
|
||||
.section-top-bar .info-option-link {
|
||||
color: #0060DF;
|
||||
margin-left: 7px; }
|
||||
.section-top-bar .info-option-manage {
|
||||
margin-top: 24px; }
|
||||
.section-top-bar .info-option-manage button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #0060DF;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.section-top-bar .info-option-manage button::after {
|
||||
background-image: url("assets/topic-show-more-12.svg");
|
||||
background-repeat: no-repeat;
|
||||
content: '';
|
||||
-moz-context-properties: fill;
|
||||
display: inline-block;
|
||||
fill: #0060DF;
|
||||
height: 16px;
|
||||
margin-inline-start: 5px;
|
||||
margin-top: 1px;
|
||||
vertical-align: middle;
|
||||
width: 12px; }
|
||||
.section-top-bar .info-option-manage button:dir(rtl)::after {
|
||||
transform: scaleX(-1); }
|
||||
|
||||
.sections-list .section-list {
|
||||
margin: 0;
|
||||
|
@ -622,6 +662,9 @@ main {
|
|||
color: #737373;
|
||||
text-align: center; }
|
||||
|
||||
section.section:hover .info-option-icon {
|
||||
opacity: 1; }
|
||||
|
||||
.topic {
|
||||
font-size: 12px;
|
||||
color: #737373;
|
||||
|
|
|
@ -2808,6 +2808,7 @@
|
|||
"default_label_loading": "בטעינה…",
|
||||
"header_top_sites": "אתרים מובילים",
|
||||
"header_stories": "סיפורים מובילים",
|
||||
"header_highlights": "מומלצים",
|
||||
"header_visit_again": "ביקור חוזר",
|
||||
"header_bookmarks": "סימניות אחרונות",
|
||||
"header_recommended_by": "מומלץ על ידי {provider}",
|
||||
|
@ -2839,6 +2840,8 @@
|
|||
"search_web_placeholder": "חיפוש ברשת",
|
||||
"search_settings": "שינוי הגדרות חיפוש",
|
||||
"section_info_option": "מידע",
|
||||
"section_info_send_feedback": "שליחת משוב",
|
||||
"section_info_privacy_notice": "הצהרת פרטיות",
|
||||
"welcome_title": "ברוכים הבאים לדף הלשונית החדשה",
|
||||
"welcome_body": "Firefox ישתמש באזור זה כדי להציג את הסימניות הרלוונטיות ביותר, מאמרים, סרטוני וידאו ודפים שביקרת בהם לאחרונה, כך שניתן יהיה לגשת אליהם שוב בקלות.",
|
||||
"welcome_label": "תחומי העניין שלך מזוהים",
|
||||
|
@ -2848,7 +2851,7 @@
|
|||
"time_label_day": "{number} ימים",
|
||||
"settings_pane_button_label": "התאמה אישית של דף הלשונית החדשה שלך",
|
||||
"settings_pane_header": "העדפות לשונית חדשה",
|
||||
"settings_pane_body": "ניתן לבחור מה יופיע בפניך בעת פתיחת לשונית חדשה.",
|
||||
"settings_pane_body2": "בחירה של מה שיופיע בעמוד הזה.",
|
||||
"settings_pane_search_header": "חיפוש",
|
||||
"settings_pane_search_body": "חיפוש באינטרנט ישירות מהלשונית החדשה שלך.",
|
||||
"settings_pane_topsites_header": "אתרים מובילים",
|
||||
|
@ -2858,8 +2861,12 @@
|
|||
"settings_pane_bookmarks_body": "הסימניות החדשות שיצרת במיקום נוח ואחיד.",
|
||||
"settings_pane_visit_again_header": "ביקור חוזר",
|
||||
"settings_pane_visit_again_body": "Firefox תציג לך חלקים מהיסטוריית הגלישה שלך שאולי יעניין אותך להיזכר בהם או לחזור אליהם.",
|
||||
"settings_pane_pocketstories_header": "סיפורים מובילים",
|
||||
"settings_pane_pocketstories_body": "Pocket, חלק ממשפחת Mozilla, יסייע לך להתחבר לתוכן באיכות גבוהה שיתכן שלא היה מגיע אליך בדרך אחרת.",
|
||||
"settings_pane_highlights_header": "מומלצים",
|
||||
"settings_pane_highlights_body2": "מציאת הדרך חזרה לדברים שמעניינים אותך בהתאם לפריטים בהם ביקרת לאחרונה או הוספת לסימניות.",
|
||||
"settings_pane_highlights_options_bookmarks": "סימניות",
|
||||
"settings_pane_highlights_options_visited": "אתרים בהם ביקרת",
|
||||
"settings_pane_snippets_header": "פתקיות",
|
||||
"settings_pane_snippets_body": "ניתן לקרוא עדכונים קטנים ומתוקים מ־Mozilla לגבי Firefox, תרבות האינטרנט ומם אקראי מדי פעם בפעם.",
|
||||
"settings_pane_done_button": "סיום",
|
||||
"edit_topsites_button_text": "עריכה",
|
||||
"edit_topsites_button_label": "התאמת אגף האתרים המובילים שלך",
|
||||
|
@ -2882,9 +2889,10 @@
|
|||
"pocket_read_more": "נושאים פופולריים:",
|
||||
"pocket_read_even_more": "צפייה בחדשות נוספות",
|
||||
"pocket_feedback_header": "המיטב מרחבי האינטרנט, נאסף על ידי 25 מיליון אנשים.",
|
||||
"pocket_feedback_body": "Pocket, חלק ממשפחת Mozilla, יסייע לך להתחבר לתוכן באיכות גבוהה שיתכן שלא היה מגיע אליך בדרך אחרת.",
|
||||
"pocket_send_feedback": "שליחת משוב",
|
||||
"manual_migration_explanation": "נסו את Firefox עם האתרים המועדפים עליך והסימניות שלך מדפדפן אחר.",
|
||||
"pocket_description": "ניתן להחשף לתוכן באיכות גבוהה שיתכן שלא היית רואה, בעזרת Pocket, שכיום מהווה חלק מ־Mozilla.",
|
||||
"highlights_empty_state": "ניתן להתחיל בגלישה ואנו נציג בפניך מספר כתבות, סרטונים ועמודים שונים מעולים בהם ביקרת לאחרונה או שהוספת לסימניות.",
|
||||
"topstories_empty_state": "התעדכנת בכל הסיפורים. כדאי לנסות שוב מאוחר יותר כדי לקבל עוד סיפורים מובילים מאת {provider}. לא רוצה לחכות? ניתן לבחור נושא נפוץ כדי למצוא עוד סיפורים נפלאים מרחבי הרשת.",
|
||||
"manual_migration_explanation2": "ניתן להתנסות ב־Firefox עם הסימניות, ההיסטוריה והססמאות מדפדפן אחר.",
|
||||
"manual_migration_cancel_button": "לא תודה",
|
||||
"manual_migration_import_button": "ייבוא כעת"
|
||||
},
|
||||
|
@ -5391,11 +5399,17 @@
|
|||
"newtab_page_title": "Filă nouă",
|
||||
"default_label_loading": "Se încarcă…",
|
||||
"header_top_sites": "Site-uri de top",
|
||||
"header_stories": "Articole de top",
|
||||
"header_highlights": "Evidențieri",
|
||||
"header_visit_again": "Vizitează din nou",
|
||||
"header_bookmarks": "Marcaje recente",
|
||||
"header_recommended_by": "Recomandat de {provider}",
|
||||
"header_bookmarks_placeholder": "Nu ai niciun marcaj încă.",
|
||||
"header_stories_from": "de la",
|
||||
"type_label_visited": "Vizitate",
|
||||
"type_label_bookmarked": "Însemnat",
|
||||
"type_label_synced": "Sincronizat de pe alt dispozitiv",
|
||||
"type_label_recommended": "În tendințe",
|
||||
"type_label_open": "Deschise",
|
||||
"type_label_topic": "Subiect",
|
||||
"type_label_now": "Acum",
|
||||
|
@ -5407,6 +5421,9 @@
|
|||
"menu_action_open_private_window": "Deschide într-o fereastră privată nouă",
|
||||
"menu_action_dismiss": "Înlătură",
|
||||
"menu_action_delete": "Șterge din istoric",
|
||||
"menu_action_pin": "Fixează",
|
||||
"menu_action_unpin": "Anulează fixarea",
|
||||
"confirm_history_delete_p1": "Sigur dorești să ştergi fiecare instanţă a acestei pagini din istoric?",
|
||||
"confirm_history_delete_notice_p2": "Această acțiune este ireversibilă.",
|
||||
"menu_action_save_to_pocket": "Salvează în Pocket",
|
||||
"search_for_something_with": "Caută {search_term} cu: ",
|
||||
|
@ -5415,6 +5432,8 @@
|
|||
"search_web_placeholder": "Caută pe web",
|
||||
"search_settings": "Schimbă setările de căutare",
|
||||
"section_info_option": "Informații",
|
||||
"section_info_send_feedback": "Trimite feedback",
|
||||
"section_info_privacy_notice": "Politica de confidențialitate",
|
||||
"welcome_title": "Bun venit în noua filă",
|
||||
"welcome_body": "Firefox va folosi acest spațiu pentru a arăta cele mai relevante semne de carte, articole, videouri și pagini vizitate recent pentru a reveni la acestea ușor.",
|
||||
"welcome_label": "Se identifică evidențierile tale",
|
||||
|
@ -5424,11 +5443,17 @@
|
|||
"time_label_day": "{number}d",
|
||||
"settings_pane_button_label": "Particularizează pagina de filă nouă",
|
||||
"settings_pane_header": "Preferințe pentru filă nouă",
|
||||
"settings_pane_body2": "Alege ceea ce vezi pe această pagină.",
|
||||
"settings_pane_search_header": "Caută",
|
||||
"settings_pane_search_body": "Caută pe web din noua filă.",
|
||||
"settings_pane_topsites_header": "Site-uri de top",
|
||||
"settings_pane_topsites_body": "Accesează site-urile pe care le vizitezi mai des.",
|
||||
"settings_pane_topsites_options_showmore": "Arată două rânduri",
|
||||
"settings_pane_bookmarks_header": "Marcaje recente",
|
||||
"settings_pane_visit_again_header": "Vizitează din nou",
|
||||
"settings_pane_highlights_header": "Evidențieri",
|
||||
"settings_pane_highlights_options_bookmarks": "Marcaje",
|
||||
"settings_pane_highlights_options_visited": "Site-uri vizitate",
|
||||
"settings_pane_done_button": "Gata",
|
||||
"edit_topsites_button_text": "Editează",
|
||||
"edit_topsites_button_label": "Particularizează secțiunea site-urilor de top",
|
||||
|
@ -5436,6 +5461,7 @@
|
|||
"edit_topsites_showless_button": "Arată mai puțin",
|
||||
"edit_topsites_done_button": "Gata",
|
||||
"edit_topsites_pin_button": "Fixează acest site",
|
||||
"edit_topsites_unpin_button": "Anulează fixarea acestui site",
|
||||
"edit_topsites_edit_button": "Editează acest site",
|
||||
"edit_topsites_dismiss_button": "Înlătură acest site",
|
||||
"edit_topsites_add_button": "Adaugă",
|
||||
|
@ -5448,6 +5474,7 @@
|
|||
"topsites_form_cancel_button": "Renunță",
|
||||
"topsites_form_url_validation": "URL valid necesar",
|
||||
"pocket_read_more": "Subiecte populare:",
|
||||
"pocket_read_even_more": "Vezi mai multe articole",
|
||||
"manual_migration_cancel_button": "Nu, mulțumesc"
|
||||
},
|
||||
"ru": {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:unpack>false</em:unpack>
|
||||
<em:version>2017.09.28.0954-66ebf91c</em:version>
|
||||
<em:version>2017.09.29.0895-52552f5e</em:version>
|
||||
<em:name>Activity Stream</em:name>
|
||||
<em:description>A rich visual history feed and a reimagined home page make it easier than ever to find exactly what you're looking for in Firefox.</em:description>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
|
|
@ -52,6 +52,10 @@ const BUILT_IN_SECTIONS = {
|
|||
title: {id: "header_highlights"},
|
||||
maxRows: 3,
|
||||
availableContextMenuOptions: ["CheckBookmark", "SaveToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "DeleteUrl"],
|
||||
infoOption: {
|
||||
header: {id: "settings_pane_highlights_header"},
|
||||
body: {id: "settings_pane_highlights_body2"}
|
||||
},
|
||||
emptyState: {
|
||||
message: {id: "highlights_empty_state"},
|
||||
icon: "highlights"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const {reducers, INITIAL_STATE, insertPinned} = require("common/Reducers.jsm");
|
||||
const {TopSites, App, Snippets, Prefs, Dialog, Sections} = reducers;
|
||||
const {TopSites, App, Snippets, Prefs, Dialog, Sections, PreferencesPane} = reducers;
|
||||
|
||||
const {actionTypes: at} = require("common/Actions.jsm");
|
||||
|
||||
|
@ -524,4 +524,19 @@ describe("Reducers", () => {
|
|||
assert.equal(state, INITIAL_STATE.Snippets);
|
||||
});
|
||||
});
|
||||
describe("PreferencesPane", () => {
|
||||
it("should return INITIAL_STATE by default", () => {
|
||||
assert.equal(INITIAL_STATE.PreferencesPane, PreferencesPane(undefined, {type: "non_existent"}));
|
||||
});
|
||||
it("should toggle visible to true on SETTINGS_OPEN", () => {
|
||||
const action = {type: at.SETTINGS_OPEN};
|
||||
const nextState = PreferencesPane(INITIAL_STATE.PreferencesPane, action);
|
||||
assert.isTrue(nextState.visible);
|
||||
});
|
||||
it("should toggle visible to false on SETTINGS_CLOSE", () => {
|
||||
const action = {type: at.SETTINGS_CLOSE};
|
||||
const nextState = PreferencesPane(INITIAL_STATE.PreferencesPane, action);
|
||||
assert.isFalse(nextState.visible);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,20 +21,17 @@ const TEST_THRESHOLD = {
|
|||
// If a user qualifies for the e10s-multi experiement, this is how many
|
||||
// content processes to use and whether to allow addons for the experiment.
|
||||
const MULTI_EXPERIMENT = {
|
||||
"beta": { buckets: { 4: 1, }, // 4 processes: 100%
|
||||
"beta": { buckets: { 4: 1 }, // 4 processes: 100%
|
||||
|
||||
// When on the "beta" channel, getAddonsDisqualifyForMulti
|
||||
// will return true if any addon installed is not a web extension.
|
||||
// Therefore, this returns true if and only if all addons
|
||||
// installed are web extensions or if no addons are installed
|
||||
// at all.
|
||||
addonsDisableExperiment(prefix) { return getAddonsDisqualifyForMulti(); } },
|
||||
// The extensions code only allows webextensions and legacy-style
|
||||
// extensions that have been verified to work with multi.
|
||||
// Therefore, we can allow all extensions.
|
||||
addonsDisableExperiment(prefix) { return false; } },
|
||||
|
||||
"release": { buckets: { 4: 1 }, // 4 processes: 100%
|
||||
|
||||
// See above for an explanation of this: we only allow users
|
||||
// with no extensions or users with WebExtensions.
|
||||
addonsDisableExperiment(prefix) { return getAddonsDisqualifyForMulti(); } }
|
||||
// See the comment above the "beta" addonsDisableExperiment.
|
||||
addonsDisableExperiment(prefix) { return false; } }
|
||||
};
|
||||
|
||||
const ADDON_ROLLOUT_POLICY = {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>e10srollout@mozilla.org</em:id>
|
||||
<em:version>3.00</em:version>
|
||||
<em:version>3.05</em:version>
|
||||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
|
|
@ -516,6 +516,26 @@ FormAutofillHandler.prototype = {
|
|||
fieldDetail.state = nextState;
|
||||
},
|
||||
|
||||
_isAddressRecordCreatable(record) {
|
||||
let hasName = 0;
|
||||
let length = 0;
|
||||
for (let key of Object.keys(record)) {
|
||||
if (!record[key]) {
|
||||
continue;
|
||||
}
|
||||
if (FormAutofillUtils.getCategoryFromFieldName(key) == "name") {
|
||||
hasName = 1;
|
||||
continue;
|
||||
}
|
||||
length++;
|
||||
}
|
||||
return (length + hasName) >= FormAutofillUtils.AUTOFILL_FIELDS_THRESHOLD;
|
||||
},
|
||||
|
||||
_isCreditCardRecordCreatable(record) {
|
||||
return record["cc-number"] && FormAutofillUtils.isCCNumber(record["cc-number"]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the records that is converted from address/creditCard fieldDetails and
|
||||
* only valid form records are included.
|
||||
|
@ -581,17 +601,14 @@ FormAutofillHandler.prototype = {
|
|||
|
||||
this._normalizeAddress(data.address);
|
||||
|
||||
if (data.address &&
|
||||
Object.values(data.address.record).filter(v => v).length <
|
||||
FormAutofillUtils.AUTOFILL_FIELDS_THRESHOLD) {
|
||||
if (data.address && !this._isAddressRecordCreatable(data.address.record)) {
|
||||
log.debug("No address record saving since there are only",
|
||||
Object.keys(data.address.record).length,
|
||||
"usable fields");
|
||||
delete data.address;
|
||||
}
|
||||
|
||||
if (data.creditCard && (!data.creditCard.record["cc-number"] ||
|
||||
!FormAutofillUtils.isCCNumber(data.creditCard.record["cc-number"]))) {
|
||||
if (data.creditCard && !this._isCreditCardRecordCreatable(data.creditCard.record)) {
|
||||
log.debug("No credit card record saving since card number is invalid");
|
||||
delete data.creditCard;
|
||||
}
|
||||
|
|
|
@ -26,19 +26,19 @@ const TESTCASES = [
|
|||
description: "\"country\" using @autocomplete shouldn't be identified aggressively",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="country" autocomplete="country">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
country: "United States",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
country: "United States",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -46,19 +46,19 @@ const TESTCASES = [
|
|||
description: "\"country\" using heuristics should be identified aggressively",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="country" name="country">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
country: "United States",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
country: "US",
|
||||
"organization": "Mozilla",
|
||||
"country": "US",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -66,20 +66,20 @@ const TESTCASES = [
|
|||
description: "\"tel\" related fields should be concatenated",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="tel-country-code" autocomplete="tel-country-code">
|
||||
<input id="tel-national" autocomplete="tel-national">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"tel-country-code": "+1",
|
||||
"tel-national": "1234567890",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"tel": "+11234567890",
|
||||
},
|
||||
},
|
||||
|
@ -88,21 +88,21 @@ const TESTCASES = [
|
|||
description: "\"tel\" should be removed if it's too short",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="country" autocomplete="country">
|
||||
<input id="tel" autocomplete="tel-national">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "1234",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "",
|
||||
},
|
||||
},
|
||||
|
@ -111,21 +111,21 @@ const TESTCASES = [
|
|||
description: "\"tel\" should be removed if it's too long",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="country" autocomplete="country">
|
||||
<input id="tel" autocomplete="tel-national">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "1234567890123456",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "",
|
||||
},
|
||||
},
|
||||
|
@ -134,25 +134,123 @@ const TESTCASES = [
|
|||
description: "\"tel\" should be removed if it contains invalid characters",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
<input id="country" autocomplete="country">
|
||||
<input id="tel" autocomplete="tel-national">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "12345###!!!",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
"country": "United States",
|
||||
"tel": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "All name related fields should be counted as 1 field only.",
|
||||
document: `<form>
|
||||
<input id="given-name" autocomplete="given-name">
|
||||
<input id="family-name" autocomplete="family-name">
|
||||
<input id="organization" autocomplete="organization">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"given-name": "John",
|
||||
"family-name": "Doe",
|
||||
"organization": "Mozilla",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "All telephone related fields should be counted as 1 field only.",
|
||||
document: `<form>
|
||||
<input id="tel-country-code" autocomplete="tel-country-code">
|
||||
<input id="tel-area-code" autocomplete="tel-area-code">
|
||||
<input id="tel-local" autocomplete="tel-local">
|
||||
<input id="organization" autocomplete="organization">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"tel-country-code": "+1",
|
||||
"tel-area-code": "123",
|
||||
"tel-local": "4567890",
|
||||
"organization": "Mozilla",
|
||||
},
|
||||
expectedRecord: {
|
||||
address: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "A credit card form with the value of cc-number, cc-exp, and cc-name.",
|
||||
document: `<form>
|
||||
<input id="cc-number" autocomplete="cc-number">
|
||||
<input id="cc-name" autocomplete="cc-name">
|
||||
<input id="cc-exp" autocomplete="cc-exp">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"cc-number": "4444000022220000",
|
||||
"cc-name": "Foo Bar",
|
||||
"cc-exp": "2022-06",
|
||||
},
|
||||
expectedRecord: {
|
||||
creditCard: {
|
||||
"cc-number": "4444000022220000",
|
||||
"cc-name": "Foo Bar",
|
||||
"cc-exp": "2022-06",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "A credit card form with cc-number value only.",
|
||||
document: `<form>
|
||||
<input id="cc-number" autocomplete="cc-number">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"cc-number": "4444000022220000",
|
||||
},
|
||||
expectedRecord: {
|
||||
creditCard: {
|
||||
"cc-number": "4444000022220000",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "A credit card form must have cc-number value.",
|
||||
document: `<form>
|
||||
<input id="cc-number" autocomplete="cc-number">
|
||||
<input id="cc-name" autocomplete="cc-name">
|
||||
<input id="cc-exp" autocomplete="cc-exp">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"cc-number": "",
|
||||
"cc-name": "Foo Bar",
|
||||
"cc-exp": "2022-06",
|
||||
},
|
||||
expectedRecord: {
|
||||
creditCard: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "A credit card form must have cc-number field.",
|
||||
document: `<form>
|
||||
<input id="cc-name" autocomplete="cc-name">
|
||||
<input id="cc-exp" autocomplete="cc-exp">
|
||||
</form>`,
|
||||
formValue: {
|
||||
"cc-name": "Foo Bar",
|
||||
"cc-exp": "2022-06",
|
||||
},
|
||||
expectedRecord: {
|
||||
creditCard: undefined,
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
for (let testcase of TESTCASES) {
|
||||
|
|
|
@ -136,10 +136,8 @@ var PocketPageAction = {
|
|||
wrapper.hidden = true;
|
||||
|
||||
wrapper.addEventListener("click", event => {
|
||||
if (event.type == "click" && event.button != 0) {
|
||||
return;
|
||||
}
|
||||
this.doCommand(event.target.ownerGlobal);
|
||||
let {BrowserPageActions} = wrapper.ownerGlobal;
|
||||
BrowserPageActions.doCommandForAction(this, event, wrapper);
|
||||
});
|
||||
},
|
||||
onPlacedInPanel(panelNode, urlbarNode) {
|
||||
|
|
|
@ -30,6 +30,7 @@ let WebCompatReporter = {
|
|||
id: "webcompat-reporter-button",
|
||||
title: wcStrings.GetStringFromName("wc-reporter.label2"),
|
||||
iconURL: "chrome://webcompat-reporter/skin/lightbulb.svg",
|
||||
labelForHistogram: "webcompat",
|
||||
onCommand: (e) => this.reportIssue(e.target.ownerGlobal),
|
||||
onShowingInPanel: (buttonNode) => this.onShowingInPanel(buttonNode)
|
||||
}));
|
||||
|
|
|
@ -399,6 +399,27 @@ this.PageActions = {
|
|||
}
|
||||
},
|
||||
|
||||
logTelemetry(type, action, node = null) {
|
||||
const kAllowedLabels = ["pocket", "screenshots", "webcompat"].concat(
|
||||
gBuiltInActions.filter(a => !a.__isSeparator).map(a => a.id)
|
||||
);
|
||||
|
||||
if (type == "used") {
|
||||
type = (node && node.closest("#urlbar-container")) ? "urlbar_used" : "panel_used";
|
||||
}
|
||||
let histogramID = "FX_PAGE_ACTION_" + type.toUpperCase();
|
||||
try {
|
||||
let histogram = Services.telemetry.getHistogramById(histogramID);
|
||||
if (kAllowedLabels.includes(action.labelForHistogram)) {
|
||||
histogram.add(action.labelForHistogram);
|
||||
} else {
|
||||
histogram.add("other");
|
||||
}
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
},
|
||||
|
||||
_storePersistedActions() {
|
||||
let json = JSON.stringify(this._persistedActions);
|
||||
Services.prefs.setStringPref(PREF_PERSISTED_ACTIONS, json);
|
||||
|
@ -538,6 +559,7 @@ function Action(options) {
|
|||
title: !options._isSeparator,
|
||||
anchorIDOverride: false,
|
||||
iconURL: false,
|
||||
labelForHistogram: false,
|
||||
nodeAttributes: false,
|
||||
onBeforePlacedInWindow: false,
|
||||
onCommand: false,
|
||||
|
@ -667,6 +689,10 @@ Action.prototype = {
|
|||
return this._subview;
|
||||
},
|
||||
|
||||
get labelForHistogram() {
|
||||
return this._labelForHistogram || this._id;
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs the command for an action. If the action has an onCommand
|
||||
* handler, then it's called. If the action has a subview or iframe, then a
|
||||
|
@ -959,6 +985,9 @@ this.PageActions.ACTION_ID_BUILT_IN_SEPARATOR = ACTION_ID_BUILT_IN_SEPARATOR;
|
|||
// Sorted in the order in which they should appear in the page action panel.
|
||||
// Does not include the page actions of extensions bundled with the browser.
|
||||
// They're added by the relevant extension code.
|
||||
// NOTE: If you add items to this list (or system add-on actions that we
|
||||
// want to keep track of), make sure to also update Histograms.json for the
|
||||
// new actions.
|
||||
var gBuiltInActions = [
|
||||
|
||||
// bookmark
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
}
|
||||
|
||||
#sidebar-search-container {
|
||||
padding: 4px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
#search-box {
|
||||
|
|
|
@ -730,11 +730,11 @@ html|span.ac-emphasize-text-url {
|
|||
#sidebar-box {
|
||||
-moz-appearance: -moz-mac-source-list;
|
||||
-moz-font-smoothing-background-color: -moz-mac-source-list;
|
||||
/* Default font size is 11px on mac, so this is 12px */
|
||||
font-size: 1.0909rem;
|
||||
}
|
||||
|
||||
#sidebar-header {
|
||||
/* system font size is a bit smaller in mac, so need more ems. */
|
||||
font-size: 1.4545em;
|
||||
border-bottom: 1px solid hsla(240, 5%, 5%, .1);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
#sidebar-search-container {
|
||||
/* Native searchbar styling already adds 4px margin on Mac, so
|
||||
* adding 4px padding results in 8px of total whitespace. */
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-twisty {
|
||||
-moz-appearance: none;
|
||||
padding: 0 2px;
|
||||
|
|
|
@ -85,7 +85,8 @@ toolbar[brighttext] .toolbarbutton-1 {
|
|||
|
||||
/* Default findbar text color doesn't look good - Bug 1125677 */
|
||||
.browserContainer > findbar .findbar-find-status,
|
||||
.browserContainer > findbar .found-matches {
|
||||
.browserContainer > findbar .found-matches,
|
||||
.browserContainer > findbar .findbar-button {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
|
|
@ -194,10 +194,6 @@
|
|||
transform: translateX(-@menuPanelWidth@);
|
||||
}
|
||||
|
||||
panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
|
||||
display: none;
|
||||
}
|
||||
|
||||
panelview {
|
||||
-moz-box-orient: vertical;
|
||||
-moz-box-flex: 1;
|
||||
|
|
|
@ -601,6 +601,7 @@ tabbrowser {
|
|||
-moz-context-properties: fill, fill-opacity;
|
||||
fill: currentColor;
|
||||
fill-opacity: var(--toolbarbutton-icon-fill-opacity);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl),
|
||||
|
|
|
@ -48,6 +48,11 @@
|
|||
min-height: 32px;
|
||||
}
|
||||
|
||||
:root[chromehidden~="toolbar"] #urlbar {
|
||||
/* Remove excess space between the address bar and the menu button in popups. */
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
#urlbar-container {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
%filter substitution
|
||||
%define toolbarShadowColor hsla(209,67%,12%,0.35)
|
||||
%define glassActiveBorderColor rgb(37, 44, 51)
|
||||
%define glassInactiveBorderColor rgb(102, 102, 102)
|
||||
|
||||
|
@ -260,7 +259,7 @@
|
|||
/* Artificially draw window borders that are covered by lwtheme, see bug 591930.
|
||||
* Borders for win7 are below, win10 doesn't need them. */
|
||||
#main-window[sizemode="normal"] > #tab-view-deck > #browser-panel:-moz-lwtheme {
|
||||
border-top: 1px solid @toolbarShadowColor@;
|
||||
border-top: 1px solid @glassShadowColor@;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,13 +289,13 @@
|
|||
/* Vertical toolbar border */
|
||||
#main-window[sizemode=normal] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):not(:-moz-lwtheme),
|
||||
#main-window[sizemode=normal] #navigator-toolbox:-moz-lwtheme {
|
||||
border-left: 1px solid @toolbarShadowColor@;
|
||||
border-right: 1px solid @toolbarShadowColor@;
|
||||
border-left: 1px solid @glassShadowColor@;
|
||||
border-right: 1px solid @glassShadowColor@;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #navigator-toolbox:not(:-moz-lwtheme)::after {
|
||||
box-shadow: 1px 0 0 @toolbarShadowColor@, -1px 0 0 @toolbarShadowColor@;
|
||||
box-shadow: 1px 0 0 @glassShadowColor@, -1px 0 0 @glassShadowColor@;
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
@ -304,12 +303,12 @@
|
|||
#main-window[sizemode=normal] #browser-border-start,
|
||||
#main-window[sizemode=normal] #browser-border-end {
|
||||
display: -moz-box;
|
||||
background-color: @toolbarShadowColor@;
|
||||
background-color: @glassShadowColor@;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
#main-window[sizemode=normal] #browser-bottombox {
|
||||
border: 1px solid @toolbarShadowColor@;
|
||||
border: 1px solid @glassShadowColor@;
|
||||
border-top-style: none;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
@ -321,11 +320,6 @@
|
|||
}
|
||||
|
||||
@media (-moz-windows-glass) {
|
||||
#main-window[sizemode=normal] #nav-bar {
|
||||
border-top-left-radius: 2.5px;
|
||||
border-top-right-radius: 2.5px;
|
||||
}
|
||||
|
||||
/* Set to full fill-opacity to improve visibility of toolbar buttons on aero glass. */
|
||||
#TabsToolbar:not(:-moz-lwtheme) {
|
||||
--toolbarbutton-icon-fill-opacity: 1;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
@namespace html url("http://www.w3.org/1999/xhtml");
|
||||
|
||||
%include ../shared/browser.inc.css
|
||||
%filter substitution
|
||||
%define glassShadowColor hsla(209,67%,12%,0.35)
|
||||
|
||||
:root {
|
||||
--titlebar-text-color: currentColor;
|
||||
|
@ -112,11 +114,10 @@
|
|||
@media (-moz-os-version: windows-win7) {
|
||||
@media (-moz-windows-default-theme) {
|
||||
:root:not(:-moz-lwtheme) {
|
||||
--tabs-border: #4A4A4F;
|
||||
--tabs-border: @glassShadowColor@;
|
||||
}
|
||||
|
||||
#TabsToolbar:not(:-moz-lwtheme),
|
||||
#TabsToolbar:not(:-moz-lwtheme) toolbarbutton[disabled="true"] {
|
||||
#TabsToolbar:not(:-moz-lwtheme) {
|
||||
color: hsl(240,9%,98%);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
@media (-moz-os-version: windows-win7) {
|
||||
@media (-moz-windows-default-theme) {
|
||||
/* Always show light toolbar elements on aero surface. */
|
||||
#TabsToolbar,
|
||||
#TabsToolbar toolbarbutton[disabled="true"] {
|
||||
#TabsToolbar {
|
||||
color: hsl(240,9%,98%);
|
||||
}
|
||||
|
||||
|
@ -121,11 +120,6 @@
|
|||
border-right: none !important;
|
||||
}
|
||||
|
||||
/* Disable dragging like in the default theme: */
|
||||
#main-window[tabsintitlebar] #navigator-toolbox > toolbar:not(#toolbar-menubar):not(#TabsToolbar):-moz-lwtheme {
|
||||
-moz-window-dragging: no-drag;
|
||||
}
|
||||
|
||||
@media (-moz-os-version: windows-win10) {
|
||||
.titlebar-button:-moz-lwtheme {
|
||||
-moz-context-properties: stroke;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
}
|
||||
|
||||
#sidebar-search-container {
|
||||
padding: 4px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.sidebar-placesTree {
|
||||
|
|
|
@ -5,16 +5,15 @@
|
|||
import os
|
||||
import sys
|
||||
from mozbuild.base import MozbuildObject
|
||||
from mozbuild.backend.configenvironment import PartialConfigEnvironment
|
||||
|
||||
config = MozbuildObject.from_environment()
|
||||
partial_config = PartialConfigEnvironment(config.topobjdir)
|
||||
|
||||
for var in ('topsrcdir', 'topobjdir', 'defines', 'non_global_defines',
|
||||
'substs'):
|
||||
for var in ('topsrcdir', 'topobjdir'):
|
||||
value = getattr(config, var)
|
||||
setattr(sys.modules[__name__], var, value)
|
||||
|
||||
substs = dict(substs)
|
||||
|
||||
for var in os.environ:
|
||||
if var not in ('CPP', 'CXXCPP', 'SHELL') and var in substs:
|
||||
substs[var] = os.environ[var]
|
||||
for var in ('defines', 'substs', 'get_dependencies'):
|
||||
value = getattr(partial_config, var)
|
||||
setattr(sys.modules[__name__], var, value)
|
||||
|
|
|
@ -17,6 +17,7 @@ sys.path.insert(0, os.path.join(base_dir, 'python', 'mozbuild'))
|
|||
from mozbuild.configure import ConfigureSandbox
|
||||
from mozbuild.makeutil import Makefile
|
||||
from mozbuild.pythonutil import iter_modules_in_path
|
||||
from mozbuild.backend.configenvironment import PartialConfigEnvironment
|
||||
from mozbuild.util import (
|
||||
indented_repr,
|
||||
encode,
|
||||
|
@ -90,6 +91,9 @@ def config_status(config):
|
|||
config_status(**args)
|
||||
'''))
|
||||
|
||||
partial_config = PartialConfigEnvironment(config['TOPOBJDIR'])
|
||||
partial_config.write_vars(sanitized_config)
|
||||
|
||||
# Write out a depfile so Make knows to re-run configure when relevant Python
|
||||
# changes.
|
||||
mk = Makefile()
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/animationinspector.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/split-box.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/SplitBox.css"/>
|
||||
<script type="application/javascript" src="chrome://devtools/content/shared/theme-switching.js"/>
|
||||
</head>
|
||||
<body class="theme-sidebar" role="application" empty="true">
|
||||
|
|
|
@ -89,7 +89,7 @@ AnimationsTimeline.prototype = {
|
|||
const ReactDOM = browserRequire("devtools/client/shared/vendor/react-dom");
|
||||
|
||||
const SplitBox = React.createFactory(
|
||||
browserRequire("devtools/client/shared/components/splitter/split-box"));
|
||||
browserRequire("devtools/client/shared/components/splitter/SplitBox"));
|
||||
|
||||
const splitter = SplitBox({
|
||||
className: "animation-root",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
const React = require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/tree-view"));
|
||||
const TreeView = React.createFactory(require("devtools/client/shared/components/tree/TreeView"));
|
||||
|
||||
// Reps
|
||||
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
|
||||
|
|
|
@ -14,7 +14,7 @@ const { createFactories } = require("devtools/client/shared/react-utils");
|
|||
const { Toolbar, ToolbarButton } = createFactories(require("devtools/client/jsonview/components/reps/toolbar"));
|
||||
|
||||
// DOM Panel
|
||||
const SearchBox = React.createFactory(require("devtools/client/shared/components/search-box"));
|
||||
const SearchBox = React.createFactory(require("devtools/client/shared/components/SearchBox"));
|
||||
|
||||
// Actions
|
||||
const { fetchProperties } = require("../actions/grips");
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<link href="resource://devtools/client/dom/content/dom-view.css" rel="stylesheet" />
|
||||
<link href="resource://devtools/client/jsonview/css/toolbar.css" rel="stylesheet" />
|
||||
<link href="resource://devtools/client/shared/components/tree/tree-view.css" rel="stylesheet" />
|
||||
<link href="resource://devtools/client/shared/components/tree/TreeView.css" rel="stylesheet" />
|
||||
|
||||
<script type="text/javascript"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
|
|
|
@ -1022,7 +1022,7 @@ Toolbox.prototype = {
|
|||
if (!this._notificationBox) {
|
||||
let { NotificationBox, PriorityLevels } =
|
||||
this.browserRequire(
|
||||
"devtools/client/shared/components/notification-box");
|
||||
"devtools/client/shared/components/NotificationBox");
|
||||
|
||||
NotificationBox = this.React.createFactory(NotificationBox);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://devtools/skin/toolbox.css" type="text/css"?>
|
||||
<?xml-stylesheet href="resource://devtools/client/shared/components/notification-box.css" type="text/css"?>
|
||||
<?xml-stylesheet href="resource://devtools/client/shared/components/NotificationBox.css" type="text/css"?>
|
||||
|
||||
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const {
|
|||
|
||||
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
|
||||
const { Rep } = REPS;
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
|
||||
const TreeView = createFactory(TreeViewClass);
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,7 @@ const { addons, createClass, createFactory, DOM: dom, PropTypes } =
|
|||
require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/SearchBox"));
|
||||
const FontList = createFactory(require("./FontList"));
|
||||
|
||||
const { getStr } = require("../utils/l10n");
|
||||
|
|
|
@ -487,7 +487,7 @@ Inspector.prototype = {
|
|||
*/
|
||||
setupSplitter: function () {
|
||||
let SplitBox = this.React.createFactory(this.browserRequire(
|
||||
"devtools/client/shared/components/splitter/split-box"));
|
||||
"devtools/client/shared/components/splitter/SplitBox"));
|
||||
|
||||
let { width, height } = this.getSidebarSize();
|
||||
let splitter = SplitBox({
|
||||
|
|
|
@ -16,13 +16,13 @@
|
|||
<link rel="stylesheet" href="chrome://devtools/skin/boxmodel.css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/layout.css"/>
|
||||
<link rel="stylesheet" href="chrome://devtools/skin/animationinspector.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabs.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabbar.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/Tabs.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/TabBar.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/inspector/components/InspectorTabPanel.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/split-box.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/splitter/SplitBox.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/inspector/layout/components/Accordion.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tree/tree-view.css"/>
|
||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/tree/TreeView.css"/>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||
|
|
|
@ -73,7 +73,7 @@ ToolSidebar.prototype = {
|
|||
|
||||
render: function () {
|
||||
let Tabbar = this.React.createFactory(this.browserRequire(
|
||||
"devtools/client/shared/components/tabs/tabbar"));
|
||||
"devtools/client/shared/components/tabs/TabBar"));
|
||||
|
||||
let sidebar = Tabbar({
|
||||
menuDocument: this._toolPanel._toolbox.doc,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
define(function (require, exports, module) {
|
||||
const { DOM: dom, createFactory, createClass, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
|
||||
const TreeView = createFactory(TreeViewClass);
|
||||
|
||||
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
|
||||
|
|
|
@ -13,7 +13,7 @@ define(function (require, exports, module) {
|
|||
const { JsonPanel } = createFactories(require("./json-panel"));
|
||||
const { TextPanel } = createFactories(require("./text-panel"));
|
||||
const { HeadersPanel } = createFactories(require("./headers-panel"));
|
||||
const { Tabs, TabPanel } = createFactories(require("devtools/client/shared/components/tabs/tabs"));
|
||||
const { Tabs, TabPanel } = createFactories(require("devtools/client/shared/components/tabs/Tabs"));
|
||||
|
||||
/**
|
||||
* This object represents the root application template
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
@import "resource://devtools/client/themes/common.css";
|
||||
@import "resource://devtools/client/themes/toolbars.css";
|
||||
|
||||
@import "resource://devtools/client/shared/components/tree/tree-view.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/tabs.css";
|
||||
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
||||
|
||||
@import "general.css";
|
||||
@import "search-box.css";
|
||||
|
|
|
@ -11,7 +11,7 @@ const {
|
|||
PropTypes
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const { L10N, formatNumber, formatPercent } = require("../utils");
|
||||
const Frame = createFactory(require("devtools/client/shared/components/frame"));
|
||||
const Frame = createFactory(require("devtools/client/shared/components/Frame"));
|
||||
const { TREE_ROW_HEIGHT } = require("../constants");
|
||||
const models = require("../models");
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const { createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Tree = createFactory(require("devtools/client/shared/components/tree"));
|
||||
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
|
||||
const CensusTreeItem = createFactory(require("./census-tree-item"));
|
||||
const { TREE_ROW_HEIGHT } = require("../constants");
|
||||
const { censusModel, diffingModel } = require("../models");
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
const { assert, isSavedFrame } = require("devtools/shared/DevToolsUtils");
|
||||
const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const { L10N, formatNumber, formatPercent } = require("../utils");
|
||||
const Frame = createFactory(require("devtools/client/shared/components/frame"));
|
||||
const Frame = createFactory(require("devtools/client/shared/components/Frame"));
|
||||
const { TREE_ROW_HEIGHT } = require("../constants");
|
||||
|
||||
const Separator = createFactory(createClass({
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
const { DOM: dom, createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const { assert } = require("devtools/shared/DevToolsUtils");
|
||||
const { createParentMap } = require("devtools/shared/heapsnapshot/CensusUtils");
|
||||
const Tree = createFactory(require("devtools/client/shared/components/tree"));
|
||||
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
|
||||
const DominatorTreeItem = createFactory(require("./dominator-tree-item"));
|
||||
const { L10N } = require("../utils");
|
||||
const { TREE_ROW_HEIGHT, dominatorTreeState } = require("../constants");
|
||||
|
|
|
@ -11,7 +11,7 @@ const CensusHeader = createFactory(require("./census-header"));
|
|||
const DominatorTree = createFactory(require("./dominator-tree"));
|
||||
const DominatorTreeHeader = createFactory(require("./dominator-tree-header"));
|
||||
const TreeMap = createFactory(require("./tree-map"));
|
||||
const HSplitBox = createFactory(require("devtools/client/shared/components/h-split-box"));
|
||||
const HSplitBox = createFactory(require("devtools/client/shared/components/HSplitBox"));
|
||||
const Individuals = createFactory(require("./individuals"));
|
||||
const IndividualsHeader = createFactory(require("./individuals-header"));
|
||||
const ShortestPaths = createFactory(require("./shortest-paths"));
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"use strict";
|
||||
|
||||
const { createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Tree = createFactory(require("devtools/client/shared/components/tree"));
|
||||
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
|
||||
const DominatorTreeItem = createFactory(require("./dominator-tree-item"));
|
||||
const { TREE_ROW_HEIGHT } = require("../constants");
|
||||
const models = require("../models");
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
@import "chrome://devtools/skin/widgets.css";
|
||||
@import "resource://devtools/client/themes/light-theme.css";
|
||||
@import "resource://devtools/client/shared/components/splitter/split-box.css";
|
||||
@import "resource://devtools/client/shared/components/tree/tree-view.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/tabs.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/tabbar.css";
|
||||
@import "resource://devtools/client/shared/components/splitter/SplitBox.css";
|
||||
@import "resource://devtools/client/shared/components/tree/TreeView.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/Tabs.css";
|
||||
@import "resource://devtools/client/shared/components/tabs/TabBar.css";
|
||||
@import "chrome://devtools/skin/components-frame.css";
|
||||
@import "chrome://devtools/content/sourceeditor/codemirror/lib/codemirror.css";
|
||||
@import "chrome://devtools/content/sourceeditor/codemirror/addon/dialog/dialog.css";
|
||||
|
|
|
@ -19,7 +19,7 @@ const { getFormDataSections } = require("../utils/request-utils");
|
|||
const { getSelectedRequest } = require("../selectors/index");
|
||||
|
||||
// Components
|
||||
const SplitBox = createFactory(require("devtools/client/shared/components/splitter/split-box"));
|
||||
const SplitBox = createFactory(require("devtools/client/shared/components/splitter/SplitBox"));
|
||||
const NetworkDetailsPanel = createFactory(require("./network-details-panel"));
|
||||
const RequestList = createFactory(require("./request-list"));
|
||||
const Toolbar = createFactory(require("./toolbar"));
|
||||
|
|
|
@ -19,10 +19,10 @@ const { Rep } = REPS;
|
|||
const { FILTER_SEARCH_DELAY } = require("../constants");
|
||||
|
||||
// Components
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/SearchBox"));
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
|
||||
const TreeView = createFactory(TreeViewClass);
|
||||
const TreeRow = createFactory(require("devtools/client/shared/components/tree/tree-row"));
|
||||
const TreeRow = createFactory(require("devtools/client/shared/components/tree/TreeRow"));
|
||||
const SourceEditor = createFactory(require("./source-editor"));
|
||||
|
||||
const { div, tr, td } = DOM;
|
||||
|
|
|
@ -13,7 +13,7 @@ const { L10N } = require("../utils/l10n");
|
|||
const { getUrlHost } = require("../utils/request-utils");
|
||||
|
||||
// Components
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/tree-view");
|
||||
const TreeViewClass = require("devtools/client/shared/components/tree/TreeView");
|
||||
const PropertiesView = createFactory(require("./properties-view"));
|
||||
|
||||
const { div, input, span } = DOM;
|
||||
|
|
|
@ -14,7 +14,7 @@ const { viewSourceInDebugger } = require("../connector/index");
|
|||
const { div } = DOM;
|
||||
|
||||
// Components
|
||||
const StackTrace = createFactory(require("devtools/client/shared/components/stack-trace"));
|
||||
const StackTrace = createFactory(require("devtools/client/shared/components/StackTrace"));
|
||||
|
||||
function StackTracePanel({
|
||||
openLink,
|
||||
|
|
|
@ -13,8 +13,8 @@ const { L10N } = require("../utils/l10n");
|
|||
const { PANELS } = require("../constants");
|
||||
|
||||
// Components
|
||||
const Tabbar = createFactory(require("devtools/client/shared/components/tabs/tabbar"));
|
||||
const TabPanel = createFactory(require("devtools/client/shared/components/tabs/tabs").TabPanel);
|
||||
const Tabbar = createFactory(require("devtools/client/shared/components/tabs/TabBar"));
|
||||
const TabPanel = createFactory(require("devtools/client/shared/components/tabs/Tabs").TabPanel);
|
||||
const CookiesPanel = createFactory(require("./cookies-panel"));
|
||||
const HeadersPanel = createFactory(require("./headers-panel"));
|
||||
const ParamsPanel = createFactory(require("./params-panel"));
|
||||
|
|
|
@ -25,7 +25,7 @@ const { autocompleteProvider } = require("../utils/filter-autocomplete-provider"
|
|||
const { L10N } = require("../utils/l10n");
|
||||
|
||||
// Components
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/search-box"));
|
||||
const SearchBox = createFactory(require("devtools/client/shared/components/SearchBox"));
|
||||
|
||||
const { button, div, input, label, span } = DOM;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const L10N = new LocalizationHelper(STRINGS_URI);
|
|||
|
||||
const {PluralForm} = require("devtools/shared/plural-form");
|
||||
const { DOM: dom, PropTypes, createClass, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Frame = createFactory(require("devtools/client/shared/components/frame"));
|
||||
const Frame = createFactory(require("devtools/client/shared/components/Frame"));
|
||||
const PROPNAME_MAX_LENGTH = 4;
|
||||
// If TREE_ROW_HEIGHT changes, be sure to change `var(--jit-tree-row-height)`
|
||||
// in `devtools/client/themes/jit-optimizations.css`
|
||||
|
|
|
@ -9,9 +9,9 @@ const L10N = new LocalizationHelper(STRINGS_URI);
|
|||
|
||||
const { assert } = require("devtools/shared/DevToolsUtils");
|
||||
const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const Tree = createFactory(require("../../shared/components/tree"));
|
||||
const Tree = createFactory(require("../../shared/components/Tree"));
|
||||
const OptimizationsItem = createFactory(require("./jit-optimizations-item"));
|
||||
const FrameView = createFactory(require("../../shared/components/frame"));
|
||||
const FrameView = createFactory(require("../../shared/components/Frame"));
|
||||
const JIT_TITLE = L10N.getStr("jit.title");
|
||||
// If TREE_ROW_HEIGHT changes, be sure to change `var(--jit-tree-row-height)`
|
||||
// in `devtools/client/themes/jit-optimizations.css`
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"use strict";
|
||||
|
||||
const { createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const Tree = createFactory(require("devtools/client/shared/components/tree"));
|
||||
const Tree = createFactory(require("devtools/client/shared/components/Tree"));
|
||||
const WaterfallTreeRow = createFactory(require("./waterfall-tree-row"));
|
||||
|
||||
// Keep in sync with var(--waterfall-tree-row-height) in performance.css
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
const { DOM: dom, createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const KeyShortcuts = require("devtools/client/shared/key-shortcuts");
|
||||
const AutocompletePopup = createFactory(require("devtools/client/shared/components/autocomplete-popup"));
|
||||
const AutocompletePopup = createFactory(require("devtools/client/shared/components/AutoCompletePopup"));
|
||||
|
||||
/**
|
||||
* A generic search box component for use across devtools
|
|
@ -7,7 +7,7 @@
|
|||
const React = require("devtools/client/shared/vendor/react");
|
||||
const { DOM: dom, createClass, createFactory, PropTypes } = React;
|
||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||
const Frame = createFactory(require("./frame"));
|
||||
const Frame = createFactory(require("./Frame"));
|
||||
|
||||
const l10n = new LocalizationHelper("devtools/client/locales/webconsole.properties");
|
||||
|
|
@ -12,16 +12,16 @@ DIRS += [
|
|||
]
|
||||
|
||||
DevToolsModules(
|
||||
'autocomplete-popup.js',
|
||||
'frame.js',
|
||||
'h-split-box.js',
|
||||
'notification-box.css',
|
||||
'notification-box.js',
|
||||
'search-box.js',
|
||||
'sidebar-toggle.css',
|
||||
'sidebar-toggle.js',
|
||||
'stack-trace.js',
|
||||
'tree.js',
|
||||
'AutoCompletePopup.js',
|
||||
'Frame.js',
|
||||
'HSplitBox.js',
|
||||
'NotificationBox.css',
|
||||
'NotificationBox.js',
|
||||
'SearchBox.js',
|
||||
'SidebarToggle.css',
|
||||
'SidebarToggle.js',
|
||||
'StackTrace.js',
|
||||
'Tree.js',
|
||||
)
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/mochitest/chrome.ini']
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
const React = require("devtools/client/shared/vendor/react");
|
||||
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
const Draggable = React.createFactory(require("devtools/client/shared/components/splitter/draggable"));
|
||||
const Draggable = React.createFactory(require("devtools/client/shared/components/splitter/Draggable"));
|
||||
const { DOM: dom, PropTypes } = React;
|
||||
|
||||
/**
|
|
@ -5,7 +5,7 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'draggable.js',
|
||||
'split-box.css',
|
||||
'split-box.js',
|
||||
'Draggable.js',
|
||||
'SplitBox.css',
|
||||
'SplitBox.js',
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"use strict";
|
||||
|
||||
const { DOM, createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const Tabs = createFactory(require("devtools/client/shared/components/tabs/tabs").Tabs);
|
||||
const Tabs = createFactory(require("devtools/client/shared/components/tabs/Tabs").Tabs);
|
||||
|
||||
const Menu = require("devtools/client/framework/menu");
|
||||
const MenuItem = require("devtools/client/framework/menu-item");
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче