summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/components/MeatballMenu.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:44:51 +0000
commit9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/framework/components/MeatballMenu.js
parentInitial commit. (diff)
downloadthunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.tar.xz
thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/framework/components/MeatballMenu.js')
-rw-r--r--devtools/client/framework/components/MeatballMenu.js299
1 files changed, 299 insertions, 0 deletions
diff --git a/devtools/client/framework/components/MeatballMenu.js b/devtools/client/framework/components/MeatballMenu.js
new file mode 100644
index 0000000000..fc694171c8
--- /dev/null
+++ b/devtools/client/framework/components/MeatballMenu.js
@@ -0,0 +1,299 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const {
+ PureComponent,
+ createFactory,
+} = require("resource://devtools/client/shared/vendor/react.js");
+const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
+const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
+const { hr } = dom;
+
+loader.lazyGetter(this, "MenuItem", function () {
+ return createFactory(
+ require("resource://devtools/client/shared/components/menu/MenuItem.js")
+ );
+});
+loader.lazyGetter(this, "MenuList", function () {
+ return createFactory(
+ require("resource://devtools/client/shared/components/menu/MenuList.js")
+ );
+});
+
+loader.lazyRequireGetter(
+ this,
+ "openDocLink",
+ "resource://devtools/client/shared/link.js",
+ true
+);
+loader.lazyRequireGetter(
+ this,
+ "assert",
+ "resource://devtools/shared/DevToolsUtils.js",
+ true
+);
+
+const openDevToolsDocsLink = () => {
+ openDocLink("https://firefox-source-docs.mozilla.org/devtools-user/");
+};
+
+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. for "browsertoolbox").
+ 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,
+
+ // Apply a pseudo-locale to the Firefox UI. This is only available in the browser
+ // toolbox. This value can be undefined, "accented", "bidi", "none".
+ pseudoLocale: PropTypes.string,
+
+ // 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,
+
+ // Manage the pseudo-localization for the Firefox UI.
+ // https://firefox-source-docs.mozilla.org/l10n/fluent/tutorial.html#manually-testing-ui-with-pseudolocalization
+ disablePseudoLocale: PropTypes.func,
+ enableAccentedPseudoLocale: PropTypes.func,
+ enableBidiPseudoLocale: PropTypes.func,
+
+ // Bug 1709191 - The help shortcut key is localized without Fluent, and still needs
+ // to be migrated. This is the only remaining use of the legacy L10N object.
+ // Everything else should prefer the Fluent API.
+ 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 pseudo locale options 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.pseudoLocale !== prevProps.pseudoLocale ||
+ 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 l10nID;
+ switch (hostType.position) {
+ case "window":
+ l10nID = "toolbox-meatball-menu-dock-separate-window-label";
+ break;
+
+ case "bottom":
+ l10nID = "toolbox-meatball-menu-dock-bottom-label";
+ break;
+
+ case "left":
+ l10nID = "toolbox-meatball-menu-dock-left-label";
+ break;
+
+ case "right":
+ l10nID = "toolbox-meatball-menu-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}`,
+ l10nID,
+ 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 l10nID = this.props.isSplitConsoleActive
+ ? "toolbox-meatball-menu-hideconsole-label"
+ : "toolbox-meatball-menu-splitconsole-label";
+ items.push(
+ MenuItem({
+ id: "toolbox-meatball-menu-splitconsole",
+ key: "splitconsole",
+ l10nID,
+ accelerator: "Esc",
+ onClick: this.props.toggleSplitConsole,
+ className: "iconic",
+ })
+ );
+ }
+
+ // Settings
+ items.push(
+ MenuItem({
+ id: "toolbox-meatball-menu-settings",
+ key: "settings",
+ l10nID: "toolbox-meatball-menu-settings-label",
+ // Bug 1709191 - The help key is localized without Fluent, and still needs to
+ // be migrated.
+ accelerator: this.props.L10N.getStr("toolbox.help.key"),
+ onClick: this.props.toggleOptions,
+ className: "iconic",
+ })
+ );
+
+ if (
+ typeof this.props.disableAutohide !== "undefined" ||
+ typeof this.props.pseudoLocale !== "undefined"
+ ) {
+ items.push(hr({ key: "docs-separator-1" }));
+ }
+
+ // 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",
+ l10nID: "toolbox-meatball-menu-noautohide-label",
+ type: "checkbox",
+ checked: this.props.disableAutohide,
+ onClick: this.props.toggleNoAutohide,
+ className: "iconic",
+ })
+ );
+ }
+
+ // Pseudo-locales.
+ if (typeof this.props.pseudoLocale !== "undefined") {
+ const {
+ pseudoLocale,
+ enableAccentedPseudoLocale,
+ enableBidiPseudoLocale,
+ disablePseudoLocale,
+ } = this.props;
+ items.push(
+ MenuItem({
+ id: "toolbox-meatball-menu-pseudo-locale-accented",
+ key: "pseudo-locale-accented",
+ l10nID: "toolbox-meatball-menu-pseudo-locale-accented",
+ type: "checkbox",
+ checked: pseudoLocale === "accented",
+ onClick:
+ pseudoLocale === "accented"
+ ? disablePseudoLocale
+ : enableAccentedPseudoLocale,
+ className: "iconic",
+ }),
+ MenuItem({
+ id: "toolbox-meatball-menu-pseudo-locale-bidi",
+ key: "pseudo-locale-bidi",
+ l10nID: "toolbox-meatball-menu-pseudo-locale-bidi",
+ type: "checkbox",
+ checked: pseudoLocale === "bidi",
+ onClick:
+ pseudoLocale === "bidi"
+ ? disablePseudoLocale
+ : enableBidiPseudoLocale,
+ className: "iconic",
+ })
+ );
+ }
+
+ items.push(hr({ key: "docs-separator-2" }));
+
+ // Getting started
+ items.push(
+ MenuItem({
+ id: "toolbox-meatball-menu-documentation",
+ key: "documentation",
+ l10nID: "toolbox-meatball-menu-documentation-label",
+ onClick: openDevToolsDocsLink,
+ })
+ );
+
+ // Give feedback
+ items.push(
+ MenuItem({
+ id: "toolbox-meatball-menu-community",
+ key: "community",
+ l10nID: "toolbox-meatball-menu-community-label",
+ onClick: openCommunityLink,
+ })
+ );
+
+ return MenuList({ id: "toolbox-meatball-menu" }, items);
+ }
+}
+
+module.exports = MeatballMenu;