зеркало из https://github.com/mozilla/gecko-dev.git
242 строки
7.1 KiB
JavaScript
242 строки
7.1 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
const {
|
|
PureComponent,
|
|
createFactory,
|
|
} = require("devtools/client/shared/vendor/react");
|
|
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
|
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
|
const { hr } = dom;
|
|
|
|
loader.lazyGetter(this, "MenuItem", function() {
|
|
return createFactory(
|
|
require("devtools/client/shared/components/menu/MenuItem")
|
|
);
|
|
});
|
|
loader.lazyGetter(this, "MenuList", function() {
|
|
return createFactory(
|
|
require("devtools/client/shared/components/menu/MenuList")
|
|
);
|
|
});
|
|
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"openDocLink",
|
|
"devtools/client/shared/link",
|
|
true
|
|
);
|
|
loader.lazyRequireGetter(this, "assert", "devtools/shared/DevToolsUtils", true);
|
|
|
|
const openDevToolsDocsLink = () => {
|
|
openDocLink(
|
|
"https://developer.mozilla.org/docs/Tools?utm_source=devtools&utm_medium=tabbar-menu"
|
|
);
|
|
};
|
|
|
|
const openCommunityLink = () => {
|
|
openDocLink(
|
|
"https://discourse.mozilla.org/c/devtools?utm_source=devtools&utm_medium=tabbar-menu"
|
|
);
|
|
};
|
|
|
|
class MeatballMenu extends PureComponent {
|
|
static get propTypes() {
|
|
return {
|
|
// The id of the currently selected tool, e.g. "inspector"
|
|
currentToolId: PropTypes.string,
|
|
|
|
// List of possible docking options.
|
|
hostTypes: PropTypes.arrayOf(
|
|
PropTypes.shape({
|
|
position: PropTypes.string.isRequired,
|
|
switchHost: PropTypes.func.isRequired,
|
|
})
|
|
),
|
|
|
|
// Current docking type. Typically one of the position values in
|
|
// |hostTypes| but this is not always the case (e.g. when it is "custom").
|
|
currentHostType: PropTypes.string,
|
|
|
|
// Is the split console currently visible?
|
|
isSplitConsoleActive: PropTypes.bool,
|
|
|
|
// Are we disabling the behavior where pop-ups are automatically closed
|
|
// when clicking outside them?
|
|
//
|
|
// This is a tri-state value that may be true/false or undefined where
|
|
// undefined means that the option is not relevant in this context
|
|
// (i.e. we're not in a browser toolbox).
|
|
disableAutohide: PropTypes.bool,
|
|
|
|
// Function to turn the options panel on / off.
|
|
toggleOptions: PropTypes.func.isRequired,
|
|
|
|
// Function to turn the split console on / off.
|
|
toggleSplitConsole: PropTypes.func,
|
|
|
|
// Function to turn the disable pop-up autohide behavior on / off.
|
|
toggleNoAutohide: PropTypes.func,
|
|
|
|
// Localization interface.
|
|
L10N: PropTypes.object.isRequired,
|
|
|
|
// Callback function that will be invoked any time the component contents
|
|
// update in such a way that its bounding box might change.
|
|
onResize: PropTypes.func,
|
|
};
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
if (!this.props.onResize) {
|
|
return;
|
|
}
|
|
|
|
// We are only expecting the following kinds of dynamic changes when a popup
|
|
// is showing:
|
|
//
|
|
// - The "Disable pop-up autohide" menu item being added after the Browser
|
|
// Toolbox is connected.
|
|
// - The split console label changing between "Show Split Console" and "Hide
|
|
// Split Console".
|
|
// - The "Show/Hide Split Console" entry being added removed or removed.
|
|
//
|
|
// The latter two cases are only likely to be noticed when "Disable pop-up
|
|
// autohide" is active, but for completeness we handle them here.
|
|
const didChange =
|
|
typeof this.props.disableAutohide !== typeof prevProps.disableAutohide ||
|
|
this.props.currentToolId !== prevProps.currentToolId ||
|
|
this.props.isSplitConsoleActive !== prevProps.isSplitConsoleActive;
|
|
|
|
if (didChange) {
|
|
this.props.onResize();
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const items = [];
|
|
|
|
// Dock options
|
|
for (const hostType of this.props.hostTypes) {
|
|
// This is more verbose than it needs to be but lets us easily search for
|
|
// l10n entities.
|
|
let l10nkey;
|
|
switch (hostType.position) {
|
|
case "window":
|
|
l10nkey = "toolbox.meatballMenu.dock.separateWindow.label";
|
|
break;
|
|
|
|
case "bottom":
|
|
l10nkey = "toolbox.meatballMenu.dock.bottom.label";
|
|
break;
|
|
|
|
case "left":
|
|
l10nkey = "toolbox.meatballMenu.dock.left.label";
|
|
break;
|
|
|
|
case "right":
|
|
l10nkey = "toolbox.meatballMenu.dock.right.label";
|
|
break;
|
|
|
|
default:
|
|
assert(false, `Unexpected hostType.position: ${hostType.position}`);
|
|
break;
|
|
}
|
|
|
|
items.push(
|
|
MenuItem({
|
|
id: `toolbox-meatball-menu-dock-${hostType.position}`,
|
|
key: `dock-${hostType.position}`,
|
|
label: this.props.L10N.getStr(l10nkey),
|
|
onClick: hostType.switchHost,
|
|
checked: hostType.position === this.props.currentHostType,
|
|
className: "iconic",
|
|
})
|
|
);
|
|
}
|
|
|
|
if (items.length) {
|
|
items.push(hr({ key: "dock-separator" }));
|
|
}
|
|
|
|
// Split console
|
|
if (this.props.currentToolId !== "webconsole") {
|
|
const l10nkey = this.props.isSplitConsoleActive
|
|
? "toolbox.meatballMenu.hideconsole.label"
|
|
: "toolbox.meatballMenu.splitconsole.label";
|
|
items.push(
|
|
MenuItem({
|
|
id: "toolbox-meatball-menu-splitconsole",
|
|
key: "splitconsole",
|
|
label: this.props.L10N.getStr(l10nkey),
|
|
accelerator: "Esc",
|
|
onClick: this.props.toggleSplitConsole,
|
|
className: "iconic",
|
|
})
|
|
);
|
|
}
|
|
|
|
// Disable pop-up autohide
|
|
//
|
|
// If |disableAutohide| is undefined, it means this feature is not available
|
|
// in this context.
|
|
if (typeof this.props.disableAutohide !== "undefined") {
|
|
items.push(
|
|
MenuItem({
|
|
id: "toolbox-meatball-menu-noautohide",
|
|
key: "noautohide",
|
|
label: this.props.L10N.getStr(
|
|
"toolbox.meatballMenu.noautohide.label"
|
|
),
|
|
type: "checkbox",
|
|
checked: this.props.disableAutohide,
|
|
onClick: this.props.toggleNoAutohide,
|
|
className: "iconic",
|
|
})
|
|
);
|
|
}
|
|
|
|
// Settings
|
|
items.push(
|
|
MenuItem({
|
|
id: "toolbox-meatball-menu-settings",
|
|
key: "settings",
|
|
label: this.props.L10N.getStr("toolbox.meatballMenu.settings.label"),
|
|
accelerator: this.props.L10N.getStr("toolbox.help.key"),
|
|
onClick: this.props.toggleOptions,
|
|
className: "iconic",
|
|
})
|
|
);
|
|
|
|
items.push(hr({ key: "docs-separator" }));
|
|
|
|
// Getting started
|
|
items.push(
|
|
MenuItem({
|
|
id: "toolbox-meatball-menu-documentation",
|
|
key: "documentation",
|
|
label: this.props.L10N.getStr(
|
|
"toolbox.meatballMenu.documentation.label"
|
|
),
|
|
onClick: openDevToolsDocsLink,
|
|
})
|
|
);
|
|
|
|
// Give feedback
|
|
items.push(
|
|
MenuItem({
|
|
id: "toolbox-meatball-menu-community",
|
|
key: "community",
|
|
label: this.props.L10N.getStr("toolbox.meatballMenu.community.label"),
|
|
onClick: openCommunityLink,
|
|
})
|
|
);
|
|
|
|
return MenuList({ id: "toolbox-meatball-menu" }, items);
|
|
}
|
|
}
|
|
|
|
module.exports = MeatballMenu;
|