From 84a28c39cd62cf72fb8e85307b9fadf68414a37b Mon Sep 17 00:00:00 2001
From: Muffin <muffin@mailbox.org>
Date: Sat, 30 Dec 2023 17:49:35 -0600
Subject: [PATCH] merge-upstream: fix addons that add buttons by the fullscreen
 button

---
 src/addons/addons/debugger/userscript.js     |  3 +-
 src/addons/addons/gamepad/userscript.js      |  3 +-
 src/addons/api.js                            | 16 +---
 src/addons/generated/upstream-meta.json      |  2 +-
 src/components/stage-header/stage-header.css |  5 ++
 src/components/stage-header/stage-header.jsx | 90 +++++++++++---------
 6 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/src/addons/addons/debugger/userscript.js b/src/addons/addons/debugger/userscript.js
index 16d1f06dccd..d55a0fca598 100644
--- a/src/addons/addons/debugger/userscript.js
+++ b/src/addons/addons/debugger/userscript.js
@@ -585,8 +585,7 @@ export default async function ({ addon, console, msg }) {
 
   while (true) {
     await addon.tab.waitForElement(
-      // Full screen button
-      '[class^="stage-header_stage-size-row"] [class^="button_outlined-button"], [class*="stage-header_unselect-wrapper_"] > [class^="button_outlined-button"]',
+      '[class^="stage-header_stage-size-row"], [class^="stage-header_fullscreen-buttons-row_"]',
       {
         markAsSeen: true,
         reduxEvents: [
diff --git a/src/addons/addons/gamepad/userscript.js b/src/addons/addons/gamepad/userscript.js
index fa3281f96a1..2e959ccdbac 100644
--- a/src/addons/addons/gamepad/userscript.js
+++ b/src/addons/addons/gamepad/userscript.js
@@ -409,8 +409,7 @@ export default async function ({ addon, console, msg }) {
 
   while (true) {
     const target = await addon.tab.waitForElement(
-      // Full screen button
-      '[class^="stage-header_stage-size-row"] [class^="button_outlined-button"], [class*="stage-header_unselect-wrapper_"] > [class^="button_outlined-button"]',
+      '[class^="stage-header_stage-size-row"], [class^="stage-header_fullscreen-buttons-row_"]',
       {
         markAsSeen: true,
         reduxEvents: [
diff --git a/src/addons/api.js b/src/addons/api.js
index dbb4fdc71c2..cdf05b5d576 100644
--- a/src/addons/api.js
+++ b/src/addons/api.js
@@ -312,19 +312,11 @@ class Tab extends EventTargetShim {
                 ]
             },
             fullscreenStageHeader: {
+                // Upstream uses sa-spacer for this one, but we don't need to
                 // Fullscreen stage header only
-                element: () => q("[class^='stage-header_stage-menu-wrapper']"),
-                from: function () {
-                    let emptyDiv = this.element().querySelector('.sa-spacer');
-                    if (!emptyDiv) {
-                        emptyDiv = document.createElement('div');
-                        emptyDiv.style.marginLeft = 'auto';
-                        emptyDiv.className = 'sa-spacer';
-                        this.element().insertBefore(emptyDiv, this.element().lastChild);
-                    }
-                    return [emptyDiv];
-                },
-                until: () => [q("[class^='stage-header_stage-menu-wrapper']").lastChild]
+                element: () => q("[class^='stage-header_fullscreen-buttons-row_']"),
+                from: () => [],
+                until: () => [q("[class^='stage-header_fullscreen-buttons-row_']").lastChild]
             },
             afterGreenFlag: {
                 element: () => q("[class^='controls_controls-container']"),
diff --git a/src/addons/generated/upstream-meta.json b/src/addons/generated/upstream-meta.json
index e97e8962200..f916e3aec5f 100644
--- a/src/addons/generated/upstream-meta.json
+++ b/src/addons/generated/upstream-meta.json
@@ -1 +1 @@
-{"commit":"80bc143"}
\ No newline at end of file
+{"commit":"40086e2"}
\ No newline at end of file
diff --git a/src/components/stage-header/stage-header.css b/src/components/stage-header/stage-header.css
index 5a0b39104d8..ec4348e0bb6 100644
--- a/src/components/stage-header/stage-header.css
+++ b/src/components/stage-header/stage-header.css
@@ -78,3 +78,8 @@
 [dir="rtl"] .stage-button-icon {
     transform: scaleX(-1);
 }
+
+.fullscreen-buttons-row {
+    /* relied on by addons */
+    display: flex;
+}
diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx
index e9086ae91b9..19f85fbfc8d 100644
--- a/src/components/stage-header/stage-header.jsx
+++ b/src/components/stage-header/stage-header.jsx
@@ -78,46 +78,52 @@ const StageHeaderComponent = function (props) {
     if (isFullScreen || isEmbedded) {
         const stageDimensions = getStageDimensions(null, customStageSize, true);
         const settingsButton = isEmbedded && enableSettingsButton ? (
-            <Button
-                className={styles.stageButton}
-                onClick={onOpenSettings}
-            >
-                <img
-                    alt={props.intl.formatMessage(messages.openSettingsMessage)}
-                    className={styles.stageButtonIcon}
-                    draggable={false}
-                    src={settingsIcon}
-                    title={props.intl.formatMessage(messages.openSettingsMessage)}
-                />
-            </Button>
+            <div className={styles.unselectWrapper}>
+                <Button
+                    className={styles.stageButton}
+                    onClick={onOpenSettings}
+                >
+                    <img
+                        alt={props.intl.formatMessage(messages.openSettingsMessage)}
+                        className={styles.stageButtonIcon}
+                        draggable={false}
+                        src={settingsIcon}
+                        title={props.intl.formatMessage(messages.openSettingsMessage)}
+                    />
+                </Button>
+            </div>
         ) : null;
         const fullscreenButton = isFullScreen ? (
-            <Button
-                className={styles.stageButton}
-                onClick={onSetStageUnFull}
-                onKeyPress={onKeyPress}
-            >
-                <img
-                    alt={props.intl.formatMessage(messages.unFullStageSizeMessage)}
-                    className={styles.stageButtonIcon}
-                    draggable={false}
-                    src={unFullScreenIcon}
-                    title={props.intl.formatMessage(messages.fullscreenControl)}
-                />
-            </Button>
+            <div className={styles.unselectWrapper}>
+                <Button
+                    className={styles.stageButton}
+                    onClick={onSetStageUnFull}
+                    onKeyPress={onKeyPress}
+                >
+                    <img
+                        alt={props.intl.formatMessage(messages.unFullStageSizeMessage)}
+                        className={styles.stageButtonIcon}
+                        draggable={false}
+                        src={unFullScreenIcon}
+                        title={props.intl.formatMessage(messages.fullscreenControl)}
+                    />
+                </Button>
+            </div>
         ) : FullscreenAPI.available() ? (
-            <Button
-                className={styles.stageButton}
-                onClick={onSetStageFull}
-            >
-                <img
-                    alt={props.intl.formatMessage(messages.fullStageSizeMessage)}
-                    className={styles.stageButtonIcon}
-                    draggable={false}
-                    src={fullScreenIcon}
-                    title={props.intl.formatMessage(messages.fullscreenControl)}
-                />
-            </Button>
+            <div className={styles.unselectWrapper}>
+                <Button
+                    className={styles.stageButton}
+                    onClick={onSetStageFull}
+                >
+                    <img
+                        alt={props.intl.formatMessage(messages.fullStageSizeMessage)}
+                        className={styles.stageButtonIcon}
+                        draggable={false}
+                        src={fullScreenIcon}
+                        title={props.intl.formatMessage(messages.fullscreenControl)}
+                    />
+                </Button>
+            </div>
         ) : null;
         header = (
             <Box
@@ -130,7 +136,10 @@ const StageHeaderComponent = function (props) {
                     style={{width: stageDimensions.width}}
                 >
                     <Controls vm={vm} />
-                    <div className={styles.embedButtons}>
+                    <div
+                        className={styles.fullscreenButtonsRow}
+                        key="fullscreen" // addons require the HTML element to be not be re-used by in-editor buttons
+                    >
                         {settingsButton}
                         {fullscreenButton}
                     </div>
@@ -170,7 +179,10 @@ const StageHeaderComponent = function (props) {
                         vm={vm}
                         isSmall={stageSizeMode === STAGE_SIZE_MODES.small}
                     />
-                    <div className={styles.stageSizeRow}>
+                    <div
+                        className={styles.stageSizeRow}
+                        key="editor" // addons require the HTML element to be not be re-used by in-editor buttons
+                    >
                         {stageControls}
                         <div>
                             <Button