mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-06 07:37:19 +02:00
Stop using MutationObserver in stream-ui
This commit is contained in:
parent
85339f09da
commit
ac20cc51cc
201
dist/better-xcloud.pretty.user.js
vendored
201
dist/better-xcloud.pretty.user.js
vendored
@ -5697,6 +5697,12 @@ ${subsVar} = subs;
|
|||||||
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;
|
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;
|
||||||
let newCode = "window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.Script.emit('error.rendered', {}));";
|
let newCode = "window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.Script.emit('error.rendered', {}));";
|
||||||
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
||||||
|
},
|
||||||
|
injectStreamMenuUseEffect(str) {
|
||||||
|
let index = str.indexOf('"StreamMenu-module__container');
|
||||||
|
if (index > -1 && (index = PatcherUtils.lastIndexOf(str, "return", index, 200)), index < 0) return !1;
|
||||||
|
let newCode = "window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.Stream.emit('ui.streamMenu.rendered', {}));";
|
||||||
|
return str = PatcherUtils.insertAt(str, index, newCode), str;
|
||||||
}
|
}
|
||||||
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
}, PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? [
|
...AppInterface && getGlobalPref("nativeMkb.mode") === "on" ? [
|
||||||
@ -5772,6 +5778,7 @@ ${subsVar} = subs;
|
|||||||
"patchStreamHud",
|
"patchStreamHud",
|
||||||
"playVibration",
|
"playVibration",
|
||||||
"alwaysShowStreamHud",
|
"alwaysShowStreamHud",
|
||||||
|
"injectStreamMenuUseEffect",
|
||||||
getGlobalPref("audio.volume.booster.enabled") && !getGlobalPref("stream.video.combineAudio") && "patchAudioMediaStream",
|
getGlobalPref("audio.volume.booster.enabled") && !getGlobalPref("stream.video.combineAudio") && "patchAudioMediaStream",
|
||||||
getGlobalPref("audio.volume.booster.enabled") && getGlobalPref("stream.video.combineAudio") && "patchCombinedAudioVideoMediaStream",
|
getGlobalPref("audio.volume.booster.enabled") && getGlobalPref("stream.video.combineAudio") && "patchCombinedAudioVideoMediaStream",
|
||||||
getGlobalPref("ui.feedbackDialog.disabled") && "skipFeedbackDialog",
|
getGlobalPref("ui.feedbackDialog.disabled") && "skipFeedbackDialog",
|
||||||
@ -10156,111 +10163,6 @@ class ProductDetailsPage {
|
|||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class StreamUiHandler {
|
|
||||||
static $btnStreamSettings;
|
|
||||||
static $btnStreamStats;
|
|
||||||
static $btnRefresh;
|
|
||||||
static $btnHome;
|
|
||||||
static observer;
|
|
||||||
static cloneStreamHudButton($btnOrg, label, svgIcon) {
|
|
||||||
if (!$btnOrg) return null;
|
|
||||||
let $container = $btnOrg.cloneNode(!0), timeout;
|
|
||||||
if (STATES.browser.capabilities.touch) {
|
|
||||||
let onTransitionStart = (e) => {
|
|
||||||
if (e.propertyName !== "opacity") return;
|
|
||||||
timeout && clearTimeout(timeout), e.target.style.pointerEvents = "none";
|
|
||||||
}, onTransitionEnd = (e) => {
|
|
||||||
if (e.propertyName !== "opacity") return;
|
|
||||||
let $streamHud = e.target.closest("#StreamHud");
|
|
||||||
if (!$streamHud) return;
|
|
||||||
if ($streamHud.style.left === "0px") {
|
|
||||||
let $target = e.target;
|
|
||||||
timeout && clearTimeout(timeout), timeout = window.setTimeout(() => {
|
|
||||||
$target.style.pointerEvents = "auto";
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
$container.addEventListener("transitionstart", onTransitionStart), $container.addEventListener("transitionend", onTransitionEnd);
|
|
||||||
}
|
|
||||||
let $button = $container.querySelector("button");
|
|
||||||
if (!$button) return null;
|
|
||||||
$button.setAttribute("title", label);
|
|
||||||
let $orgSvg = $button.querySelector("svg");
|
|
||||||
if (!$orgSvg) return null;
|
|
||||||
let $svg = createSvgIcon(svgIcon);
|
|
||||||
return $svg.style.fill = "none", $svg.setAttribute("class", $orgSvg.getAttribute("class") || ""), $svg.ariaHidden = "true", $orgSvg.replaceWith($svg), $container;
|
|
||||||
}
|
|
||||||
static cloneCloseButton($btnOrg, icon, className, onChange) {
|
|
||||||
if (!$btnOrg) return null;
|
|
||||||
let $btn = $btnOrg.cloneNode(!0), $svg = createSvgIcon(icon);
|
|
||||||
return $svg.setAttribute("class", $btn.firstElementChild.getAttribute("class") || ""), $svg.style.fill = "none", $btn.classList.add(className), $btn.removeChild($btn.firstElementChild), $btn.appendChild($svg), $btn.addEventListener("click", onChange), $btn;
|
|
||||||
}
|
|
||||||
static async handleStreamMenu() {
|
|
||||||
let $btnCloseHud = document.querySelector("button[class*=StreamMenu-module__backButton]");
|
|
||||||
if (!$btnCloseHud) return;
|
|
||||||
let { $btnRefresh, $btnHome } = StreamUiHandler;
|
|
||||||
if (typeof $btnRefresh === "undefined") $btnRefresh = StreamUiHandler.cloneCloseButton($btnCloseHud, BxIcon.REFRESH, "bx-stream-refresh-button", () => {
|
|
||||||
confirm(t("confirm-reload-stream")) && window.location.reload();
|
|
||||||
});
|
|
||||||
if (typeof $btnHome === "undefined") $btnHome = StreamUiHandler.cloneCloseButton($btnCloseHud, BxIcon.HOME, "bx-stream-home-button", () => {
|
|
||||||
confirm(t("back-to-home-confirm")) && (window.location.href = window.location.href.substring(0, 31));
|
|
||||||
});
|
|
||||||
if ($btnRefresh && $btnHome) $btnCloseHud.insertAdjacentElement("afterend", $btnRefresh), $btnRefresh.insertAdjacentElement("afterend", $btnHome);
|
|
||||||
document.querySelector("div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]")?.appendChild(await StreamBadges.getInstance().render());
|
|
||||||
}
|
|
||||||
static handleSystemMenu($streamHud) {
|
|
||||||
let $orgButton = $streamHud.querySelector("div[class^=HUDButton]");
|
|
||||||
if (!$orgButton) return;
|
|
||||||
let hideGripHandle = () => {
|
|
||||||
let $gripHandle = document.querySelector("#StreamHud button[class^=GripHandle]");
|
|
||||||
if ($gripHandle && $gripHandle.ariaExpanded === "true") $gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click(), $gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click();
|
|
||||||
}, $btnStreamSettings = StreamUiHandler.$btnStreamSettings;
|
|
||||||
if (typeof $btnStreamSettings === "undefined") $btnStreamSettings = StreamUiHandler.cloneStreamHudButton($orgButton, t("better-xcloud"), BxIcon.BETTER_XCLOUD), $btnStreamSettings?.addEventListener("click", (e) => {
|
|
||||||
hideGripHandle(), e.preventDefault(), SettingsDialog.getInstance().show();
|
|
||||||
}), StreamUiHandler.$btnStreamSettings = $btnStreamSettings;
|
|
||||||
let streamStats = StreamStats.getInstance(), $btnStreamStats = StreamUiHandler.$btnStreamStats;
|
|
||||||
if (typeof $btnStreamStats === "undefined") $btnStreamStats = StreamUiHandler.cloneStreamHudButton($orgButton, t("stream-stats"), BxIcon.STREAM_STATS), $btnStreamStats?.addEventListener("click", async (e) => {
|
|
||||||
hideGripHandle(), e.preventDefault(), await streamStats.toggle();
|
|
||||||
let btnStreamStatsOn = !streamStats.isHidden() && !streamStats.isGlancing();
|
|
||||||
$btnStreamStats.classList.toggle("bx-stream-menu-button-on", btnStreamStatsOn);
|
|
||||||
}), StreamUiHandler.$btnStreamStats = $btnStreamStats;
|
|
||||||
let $btnParent = $orgButton.parentElement;
|
|
||||||
if ($btnStreamSettings && $btnStreamStats) {
|
|
||||||
let btnStreamStatsOn = !streamStats.isHidden() && !streamStats.isGlancing();
|
|
||||||
$btnStreamStats.classList.toggle("bx-stream-menu-button-on", btnStreamStatsOn), $btnParent.insertBefore($btnStreamStats, $btnParent.lastElementChild), $btnParent.insertBefore($btnStreamSettings, $btnStreamStats);
|
|
||||||
}
|
|
||||||
let $dotsButton = $btnParent.lastElementChild;
|
|
||||||
$dotsButton.parentElement.insertBefore($dotsButton, $dotsButton.parentElement.firstElementChild);
|
|
||||||
}
|
|
||||||
static reset() {
|
|
||||||
StreamUiHandler.$btnStreamSettings = void 0, StreamUiHandler.$btnStreamStats = void 0, StreamUiHandler.$btnRefresh = void 0, StreamUiHandler.$btnHome = void 0, StreamUiHandler.observer && StreamUiHandler.observer.disconnect(), StreamUiHandler.observer = void 0;
|
|
||||||
}
|
|
||||||
static observe() {
|
|
||||||
StreamUiHandler.reset();
|
|
||||||
let $screen = document.querySelector("#PageContent section[class*=PureScreens]");
|
|
||||||
if (!$screen) return;
|
|
||||||
let observer = new MutationObserver((mutationList) => {
|
|
||||||
let item2;
|
|
||||||
for (item2 of mutationList) {
|
|
||||||
if (item2.type !== "childList") continue;
|
|
||||||
item2.addedNodes.forEach(async ($node) => {
|
|
||||||
if (!$node || $node.nodeType !== Node.ELEMENT_NODE) return;
|
|
||||||
let $elm = $node;
|
|
||||||
if (!($elm instanceof HTMLElement)) return;
|
|
||||||
let className = $elm.className || "";
|
|
||||||
if (className.startsWith("StreamMenu-module__container")) {
|
|
||||||
StreamUiHandler.handleStreamMenu();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (className.startsWith("Overlay-module_") || className.startsWith("InProgressScreen")) $elm = $elm.querySelector("#StreamHud");
|
|
||||||
if (!$elm || ($elm.id || "") !== "StreamHud") return;
|
|
||||||
StreamUiHandler.handleSystemMenu($elm);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
observer.observe($screen, { subtree: !0, childList: !0 }), StreamUiHandler.observer = observer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class RootDialogObserver {
|
class RootDialogObserver {
|
||||||
static $btnShortcut = AppInterface && createButton({
|
static $btnShortcut = AppInterface && createButton({
|
||||||
icon: BxIcon.CREATE_SHORTCUT,
|
icon: BxIcon.CREATE_SHORTCUT,
|
||||||
@ -10405,6 +10307,86 @@ class DeviceVibrationManager {
|
|||||||
this.removeEventListeners(), this.dataChannel = null;
|
this.removeEventListeners(), this.dataChannel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class StreamUiHandler {
|
||||||
|
static $btnStreamSettings;
|
||||||
|
static $btnStreamStats;
|
||||||
|
static $btnRefresh;
|
||||||
|
static $btnHome;
|
||||||
|
static cloneStreamHudButton($btnOrg, label, svgIcon) {
|
||||||
|
if (!$btnOrg) return null;
|
||||||
|
let $container = $btnOrg.cloneNode(!0), timeout;
|
||||||
|
if (STATES.browser.capabilities.touch) {
|
||||||
|
let onTransitionStart = (e) => {
|
||||||
|
if (e.propertyName !== "opacity") return;
|
||||||
|
timeout && clearTimeout(timeout), e.target.style.pointerEvents = "none";
|
||||||
|
}, onTransitionEnd = (e) => {
|
||||||
|
if (e.propertyName !== "opacity") return;
|
||||||
|
let $streamHud = e.target.closest("#StreamHud");
|
||||||
|
if (!$streamHud) return;
|
||||||
|
if ($streamHud.style.left === "0px") {
|
||||||
|
let $target = e.target;
|
||||||
|
timeout && clearTimeout(timeout), timeout = window.setTimeout(() => {
|
||||||
|
$target.style.pointerEvents = "auto";
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$container.addEventListener("transitionstart", onTransitionStart), $container.addEventListener("transitionend", onTransitionEnd);
|
||||||
|
}
|
||||||
|
let $button = $container.querySelector("button");
|
||||||
|
if (!$button) return null;
|
||||||
|
$button.setAttribute("title", label);
|
||||||
|
let $orgSvg = $button.querySelector("svg");
|
||||||
|
if (!$orgSvg) return null;
|
||||||
|
let $svg = createSvgIcon(svgIcon);
|
||||||
|
return $svg.style.fill = "none", $svg.setAttribute("class", $orgSvg.getAttribute("class") || ""), $svg.ariaHidden = "true", $orgSvg.replaceWith($svg), $container;
|
||||||
|
}
|
||||||
|
static cloneCloseButton($btnOrg, icon, className, onChange) {
|
||||||
|
if (!$btnOrg) return null;
|
||||||
|
let $btn = $btnOrg.cloneNode(!0), $svg = createSvgIcon(icon);
|
||||||
|
return $svg.setAttribute("class", $btn.firstElementChild.getAttribute("class") || ""), $svg.style.fill = "none", $btn.classList.add(className), $btn.removeChild($btn.firstElementChild), $btn.appendChild($svg), $btn.addEventListener("click", onChange), $btn;
|
||||||
|
}
|
||||||
|
static async handleStreamMenu() {
|
||||||
|
let $btnCloseHud = document.querySelector("button[class*=StreamMenu-module__backButton]");
|
||||||
|
if (!$btnCloseHud) return;
|
||||||
|
let { $btnRefresh, $btnHome } = StreamUiHandler;
|
||||||
|
if (typeof $btnRefresh === "undefined") $btnRefresh = StreamUiHandler.cloneCloseButton($btnCloseHud, BxIcon.REFRESH, "bx-stream-refresh-button", () => {
|
||||||
|
confirm(t("confirm-reload-stream")) && window.location.reload();
|
||||||
|
});
|
||||||
|
if (typeof $btnHome === "undefined") $btnHome = StreamUiHandler.cloneCloseButton($btnCloseHud, BxIcon.HOME, "bx-stream-home-button", () => {
|
||||||
|
confirm(t("back-to-home-confirm")) && (window.location.href = window.location.href.substring(0, 31));
|
||||||
|
});
|
||||||
|
if ($btnRefresh && $btnHome) $btnCloseHud.insertAdjacentElement("afterend", $btnRefresh), $btnRefresh.insertAdjacentElement("afterend", $btnHome);
|
||||||
|
document.querySelector("div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]")?.appendChild(await StreamBadges.getInstance().render());
|
||||||
|
}
|
||||||
|
static handleSystemMenu($streamHud) {
|
||||||
|
let $orgButton = $streamHud.querySelector("div[class^=HUDButton]");
|
||||||
|
if (!$orgButton) return;
|
||||||
|
if (StreamUiHandler.$btnStreamSettings && $streamHud.contains(StreamUiHandler.$btnStreamSettings)) return;
|
||||||
|
let hideGripHandle = () => {
|
||||||
|
let $gripHandle = document.querySelector("#StreamHud button[class^=GripHandle]");
|
||||||
|
if ($gripHandle && $gripHandle.ariaExpanded === "true") $gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click(), $gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click();
|
||||||
|
}, $btnStreamSettings = StreamUiHandler.$btnStreamSettings;
|
||||||
|
if (typeof $btnStreamSettings === "undefined") $btnStreamSettings = StreamUiHandler.cloneStreamHudButton($orgButton, t("better-xcloud"), BxIcon.BETTER_XCLOUD), $btnStreamSettings?.addEventListener("click", (e) => {
|
||||||
|
hideGripHandle(), e.preventDefault(), SettingsDialog.getInstance().show();
|
||||||
|
}), StreamUiHandler.$btnStreamSettings = $btnStreamSettings;
|
||||||
|
let streamStats = StreamStats.getInstance(), $btnStreamStats = StreamUiHandler.$btnStreamStats;
|
||||||
|
if (typeof $btnStreamStats === "undefined") $btnStreamStats = StreamUiHandler.cloneStreamHudButton($orgButton, t("stream-stats"), BxIcon.STREAM_STATS), $btnStreamStats?.addEventListener("click", async (e) => {
|
||||||
|
hideGripHandle(), e.preventDefault(), await streamStats.toggle();
|
||||||
|
let btnStreamStatsOn = !streamStats.isHidden() && !streamStats.isGlancing();
|
||||||
|
$btnStreamStats.classList.toggle("bx-stream-menu-button-on", btnStreamStatsOn);
|
||||||
|
}), StreamUiHandler.$btnStreamStats = $btnStreamStats;
|
||||||
|
let $btnParent = $orgButton.parentElement;
|
||||||
|
if ($btnStreamSettings && $btnStreamStats) {
|
||||||
|
let btnStreamStatsOn = !streamStats.isHidden() && !streamStats.isGlancing();
|
||||||
|
$btnStreamStats.classList.toggle("bx-stream-menu-button-on", btnStreamStatsOn), $btnParent.insertBefore($btnStreamStats, $btnParent.lastElementChild), $btnParent.insertBefore($btnStreamSettings, $btnStreamStats);
|
||||||
|
}
|
||||||
|
let $dotsButton = $btnParent.lastElementChild;
|
||||||
|
$dotsButton.parentElement.insertBefore($dotsButton, $dotsButton.parentElement.firstElementChild);
|
||||||
|
}
|
||||||
|
static reset() {
|
||||||
|
StreamUiHandler.$btnStreamSettings = void 0, StreamUiHandler.$btnStreamStats = void 0, StreamUiHandler.$btnRefresh = void 0, StreamUiHandler.$btnHome = void 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
SettingsManager.getInstance();
|
SettingsManager.getInstance();
|
||||||
if (window.location.pathname.includes("/auth/msa")) {
|
if (window.location.pathname.includes("/auth/msa")) {
|
||||||
let nativePushState = window.history.pushState;
|
let nativePushState = window.history.pushState;
|
||||||
@ -10468,7 +10450,7 @@ BxEventBus.Stream.on("state.starting", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
BxEventBus.Stream.on("state.playing", (payload) => {
|
BxEventBus.Stream.on("state.playing", (payload) => {
|
||||||
window.BX_STREAM_SETTINGS = StreamSettings.settings, StreamSettings.refreshAllSettings(), STATES.isPlaying = !0, StreamUiHandler.observe();
|
window.BX_STREAM_SETTINGS = StreamSettings.settings, StreamSettings.refreshAllSettings(), STATES.isPlaying = !0;
|
||||||
{
|
{
|
||||||
let gameBar = GameBar.getInstance();
|
let gameBar = GameBar.getInstance();
|
||||||
if (gameBar) gameBar.reset(), gameBar.enable(), gameBar.showBar();
|
if (gameBar) gameBar.reset(), gameBar.enable(), gameBar.showBar();
|
||||||
@ -10481,6 +10463,13 @@ BxEventBus.Stream.on("state.playing", (payload) => {
|
|||||||
BxEventBus.Script.on("error.rendered", () => {
|
BxEventBus.Script.on("error.rendered", () => {
|
||||||
BxEventBus.Stream.emit("state.stopped", {});
|
BxEventBus.Stream.emit("state.stopped", {});
|
||||||
});
|
});
|
||||||
|
BxEventBus.Stream.on("ui.streamMenu.rendered", async () => {
|
||||||
|
await StreamUiHandler.handleStreamMenu();
|
||||||
|
});
|
||||||
|
BxEventBus.Stream.on("ui.streamHud.rendered", async () => {
|
||||||
|
let $elm = document.querySelector("#StreamHud");
|
||||||
|
$elm && StreamUiHandler.handleSystemMenu($elm);
|
||||||
|
});
|
||||||
window.addEventListener(BxEvent.XCLOUD_RENDERING_COMPONENT, (e) => {
|
window.addEventListener(BxEvent.XCLOUD_RENDERING_COMPONENT, (e) => {
|
||||||
if (e.component === "product-detail") ProductDetailsPage.injectButtons();
|
if (e.component === "product-detail") ProductDetailsPage.injectButtons();
|
||||||
});
|
});
|
||||||
|
10
dist/better-xcloud.user.js
vendored
10
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
13
src/index.ts
13
src/index.ts
@ -33,7 +33,6 @@ import { GameTile } from "./modules/ui/game-tile";
|
|||||||
import { ProductDetailsPage } from "./modules/ui/product-details";
|
import { ProductDetailsPage } from "./modules/ui/product-details";
|
||||||
import { NavigationDialogManager } from "./modules/ui/dialog/navigation-dialog";
|
import { NavigationDialogManager } from "./modules/ui/dialog/navigation-dialog";
|
||||||
import { GlobalPref, StreamPref } from "./enums/pref-keys";
|
import { GlobalPref, StreamPref } from "./enums/pref-keys";
|
||||||
import { StreamUiHandler } from "./modules/stream/stream-ui";
|
|
||||||
import { UserAgent } from "./utils/user-agent";
|
import { UserAgent } from "./utils/user-agent";
|
||||||
import { XboxApi } from "./utils/xbox-api";
|
import { XboxApi } from "./utils/xbox-api";
|
||||||
import { StreamStatsCollector } from "./utils/stream-stats-collector";
|
import { StreamStatsCollector } from "./utils/stream-stats-collector";
|
||||||
@ -47,6 +46,7 @@ import { getGlobalPref, getStreamPref } from "./utils/pref-utils";
|
|||||||
import { SettingsManager } from "./modules/settings-manager";
|
import { SettingsManager } from "./modules/settings-manager";
|
||||||
import { Toast } from "./utils/toast";
|
import { Toast } from "./utils/toast";
|
||||||
import { WebGPUPlayer } from "./modules/player/webgpu/webgpu-player";
|
import { WebGPUPlayer } from "./modules/player/webgpu/webgpu-player";
|
||||||
|
import { StreamUiHandler } from "./modules/stream/stream-ui";
|
||||||
|
|
||||||
SettingsManager.getInstance();
|
SettingsManager.getInstance();
|
||||||
|
|
||||||
@ -234,7 +234,6 @@ BxEventBus.Stream.on('state.playing', payload => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATES.isPlaying = true;
|
STATES.isPlaying = true;
|
||||||
StreamUiHandler.observe();
|
|
||||||
|
|
||||||
if (isFullVersion()) {
|
if (isFullVersion()) {
|
||||||
const gameBar = GameBar.getInstance();
|
const gameBar = GameBar.getInstance();
|
||||||
@ -265,6 +264,16 @@ BxEventBus.Script.on('error.rendered', () => {
|
|||||||
BxEventBus.Stream.emit('state.stopped', {});
|
BxEventBus.Stream.emit('state.stopped', {});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
BxEventBus.Stream.on('ui.streamMenu.rendered', async () => {
|
||||||
|
await StreamUiHandler.handleStreamMenu();
|
||||||
|
});
|
||||||
|
|
||||||
|
BxEventBus.Stream.on('ui.streamHud.rendered', async () => {
|
||||||
|
const $elm = document.querySelector<HTMLElement>('#StreamHud');
|
||||||
|
$elm && StreamUiHandler.handleSystemMenu($elm);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
isFullVersion() && window.addEventListener(BxEvent.XCLOUD_RENDERING_COMPONENT, e => {
|
isFullVersion() && window.addEventListener(BxEvent.XCLOUD_RENDERING_COMPONENT, e => {
|
||||||
const component = (e as any).component;
|
const component = (e as any).component;
|
||||||
if (component === 'product-detail') {
|
if (component === 'product-detail') {
|
||||||
|
@ -1156,6 +1156,18 @@ ${subsVar} = subs;
|
|||||||
str = PatcherUtils.insertAt(str, index, newCode);
|
str = PatcherUtils.insertAt(str, index, newCode);
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
injectStreamMenuUseEffect(str: string) {
|
||||||
|
let index = str.indexOf('"StreamMenu-module__container');
|
||||||
|
index > -1 && (index = PatcherUtils.lastIndexOf(str, 'return', index, 200));
|
||||||
|
if (index < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newCode = `window.BX_EXPOSED.reactUseEffect(() => window.BxEventBus.Stream.emit('ui.streamMenu.rendered', {}));`;
|
||||||
|
str = PatcherUtils.insertAt(str, index, newCode);
|
||||||
|
return str;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let PATCH_ORDERS = PatcherUtils.filterPatches([
|
let PATCH_ORDERS = PatcherUtils.filterPatches([
|
||||||
@ -1265,6 +1277,8 @@ let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
|
|||||||
|
|
||||||
'alwaysShowStreamHud',
|
'alwaysShowStreamHud',
|
||||||
|
|
||||||
|
'injectStreamMenuUseEffect',
|
||||||
|
|
||||||
// 'exposeEventTarget',
|
// 'exposeEventTarget',
|
||||||
|
|
||||||
// Patch volume control for normal stream
|
// Patch volume control for normal stream
|
||||||
|
@ -12,7 +12,6 @@ export class StreamUiHandler {
|
|||||||
private static $btnStreamStats: HTMLElement | null | undefined;
|
private static $btnStreamStats: HTMLElement | null | undefined;
|
||||||
private static $btnRefresh: HTMLElement | null | undefined;
|
private static $btnRefresh: HTMLElement | null | undefined;
|
||||||
private static $btnHome: HTMLElement | null | undefined;
|
private static $btnHome: HTMLElement | null | undefined;
|
||||||
private static observer: MutationObserver | undefined;
|
|
||||||
|
|
||||||
private static cloneStreamHudButton($btnOrg: HTMLElement, label: string, svgIcon: BxIconRaw): HTMLElement | null {
|
private static cloneStreamHudButton($btnOrg: HTMLElement, label: string, svgIcon: BxIconRaw): HTMLElement | null {
|
||||||
if (!$btnOrg) {
|
if (!$btnOrg) {
|
||||||
@ -100,7 +99,7 @@ export class StreamUiHandler {
|
|||||||
return $btn;
|
return $btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async handleStreamMenu() {
|
static async handleStreamMenu() {
|
||||||
const $btnCloseHud = document.querySelector<HTMLElement>('button[class*=StreamMenu-module__backButton]');
|
const $btnCloseHud = document.querySelector<HTMLElement>('button[class*=StreamMenu-module__backButton]');
|
||||||
if (!$btnCloseHud) {
|
if (!$btnCloseHud) {
|
||||||
return;
|
return;
|
||||||
@ -133,13 +132,17 @@ export class StreamUiHandler {
|
|||||||
$menu?.appendChild(await StreamBadges.getInstance().render());
|
$menu?.appendChild(await StreamBadges.getInstance().render());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static handleSystemMenu($streamHud: HTMLElement) {
|
static handleSystemMenu($streamHud: HTMLElement) {
|
||||||
// Get the last button
|
// Get the last button
|
||||||
const $orgButton = $streamHud.querySelector<HTMLElement>('div[class^=HUDButton]');
|
const $orgButton = $streamHud.querySelector<HTMLElement>('div[class^=HUDButton]');
|
||||||
if (!$orgButton) {
|
if (!$orgButton) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (StreamUiHandler.$btnStreamSettings && $streamHud.contains(StreamUiHandler.$btnStreamSettings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const hideGripHandle = () => {
|
const hideGripHandle = () => {
|
||||||
// Grip handle
|
// Grip handle
|
||||||
const $gripHandle = document.querySelector<HTMLElement>('#StreamHud button[class^=GripHandle]');
|
const $gripHandle = document.querySelector<HTMLElement>('#StreamHud button[class^=GripHandle]');
|
||||||
@ -206,60 +209,5 @@ export class StreamUiHandler {
|
|||||||
StreamUiHandler.$btnStreamStats = undefined;
|
StreamUiHandler.$btnStreamStats = undefined;
|
||||||
StreamUiHandler.$btnRefresh = undefined;
|
StreamUiHandler.$btnRefresh = undefined;
|
||||||
StreamUiHandler.$btnHome = undefined;
|
StreamUiHandler.$btnHome = undefined;
|
||||||
|
|
||||||
StreamUiHandler.observer && StreamUiHandler.observer.disconnect();
|
|
||||||
StreamUiHandler.observer = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
static observe() {
|
|
||||||
StreamUiHandler.reset();
|
|
||||||
|
|
||||||
const $screen = document.querySelector('#PageContent section[class*=PureScreens]');
|
|
||||||
if (!$screen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const observer = new MutationObserver(mutationList => {
|
|
||||||
let item: MutationRecord;
|
|
||||||
for (item of mutationList) {
|
|
||||||
if (item.type !== 'childList') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
item.addedNodes.forEach(async $node => {
|
|
||||||
if (!$node || $node.nodeType !== Node.ELEMENT_NODE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let $elm: HTMLElement | null = $node as HTMLElement;
|
|
||||||
|
|
||||||
// Ignore non-HTML elements
|
|
||||||
if (!($elm instanceof HTMLElement)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const className = $elm.className || '';
|
|
||||||
// Render badges
|
|
||||||
if (className.startsWith('StreamMenu-module__container')) {
|
|
||||||
StreamUiHandler.handleStreamMenu();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (className.startsWith('Overlay-module_') || className.startsWith('InProgressScreen')) {
|
|
||||||
$elm = $elm.querySelector('#StreamHud');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$elm || ($elm.id || '') !== 'StreamHud') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle System Menu bar
|
|
||||||
StreamUiHandler.handleSystemMenu($elm);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe($screen, { subtree: true, childList: true });
|
|
||||||
StreamUiHandler.observer = observer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ type StreamEvents = {
|
|||||||
'microphone.state.changed': { state: MicrophoneState };
|
'microphone.state.changed': { state: MicrophoneState };
|
||||||
|
|
||||||
'ui.streamHud.rendered': { expanded: boolean },
|
'ui.streamHud.rendered': { expanded: boolean },
|
||||||
|
'ui.streamMenu.rendered': {},
|
||||||
|
|
||||||
dataChannelCreated: { dataChannel: RTCDataChannel };
|
dataChannelCreated: { dataChannel: RTCDataChannel };
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user