From e69fa19ef3b2c3d03082fa2f9bf7a82676229534 Mon Sep 17 00:00:00 2001
From: redphx <96280+redphx@users.noreply.github.com>
Date: Wed, 25 Sep 2024 19:44:33 +0700
Subject: [PATCH] Update better-xcloud.user.js
---
dist/better-xcloud.user.js | 1635 ++++++++++++------------------------
1 file changed, 543 insertions(+), 1092 deletions(-)
diff --git a/dist/better-xcloud.user.js b/dist/better-xcloud.user.js
index 18d8d96..c5a53ec 100644
--- a/dist/better-xcloud.user.js
+++ b/dist/better-xcloud.user.js
@@ -44,15 +44,13 @@ var DEFAULT_FLAGS = {
try {
delete window.BX_FLAGS;
} catch (e) {}
-if (!BX_FLAGS.DeviceInfo.userAgent)
- BX_FLAGS.DeviceInfo.userAgent = window.navigator.userAgent;
+if (!BX_FLAGS.DeviceInfo.userAgent) BX_FLAGS.DeviceInfo.userAgent = window.navigator.userAgent;
BxLogger.info("BxFlags", BX_FLAGS);
var NATIVE_FETCH = window.fetch;
var SMART_TV_UNIQUE_ID = "FC4A1DA2-711C-4E9C-BC7F-047AF8A672EA", CHROMIUM_VERSION = "123.0.0.0";
if (!!window.chrome || window.navigator.userAgent.includes("Chrome")) {
const match = window.navigator.userAgent.match(/\s(?:Chrome|Edg)\/([\d\.]+)/);
- if (match)
- CHROMIUM_VERSION = match[1];
+ if (match) CHROMIUM_VERSION = match[1];
}
class UserAgent {
static STORAGE_KEY = "better_xcloud_user_agent";
@@ -68,16 +66,13 @@ class UserAgent {
"vr-oculus": window.navigator.userAgent + " OculusBrowser VR"
};
static init() {
- if (UserAgent.#config = JSON.parse(window.localStorage.getItem(UserAgent.STORAGE_KEY) || "{}"), !UserAgent.#config.profile)
- UserAgent.#config.profile = BX_FLAGS.DeviceInfo.deviceType === "android-tv" || BX_FLAGS.DeviceInfo.deviceType === "webos" ? "vr-oculus" : "default";
- if (!UserAgent.#config.custom)
- UserAgent.#config.custom = "";
+ if (UserAgent.#config = JSON.parse(window.localStorage.getItem(UserAgent.STORAGE_KEY) || "{}"), !UserAgent.#config.profile) UserAgent.#config.profile = BX_FLAGS.DeviceInfo.deviceType === "android-tv" || BX_FLAGS.DeviceInfo.deviceType === "webos" ? "vr-oculus" : "default";
+ if (!UserAgent.#config.custom) UserAgent.#config.custom = "";
UserAgent.spoof();
}
static updateStorage(profile, custom) {
const config = UserAgent.#config;
- if (config.profile = profile, profile === "custom" && typeof custom !== "undefined")
- config.custom = custom;
+ if (config.profile = profile, profile === "custom" && typeof custom !== "undefined") config.custom = custom;
window.localStorage.setItem(UserAgent.STORAGE_KEY, JSON.stringify(config));
}
static getDefault() {
@@ -114,8 +109,7 @@ class UserAgent {
const profile = UserAgent.#config.profile;
if (profile === "default") return;
let newUserAgent = UserAgent.get(profile);
- if ("userAgentData" in window.navigator)
- window.navigator.orgUserAgentData = window.navigator.userAgentData, Object.defineProperty(window.navigator, "userAgentData", {});
+ if ("userAgentData" in window.navigator) window.navigator.orgUserAgentData = window.navigator.userAgentData, Object.defineProperty(window.navigator, "userAgentData", {});
window.navigator.orgUserAgent = window.navigator.userAgent, Object.defineProperty(window.navigator, "userAgent", {
value: newUserAgent
});
@@ -162,8 +156,7 @@ var BxEvent;
return;
}
const event = new Event(eventName);
- if (data)
- for (let key in data)
+ if (data) for (let key in data)
event[key] = data[key];
target.dispatchEvent(event), AppInterface && AppInterface.onEvent(eventName), BX_FLAGS.Debug && BxLogger.warning("BxEvent", "dispatch", eventName, data);
}
@@ -182,29 +175,20 @@ var setNearby = NavigationUtils.setNearby;
function createElement(elmName, props = {}, ..._) {
let $elm;
const hasNs = "xmlns" in props;
- if (hasNs)
- $elm = document.createElementNS(props.xmlns, elmName), delete props.xmlns;
- else
- $elm = document.createElement(elmName);
- if (props._nearby)
- setNearby($elm, props._nearby), delete props._nearby;
+ if (hasNs) $elm = document.createElementNS(props.xmlns, elmName), delete props.xmlns;
+ else $elm = document.createElement(elmName);
+ if (props._nearby) setNearby($elm, props._nearby), delete props._nearby;
for (let key in props) {
- if ($elm.hasOwnProperty(key))
- continue;
- if (hasNs)
- $elm.setAttributeNS(null, key, props[key]);
- else if (key === "on")
- for (let eventName in props[key])
+ if ($elm.hasOwnProperty(key)) continue;
+ if (hasNs) $elm.setAttributeNS(null, key, props[key]);
+ else if (key === "on") for (let eventName in props[key])
$elm.addEventListener(eventName, props[key][eventName]);
- else
- $elm.setAttribute(key, props[key]);
+ else $elm.setAttribute(key, props[key]);
}
for (let i = 2, size = arguments.length;i < size; i++) {
const arg = arguments[i];
- if (arg instanceof Node)
- $elm.appendChild(arg);
- else if (arg !== null && arg !== !1 && typeof arg !== "undefined")
- $elm.appendChild(document.createTextNode(arg));
+ if (arg instanceof Node) $elm.appendChild(arg);
+ else if (arg !== null && arg !== !1 && typeof arg !== "undefined") $elm.appendChild(document.createTextNode(arg));
}
return $elm;
}
@@ -226,8 +210,7 @@ function removeChildElements($parent) {
$parent.firstElementChild.remove();
}
function clearFocus() {
- if (document.activeElement instanceof HTMLElement)
- document.activeElement.blur();
+ if (document.activeElement instanceof HTMLElement) document.activeElement.blur();
}
function clearDataSet($elm) {
Object.keys($elm.dataset).forEach((key) => {
@@ -251,17 +234,14 @@ var ButtonStyleClass = {
return svgParser(icon.toString());
}, ButtonStyleIndices = Object.keys(ButtonStyleClass).map((i) => parseInt(i)), createButton = (options) => {
let $btn;
- if (options.url)
- $btn = CE("a", { class: "bx-button" }), $btn.href = options.url, $btn.target = "_blank";
- else
- $btn = CE("button", { class: "bx-button", type: "button" });
+ if (options.url) $btn = CE("a", { class: "bx-button" }), $btn.href = options.url, $btn.target = "_blank";
+ else $btn = CE("button", { class: "bx-button", type: "button" });
const style = options.style || 0;
style && ButtonStyleIndices.forEach((index) => {
style & index && $btn.classList.add(ButtonStyleClass[index]);
}), options.classes && $btn.classList.add(...options.classes), options.icon && $btn.appendChild(createSvgIcon(options.icon)), options.label && $btn.appendChild(CE("span", {}, options.label)), options.title && $btn.setAttribute("title", options.title), options.disabled && ($btn.disabled = !0), options.onClick && $btn.addEventListener("click", options.onClick), $btn.tabIndex = typeof options.tabIndex === "number" ? options.tabIndex : 0;
for (let key in options.attributes)
- if (!$btn.hasOwnProperty(key))
- $btn.setAttribute(key, options.attributes[key]);
+ if (!$btn.hasOwnProperty(key)) $btn.setAttribute(key, options.attributes[key]);
return $btn;
}, CTN = document.createTextNode.bind(document);
window.BX_CE = createElement;
@@ -644,24 +624,19 @@ class Translations {
}
static refreshLocale(newLocale) {
let locale;
- if (newLocale)
- localStorage.setItem(Translations.#KEY_LOCALE, newLocale), locale = newLocale;
- else
- locale = localStorage.getItem(Translations.#KEY_LOCALE);
+ if (newLocale) localStorage.setItem(Translations.#KEY_LOCALE, newLocale), locale = newLocale;
+ else locale = localStorage.getItem(Translations.#KEY_LOCALE);
const supportedLocales = Translations.#supportedLocales;
if (!locale) {
- if (locale = window.navigator.language || Translations.#EN_US, supportedLocales.indexOf(locale) === -1)
- locale = Translations.#EN_US;
+ if (locale = window.navigator.language || Translations.#EN_US, supportedLocales.indexOf(locale) === -1) locale = Translations.#EN_US;
localStorage.setItem(Translations.#KEY_LOCALE, locale);
}
Translations.#selectedLocale = locale, Translations.#selectedLocaleIndex = supportedLocales.indexOf(locale);
}
static get(key, values) {
let text = null;
- if (Translations.#foreignTranslations && Translations.#selectedLocale !== Translations.#EN_US)
- text = Translations.#foreignTranslations[key];
- if (!text)
- text = Texts[key] || alert(`Missing translation key: ${key}`);
+ if (Translations.#foreignTranslations && Translations.#selectedLocale !== Translations.#EN_US) text = Translations.#foreignTranslations[key];
+ if (!text) text = Texts[key] || alert(`Missing translation key: ${key}`);
let translation;
if (Array.isArray(text)) return translation = text[Translations.#selectedLocaleIndex] || text[Translations.#enUsIndex], translation(values);
return translation = text, translation;
@@ -671,24 +646,20 @@ class Translations {
try {
Translations.#foreignTranslations = JSON.parse(window.localStorage.getItem(Translations.#KEY_TRANSLATIONS));
} catch (e) {}
- if (!Translations.#foreignTranslations)
- await this.downloadTranslations(Translations.#selectedLocale);
+ if (!Translations.#foreignTranslations) await this.downloadTranslations(Translations.#selectedLocale);
}
static async updateTranslations(async = !1) {
if (Translations.#selectedLocale === Translations.#EN_US) {
localStorage.removeItem(Translations.#KEY_TRANSLATIONS);
return;
}
- if (async)
- Translations.downloadTranslationsAsync(Translations.#selectedLocale);
- else
- await Translations.downloadTranslations(Translations.#selectedLocale);
+ if (async) Translations.downloadTranslationsAsync(Translations.#selectedLocale);
+ else await Translations.downloadTranslations(Translations.#selectedLocale);
}
static async downloadTranslations(locale) {
try {
const translations = await (await NATIVE_FETCH(`https://raw.githubusercontent.com/redphx/better-xcloud/gh-pages/translations/${locale}.json`)).json();
- if (localStorage.getItem(Translations.#KEY_LOCALE) === locale)
- window.localStorage.setItem(Translations.#KEY_TRANSLATIONS, JSON.stringify(translations)), Translations.#foreignTranslations = translations;
+ if (localStorage.getItem(Translations.#KEY_LOCALE) === locale) window.localStorage.setItem(Translations.#KEY_TRANSLATIONS, JSON.stringify(translations)), Translations.#foreignTranslations = translations;
return !0;
} catch (e) {
debugger;
@@ -722,8 +693,7 @@ var BypassServers = {
class StreamStats {
static instance;
static getInstance() {
- if (!StreamStats.instance)
- StreamStats.instance = new StreamStats;
+ if (!StreamStats.instance) StreamStats.instance = new StreamStats;
return StreamStats.instance;
}
#timeoutId;
@@ -742,20 +712,16 @@ class StreamStats {
}
start(glancing = !1) {
if (!this.isHidden() || glancing && this.isGlancing()) return;
- if (this.#$container)
- this.#$container.classList.remove("bx-gone"), this.#$container.dataset.display = glancing ? "glancing" : "fixed";
+ if (this.#$container) this.#$container.classList.remove("bx-gone"), this.#$container.dataset.display = glancing ? "glancing" : "fixed";
this.#timeoutId = window.setTimeout(this.#update.bind(this), this.#updateInterval);
}
stop(glancing = !1) {
if (glancing && !this.isGlancing()) return;
- if (this.#timeoutId && clearTimeout(this.#timeoutId), this.#timeoutId = null, this.#lastVideoStat = null, this.#$container)
- this.#$container.removeAttribute("data-display"), this.#$container.classList.add("bx-gone");
+ if (this.#timeoutId && clearTimeout(this.#timeoutId), this.#timeoutId = null, this.#lastVideoStat = null, this.#$container) this.#$container.removeAttribute("data-display"), this.#$container.classList.add("bx-gone");
}
toggle() {
- if (this.isGlancing())
- this.#$container && (this.#$container.dataset.display = "fixed");
- else
- this.isHidden() ? this.start() : this.stop();
+ if (this.isGlancing()) this.#$container && (this.#$container.dataset.display = "fixed");
+ else this.isHidden() ? this.start() : this.stop();
}
onStoppedPlaying() {
this.stop(), this.quickGlanceStop(), this.hideSettingsUi();
@@ -768,11 +734,8 @@ class StreamStats {
if (!$uiContainer) return;
this.#quickGlanceObserver = new MutationObserver((mutationList, observer) => {
for (let record of mutationList)
- if (record.attributeName && record.attributeName === "aria-expanded")
- if (record.target.ariaExpanded === "true")
- this.isHidden() && this.start(!0);
- else
- this.stop(!0);
+ if (record.attributeName && record.attributeName === "aria-expanded") if (record.target.ariaExpanded === "true") this.isHidden() && this.start(!0);
+ else this.stop(!0);
}), this.#quickGlanceObserver.observe($uiContainer, {
attributes: !0,
attributeFilter: ["aria-expanded"],
@@ -803,17 +766,13 @@ class StreamStats {
const lastStat = this.#lastVideoStat, timeDiff = stat.timestamp - lastStat.timestamp, bitrate = 8 * (stat.bytesReceived - lastStat.bytesReceived) / timeDiff / 1000;
this.#$br.textContent = `${bitrate.toFixed(2)} Mbps`;
const totalDecodeTimeDiff = stat.totalDecodeTime - lastStat.totalDecodeTime, framesDecodedDiff = stat.framesDecoded - lastStat.framesDecoded, currentDecodeTime = totalDecodeTimeDiff / framesDecodedDiff * 1000;
- if (isNaN(currentDecodeTime))
- this.#$dt.textContent = "??ms";
- else
- this.#$dt.textContent = `${currentDecodeTime.toFixed(2)}ms`;
- if (PREF_STATS_CONDITIONAL_FORMATTING)
- grade = currentDecodeTime > 12 ? "bad" : currentDecodeTime > 9 ? "ok" : currentDecodeTime > 6 ? "good" : "", this.#$dt.dataset.grade = grade;
+ if (isNaN(currentDecodeTime)) this.#$dt.textContent = "??ms";
+ else this.#$dt.textContent = `${currentDecodeTime.toFixed(2)}ms`;
+ if (PREF_STATS_CONDITIONAL_FORMATTING) grade = currentDecodeTime > 12 ? "bad" : currentDecodeTime > 9 ? "ok" : currentDecodeTime > 6 ? "good" : "", this.#$dt.dataset.grade = grade;
this.#lastVideoStat = stat;
} else if (stat.type === "candidate-pair" && stat.packetsReceived > 0 && stat.state === "succeeded") {
const roundTripTime = stat.currentRoundTripTime ? stat.currentRoundTripTime * 1000 : -1;
- if (this.#$ping.textContent = roundTripTime === -1 ? "???" : roundTripTime.toString(), PREF_STATS_CONDITIONAL_FORMATTING)
- grade = roundTripTime > 100 ? "bad" : roundTripTime > 75 ? "ok" : roundTripTime > 40 ? "good" : "", this.#$ping.dataset.grade = grade;
+ if (this.#$ping.textContent = roundTripTime === -1 ? "???" : roundTripTime.toString(), PREF_STATS_CONDITIONAL_FORMATTING) grade = roundTripTime > 100 ? "bad" : roundTripTime > 75 ? "ok" : roundTripTime > 40 ? "good" : "", this.#$ping.dataset.grade = grade;
}
});
const lapsedTime = performance.now() - startTime;
@@ -824,8 +783,7 @@ class StreamStats {
$container.dataset.stats = "[" + PREF_ITEMS.join("][") + "]", $container.dataset.position = PREF_POSITION, $container.dataset.transparent = PREF_TRANSPARENT, $container.style.opacity = PREF_OPACITY + "%", $container.style.fontSize = PREF_TEXT_SIZE;
}
hideSettingsUi() {
- if (this.isGlancing() && !getPref("stats_quick_glance"))
- this.stop();
+ if (this.isGlancing() && !getPref("stats_quick_glance")) this.stop();
}
#render() {
const stats = {
@@ -849,10 +807,8 @@ class StreamStats {
static setupEvents() {
window.addEventListener(BxEvent.STREAM_PLAYING, (e) => {
const PREF_STATS_QUICK_GLANCE = getPref("stats_quick_glance"), PREF_STATS_SHOW_WHEN_PLAYING = getPref("stats_show_when_playing"), streamStats = StreamStats.getInstance();
- if (PREF_STATS_SHOW_WHEN_PLAYING)
- streamStats.start();
- else if (PREF_STATS_QUICK_GLANCE)
- streamStats.quickGlanceSetup(), !PREF_STATS_SHOW_WHEN_PLAYING && streamStats.start(!0);
+ if (PREF_STATS_SHOW_WHEN_PLAYING) streamStats.start();
+ else if (PREF_STATS_QUICK_GLANCE) streamStats.quickGlanceSetup(), !PREF_STATS_SHOW_WHEN_PLAYING && streamStats.start(!0);
});
}
static refreshStyles() {
@@ -865,12 +821,10 @@ class SettingElement {
tabindex: 0
});
let $parent;
- if (setting.optionsGroup)
- $parent = CE("optgroup", {
+ if (setting.optionsGroup) $parent = CE("optgroup", {
label: setting.optionsGroup
}), $control.appendChild($parent);
- else
- $parent = $control;
+ else $parent = $control;
for (let value in setting.options) {
const label = setting.options[value], $option = CE("option", { value }, label);
$parent.appendChild($option);
@@ -887,8 +841,7 @@ class SettingElement {
multiple: !0,
tabindex: 0
});
- if (params && params.size)
- $control.setAttribute("size", params.size.toString());
+ if (params && params.size) $control.setAttribute("size", params.size.toString());
for (let value in setting.multipleOptions) {
const label = setting.multipleOptions[value], $option = CE("option", { value }, label);
$option.selected = currentValue.indexOf(value) > -1, $option.addEventListener("mousedown", function(e) {
@@ -933,10 +886,8 @@ class SettingElement {
const { min: MIN, max: MAX } = setting, STEPS = Math.max(setting.steps || 1, 1), renderTextValue = (value2) => {
value2 = parseInt(value2);
let textContent = null;
- if (options.customTextValue)
- textContent = options.customTextValue(value2);
- if (textContent === null)
- textContent = value2.toString() + options.suffix;
+ if (options.customTextValue) textContent = options.customTextValue(value2);
+ if (textContent === null) textContent = value2.toString() + options.suffix;
return textContent;
}, updateButtonsVisibility = () => {
$btnDec.classList.toggle("bx-inactive", controlValue === MIN), $btnInc.classList.toggle("bx-inactive", controlValue === MAX);
@@ -969,12 +920,10 @@ class SettingElement {
const markersId = `markers-${key}`, $markers = CE("datalist", { id: markersId });
if ($range.setAttribute("list", markersId), options.exactTicks) {
let start = Math.max(Math.floor(MIN / options.exactTicks), 1) * options.exactTicks;
- if (start === MIN)
- start += options.exactTicks;
+ if (start === MIN) start += options.exactTicks;
for (let i = start;i < MAX; i += options.exactTicks)
$markers.appendChild(CE("option", { value: i }));
- } else
- for (let i = MIN + options.ticks;i < MAX; i += options.ticks)
+ } else for (let i = MIN + options.ticks;i < MAX; i += options.ticks)
$markers.appendChild(CE("option", { value: i }));
$wrapper.appendChild($markers);
}
@@ -987,10 +936,8 @@ class SettingElement {
}
const $btn = e.target;
let value2 = parseInt(controlValue);
- if ($btn.dataset.type === "dec")
- value2 = Math.max(MIN, value2 - STEPS);
- else
- value2 = Math.min(MAX, value2 + STEPS);
+ if ($btn.dataset.type === "dec") value2 = Math.max(MIN, value2 - STEPS);
+ else value2 = Math.min(MAX, value2 + STEPS);
controlValue = value2, updateButtonsVisibility(), $text.textContent = renderTextValue(value2), $range && ($range.value = value2.toString()), isHolding = !1, !e.ignoreOnChange && onChange && onChange(e, value2);
}, onMouseDown = (e) => {
e.preventDefault(), isHolding = !0;
@@ -1018,30 +965,21 @@ class SettingElement {
};
static render(type, key, setting, currentValue, onChange, options) {
const method = SettingElement.#METHOD_MAP[type], $control = method(...Array.from(arguments).slice(1));
- if (type !== "number-stepper")
- $control.id = `bx_setting_${key}`;
- if (type === "options" || type === "multiple-options")
- $control.name = $control.id;
+ if (type !== "number-stepper") $control.id = `bx_setting_${key}`;
+ if (type === "options" || type === "multiple-options") $control.name = $control.id;
return $control;
}
static fromPref(key, storage, onChange, overrideParams = {}) {
const definition = storage.getDefinition(key);
let currentValue = storage.getSetting(key), type;
- if ("type" in definition)
- type = definition.type;
- else if ("options" in definition)
- type = "options";
- else if ("multipleOptions" in definition)
- type = "multiple-options";
- else if (typeof definition.default === "number")
- type = "number";
- else
- type = "checkbox";
+ if ("type" in definition) type = definition.type;
+ else if ("options" in definition) type = "options";
+ else if ("multipleOptions" in definition) type = "multiple-options";
+ else if (typeof definition.default === "number") type = "number";
+ else type = "checkbox";
let params = {};
- if ("params" in definition)
- params = Object.assign(overrideParams, definition.params || {});
- if (params.disabled)
- currentValue = definition.default;
+ if ("params" in definition) params = Object.assign(overrideParams, definition.params || {});
+ if (params.disabled) currentValue = definition.default;
return SettingElement.render(type, key, definition, currentValue, (e, value) => {
storage.setSetting(key, value), onChange && onChange(e, value);
}, params);
@@ -1079,8 +1017,7 @@ class BaseSettingsStore {
return;
}
if (checkUnsupported && this.definitions[key].unsupported) return this.definitions[key].default;
- if (!(key in this.settings))
- this.settings[key] = this.validateValue(key, null);
+ if (!(key in this.settings)) this.settings[key] = this.validateValue(key, null);
return this.settings[key];
}
setSetting(key, value, emitEvent = !1) {
@@ -1096,14 +1033,10 @@ class BaseSettingsStore {
validateValue(key, value) {
const def = this.definitions[key];
if (!def) return value;
- if (typeof value === "undefined" || value === null)
- value = def.default;
- if ("min" in def)
- value = Math.max(def.min, value);
- if ("max" in def)
- value = Math.min(def.max, value);
- if ("options" in def && !(value in def.options))
- value = def.default;
+ if (typeof value === "undefined" || value === null) value = def.default;
+ if ("min" in def) value = Math.max(def.min, value);
+ if ("max" in def) value = Math.min(def.max, value);
+ if ("options" in def && !(value in def.options)) value = def.default;
else if ("multipleOptions" in def) {
if (value.length) {
const validOptions = Object.keys(def.multipleOptions);
@@ -1111,8 +1044,7 @@ class BaseSettingsStore {
validOptions.indexOf(item2) === -1 && value.splice(idx, 1);
});
}
- if (!value.length)
- value = def.default;
+ if (!value.length) value = def.default;
}
return value;
}
@@ -1143,31 +1075,18 @@ function getSupportedCodecProfiles() {
let hasLowCodec = !1, hasNormalCodec = !1, hasHighCodec = !1;
const codecs = RTCRtpReceiver.getCapabilities("video").codecs;
for (let codec of codecs) {
- if (codec.mimeType.toLowerCase() !== "video/h264" || !codec.sdpFmtpLine)
- continue;
+ if (codec.mimeType.toLowerCase() !== "video/h264" || !codec.sdpFmtpLine) continue;
const fmtp = codec.sdpFmtpLine.toLowerCase();
- if (fmtp.includes("profile-level-id=4d"))
- hasHighCodec = !0;
- else if (fmtp.includes("profile-level-id=42e"))
- hasNormalCodec = !0;
- else if (fmtp.includes("profile-level-id=420"))
- hasLowCodec = !0;
+ if (fmtp.includes("profile-level-id=4d")) hasHighCodec = !0;
+ else if (fmtp.includes("profile-level-id=42e")) hasNormalCodec = !0;
+ else if (fmtp.includes("profile-level-id=420")) hasLowCodec = !0;
}
- if (hasLowCodec)
- if (!hasNormalCodec && !hasHighCodec)
- options.default = `${t("visual-quality-low")} (${t("default")})`;
- else
- options.low = t("visual-quality-low");
- if (hasNormalCodec)
- if (!hasLowCodec && !hasHighCodec)
- options.default = `${t("visual-quality-normal")} (${t("default")})`;
- else
- options.normal = t("visual-quality-normal");
- if (hasHighCodec)
- if (!hasLowCodec && !hasNormalCodec)
- options.default = `${t("visual-quality-high")} (${t("default")})`;
- else
- options.high = t("visual-quality-high");
+ if (hasLowCodec) if (!hasNormalCodec && !hasHighCodec) options.default = `${t("visual-quality-low")} (${t("default")})`;
+ else options.low = t("visual-quality-low");
+ if (hasNormalCodec) if (!hasLowCodec && !hasHighCodec) options.default = `${t("visual-quality-normal")} (${t("default")})`;
+ else options.normal = t("visual-quality-normal");
+ if (hasHighCodec) if (!hasLowCodec && !hasNormalCodec) options.default = `${t("visual-quality-high")} (${t("default")})`;
+ else options.high = t("visual-quality-high");
return options;
}
class GlobalSettingsStorage extends BaseSettingsStore {
@@ -1252,8 +1171,7 @@ class GlobalSettingsStorage extends BaseSettingsStore {
options: getSupportedCodecProfiles(),
ready: (setting) => {
const options = setting.options, keys = Object.keys(options);
- if (keys.length <= 1)
- setting.unsupported = !0, setting.note = "⚠️ " + t("browser-unsupported-feature");
+ if (keys.length <= 1) setting.unsupported = !0, setting.note = "⚠️ " + t("browser-unsupported-feature");
setting.suggest = {
lowest: keys.length === 1 ? keys[0] : keys[1],
highest: keys[keys.length - 1]
@@ -1292,8 +1210,7 @@ class GlobalSettingsStorage extends BaseSettingsStore {
},
unsupported: !STATES.userAgent.capabilities.touch,
ready: (setting) => {
- if (setting.unsupported)
- setting.default = "default";
+ if (setting.unsupported) setting.default = "default";
}
},
stream_touch_controller_auto_off: {
@@ -1423,10 +1340,8 @@ class GlobalSettingsStorage extends BaseSettingsStore {
})(),
ready: (setting) => {
let note, url;
- if (setting.unsupported)
- note = t("browser-unsupported-feature"), url = "https://github.com/redphx/better-xcloud/issues/206#issuecomment-1920475657";
- else
- note = t("mkb-disclaimer"), url = "https://better-xcloud.github.io/mouse-and-keyboard/#disclaimer";
+ if (setting.unsupported) note = t("browser-unsupported-feature"), url = "https://github.com/redphx/better-xcloud/issues/206#issuecomment-1920475657";
+ else note = t("mkb-disclaimer"), url = "https://better-xcloud.github.io/mouse-and-keyboard/#disclaimer";
setting.note = CE("a", {
href: url,
target: "_blank"
@@ -1442,12 +1357,9 @@ class GlobalSettingsStorage extends BaseSettingsStore {
off: t("off")
},
ready: (setting) => {
- if (AppInterface)
- ;
- else if (UserAgent.isMobile())
- setting.unsupported = !0, setting.default = "off", delete setting.options.default, delete setting.options.on;
- else
- delete setting.options.on;
+ if (AppInterface) ;
+ else if (UserAgent.isMobile()) setting.unsupported = !0, setting.default = "off", delete setting.options.default, delete setting.options.on;
+ else delete setting.options.on;
}
},
native_mkb_scroll_x_sensitivity: {
@@ -1784,8 +1696,7 @@ class Screenshot {
}
static updateCanvasSize(width, height) {
const $canvas = Screenshot.#$canvas;
- if ($canvas)
- $canvas.width = width, $canvas.height = height;
+ if ($canvas) $canvas.width = width, $canvas.height = height;
}
static updateCanvasFilters(filters) {
Screenshot.#canvasContext.filter = filters;
@@ -1797,15 +1708,12 @@ class Screenshot {
const currentStream = STATES.currentStream, streamPlayer = currentStream.streamPlayer, $canvas = Screenshot.#$canvas;
if (!streamPlayer || !$canvas) return;
let $player;
- if (getPref("screenshot_apply_filters"))
- $player = streamPlayer.getPlayerElement();
- else
- $player = streamPlayer.getPlayerElement("default");
+ if (getPref("screenshot_apply_filters")) $player = streamPlayer.getPlayerElement();
+ else $player = streamPlayer.getPlayerElement("default");
if (!$player || !$player.isConnected) return;
$player.parentElement.addEventListener("animationend", this.#onAnimationEnd, { once: !0 }), $player.parentElement.classList.add("bx-taking-screenshot");
const canvasContext = Screenshot.#canvasContext;
- if ($player instanceof HTMLCanvasElement)
- streamPlayer.getWebGL2Player().drawFrame();
+ if ($player instanceof HTMLCanvasElement) streamPlayer.getWebGL2Player().drawFrame();
if (canvasContext.drawImage($player, 0, 0, $canvas.width, $canvas.height), AppInterface) {
const data = $canvas.toDataURL("image/png").split(";base64,")[1];
AppInterface.saveScreenshot(currentStream.titleSlug, data), canvasContext.clearRect(0, 0, $canvas.width, $canvas.height), callback && callback();
@@ -1945,10 +1853,8 @@ class MkbPreset {
const mouse = obj.mouse;
mouse["sensitivity_x"] *= EmulatedMkbHandler.DEFAULT_PANNING_SENSITIVITY, mouse["sensitivity_y"] *= EmulatedMkbHandler.DEFAULT_PANNING_SENSITIVITY, mouse["deadzone_counterweight"] *= EmulatedMkbHandler.DEFAULT_DEADZONE_COUNTERWEIGHT;
const mouseMapTo = MouseMapTo[mouse["map_to"]];
- if (typeof mouseMapTo !== "undefined")
- mouse["map_to"] = mouseMapTo;
- else
- mouse["map_to"] = MkbPreset.MOUSE_SETTINGS["map_to"].default;
+ if (typeof mouseMapTo !== "undefined") mouse["map_to"] = mouseMapTo;
+ else mouse["map_to"] = MkbPreset.MOUSE_SETTINGS["map_to"].default;
return console.log(obj), obj;
}
}
@@ -1963,10 +1869,8 @@ class Toast {
static show(msg, status, options = {}) {
options = options || {};
const args = Array.from(arguments);
- if (options.instant)
- Toast.#stack = [args], Toast.#showNext();
- else
- Toast.#stack.push(args), !Toast.#isShowing && Toast.#showNext();
+ if (options.instant) Toast.#stack = [args], Toast.#showNext();
+ else Toast.#stack.push(args), !Toast.#isShowing && Toast.#showNext();
}
static #showNext() {
if (!Toast.#stack.length) {
@@ -1975,14 +1879,10 @@ class Toast {
}
Toast.#isShowing = !0, Toast.#timeout && clearTimeout(Toast.#timeout), Toast.#timeout = window.setTimeout(Toast.#hide, Toast.#DURATION);
const [msg, status, options] = Toast.#stack.shift();
- if (options && options.html)
- Toast.#$msg.innerHTML = msg;
- else
- Toast.#$msg.textContent = msg;
- if (status)
- Toast.#$status.classList.remove("bx-gone"), Toast.#$status.textContent = status;
- else
- Toast.#$status.classList.add("bx-gone");
+ if (options && options.html) Toast.#$msg.innerHTML = msg;
+ else Toast.#$msg.textContent = msg;
+ if (status) Toast.#$status.classList.remove("bx-gone"), Toast.#$status.textContent = status;
+ else Toast.#$status.classList.add("bx-gone");
const classList = Toast.#$wrapper.classList;
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-show");
}
@@ -1994,16 +1894,14 @@ class Toast {
static setup() {
Toast.#$wrapper = CE("div", { class: "bx-toast bx-offscreen" }, Toast.#$msg = CE("span", { class: "bx-toast-msg" }), Toast.#$status = CE("span", { class: "bx-toast-status" })), Toast.#$wrapper.addEventListener("transitionend", (e) => {
const classList = Toast.#$wrapper.classList;
- if (classList.contains("bx-hide"))
- classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.#showNext();
+ if (classList.contains("bx-hide")) classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.#showNext();
}), document.documentElement.appendChild(Toast.#$wrapper);
}
}
class LocalDb {
static #instance;
static get INSTANCE() {
- if (!LocalDb.#instance)
- LocalDb.#instance = new LocalDb;
+ if (!LocalDb.#instance) LocalDb.#instance = new LocalDb;
return LocalDb.#instance;
}
static DB_NAME = "BetterXcloud";
@@ -2108,21 +2006,14 @@ class KeyHelper {
};
static getKeyFromEvent(e) {
let code, name;
- if (e instanceof KeyboardEvent)
- code = e.code || e.key;
+ if (e instanceof KeyboardEvent) code = e.code || e.key;
else if (e instanceof WheelEvent) {
- if (e.deltaY < 0)
- code = "ScrollUp";
- else if (e.deltaY > 0)
- code = "ScrollDown";
- else if (e.deltaX < 0)
- code = "ScrollLeft";
- else if (e.deltaX > 0)
- code = "ScrollRight";
- } else if (e instanceof MouseEvent)
- code = "Mouse" + e.button;
- if (code)
- name = KeyHelper.codeToKeyName(code);
+ if (e.deltaY < 0) code = "ScrollUp";
+ else if (e.deltaY > 0) code = "ScrollDown";
+ else if (e.deltaX < 0) code = "ScrollLeft";
+ else if (e.deltaX > 0) code = "ScrollRight";
+ } else if (e instanceof MouseEvent) code = "Mouse" + e.button;
+ if (code) name = KeyHelper.codeToKeyName(code);
return code ? { code, name } : null;
}
static codeToKeyName(code) {
@@ -2133,15 +2024,13 @@ var LOG_TAG = "PointerClient";
class PointerClient {
static instance;
static getInstance() {
- if (!PointerClient.instance)
- PointerClient.instance = new PointerClient;
+ if (!PointerClient.instance) PointerClient.instance = new PointerClient;
return PointerClient.instance;
}
#socket;
#mkbHandler;
start(port, mkbHandler) {
- if (!port)
- throw new Error("PointerServer port is 0");
+ if (!port) throw new Error("PointerServer port is 0");
this.#mkbHandler = mkbHandler, this.#socket = new WebSocket(`ws://localhost:${port}`), this.#socket.binaryType = "arraybuffer", this.#socket.addEventListener("open", (event) => {
BxLogger.info(LOG_TAG, "connected");
}), this.#socket.addEventListener("error", (event) => {
@@ -2221,8 +2110,7 @@ class NativeMkbHandler extends MkbHandler {
#inputSink;
#$message;
static getInstance() {
- if (!NativeMkbHandler.instance)
- NativeMkbHandler.instance = new NativeMkbHandler;
+ if (!NativeMkbHandler.instance) NativeMkbHandler.instance = new NativeMkbHandler;
return NativeMkbHandler.instance;
}
#onKeyboardEvent(e) {
@@ -2239,17 +2127,14 @@ class NativeMkbHandler extends MkbHandler {
}
#onPollingModeChanged = (e) => {
if (!this.#$message) return;
- if (e.mode === "none")
- this.#$message.classList.remove("bx-offscreen");
- else
- this.#$message.classList.add("bx-offscreen");
+ if (e.mode === "none") this.#$message.classList.remove("bx-offscreen");
+ else this.#$message.classList.add("bx-offscreen");
};
#onDialogShown = () => {
document.pointerLockElement && document.exitPointerLock();
};
#initMessage() {
- if (!this.#$message)
- this.#$message = CE("div", { class: "bx-mkb-pointer-lock-msg" }, CE("div", {}, CE("p", {}, t("native-mkb")), CE("p", {}, t("press-key-to-toggle-mkb", { key: "F8" }))), CE("div", { "data-type": "native" }, createButton({
+ if (!this.#$message) this.#$message = CE("div", { class: "bx-mkb-pointer-lock-msg" }, CE("div", {}, CE("p", {}, t("native-mkb")), CE("p", {}, t("press-key-to-toggle-mkb", { key: "F8" }))), CE("div", { "data-type": "native" }, createButton({
style: 1 | 64 | 256,
label: t("activate"),
onClick: ((e) => {
@@ -2262,8 +2147,7 @@ class NativeMkbHandler extends MkbHandler {
e.preventDefault(), e.stopPropagation(), this.#$message?.classList.add("bx-gone");
}
})));
- if (!this.#$message.isConnected)
- document.documentElement.appendChild(this.#$message);
+ if (!this.#$message.isConnected) document.documentElement.appendChild(this.#$message);
}
handleEvent(event) {
switch (event.type) {
@@ -2291,21 +2175,15 @@ class NativeMkbHandler extends MkbHandler {
} catch (e) {
Toast.show("Cannot enable Mouse & Keyboard feature");
}
- if (this.#mouseVerticalMultiply = getPref("native_mkb_scroll_y_sensitivity"), this.#mouseHorizontalMultiply = getPref("native_mkb_scroll_x_sensitivity"), window.addEventListener("keyup", this), window.addEventListener(BxEvent.XCLOUD_DIALOG_SHOWN, this), window.addEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.addEventListener(BxEvent.POINTER_LOCK_EXITED, this), window.addEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this), this.#initMessage(), AppInterface)
- Toast.show(t("press-key-to-toggle-mkb", { key: "F8" }), t("native-mkb"), { html: !0 }), this.#$message?.classList.add("bx-gone");
- else
- this.#$message?.classList.remove("bx-gone");
+ if (this.#mouseVerticalMultiply = getPref("native_mkb_scroll_y_sensitivity"), this.#mouseHorizontalMultiply = getPref("native_mkb_scroll_x_sensitivity"), window.addEventListener("keyup", this), window.addEventListener(BxEvent.XCLOUD_DIALOG_SHOWN, this), window.addEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.addEventListener(BxEvent.POINTER_LOCK_EXITED, this), window.addEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this), this.#initMessage(), AppInterface) Toast.show(t("press-key-to-toggle-mkb", { key: "F8" }), t("native-mkb"), { html: !0 }), this.#$message?.classList.add("bx-gone");
+ else this.#$message?.classList.remove("bx-gone");
}
toggle(force) {
let setEnable;
- if (typeof force !== "undefined")
- setEnable = force;
- else
- setEnable = !this.#enabled;
- if (setEnable)
- document.documentElement.requestPointerLock();
- else
- document.exitPointerLock();
+ if (typeof force !== "undefined") setEnable = force;
+ else setEnable = !this.#enabled;
+ if (setEnable) document.documentElement.requestPointerLock();
+ else document.exitPointerLock();
}
#updateInputConfigurationAsync(enabled) {
window.BX_EXPOSED.streamSession.updateInputConfigurationAsync({
@@ -2335,10 +2213,8 @@ class NativeMkbHandler extends MkbHandler {
}
handleMouseClick(data) {
const { pointerButton, pressed } = data;
- if (pressed)
- this.#mouseButtonsPressed |= pointerButton;
- else
- this.#mouseButtonsPressed ^= pointerButton;
+ if (pressed) this.#mouseButtonsPressed |= pointerButton;
+ else this.#mouseButtonsPressed ^= pointerButton;
this.#mouseButtonsPressed = Math.max(0, this.#mouseButtonsPressed), this.#sendMouseInput({
X: 0,
Y: 0,
@@ -2349,10 +2225,8 @@ class NativeMkbHandler extends MkbHandler {
}
handleMouseWheel(data) {
const { vertical, horizontal } = data;
- if (this.#mouseWheelX = horizontal, this.#mouseHorizontalMultiply && this.#mouseHorizontalMultiply !== 1)
- this.#mouseWheelX *= this.#mouseHorizontalMultiply;
- if (this.#mouseWheelY = vertical, this.#mouseVerticalMultiply && this.#mouseVerticalMultiply !== 1)
- this.#mouseWheelY *= this.#mouseVerticalMultiply;
+ if (this.#mouseWheelX = horizontal, this.#mouseHorizontalMultiply && this.#mouseHorizontalMultiply !== 1) this.#mouseWheelX *= this.#mouseHorizontalMultiply;
+ if (this.#mouseWheelY = vertical, this.#mouseVerticalMultiply && this.#mouseVerticalMultiply !== 1) this.#mouseWheelY *= this.#mouseVerticalMultiply;
return this.#sendMouseInput({
X: 0,
Y: 0,
@@ -2389,10 +2263,8 @@ function onChangeVideoPlayerType() {
if (!$videoProcessing) return;
let isDisabled = !1;
const $optCas = $videoProcessing.querySelector(`option[value=${"cas"}]`);
- if (playerType === "webgl2")
- $optCas && ($optCas.disabled = !1);
- else if ($videoProcessing.value = "usm", setPref("video_processing", "usm"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari())
- isDisabled = !0;
+ if (playerType === "webgl2") $optCas && ($optCas.disabled = !1);
+ else if ($videoProcessing.value = "usm", setPref("video_processing", "usm"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0;
$videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), updateVideoPlayer();
}
function updateVideoPlayer() {
@@ -2414,8 +2286,7 @@ class NavigationDialog {
this.dialogManager = NavigationDialogManager.getInstance();
}
show() {
- if (NavigationDialogManager.getInstance().show(this), !this.getFocusedElement())
- this.focusIfNeeded();
+ if (NavigationDialogManager.getInstance().show(this), !this.getFocusedElement()) this.focusIfNeeded();
}
hide() {
NavigationDialogManager.getInstance().hide();
@@ -2440,8 +2311,7 @@ class NavigationDialog {
class NavigationDialogManager {
static instance;
static getInstance() {
- if (!NavigationDialogManager.instance)
- NavigationDialogManager.instance = new NavigationDialogManager;
+ if (!NavigationDialogManager.instance) NavigationDialogManager.instance = new NavigationDialogManager;
return NavigationDialogManager.instance;
}
static GAMEPAD_POLLING_INTERVAL = 50;
@@ -2495,10 +2365,8 @@ class NavigationDialogManager {
const rect = $select.getBoundingClientRect(), $parent = $select.parentElement;
$parent.dataset.calculated = "true";
let $label, width = Math.ceil(rect.width);
- if ($select.multiple)
- $label = $parent.querySelector(".bx-select-value"), width += 15;
- else
- $label = $parent.querySelector("div");
+ if ($select.multiple) $label = $parent.querySelector(".bx-select-value"), width += 15;
+ else $label = $parent.querySelector("div");
$label.style.minWidth = width + "px";
});
}).observe(this.$container, { childList: !0 });
@@ -2512,18 +2380,13 @@ class NavigationDialogManager {
event.preventDefault(), event.stopPropagation();
return;
}
- if (keyCode === "ArrowUp" || keyCode === "ArrowDown")
- handled = !0, this.focusDirection(keyCode === "ArrowUp" ? 1 : 3);
+ if (keyCode === "ArrowUp" || keyCode === "ArrowDown") handled = !0, this.focusDirection(keyCode === "ArrowUp" ? 1 : 3);
else if (keyCode === "ArrowLeft" || keyCode === "ArrowRight") {
- if (!($target instanceof HTMLInputElement && ($target.type === "text" || $target.type === "range")))
- handled = !0, this.focusDirection(keyCode === "ArrowLeft" ? 4 : 2);
+ if (!($target instanceof HTMLInputElement && ($target.type === "text" || $target.type === "range"))) handled = !0, this.focusDirection(keyCode === "ArrowLeft" ? 4 : 2);
} else if (keyCode === "Enter" || keyCode === "NumpadEnter" || keyCode === "Space") {
- if (!($target instanceof HTMLInputElement && $target.type === "text"))
- handled = !0, $target.dispatchEvent(new MouseEvent("click"));
- } else if (keyCode === "Escape")
- handled = !0, this.hide();
- if (handled)
- event.preventDefault(), event.stopPropagation();
+ if (!($target instanceof HTMLInputElement && $target.type === "text")) handled = !0, $target.dispatchEvent(new MouseEvent("click"));
+ } else if (keyCode === "Escape") handled = !0, this.hide();
+ if (handled) event.preventDefault(), event.stopPropagation();
break;
}
}
@@ -2533,16 +2396,12 @@ class NavigationDialogManager {
pollGamepad() {
const gamepads = window.navigator.getGamepads();
for (let gamepad of gamepads) {
- if (!gamepad || !gamepad.connected)
- continue;
- if (gamepad.id === EmulatedMkbHandler.VIRTUAL_GAMEPAD_ID)
- continue;
+ if (!gamepad || !gamepad.connected) continue;
+ if (gamepad.id === EmulatedMkbHandler.VIRTUAL_GAMEPAD_ID) continue;
const { axes, buttons } = gamepad;
let releasedButton = null, heldButton = null, lastState = this.gamepadLastStates[gamepad.index], lastTimestamp, lastKey, lastKeyPressed;
- if (lastState)
- [lastTimestamp, lastKey, lastKeyPressed] = lastState;
- if (lastTimestamp && lastTimestamp === gamepad.timestamp)
- continue;
+ if (lastState) [lastTimestamp, lastKey, lastKeyPressed] = lastState;
+ if (lastTimestamp && lastTimestamp === gamepad.timestamp) continue;
for (let key of NavigationDialogManager.GAMEPAD_KEYS)
if (lastKey === key && !buttons[key].pressed) {
releasedButton = key;
@@ -2554,22 +2413,15 @@ class NavigationDialogManager {
if (heldButton === null && releasedButton === null && axes && axes.length >= 2) {
if (lastKey) {
const releasedHorizontal = Math.abs(axes[0]) < 0.1 && (lastKey === 102 || lastKey === 103), releasedVertical = Math.abs(axes[1]) < 0.1 && (lastKey === 100 || lastKey === 101);
- if (releasedHorizontal || releasedVertical)
- releasedButton = lastKey;
- else
- heldButton = lastKey;
- } else if (axes[0] < -0.5)
- heldButton = 102;
- else if (axes[0] > 0.5)
- heldButton = 103;
- else if (axes[1] < -0.5)
- heldButton = 100;
- else if (axes[1] > 0.5)
- heldButton = 101;
+ if (releasedHorizontal || releasedVertical) releasedButton = lastKey;
+ else heldButton = lastKey;
+ } else if (axes[0] < -0.5) heldButton = 102;
+ else if (axes[0] > 0.5) heldButton = 103;
+ else if (axes[1] < -0.5) heldButton = 100;
+ else if (axes[1] > 0.5) heldButton = 101;
}
if (heldButton !== null) {
- if (this.gamepadLastStates[gamepad.index] = [gamepad.timestamp, heldButton, !1], this.clearGamepadHoldingInterval(), NavigationDialogManager.GAMEPAD_DIRECTION_MAP[heldButton])
- this.gamepadHoldingIntervalId = window.setInterval(() => {
+ if (this.gamepadLastStates[gamepad.index] = [gamepad.timestamp, heldButton, !1], this.clearGamepadHoldingInterval(), NavigationDialogManager.GAMEPAD_DIRECTION_MAP[heldButton]) this.gamepadHoldingIntervalId = window.setInterval(() => {
const lastState2 = this.gamepadLastStates[gamepad.index];
if (lastState2) {
if ([lastTimestamp, lastKey, lastKeyPressed] = lastState2, lastKey === heldButton) {
@@ -2603,19 +2455,16 @@ class NavigationDialogManager {
if (!direction) return !1;
if (document.activeElement instanceof HTMLInputElement && document.activeElement.type === "range") {
const $range = document.activeElement;
- if (direction === 4 || direction === 2)
- $range.value = (parseInt($range.value) + parseInt($range.step) * (direction === 4 ? -1 : 1)).toString(), $range.dispatchEvent(new InputEvent("input")), handled = !0;
+ if (direction === 4 || direction === 2) $range.value = (parseInt($range.value) + parseInt($range.step) * (direction === 4 ? -1 : 1)).toString(), $range.dispatchEvent(new InputEvent("input")), handled = !0;
}
- if (!handled)
- this.focusDirection(direction);
+ if (!handled) this.focusDirection(direction);
return this.gamepadLastStates[gamepad.index] && (this.gamepadLastStates[gamepad.index][2] = !0), !0;
}
clearGamepadHoldingInterval() {
this.gamepadHoldingIntervalId && window.clearInterval(this.gamepadHoldingIntervalId), this.gamepadHoldingIntervalId = null;
}
show(dialog) {
- if (this.clearGamepadHoldingInterval(), BxEvent.dispatch(window, BxEvent.XCLOUD_DIALOG_SHOWN), window.BX_EXPOSED.disableGamepadPolling = !0, document.body.classList.add("bx-no-scroll"), this.$overlay.classList.remove("bx-gone"), STATES.isPlaying)
- this.$overlay.classList.add("bx-invisible");
+ if (this.clearGamepadHoldingInterval(), BxEvent.dispatch(window, BxEvent.XCLOUD_DIALOG_SHOWN), window.BX_EXPOSED.disableGamepadPolling = !0, document.body.classList.add("bx-no-scroll"), this.$overlay.classList.remove("bx-gone"), STATES.isPlaying) this.$overlay.classList.add("bx-invisible");
this.unmountCurrentDialog(), this.dialog = dialog, dialog.onBeforeMount(), this.$container.appendChild(dialog.getContent()), dialog.onMounted(), this.$container.classList.remove("bx-gone"), this.$container.addEventListener("keydown", this), this.startGamepadPolling();
}
hide() {
@@ -2623,8 +2472,7 @@ class NavigationDialogManager {
}
focus($elm) {
if (!$elm) return !1;
- if ($elm.nearby && $elm.nearby.focus)
- if ($elm.nearby.focus instanceof HTMLElement) return this.focus($elm.nearby.focus);
+ if ($elm.nearby && $elm.nearby.focus) if ($elm.nearby.focus instanceof HTMLElement) return this.focus($elm.nearby.focus);
else return $elm.nearby.focus();
return $elm.focus(), $elm === document.activeElement;
}
@@ -2678,8 +2526,7 @@ class NavigationDialogManager {
}
}
const children = Array.from($elm.children), orientation = $elm.nearby?.orientation || "vertical";
- if (orientation === "horizontal" || orientation === "vertical" && direction === 1)
- children.reverse();
+ if (orientation === "horizontal" || orientation === "vertical" && direction === 1) children.reverse();
for (let $child of children) {
if (!$child || !($child instanceof HTMLElement)) return null;
const $target = this.findFocusableElement($child, direction);
@@ -2757,10 +2604,8 @@ class Dialog {
onClose,
helpUrl
} = options, $overlay = document.querySelector(".bx-dialog-overlay");
- if (!$overlay)
- this.$overlay = CE("div", { class: "bx-dialog-overlay bx-gone" }), this.$overlay.addEventListener("contextmenu", (e) => e.preventDefault()), document.documentElement.appendChild(this.$overlay);
- else
- this.$overlay = $overlay;
+ if (!$overlay) this.$overlay = CE("div", { class: "bx-dialog-overlay bx-gone" }), this.$overlay.addEventListener("contextmenu", (e) => e.preventDefault()), document.documentElement.appendChild(this.$overlay);
+ else this.$overlay = $overlay;
let $close;
this.onClose = onClose, this.$dialog = CE("div", { class: `bx-dialog ${className || ""} bx-gone` }, this.$title = CE("h2", {}, CE("b", {}, title), helpUrl && createButton({
icon: BxIcon.QUESTION,
@@ -2772,8 +2617,7 @@ class Dialog {
}), !title && this.$title.classList.add("bx-gone"), !content && this.$content.classList.add("bx-gone"), this.$dialog.addEventListener("contextmenu", (e) => e.preventDefault()), document.documentElement.appendChild(this.$dialog);
}
show(newOptions) {
- if (document.activeElement && document.activeElement.blur(), newOptions && newOptions.title)
- this.$title.querySelector("b").textContent = newOptions.title, this.$title.classList.remove("bx-gone");
+ if (document.activeElement && document.activeElement.blur(), newOptions && newOptions.title) this.$title.querySelector("b").textContent = newOptions.title, this.$title.classList.remove("bx-gone");
this.$dialog.classList.remove("bx-gone"), this.$overlay.classList.remove("bx-gone"), document.body.classList.add("bx-no-scroll");
}
hide(e) {
@@ -2813,8 +2657,7 @@ class MkbRemapper {
];
static #instance;
static get INSTANCE() {
- if (!MkbRemapper.#instance)
- MkbRemapper.#instance = new MkbRemapper;
+ if (!MkbRemapper.#instance) MkbRemapper.#instance = new MkbRemapper;
return MkbRemapper.#instance;
}
#STATE = {
@@ -2846,8 +2689,7 @@ class MkbRemapper {
const buttonIndex = parseInt($elm.getAttribute("data-button-index")), keySlot = parseInt($elm.getAttribute("data-key-slot"));
if ($elm.getAttribute("data-key-code") === key.code) return;
for (let $otherElm of this.#$.allKeyElements)
- if ($otherElm.getAttribute("data-key-code") === key.code)
- this.#unbindKey($otherElm);
+ if ($otherElm.getAttribute("data-key-code") === key.code) this.#unbindKey($otherElm);
this.#STATE.editingPresetData.mapping[buttonIndex][keySlot] = key.code, $elm.textContent = key.name, $elm.setAttribute("data-key-code", key.code);
};
#unbindKey = ($elm) => {
@@ -2861,8 +2703,7 @@ class MkbRemapper {
e.preventDefault(), this.#clearEventListeners(), this.#bindKey(this.#$.currentBindingKey, KeyHelper.getKeyFromEvent(e)), window.setTimeout(() => this.bindingDialog.hide(), 200);
};
#onKeyDown = (e) => {
- if (e.preventDefault(), e.stopPropagation(), this.#clearEventListeners(), e.code !== "Escape")
- this.#bindKey(this.#$.currentBindingKey, KeyHelper.getKeyFromEvent(e));
+ if (e.preventDefault(), e.stopPropagation(), this.#clearEventListeners(), e.code !== "Escape") this.#bindKey(this.#$.currentBindingKey, KeyHelper.getKeyFromEvent(e));
window.setTimeout(() => this.bindingDialog.hide(), 200);
};
#onBindingKey = (e) => {
@@ -2884,17 +2725,14 @@ class MkbRemapper {
const presetData = this.#getCurrentPreset().data;
for (let $elm of this.#$.allKeyElements) {
const buttonIndex = parseInt($elm.getAttribute("data-button-index")), keySlot = parseInt($elm.getAttribute("data-key-slot")), buttonKeys = presetData.mapping[buttonIndex];
- if (buttonKeys && buttonKeys[keySlot])
- $elm.textContent = KeyHelper.codeToKeyName(buttonKeys[keySlot]), $elm.setAttribute("data-key-code", buttonKeys[keySlot]);
- else
- $elm.textContent = "", $elm.removeAttribute("data-key-code");
+ if (buttonKeys && buttonKeys[keySlot]) $elm.textContent = KeyHelper.codeToKeyName(buttonKeys[keySlot]), $elm.setAttribute("data-key-code", buttonKeys[keySlot]);
+ else $elm.textContent = "", $elm.removeAttribute("data-key-code");
}
let key;
for (key in this.#$.allMouseElements) {
const $elm = this.#$.allMouseElements[key];
let value = presetData.mouse[key];
- if (typeof value === "undefined")
- value = MkbPreset.MOUSE_SETTINGS[key].default;
+ if (typeof value === "undefined") value = MkbPreset.MOUSE_SETTINGS[key].default;
"setValue" in $elm && $elm.setValue(value);
}
const activated = getPref("mkb_default_preset_id") === this.#STATE.currentPresetId;
@@ -2907,14 +2745,11 @@ class MkbRemapper {
this.#STATE.presets = presets;
const $fragment = document.createDocumentFragment();
let defaultPresetId;
- if (this.#STATE.currentPresetId === 0)
- this.#STATE.currentPresetId = parseInt(Object.keys(presets)[0]), defaultPresetId = this.#STATE.currentPresetId, setPref("mkb_default_preset_id", defaultPresetId), EmulatedMkbHandler.getInstance().refreshPresetData();
- else
- defaultPresetId = getPref("mkb_default_preset_id");
+ if (this.#STATE.currentPresetId === 0) this.#STATE.currentPresetId = parseInt(Object.keys(presets)[0]), defaultPresetId = this.#STATE.currentPresetId, setPref("mkb_default_preset_id", defaultPresetId), EmulatedMkbHandler.getInstance().refreshPresetData();
+ else defaultPresetId = getPref("mkb_default_preset_id");
for (let id2 in presets) {
let name = presets[id2].name;
- if (id2 === defaultPresetId)
- name = "🎮 " + name;
+ if (id2 === defaultPresetId) name = "🎮 " + name;
const $options = CE("option", { value: id2 }, name);
$options.selected = parseInt(id2) === this.#STATE.currentPresetId, $fragment.appendChild($options);
}
@@ -2924,17 +2759,13 @@ class MkbRemapper {
});
}
#toggleEditing = (force) => {
- if (this.#STATE.isEditing = typeof force !== "undefined" ? force : !this.#STATE.isEditing, this.#$.wrapper.classList.toggle("bx-editing", this.#STATE.isEditing), this.#STATE.isEditing)
- this.#STATE.editingPresetData = deepClone(this.#getCurrentPreset().data);
- else
- this.#STATE.editingPresetData = null;
+ if (this.#STATE.isEditing = typeof force !== "undefined" ? force : !this.#STATE.isEditing, this.#$.wrapper.classList.toggle("bx-editing", this.#STATE.isEditing), this.#STATE.isEditing) this.#STATE.editingPresetData = deepClone(this.#getCurrentPreset().data);
+ else this.#STATE.editingPresetData = null;
const childElements = this.#$.wrapper.querySelectorAll("select, button, input");
for (let $elm of Array.from(childElements)) {
- if ($elm.parentElement.parentElement.classList.contains("bx-mkb-action-buttons"))
- continue;
+ if ($elm.parentElement.parentElement.classList.contains("bx-mkb-action-buttons")) continue;
let disable = !this.#STATE.isEditing;
- if ($elm.parentElement.classList.contains("bx-mkb-preset-tools"))
- disable = !disable;
+ if ($elm.parentElement.classList.contains("bx-mkb-preset-tools")) disable = !disable;
$elm.disabled = disable;
}
};
@@ -3049,8 +2880,7 @@ class MkbRemapper {
onClick: (e) => {
const updatedPreset = deepClone(this.#getCurrentPreset());
updatedPreset.data = this.#STATE.editingPresetData, LocalDb.INSTANCE.updatePreset(updatedPreset).then((id2) => {
- if (id2 === getPref("mkb_default_preset_id"))
- EmulatedMkbHandler.getInstance().refreshPresetData();
+ if (id2 === getPref("mkb_default_preset_id")) EmulatedMkbHandler.getInstance().refreshPresetData();
this.#toggleEditing(!1), this.#refresh();
});
}
@@ -3068,8 +2898,7 @@ function checkForUpdate() {
}
function disablePwa() {
if (!(window.navigator.orgUserAgent || window.navigator.userAgent || "").toLowerCase()) return;
- if (!!AppInterface || UserAgent.isSafariMobile())
- Object.defineProperty(window.navigator, "standalone", {
+ if (!!AppInterface || UserAgent.isSafariMobile()) Object.defineProperty(window.navigator, "standalone", {
value: !0
});
}
@@ -3110,15 +2939,11 @@ class SoundShortcut {
if (!getPref("audio_enable_volume_control")) return 0;
const currentValue = getPref("audio_volume");
let nearestValue;
- if (amount > 0)
- nearestValue = ceilToNearest(currentValue, amount);
- else
- nearestValue = floorToNearest(currentValue, -1 * amount);
+ if (amount > 0) nearestValue = ceilToNearest(currentValue, amount);
+ else nearestValue = floorToNearest(currentValue, -1 * amount);
let newValue;
- if (currentValue !== nearestValue)
- newValue = nearestValue;
- else
- newValue = currentValue + amount;
+ if (currentValue !== nearestValue) newValue = nearestValue;
+ else newValue = currentValue + amount;
return newValue = setPref("audio_volume", newValue, !0), SoundShortcut.setGainNodeVolume(newValue), Toast.show(`${t("stream")} ❯ ${t("volume")}`, newValue + "%", { instant: !0 }), newValue;
}
static setGainNodeVolume(value) {
@@ -3128,25 +2953,19 @@ class SoundShortcut {
if (getPref("audio_enable_volume_control") && STATES.currentStream.audioGainNode) {
const gainValue = STATES.currentStream.audioGainNode.gain.value, settingValue = getPref("audio_volume");
let targetValue;
- if (settingValue === 0)
- targetValue = 100, setPref("audio_volume", targetValue, !0);
- else if (gainValue === 0)
- targetValue = settingValue;
- else
- targetValue = 0;
+ if (settingValue === 0) targetValue = 100, setPref("audio_volume", targetValue, !0);
+ else if (gainValue === 0) targetValue = settingValue;
+ else targetValue = 0;
let status;
- if (targetValue === 0)
- status = t("muted");
- else
- status = targetValue + "%";
+ if (targetValue === 0) status = t("muted");
+ else status = targetValue + "%";
SoundShortcut.setGainNodeVolume(targetValue), Toast.show(`${t("stream")} ❯ ${t("volume")}`, status, { instant: !0 }), BxEvent.dispatch(window, BxEvent.SPEAKER_STATE_CHANGED, {
speakerState: targetValue === 0 ? 1 : 0
});
return;
}
let $media;
- if ($media = document.querySelector("div[data-testid=media-container] audio"), !$media)
- $media = document.querySelector("div[data-testid=media-container] video");
+ if ($media = document.querySelector("div[data-testid=media-container] audio"), !$media) $media = document.querySelector("div[data-testid=media-container] video");
if ($media) {
$media.muted = !$media.muted;
const status = $media.muted ? t("muted") : t("unmuted");
@@ -3231,10 +3050,8 @@ class TouchController {
const json = await (await NATIVE_FETCH(url)).json(), layouts = {};
json.layouts.forEach(async (layoutName) => {
let baseLayouts = {};
- if (layoutName in TouchController.#baseCustomLayouts)
- baseLayouts = TouchController.#baseCustomLayouts[layoutName];
- else
- try {
+ if (layoutName in TouchController.#baseCustomLayouts) baseLayouts = TouchController.#baseCustomLayouts[layoutName];
+ else try {
const layoutUrl = `${baseUrl}/layouts/${layoutName}.json`;
baseLayouts = (await (await NATIVE_FETCH(layoutUrl)).json()).layouts, TouchController.#baseCustomLayouts[layoutName] = baseLayouts;
} catch (e) {}
@@ -3247,8 +3064,7 @@ class TouchController {
static applyCustomLayout(layoutId, delay = 0) {
if (!window.BX_EXPOSED.touchLayoutManager) {
const listener = (e) => {
- if (window.removeEventListener(BxEvent.TOUCH_LAYOUT_MANAGER_READY, listener), TouchController.#enabled)
- TouchController.applyCustomLayout(layoutId, 0);
+ if (window.removeEventListener(BxEvent.TOUCH_LAYOUT_MANAGER_READY, listener), TouchController.#enabled) TouchController.applyCustomLayout(layoutId, 0);
};
window.addEventListener(BxEvent.TOUCH_LAYOUT_MANAGER_READY, listener);
return;
@@ -3258,8 +3074,7 @@ class TouchController {
BxLogger.error(LOG_TAG2, "Invalid xboxTitleId");
return;
}
- if (!layoutId)
- layoutId = TouchController.#customLayouts[xboxTitleId]?.default_layout || null;
+ if (!layoutId) layoutId = TouchController.#customLayouts[xboxTitleId]?.default_layout || null;
if (!layoutId) {
BxLogger.error(LOG_TAG2, "Invalid layoutId, show default controller"), TouchController.#enabled && TouchController.#showDefault();
return;
@@ -3277,8 +3092,7 @@ class TouchController {
if (layout.author) {
const author = `${escapeHtml(layout.author)}`;
msg = t("touch-control-layout-by", { name: author }), html = !0;
- } else
- msg = t("touch-control-layout");
+ } else msg = t("touch-control-layout");
layoutChanged && Toast.show(msg, layout.name, { html }), window.setTimeout(() => {
window.BX_EXPOSED.shouldShowSensorControls = JSON.stringify(layout).includes("gyroscope"), window.BX_EXPOSED.touchLayoutManager.changeLayoutForScope({
type: "showLayout",
@@ -3322,16 +3136,11 @@ class TouchController {
if (!dataChannel || dataChannel.label !== "message") return;
let filter = "";
if (TouchController.#enabled) {
- if (PREF_STYLE_STANDARD === "white")
- filter = "grayscale(1) brightness(2)";
- else if (PREF_STYLE_STANDARD === "muted")
- filter = "sepia(0.5)";
- } else if (PREF_STYLE_CUSTOM === "muted")
- filter = "sepia(0.5)";
- if (filter)
- $style.textContent = `#babylon-canvas { filter: ${filter} !important; }`;
- else
- $style.textContent = "";
+ if (PREF_STYLE_STANDARD === "white") filter = "grayscale(1) brightness(2)";
+ else if (PREF_STYLE_STANDARD === "muted") filter = "sepia(0.5)";
+ } else if (PREF_STYLE_CUSTOM === "muted") filter = "sepia(0.5)";
+ if (filter) $style.textContent = `#babylon-canvas { filter: ${filter} !important; }`;
+ else $style.textContent = "";
TouchController.#dataChannel = dataChannel, dataChannel.addEventListener("open", () => {
window.setTimeout(TouchController.#show, 1000);
});
@@ -3339,18 +3148,14 @@ class TouchController {
dataChannel.addEventListener("message", (msg) => {
if (msg.origin === "better-xcloud" || typeof msg.data !== "string") return;
if (msg.data.includes("touchcontrols/showtitledefault")) {
- if (TouchController.#enabled)
- if (focused)
- TouchController.requestCustomLayouts();
- else
- TouchController.#showDefault();
+ if (TouchController.#enabled) if (focused) TouchController.requestCustomLayouts();
+ else TouchController.#showDefault();
return;
}
try {
if (msg.data.includes("/titleinfo")) {
const json = JSON.parse(JSON.parse(msg.data).content);
- if (focused = json.focused, !json.focused)
- TouchController.#show();
+ if (focused = json.focused, !json.focused) TouchController.#show();
TouchController.setXboxTitleId(parseInt(json.titleid, 16).toString());
}
} catch (e2) {
@@ -3396,8 +3201,7 @@ class VibrationManager {
stopVibration && window.navigator.vibrate(0);
const value = getPref("controller_device_vibration");
let enabled;
- if (value === "on")
- enabled = !0;
+ if (value === "on") enabled = !0;
else if (value === "auto") {
enabled = !0;
const gamepads = window.navigator.getGamepads();
@@ -3406,8 +3210,7 @@ class VibrationManager {
enabled = !1;
break;
}
- } else
- enabled = !1;
+ } else enabled = !1;
window.BX_ENABLE_DEVICE_VIBRATION = enabled;
}
static #onMessage(e) {
@@ -3415,20 +3218,16 @@ class VibrationManager {
if (typeof e !== "object" || !(e.data instanceof ArrayBuffer)) return;
const dataView = new DataView(e.data);
let offset = 0, messageType;
- if (dataView.byteLength === 13)
- messageType = dataView.getUint16(offset, !0), offset += Uint16Array.BYTES_PER_ELEMENT;
- else
- messageType = dataView.getUint8(offset), offset += Uint8Array.BYTES_PER_ELEMENT;
+ if (dataView.byteLength === 13) messageType = dataView.getUint16(offset, !0), offset += Uint16Array.BYTES_PER_ELEMENT;
+ else messageType = dataView.getUint8(offset), offset += Uint8Array.BYTES_PER_ELEMENT;
if (!(messageType & 128)) return;
const vibrationType = dataView.getUint8(offset);
if (offset += Uint8Array.BYTES_PER_ELEMENT, vibrationType !== 0) return;
const data = {};
let key;
for (key in VIBRATION_DATA_MAP)
- if (VIBRATION_DATA_MAP[key] === 16)
- data[key] = dataView.getUint16(offset, !0), offset += Uint16Array.BYTES_PER_ELEMENT;
- else
- data[key] = dataView.getUint8(offset), offset += Uint8Array.BYTES_PER_ELEMENT;
+ if (VIBRATION_DATA_MAP[key] === 16) data[key] = dataView.getUint16(offset, !0), offset += Uint16Array.BYTES_PER_ELEMENT;
+ else data[key] = dataView.getUint8(offset), offset += Uint8Array.BYTES_PER_ELEMENT;
VibrationManager.#playDeviceVibration(data);
}
static initialSetup() {
@@ -3450,8 +3249,7 @@ class BxSelectElement {
style: 32
}), isMultiple = $select.multiple;
let $checkBox, $label, visibleIndex = $select.selectedIndex, $content;
- if (isMultiple)
- $content = CE("button", {
+ if (isMultiple) $content = CE("button", {
class: "bx-select-value bx-focusable",
tabindex: 0
}, $checkBox = CE("input", { type: "checkbox" }), $label = CE("span", {}, "")), $content.addEventListener("click", (e) => {
@@ -3460,27 +3258,21 @@ class BxSelectElement {
const $option = getOptionAtIndex(visibleIndex);
$option && ($option.selected = e.target.checked), BxEvent.dispatch($select, "input");
});
- else
- $content = CE("div", {}, $label = CE("label", { for: $select.id + "_checkbox" }, ""));
+ else $content = CE("div", {}, $label = CE("label", { for: $select.id + "_checkbox" }, ""));
const getOptionAtIndex = (index) => {
return Array.from($select.querySelectorAll("option"))[index];
}, render = (e) => {
- if (e && e.manualTrigger)
- visibleIndex = $select.selectedIndex;
+ if (e && e.manualTrigger) visibleIndex = $select.selectedIndex;
visibleIndex = normalizeIndex(visibleIndex);
const $option = getOptionAtIndex(visibleIndex);
let content = "";
- if ($option)
- if (content = $option.textContent || "", content && $option.parentElement.tagName === "OPTGROUP") {
+ if ($option) if (content = $option.textContent || "", content && $option.parentElement.tagName === "OPTGROUP") {
$label.innerHTML = "";
const fragment = document.createDocumentFragment();
fragment.appendChild(CE("span", {}, $option.parentElement.label)), fragment.appendChild(document.createTextNode(content)), $label.appendChild(fragment);
- } else
- $label.textContent = content;
- else
- $label.textContent = content;
- if ($label.classList.toggle("bx-line-through", $option && $option.disabled), isMultiple)
- $checkBox.checked = $option?.selected || !1, $checkBox.classList.toggle("bx-gone", !content);
+ } else $label.textContent = content;
+ else $label.textContent = content;
+ if ($label.classList.toggle("bx-line-through", $option && $option.disabled), isMultiple) $checkBox.checked = $option?.selected || !1, $checkBox.classList.toggle("bx-gone", !content);
const disablePrev = visibleIndex <= 0, disableNext = visibleIndex === $select.querySelectorAll("option").length - 1;
$btnPrev.classList.toggle("bx-inactive", disablePrev), $btnNext.classList.toggle("bx-inactive", disableNext), disablePrev && !disableNext && document.activeElement === $btnPrev && $btnNext.focus(), disableNext && !disablePrev && document.activeElement === $btnNext && $btnPrev.focus();
}, normalizeIndex = (index) => {
@@ -3489,17 +3281,13 @@ class BxSelectElement {
if (!e.target) return;
const goNext = e.target.closest("button") === $btnNext, currentIndex = visibleIndex;
let newIndex = goNext ? currentIndex + 1 : currentIndex - 1;
- if (newIndex = normalizeIndex(newIndex), visibleIndex = newIndex, !isMultiple && newIndex !== currentIndex)
- $select.selectedIndex = newIndex;
- if (isMultiple)
- render();
- else
- BxEvent.dispatch($select, "input");
+ if (newIndex = normalizeIndex(newIndex), visibleIndex = newIndex, !isMultiple && newIndex !== currentIndex) $select.selectedIndex = newIndex;
+ if (isMultiple) render();
+ else BxEvent.dispatch($select, "input");
};
$select.addEventListener("input", render), $btnPrev.addEventListener("click", onPrevNext), $btnNext.addEventListener("click", onPrevNext), new MutationObserver((mutationList, observer2) => {
mutationList.forEach((mutation) => {
- if (mutation.type === "childList" || mutation.type === "attributes")
- render();
+ if (mutation.type === "childList" || mutation.type === "attributes") render();
});
}).observe($select, {
subtree: !0,
@@ -3527,10 +3315,8 @@ class BxSelectElement {
}, $div.dispatchEvent = function() {
return $select.dispatchEvent.apply($select, arguments);
}, $div.setValue = (value) => {
- if ("setValue" in $select)
- $select.setValue(value);
- else
- $select.value = value;
+ if ("setValue" in $select) $select.setValue(value);
+ else $select.value = value;
}, $div;
}
}
@@ -3547,12 +3333,9 @@ var FeatureGates = {
EnableUpdateRequiredPage: !1,
ShowForcedUpdateScreen: !1
};
-if (getPref("ui_home_context_menu_disabled"))
- FeatureGates.EnableHomeContextMenu = !1;
-if (getPref("block_social_features"))
- FeatureGates.EnableGuideChatTab = !1;
-if (BX_FLAGS.FeatureGates)
- FeatureGates = Object.assign(BX_FLAGS.FeatureGates, FeatureGates);
+if (getPref("ui_home_context_menu_disabled")) FeatureGates.EnableHomeContextMenu = !1;
+if (getPref("block_social_features")) FeatureGates.EnableGuideChatTab = !1;
+if (BX_FLAGS.FeatureGates) FeatureGates = Object.assign(BX_FLAGS.FeatureGates, FeatureGates);
class PatcherUtils {
static indexOf(txt, searchString, startIndex, maxRange) {
const index = txt.indexOf(searchString, startIndex);
@@ -3649,8 +3432,7 @@ var ENDING_CHUNKS_PATCH_NAME = "loadingEndingChunks", LOG_TAG3 = "Patcher", PATC
const nextIndex = str.indexOf("setTimeout(this.pollGamepads", index);
if (nextIndex === -1) return !1;
let codeBlock = str.substring(index, nextIndex);
- if (getPref("block_tracking"))
- codeBlock = codeBlock.replaceAll("this.inputPollingIntervalStats.addValue", "");
+ if (getPref("block_tracking")) codeBlock = codeBlock.replaceAll("this.inputPollingIntervalStats.addValue", "");
const match = codeBlock.match(/this\.gamepadTimestamps\.set\((\w+)\.index/);
if (match) {
const gamepadVar = match[1], newCode = renderString(controller_shortcuts_default, {
@@ -3754,10 +3536,8 @@ if (window.BX_EXPOSED.stopTakRendering) {
let text = "const{TakRenderer:";
if (!str.includes(text)) return !1;
let autoOffCode = "";
- if (getPref("stream_touch_controller") === "off")
- autoOffCode = "return;";
- else if (getPref("stream_touch_controller_auto_off"))
- autoOffCode = `
+ if (getPref("stream_touch_controller") === "off") autoOffCode = "return;";
+ else if (getPref("stream_touch_controller_auto_off")) autoOffCode = `
const gamepads = window.navigator.getGamepads();
let gamepadFound = false;
for (let gamepad of gamepads) {
@@ -3793,8 +3573,7 @@ window.BX_EXPOSED.showStreamMenu = e.onShowStreamMenu;
// Restore the "..." button
e.guideUI = null;
`;
- if (getPref("stream_touch_controller") === "off")
- newCode += "e.canShowTakHUD = false;";
+ if (getPref("stream_touch_controller") === "off") newCode += "e.canShowTakHUD = false;";
return str = str.replace(text, newCode + text), str;
},
broadcastPollingMode(str) {
@@ -4073,12 +3852,10 @@ class Patcher {
Function.prototype.bind = function() {
let valid = !1;
if (this.name.length <= 2 && arguments.length === 2 && arguments[0] === null) {
- if (arguments[1] === 0 || typeof arguments[1] === "function")
- valid = !0;
+ if (arguments[1] === 0 || typeof arguments[1] === "function") valid = !0;
}
if (!valid) return nativeBind.apply(this, arguments);
- if (PatcherCache.init(), typeof arguments[1] === "function")
- BxLogger.info(LOG_TAG3, "Restored Function.prototype.bind()"), Function.prototype.bind = nativeBind;
+ if (PatcherCache.init(), typeof arguments[1] === "function") BxLogger.info(LOG_TAG3, "Restored Function.prototype.bind()"), Function.prototype.bind = nativeBind;
const orgFunc = this, newFunc = (a, item2) => {
Patcher.patch(item2), orgFunc(a, item2);
};
@@ -4091,37 +3868,27 @@ class Patcher {
for (let id in item[1]) {
appliedPatches = [];
const cachedPatches = PatcherCache.getPatches(id);
- if (cachedPatches)
- patchesToCheck = cachedPatches.slice(0), patchesToCheck.push(...PATCH_ORDERS);
- else
- patchesToCheck = PATCH_ORDERS.slice(0);
- if (!patchesToCheck.length)
- continue;
+ if (cachedPatches) patchesToCheck = cachedPatches.slice(0), patchesToCheck.push(...PATCH_ORDERS);
+ else patchesToCheck = PATCH_ORDERS.slice(0);
+ if (!patchesToCheck.length) continue;
const func = item[1][id], funcStr = func.toString();
let patchedFuncStr = funcStr, modified = !1;
for (let patchIndex = 0;patchIndex < patchesToCheck.length; patchIndex++) {
const patchName = patchesToCheck[patchIndex];
- if (appliedPatches.indexOf(patchName) > -1)
- continue;
- if (!PATCHES[patchName])
- continue;
+ if (appliedPatches.indexOf(patchName) > -1) continue;
+ if (!PATCHES[patchName]) continue;
const tmpStr = PATCHES[patchName].call(null, patchedFuncStr);
- if (!tmpStr)
- continue;
+ if (!tmpStr) continue;
modified = !0, patchedFuncStr = tmpStr, BxLogger.info(LOG_TAG3, `✅ ${patchName}`), appliedPatches.push(patchName), patchesToCheck.splice(patchIndex, 1), patchIndex--, PATCH_ORDERS = PATCH_ORDERS.filter((item2) => item2 != patchName);
}
- if (modified)
- try {
+ if (modified) try {
item[1][id] = eval(patchedFuncStr);
} catch (e) {
- if (e instanceof Error)
- BxLogger.error(LOG_TAG3, "Error", appliedPatches, e.message, patchedFuncStr);
+ if (e instanceof Error) BxLogger.error(LOG_TAG3, "Error", appliedPatches, e.message, patchedFuncStr);
}
- if (appliedPatches.length)
- patchesMap[id] = appliedPatches;
+ if (appliedPatches.length) patchesMap[id] = appliedPatches;
}
- if (Object.keys(patchesMap).length)
- PatcherCache.saveToCache(patchesMap);
+ if (Object.keys(patchesMap).length) PatcherCache.saveToCache(patchesMap);
}
static init() {
Patcher.#patchFunctionBind();
@@ -4141,10 +3908,8 @@ class PatcherCache {
}
static checkSignature() {
const storedSig = window.localStorage.getItem(PatcherCache.#KEY_SIGNATURE) || 0, currentSig = PatcherCache.#getSignature();
- if (currentSig !== parseInt(storedSig))
- BxLogger.warning(LOG_TAG3, "Signature changed"), window.localStorage.setItem(PatcherCache.#KEY_SIGNATURE, currentSig.toString()), PatcherCache.clear();
- else
- BxLogger.info(LOG_TAG3, "Signature unchanged");
+ if (currentSig !== parseInt(storedSig)) BxLogger.warning(LOG_TAG3, "Signature changed"), window.localStorage.setItem(PatcherCache.#KEY_SIGNATURE, currentSig.toString()), PatcherCache.clear();
+ else BxLogger.info(LOG_TAG3, "Signature unchanged");
}
static #cleanupPatches(patches) {
return patches.filter((item2) => {
@@ -4160,29 +3925,23 @@ class PatcherCache {
for (let id2 in subCache) {
const patchNames = subCache[id2];
let data = PatcherCache.#CACHE[id2];
- if (!data)
- PatcherCache.#CACHE[id2] = patchNames;
- else
- for (let patchName of patchNames)
- if (!data.includes(patchName))
- data.push(patchName);
+ if (!data) PatcherCache.#CACHE[id2] = patchNames;
+ else for (let patchName of patchNames)
+ if (!data.includes(patchName)) data.push(patchName);
}
window.localStorage.setItem(PatcherCache.#KEY_CACHE, JSON.stringify(PatcherCache.#CACHE));
}
static init() {
if (PatcherCache.#isInitialized) return;
- if (PatcherCache.#isInitialized = !0, PatcherCache.checkSignature(), PatcherCache.#CACHE = JSON.parse(window.localStorage.getItem(PatcherCache.#KEY_CACHE) || "{}"), BxLogger.info(LOG_TAG3, PatcherCache.#CACHE), window.location.pathname.includes("/play/"))
- PATCH_ORDERS.push(...PLAYING_PATCH_ORDERS);
- else
- PATCH_ORDERS.push(ENDING_CHUNKS_PATCH_NAME);
+ if (PatcherCache.#isInitialized = !0, PatcherCache.checkSignature(), PatcherCache.#CACHE = JSON.parse(window.localStorage.getItem(PatcherCache.#KEY_CACHE) || "{}"), BxLogger.info(LOG_TAG3, PatcherCache.#CACHE), window.location.pathname.includes("/play/")) PATCH_ORDERS.push(...PLAYING_PATCH_ORDERS);
+ else PATCH_ORDERS.push(ENDING_CHUNKS_PATCH_NAME);
PATCH_ORDERS = PatcherCache.#cleanupPatches(PATCH_ORDERS), PLAYING_PATCH_ORDERS = PatcherCache.#cleanupPatches(PLAYING_PATCH_ORDERS), BxLogger.info(LOG_TAG3, PATCH_ORDERS.slice(0)), BxLogger.info(LOG_TAG3, PLAYING_PATCH_ORDERS.slice(0));
}
}
class FullscreenText {
static instance;
static getInstance() {
- if (!FullscreenText.instance)
- FullscreenText.instance = new FullscreenText;
+ if (!FullscreenText.instance) FullscreenText.instance = new FullscreenText;
return FullscreenText.instance;
}
$text;
@@ -4201,8 +3960,7 @@ class FullscreenText {
class SettingsNavigationDialog extends NavigationDialog {
static instance;
static getInstance() {
- if (!SettingsNavigationDialog.instance)
- SettingsNavigationDialog.instance = new SettingsNavigationDialog;
+ if (!SettingsNavigationDialog.instance) SettingsNavigationDialog.instance = new SettingsNavigationDialog;
return SettingsNavigationDialog.instance;
}
$container;
@@ -4233,14 +3991,11 @@ class SettingsNavigationDialog extends NavigationDialog {
label: "🌟 " + t("new-version-available", { version: PREF_LATEST_VERSION }),
style: 1 | 32 | 64
};
- if (AppInterface && AppInterface.updateLatestScript)
- opts.onClick = (e) => AppInterface.updateLatestScript();
- else
- opts.url = "https://github.com/redphx/better-xcloud/releases/latest";
+ if (AppInterface && AppInterface.updateLatestScript) opts.onClick = (e) => AppInterface.updateLatestScript();
+ else opts.url = "https://github.com/redphx/better-xcloud/releases/latest";
topButtons.push(createButton(opts));
}
- if (AppInterface)
- topButtons.push(createButton({
+ if (AppInterface) topButtons.push(createButton({
label: t("app-settings"),
icon: BxIcon.STREAM_SETTINGS,
style: 64 | 32,
@@ -4248,8 +4003,7 @@ class SettingsNavigationDialog extends NavigationDialog {
AppInterface.openAppSettings && AppInterface.openAppSettings(), this.hide();
}
}));
- else if (UserAgent.getDefault().toLowerCase().includes("android"))
- topButtons.push(createButton({
+ else if (UserAgent.getDefault().toLowerCase().includes("android")) topButtons.push(createButton({
label: "🔥 " + t("install-android"),
style: 64 | 32,
url: "https://better-xcloud.github.io/android"
@@ -4529,10 +4283,8 @@ class SettingsNavigationDialog extends NavigationDialog {
for (let key in customLayouts.layouts) {
const layout = customLayouts.layouts[key];
let name;
- if (layout.author)
- name = `${layout.name} (${layout.author})`;
- else
- name = layout.name;
+ if (layout.author) name = `${layout.name} (${layout.author})`;
+ else name = layout.name;
const $option = CE("option", { value: key }, name);
$fragment.appendChild($option);
}
@@ -4658,11 +4410,9 @@ class SettingsNavigationDialog extends NavigationDialog {
}
onMounted() {
if (!this.renderFullSettings) return;
- if (onChangeVideoPlayerType(), STATES.userAgent.capabilities.touch)
- BxEvent.dispatch(window, BxEvent.CUSTOM_TOUCH_LAYOUTS_LOADED);
+ if (onChangeVideoPlayerType(), STATES.userAgent.capabilities.touch) BxEvent.dispatch(window, BxEvent.CUSTOM_TOUCH_LAYOUTS_LOADED);
const $selectUserAgent = document.querySelector(`#bx_setting_${"user_agent_profile"}`);
- if ($selectUserAgent)
- $selectUserAgent.disabled = !0, BxEvent.dispatch($selectUserAgent, "input", {}), $selectUserAgent.disabled = !1;
+ if ($selectUserAgent) $selectUserAgent.disabled = !0, BxEvent.dispatch($selectUserAgent, "input", {}), $selectUserAgent.disabled = !1;
}
reloadPage() {
this.$btnGlobalReload.disabled = !0, this.$btnGlobalReload.firstElementChild.textContent = t("settings-reloading"), this.hide(), FullscreenText.getInstance().show(t("settings-reloading")), window.location.reload();
@@ -4688,18 +4438,15 @@ class SettingsNavigationDialog extends NavigationDialog {
addDefaultSuggestedSetting(prefKey, value) {
let key;
for (key in this.suggestedSettings)
- if (key !== "default" && !(prefKey in this.suggestedSettings))
- this.suggestedSettings[key][prefKey] = value;
+ if (key !== "default" && !(prefKey in this.suggestedSettings)) this.suggestedSettings[key][prefKey] = value;
}
generateDefaultSuggestedSettings() {
let key;
for (key in this.suggestedSettings) {
- if (key === "default")
- continue;
+ if (key === "default") continue;
let prefKey;
for (prefKey in this.suggestedSettings[key])
- if (!(prefKey in this.suggestedSettings.default))
- this.suggestedSettings.default[prefKey] = getPrefDefinition(prefKey).default;
+ if (!(prefKey in this.suggestedSettings.default)) this.suggestedSettings.default[prefKey] = getPrefDefinition(prefKey).default;
}
}
async renderSuggestions(e) {
@@ -4711,19 +4458,14 @@ class SettingsNavigationDialog extends NavigationDialog {
return;
}
for (let settingTab of this.SETTINGS_UI) {
- if (!settingTab || !settingTab.items)
- continue;
+ if (!settingTab || !settingTab.items) continue;
for (let settingTabContent of settingTab.items) {
- if (!settingTabContent || !settingTabContent.items)
- continue;
+ if (!settingTabContent || !settingTabContent.items) continue;
for (let setting of settingTabContent.items) {
let prefKey;
- if (typeof setting === "string")
- prefKey = setting;
- else if (typeof setting === "object")
- prefKey = setting.pref;
- if (prefKey)
- this.suggestedSettingLabels[prefKey] = settingTabContent.label;
+ if (typeof setting === "string") prefKey = setting;
+ else if (typeof setting === "object") prefKey = setting.pref;
+ if (prefKey) this.suggestedSettingLabels[prefKey] = settingTabContent.label;
}
}
}
@@ -4735,12 +4477,9 @@ class SettingsNavigationDialog extends NavigationDialog {
}
}
const hasRecommendedSettings = Object.keys(this.suggestedSettings.recommended).length > 0, deviceType = BX_FLAGS.DeviceInfo.deviceType;
- if (deviceType === "android-handheld")
- this.addDefaultSuggestedSetting("stream_touch_controller", "off"), this.addDefaultSuggestedSetting("controller_device_vibration", "on");
- else if (deviceType === "android")
- this.addDefaultSuggestedSetting("controller_device_vibration", "auto");
- else if (deviceType === "android-tv")
- this.addDefaultSuggestedSetting("stream_touch_controller", "off");
+ if (deviceType === "android-handheld") this.addDefaultSuggestedSetting("stream_touch_controller", "off"), this.addDefaultSuggestedSetting("controller_device_vibration", "on");
+ else if (deviceType === "android") this.addDefaultSuggestedSetting("controller_device_vibration", "auto");
+ else if (deviceType === "android-tv") this.addDefaultSuggestedSetting("stream_touch_controller", "off");
this.generateDefaultSuggestedSettings();
const $suggestedSettings = CE("div", { class: "bx-suggest-wrapper" }), $select = CE("select", {}, hasRecommendedSettings && CE("option", { value: "recommended" }, t("recommended")), !hasRecommendedSettings && CE("option", { value: "highest" }, t("highest-quality")), CE("option", { value: "default" }, t("default")), CE("option", { value: "lowest" }, t("lowest-quality")));
$select.addEventListener("input", (e2) => {
@@ -4748,18 +4487,15 @@ class SettingsNavigationDialog extends NavigationDialog {
removeChildElements($suggestedSettings);
const fragment = document.createDocumentFragment();
let note;
- if (profile === "recommended")
- note = t("recommended-settings-for-device", { device: recommendedDevice });
- else if (profile === "highest")
- note = "⚠️ " + t("highest-quality-note");
+ if (profile === "recommended") note = t("recommended-settings-for-device", { device: recommendedDevice });
+ else if (profile === "highest") note = "⚠️ " + t("highest-quality-note");
note && fragment.appendChild(CE("div", { class: "bx-suggest-note" }, note));
const settings = this.suggestedSettings[profile];
let prefKey;
for (prefKey in settings) {
const currentValue = getPref(prefKey, !1), suggestedValue = settings[prefKey], currentValueText = STORAGE.Global.getValueText(prefKey, currentValue), isSameValue = currentValue === suggestedValue;
let $child, $value;
- if (isSameValue)
- $value = currentValueText;
+ if (isSameValue) $value = currentValueText;
else {
const suggestedValueText = STORAGE.Global.getValueText(prefKey, suggestedValue);
$value = currentValueText + " ➔ " + suggestedValueText;
@@ -4790,17 +4526,14 @@ class SettingsNavigationDialog extends NavigationDialog {
let prefKey;
for (prefKey in settings) {
const suggestedValue = settings[prefKey], $checkBox = $content.querySelector(`#bx_suggest_${prefKey}`);
- if (!$checkBox.checked || $checkBox.disabled)
- continue;
+ if (!$checkBox.checked || $checkBox.disabled) continue;
const $control = this.settingElements[prefKey];
if (!$control) {
setPref(prefKey, suggestedValue);
continue;
}
- if ("setValue" in $control)
- $control.setValue(suggestedValue);
- else
- $control.value = suggestedValue;
+ if ("setValue" in $control) $control.setValue(suggestedValue);
+ else $control.value = suggestedValue;
BxEvent.dispatch($control, "input", {
manualTrigger: !0
});
@@ -4832,10 +4565,8 @@ class SettingsNavigationDialog extends NavigationDialog {
const $svg = createSvgIcon(settingTab.icon);
return $svg.dataset.group = settingTab.group, $svg.tabIndex = 0, $svg.addEventListener("click", (e) => {
for (let $child of Array.from(this.$settings.children))
- if ($child.getAttribute("data-tab-group") === settingTab.group)
- $child.classList.remove("bx-gone");
- else
- $child.classList.add("bx-gone");
+ if ($child.getAttribute("data-tab-group") === settingTab.group) $child.classList.remove("bx-gone");
+ else $child.classList.add("bx-gone");
for (let $child of Array.from(this.$tabs.children))
$child.classList.remove("bx-active");
$svg.classList.add("bx-active");
@@ -4858,8 +4589,7 @@ class SettingsNavigationDialog extends NavigationDialog {
const region = STATES.serverRegions[regionName];
let value = regionName, label = `${region.shortName} - ${regionName}`;
if (region.isDefault) {
- if (label += ` (${t("default")})`, value = "default", selectedValue === regionName)
- selectedValue = "default";
+ if (label += ` (${t("default")})`, value = "default", selectedValue === regionName) selectedValue = "default";
}
setting.options[value] = label;
}
@@ -4870,34 +4600,26 @@ class SettingsNavigationDialog extends NavigationDialog {
return $control.disabled = Object.keys(STATES.serverRegions).length === 0, $control.value = selectedValue, $control;
}
renderSettingRow(settingTab, $tabContent, settingTabContent, setting) {
- if (typeof setting === "string")
- setting = {
+ if (typeof setting === "string") setting = {
pref: setting
};
const pref = setting.pref;
let $control;
- if (setting.content)
- if (typeof setting.content === "function")
- $control = setting.content.apply(this);
- else
- $control = setting.content;
+ if (setting.content) if (typeof setting.content === "function") $control = setting.content.apply(this);
+ else $control = setting.content;
else if (!setting.unsupported) {
- if (pref === "server_region")
- $control = this.renderServerSetting(setting);
- else if (pref === "bx_locale")
- $control = SettingElement.fromPref(pref, STORAGE.Global, async (e) => {
+ if (pref === "server_region") $control = this.renderServerSetting(setting);
+ else if (pref === "bx_locale") $control = SettingElement.fromPref(pref, STORAGE.Global, async (e) => {
const newLocale = e.target.value;
if (getPref("ui_controller_friendly")) {
let timeoutId = e.target.timeoutId;
timeoutId && window.clearTimeout(timeoutId), e.target.timeoutId = window.setTimeout(() => {
Translations.refreshLocale(newLocale), Translations.updateTranslations();
}, 500);
- } else
- Translations.refreshLocale(newLocale), Translations.updateTranslations();
+ } else Translations.refreshLocale(newLocale), Translations.updateTranslations();
this.onGlobalSettingChanged(e);
});
- else if (pref === "user_agent_profile")
- $control = SettingElement.fromPref("user_agent_profile", STORAGE.Global, (e) => {
+ else if (pref === "user_agent_profile") $control = SettingElement.fromPref("user_agent_profile", STORAGE.Global, (e) => {
const value = e.target.value;
let isCustom = value === "custom", userAgent2 = UserAgent.get(value);
UserAgent.updateStorage(value);
@@ -4906,28 +4628,21 @@ class SettingsNavigationDialog extends NavigationDialog {
});
else {
let onChange = setting.onChange;
- if (!onChange && settingTab.group === "global")
- onChange = this.onGlobalSettingChanged.bind(this);
+ if (!onChange && settingTab.group === "global") onChange = this.onGlobalSettingChanged.bind(this);
$control = SettingElement.fromPref(pref, STORAGE.Global, onChange, setting.params);
}
- if ($control instanceof HTMLSelectElement && getPref("ui_controller_friendly"))
- $control = BxSelectElement.wrap($control);
+ if ($control instanceof HTMLSelectElement && getPref("ui_controller_friendly")) $control = BxSelectElement.wrap($control);
pref && (this.settingElements[pref] = $control);
}
let prefDefinition = null;
- if (pref)
- prefDefinition = getPrefDefinition(pref);
+ if (pref) prefDefinition = getPrefDefinition(pref);
let label = prefDefinition?.label || setting.label, note = prefDefinition?.note || setting.note;
const experimental = prefDefinition?.experimental || setting.experimental;
if (settingTabContent.label && setting.pref) {
- if (prefDefinition?.suggest)
- typeof prefDefinition.suggest.lowest !== "undefined" && (this.suggestedSettings.lowest[setting.pref] = prefDefinition.suggest.lowest), typeof prefDefinition.suggest.highest !== "undefined" && (this.suggestedSettings.highest[setting.pref] = prefDefinition.suggest.highest);
+ if (prefDefinition?.suggest) typeof prefDefinition.suggest.lowest !== "undefined" && (this.suggestedSettings.lowest[setting.pref] = prefDefinition.suggest.lowest), typeof prefDefinition.suggest.highest !== "undefined" && (this.suggestedSettings.highest[setting.pref] = prefDefinition.suggest.highest);
}
- if (experimental)
- if (label = "🧪 " + label, !note)
- note = t("experimental");
- else
- note = `${t("experimental")}: ${note}`;
+ if (experimental) if (label = "🧪 " + label, !note) note = t("experimental");
+ else note = `${t("experimental")}: ${note}`;
let $label;
const $row = CE("label", {
class: "bx-settings-row",
@@ -4937,8 +4652,7 @@ class SettingsNavigationDialog extends NavigationDialog {
orientation: "horizontal"
}
}, $label = CE("span", { class: "bx-settings-label" }, label, note && CE("div", { class: "bx-settings-dialog-note" }, note), setting.unsupported && CE("div", { class: "bx-settings-dialog-note" }, t("browser-unsupported-feature"))), !setting.unsupported && $control), $link = $label.querySelector("a");
- if ($link)
- $link.classList.add("bx-focusable"), setNearby($label, {
+ if ($link) $link.classList.add("bx-focusable"), setNearby($label, {
focus: $link
});
$tabContent.appendChild($row), setting.onCreated && setting.onCreated(setting, $control);
@@ -4991,14 +4705,11 @@ class SettingsNavigationDialog extends NavigationDialog {
}
}));
this.$container = $container, this.$tabs = $tabs, this.$settings = $settings, $container.addEventListener("click", (e) => {
- if (e.target === $container)
- e.preventDefault(), e.stopPropagation(), this.hide();
+ if (e.target === $container) e.preventDefault(), e.stopPropagation(), this.hide();
});
for (let settingTab of this.SETTINGS_UI) {
- if (!settingTab)
- continue;
- if (settingTab.group !== "global" && !this.renderFullSettings)
- continue;
+ if (!settingTab) continue;
+ if (settingTab.group !== "global" && !this.renderFullSettings) continue;
const $svg = this.renderTab(settingTab);
$tabs.appendChild($svg);
const $tabContent = CE("div", {
@@ -5006,13 +4717,10 @@ class SettingsNavigationDialog extends NavigationDialog {
"data-tab-group": settingTab.group
});
for (let settingTabContent of settingTab.items) {
- if (settingTabContent === !1)
- continue;
- if (!this.renderFullSettings && settingTab.group === "global" && settingTabContent.group !== "general" && settingTabContent.group !== "footer")
- continue;
+ if (settingTabContent === !1) continue;
+ if (!this.renderFullSettings && settingTab.group === "global" && settingTabContent.group !== "general" && settingTabContent.group !== "footer") continue;
let label = settingTabContent.label;
- if (label === t("better-xcloud"))
- label += " " + SCRIPT_VERSION, label = createButton({
+ if (label === t("better-xcloud")) label += " " + SCRIPT_VERSION, label = createButton({
label,
url: "https://github.com/redphx/better-xcloud/releases",
style: 1024 | 8 | 32
@@ -5032,22 +4740,18 @@ class SettingsNavigationDialog extends NavigationDialog {
}
if (settingTabContent.note) {
let $note;
- if (typeof settingTabContent.note === "string")
- $note = CE("b", { class: "bx-note-unsupported" }, settingTabContent.note);
- else
- $note = settingTabContent.note;
+ if (typeof settingTabContent.note === "string") $note = CE("b", { class: "bx-note-unsupported" }, settingTabContent.note);
+ else $note = settingTabContent.note;
$tabContent.appendChild($note);
}
- if (settingTabContent.unsupported)
- continue;
+ if (settingTabContent.unsupported) continue;
if (settingTabContent.content) {
$tabContent.appendChild(settingTabContent.content);
continue;
}
settingTabContent.items = settingTabContent.items || [];
for (let setting of settingTabContent.items) {
- if (setting === !1)
- continue;
+ if (setting === !1) continue;
if (typeof setting === "function") {
setting.apply(this, [$tabContent]);
continue;
@@ -5073,11 +4777,9 @@ class SettingsNavigationDialog extends NavigationDialog {
focusVisibleSetting(type = "first") {
const controls = Array.from(this.$settings.querySelectorAll("div[data-tab-group]:not(.bx-gone) > *"));
if (!controls.length) return !1;
- if (type === "last")
- controls.reverse();
+ if (type === "last") controls.reverse();
for (let $control of controls) {
- if (!($control instanceof HTMLElement))
- continue;
+ if (!($control instanceof HTMLElement)) continue;
const $focusable = this.dialogManager.findFocusableElement($control);
if ($focusable) {
if (this.dialogManager.focus($focusable)) return !0;
@@ -5088,8 +4790,7 @@ class SettingsNavigationDialog extends NavigationDialog {
focusVisibleTab(type = "first") {
const tabs = Array.from(this.$tabs.querySelectorAll("svg:not(.bx-gone)"));
if (!tabs.length) return !1;
- if (type === "last")
- tabs.reverse();
+ if (type === "last") tabs.reverse();
for (let $tab of tabs)
if (this.dialogManager.focus($tab)) return !0;
return !1;
@@ -5099,26 +4800,22 @@ class SettingsNavigationDialog extends NavigationDialog {
if (!$tabContent) return !1;
let $header;
const $focusing = document.activeElement;
- if (!$focusing || !$tabContent.contains($focusing))
- $header = $tabContent.querySelector("h2");
+ if (!$focusing || !$tabContent.contains($focusing)) $header = $tabContent.querySelector("h2");
else {
const $parent = $focusing.closest("[data-tab-group] > *"), siblingProperty = direction === "next" ? "nextSibling" : "previousSibling";
let $tmp = $parent, times = 0;
while (!0) {
- if (!$tmp)
- break;
+ if (!$tmp) break;
if ($tmp.tagName === "H2") {
if ($header = $tmp, !$tmp.nextElementSibling?.classList.contains("bx-note-unsupported")) {
- if (++times, direction === "next" || times >= 2)
- break;
+ if (++times, direction === "next" || times >= 2) break;
}
}
$tmp = $tmp[siblingProperty];
}
}
let $target;
- if ($header)
- $target = this.dialogManager.findNextTarget($header, 3, !1);
+ if ($header) $target = this.dialogManager.findNextTarget($header, 3, !1);
if ($target) return this.dialogManager.focus($target);
return !1;
}
@@ -5221,16 +4918,14 @@ class PointerLockMouseDataProvider extends MouseDataProvider {
vertical: e.deltaY,
horizontal: e.deltaX
};
- if (this.mkbHandler.handleMouseWheel(data))
- e.preventDefault();
+ if (this.mkbHandler.handleMouseWheel(data)) e.preventDefault();
};
#disableContextMenu = (e) => e.preventDefault();
}
class EmulatedMkbHandler extends MkbHandler {
static #instance;
static getInstance() {
- if (!EmulatedMkbHandler.#instance)
- EmulatedMkbHandler.#instance = new EmulatedMkbHandler;
+ if (!EmulatedMkbHandler.#instance) EmulatedMkbHandler.#instance = new EmulatedMkbHandler;
return EmulatedMkbHandler.#instance;
}
#CURRENT_PRESET_DATA = MkbPreset.convert(MkbPreset.DEFAULT_PRESET);
@@ -5300,34 +4995,26 @@ class EmulatedMkbHandler extends MkbHandler {
let [valueArr, axisIndex] = this.#STICK_MAP[buttonIndex];
valueArr = valueArr, axisIndex = axisIndex;
for (let i = valueArr.length - 1;i >= 0; i--)
- if (valueArr[i] === buttonIndex)
- valueArr.splice(i, 1);
+ if (valueArr[i] === buttonIndex) valueArr.splice(i, 1);
pressed && valueArr.push(buttonIndex);
let value;
- if (valueArr.length)
- value = this.#STICK_MAP[valueArr[valueArr.length - 1]][2];
- else
- value = 0;
+ if (valueArr.length) value = this.#STICK_MAP[valueArr[valueArr.length - 1]][2];
+ else value = 0;
virtualGamepad.axes[axisIndex] = value;
- } else
- virtualGamepad.buttons[buttonIndex].pressed = pressed, virtualGamepad.buttons[buttonIndex].value = pressed ? 1 : 0;
+ } else virtualGamepad.buttons[buttonIndex].pressed = pressed, virtualGamepad.buttons[buttonIndex].value = pressed ? 1 : 0;
virtualGamepad.timestamp = performance.now();
};
#onKeyboardEvent = (e) => {
const isKeyDown = e.type === "keydown";
if (e.code === "F8") {
- if (!isKeyDown)
- e.preventDefault(), this.toggle();
+ if (!isKeyDown) e.preventDefault(), this.toggle();
return;
}
if (e.code === "Escape") {
if (e.preventDefault(), this.#enabled && isKeyDown) {
- if (this.#escKeyDownTime === -1)
- this.#escKeyDownTime = performance.now();
- else if (performance.now() - this.#escKeyDownTime >= 1000)
- this.stop();
- } else
- this.#escKeyDownTime = -1;
+ if (this.#escKeyDownTime === -1) this.#escKeyDownTime = performance.now();
+ else if (performance.now() - this.#escKeyDownTime >= 1000) this.stop();
+ } else this.#escKeyDownTime = -1;
return;
}
if (!this.#isPolling) return;
@@ -5343,10 +5030,8 @@ class EmulatedMkbHandler extends MkbHandler {
};
handleMouseClick = (data) => {
let mouseButton;
- if (typeof data.mouseButton !== "undefined")
- mouseButton = data.mouseButton;
- else if (typeof data.pointerButton !== "undefined")
- mouseButton = PointerToMouseButton[data.pointerButton];
+ if (typeof data.mouseButton !== "undefined") mouseButton = data.mouseButton;
+ else if (typeof data.pointerButton !== "undefined") mouseButton = PointerToMouseButton[data.pointerButton];
const keyCode = "Mouse" + mouseButton, key = {
code: keyCode,
name: KeyHelper.codeToKeyName(keyCode)
@@ -5362,44 +5047,33 @@ class EmulatedMkbHandler extends MkbHandler {
this.#detectMouseStoppedTimeout && clearTimeout(this.#detectMouseStoppedTimeout), this.#detectMouseStoppedTimeout = window.setTimeout(this.#onMouseStopped.bind(this), 50);
const deadzoneCounterweight = this.#CURRENT_PRESET_DATA.mouse["deadzone_counterweight"];
let x = data.movementX * this.#CURRENT_PRESET_DATA.mouse["sensitivity_x"], y = data.movementY * this.#CURRENT_PRESET_DATA.mouse["sensitivity_y"], length = this.#vectorLength(x, y);
- if (length !== 0 && length < deadzoneCounterweight)
- x *= deadzoneCounterweight / length, y *= deadzoneCounterweight / length;
- else if (length > EmulatedMkbHandler.MAXIMUM_STICK_RANGE)
- x *= EmulatedMkbHandler.MAXIMUM_STICK_RANGE / length, y *= EmulatedMkbHandler.MAXIMUM_STICK_RANGE / length;
+ if (length !== 0 && length < deadzoneCounterweight) x *= deadzoneCounterweight / length, y *= deadzoneCounterweight / length;
+ else if (length > EmulatedMkbHandler.MAXIMUM_STICK_RANGE) x *= EmulatedMkbHandler.MAXIMUM_STICK_RANGE / length, y *= EmulatedMkbHandler.MAXIMUM_STICK_RANGE / length;
const analog = mouseMapTo === 1 ? 0 : 1;
this.#updateStick(analog, x, y);
};
handleMouseWheel = (data) => {
let code = "";
- if (data.vertical < 0)
- code = "ScrollUp";
- else if (data.vertical > 0)
- code = "ScrollDown";
- else if (data.horizontal < 0)
- code = "ScrollLeft";
- else if (data.horizontal > 0)
- code = "ScrollRight";
+ if (data.vertical < 0) code = "ScrollUp";
+ else if (data.vertical > 0) code = "ScrollDown";
+ else if (data.horizontal < 0) code = "ScrollLeft";
+ else if (data.horizontal > 0) code = "ScrollRight";
if (!code) return !1;
const key = {
code,
name: KeyHelper.codeToKeyName(code)
}, buttonIndex = this.#CURRENT_PRESET_DATA.mapping[key.code];
if (typeof buttonIndex === "undefined") return !1;
- if (this.#prevWheelCode === null || this.#prevWheelCode === key.code)
- this.#wheelStoppedTimeout && clearTimeout(this.#wheelStoppedTimeout), this.#pressButton(buttonIndex, !0);
+ if (this.#prevWheelCode === null || this.#prevWheelCode === key.code) this.#wheelStoppedTimeout && clearTimeout(this.#wheelStoppedTimeout), this.#pressButton(buttonIndex, !0);
return this.#wheelStoppedTimeout = window.setTimeout(() => {
this.#prevWheelCode = null, this.#pressButton(buttonIndex, !1);
}, 20), !0;
};
toggle = (force) => {
- if (typeof force !== "undefined")
- this.#enabled = force;
- else
- this.#enabled = !this.#enabled;
- if (this.#enabled)
- document.body.requestPointerLock();
- else
- document.pointerLockElement && document.exitPointerLock();
+ if (typeof force !== "undefined") this.#enabled = force;
+ else this.#enabled = !this.#enabled;
+ if (this.#enabled) document.body.requestPointerLock();
+ else document.pointerLockElement && document.exitPointerLock();
};
#getCurrentPreset = () => {
return new Promise((resolve) => {
@@ -5419,17 +5093,14 @@ class EmulatedMkbHandler extends MkbHandler {
};
#onPollingModeChanged = (e) => {
if (!this.#$message) return;
- if (e.mode === "none")
- this.#$message.classList.remove("bx-offscreen");
- else
- this.#$message.classList.add("bx-offscreen");
+ if (e.mode === "none") this.#$message.classList.remove("bx-offscreen");
+ else this.#$message.classList.add("bx-offscreen");
};
#onDialogShown = () => {
document.pointerLockElement && document.exitPointerLock();
};
#initMessage = () => {
- if (!this.#$message)
- this.#$message = CE("div", { class: "bx-mkb-pointer-lock-msg bx-gone" }, CE("div", {}, CE("p", {}, t("virtual-controller")), CE("p", {}, t("press-key-to-toggle-mkb", { key: "F8" }))), CE("div", { "data-type": "virtual" }, createButton({
+ if (!this.#$message) this.#$message = CE("div", { class: "bx-mkb-pointer-lock-msg bx-gone" }, CE("div", {}, CE("p", {}, t("virtual-controller")), CE("p", {}, t("press-key-to-toggle-mkb", { key: "F8" }))), CE("div", { "data-type": "virtual" }, createButton({
style: 1 | 256 | 64,
label: t("activate"),
onClick: ((e) => {
@@ -5449,14 +5120,11 @@ class EmulatedMkbHandler extends MkbHandler {
dialog.focusTab("mkb"), NavigationDialogManager.getInstance().show(dialog);
}
}))));
- if (!this.#$message.isConnected)
- document.documentElement.appendChild(this.#$message);
+ if (!this.#$message.isConnected) document.documentElement.appendChild(this.#$message);
};
#onPointerLockChange = () => {
- if (document.pointerLockElement)
- this.start();
- else
- this.stop();
+ if (document.pointerLockElement) this.start();
+ else this.stop();
};
#onPointerLockError = (e) => {
console.log(e), this.stop();
@@ -5478,29 +5146,20 @@ class EmulatedMkbHandler extends MkbHandler {
}
}
init = () => {
- if (this.refreshPresetData(), this.#enabled = !1, AppInterface)
- this.#mouseDataProvider = new WebSocketMouseDataProvider(this);
- else
- this.#mouseDataProvider = new PointerLockMouseDataProvider(this);
- if (this.#mouseDataProvider.init(), window.addEventListener("keydown", this.#onKeyboardEvent), window.addEventListener("keyup", this.#onKeyboardEvent), window.addEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.#onPollingModeChanged), window.addEventListener(BxEvent.XCLOUD_DIALOG_SHOWN, this.#onDialogShown), AppInterface)
- window.addEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.addEventListener(BxEvent.POINTER_LOCK_EXITED, this);
- else
- document.addEventListener("pointerlockchange", this.#onPointerLockChange), document.addEventListener("pointerlockerror", this.#onPointerLockError);
- if (this.#initMessage(), this.#$message?.classList.add("bx-gone"), AppInterface)
- Toast.show(t("press-key-to-toggle-mkb", { key: "F8" }), t("virtual-controller"), { html: !0 }), this.waitForMouseData(!1);
- else
- this.waitForMouseData(!0);
+ if (this.refreshPresetData(), this.#enabled = !1, AppInterface) this.#mouseDataProvider = new WebSocketMouseDataProvider(this);
+ else this.#mouseDataProvider = new PointerLockMouseDataProvider(this);
+ if (this.#mouseDataProvider.init(), window.addEventListener("keydown", this.#onKeyboardEvent), window.addEventListener("keyup", this.#onKeyboardEvent), window.addEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.#onPollingModeChanged), window.addEventListener(BxEvent.XCLOUD_DIALOG_SHOWN, this.#onDialogShown), AppInterface) window.addEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.addEventListener(BxEvent.POINTER_LOCK_EXITED, this);
+ else document.addEventListener("pointerlockchange", this.#onPointerLockChange), document.addEventListener("pointerlockerror", this.#onPointerLockError);
+ if (this.#initMessage(), this.#$message?.classList.add("bx-gone"), AppInterface) Toast.show(t("press-key-to-toggle-mkb", { key: "F8" }), t("virtual-controller"), { html: !0 }), this.waitForMouseData(!1);
+ else this.waitForMouseData(!0);
};
destroy = () => {
- if (this.#isPolling = !1, this.#enabled = !1, this.stop(), this.waitForMouseData(!1), document.pointerLockElement && document.exitPointerLock(), window.removeEventListener("keydown", this.#onKeyboardEvent), window.removeEventListener("keyup", this.#onKeyboardEvent), AppInterface)
- window.removeEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.removeEventListener(BxEvent.POINTER_LOCK_EXITED, this);
- else
- document.removeEventListener("pointerlockchange", this.#onPointerLockChange), document.removeEventListener("pointerlockerror", this.#onPointerLockError);
+ if (this.#isPolling = !1, this.#enabled = !1, this.stop(), this.waitForMouseData(!1), document.pointerLockElement && document.exitPointerLock(), window.removeEventListener("keydown", this.#onKeyboardEvent), window.removeEventListener("keyup", this.#onKeyboardEvent), AppInterface) window.removeEventListener(BxEvent.POINTER_LOCK_REQUESTED, this), window.removeEventListener(BxEvent.POINTER_LOCK_EXITED, this);
+ else document.removeEventListener("pointerlockchange", this.#onPointerLockChange), document.removeEventListener("pointerlockerror", this.#onPointerLockError);
window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.#onPollingModeChanged), window.removeEventListener(BxEvent.XCLOUD_DIALOG_SHOWN, this.#onDialogShown), this.#mouseDataProvider?.destroy(), window.removeEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, this.#onPollingModeChanged);
};
start = () => {
- if (!this.#enabled)
- this.#enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
+ if (!this.#enabled) this.#enabled = !0, Toast.show(t("virtual-controller"), t("enabled"), { instant: !0 });
this.#isPolling = !0, this.#escKeyDownTime = -1, this.#resetGamepad(), window.navigator.getGamepads = this.#patchedGetGamepads, this.waitForMouseData(!1), this.#mouseDataProvider?.start();
const virtualGamepad = this.#getVirtualGamepad();
virtualGamepad.connected = !0, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepadconnected", {
@@ -5510,8 +5169,7 @@ class EmulatedMkbHandler extends MkbHandler {
stop = () => {
this.#enabled = !1, this.#isPolling = !1, this.#escKeyDownTime = -1;
const virtualGamepad = this.#getVirtualGamepad();
- if (virtualGamepad.connected)
- this.#resetGamepad(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
+ if (virtualGamepad.connected) this.#resetGamepad(), virtualGamepad.connected = !1, virtualGamepad.timestamp = performance.now(), BxEvent.dispatch(window, "gamepaddisconnected", {
gamepad: virtualGamepad
}), window.navigator.getGamepads = this.#nativeGetGamepads;
this.waitForMouseData(!0), this.#mouseDataProvider?.stop();
@@ -5519,10 +5177,8 @@ class EmulatedMkbHandler extends MkbHandler {
static setupEvents() {
window.addEventListener(BxEvent.STREAM_PLAYING, () => {
if (STATES.currentStream.titleInfo?.details.hasMkbSupport) {
- if (AppInterface && getPref("native_mkb_enabled") === "on")
- AppInterface && NativeMkbHandler.getInstance().init();
- } else if (getPref("mkb_enabled") && (AppInterface || !UserAgent.isMobile()))
- BxLogger.info(LOG_TAG4, "Emulate MKB"), EmulatedMkbHandler.getInstance().init();
+ if (AppInterface && getPref("native_mkb_enabled") === "on") AppInterface && NativeMkbHandler.getInstance().init();
+ } else if (getPref("mkb_enabled") && (AppInterface || !UserAgent.isMobile())) BxLogger.info(LOG_TAG4, "Emulate MKB"), EmulatedMkbHandler.getInstance().init();
});
}
}
@@ -5555,8 +5211,7 @@ class ControllerShortcut {
ControllerShortcut.#buttonsCache[index] = [], ControllerShortcut.#buttonsStatus[index] = [];
}
static handle(gamepad) {
- if (!ControllerShortcut.#ACTIONS)
- ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
+ if (!ControllerShortcut.#ACTIONS) ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
const gamepadIndex = gamepad.index, actions = ControllerShortcut.#ACTIONS[gamepad.id];
if (!actions) return !1;
ControllerShortcut.#buttonsCache[gamepadIndex] = ControllerShortcut.#buttonsStatus[gamepadIndex].slice(0), ControllerShortcut.#buttonsStatus[gamepadIndex] = [];
@@ -5564,8 +5219,7 @@ class ControllerShortcut {
let otherButtonPressed = !1;
return gamepad.buttons.forEach((button, index) => {
if (button.pressed && index !== 16) {
- if (otherButtonPressed = !0, pressed[index] = !0, actions[index] && !ControllerShortcut.#buttonsCache[gamepadIndex][index])
- setTimeout(() => ControllerShortcut.#runAction(actions[index]), 0);
+ if (otherButtonPressed = !0, pressed[index] = !0, actions[index] && !ControllerShortcut.#buttonsCache[gamepadIndex][index]) setTimeout(() => ControllerShortcut.#runAction(actions[index]), 0);
}
}), ControllerShortcut.#buttonsStatus[gamepadIndex] = pressed, otherButtonPressed;
}
@@ -5606,10 +5260,8 @@ class ControllerShortcut {
}
static #updateAction(profile, button, action) {
const actions = ControllerShortcut.#ACTIONS;
- if (!(profile in actions))
- actions[profile] = [];
- if (!action)
- action = null;
+ if (!(profile in actions)) actions[profile] = [];
+ if (!action) action = null;
actions[profile][button] = action;
for (let key in ControllerShortcut.#ACTIONS) {
let empty = !0;
@@ -5618,8 +5270,7 @@ class ControllerShortcut {
empty = !1;
break;
}
- if (empty)
- delete ControllerShortcut.#ACTIONS[key];
+ if (empty) delete ControllerShortcut.#ACTIONS[key];
}
window.localStorage.setItem(ControllerShortcut.#STORAGE_KEY, JSON.stringify(ControllerShortcut.#ACTIONS)), console.log(ControllerShortcut.#ACTIONS);
}
@@ -5629,21 +5280,17 @@ class ControllerShortcut {
const gamepads = navigator.getGamepads();
let hasGamepad = !1;
for (let gamepad of gamepads) {
- if (!gamepad || !gamepad.connected)
- continue;
- if (gamepad.id === EmulatedMkbHandler.VIRTUAL_GAMEPAD_ID)
- continue;
+ if (!gamepad || !gamepad.connected) continue;
+ if (gamepad.id === EmulatedMkbHandler.VIRTUAL_GAMEPAD_ID) continue;
hasGamepad = !0;
const $option = CE("option", { value: gamepad.id }, gamepad.id);
$fragment.appendChild($option);
}
- if ($container.dataset.hasGamepad = hasGamepad.toString(), hasGamepad)
- $select.appendChild($fragment), $select.selectedIndex = 0, $select.dispatchEvent(new Event("input"));
+ if ($container.dataset.hasGamepad = hasGamepad.toString(), hasGamepad) $select.appendChild($fragment), $select.selectedIndex = 0, $select.dispatchEvent(new Event("input"));
}
static #switchProfile(profile) {
let actions = ControllerShortcut.#ACTIONS[profile];
- if (!actions)
- actions = [];
+ if (!actions) actions = [];
let button;
for (button in ControllerShortcut.#$selectActions) {
const $select = ControllerShortcut.#$selectActions[button];
@@ -5684,15 +5331,12 @@ class ControllerShortcut {
}, $baseSelect = CE("select", { autocomplete: "off" }, CE("option", { value: "" }, "---"));
for (let groupLabel in actions) {
const items = actions[groupLabel];
- if (!items)
- continue;
+ if (!items) continue;
const $optGroup = CE("optgroup", { label: groupLabel });
for (let action in items) {
let label = items[action];
- if (!label)
- continue;
- if (Array.isArray(label))
- label = label.join(" ❯ ");
+ if (!label) continue;
+ if (Array.isArray(label)) label = label.join(" ❯ ");
const $option = CE("option", { value: action }, label);
$optGroup.appendChild($option);
}
@@ -5739,8 +5383,7 @@ class ControllerShortcut {
$div.appendChild($bxSelect), setNearby($row, {
focus: $bxSelect
});
- } else
- $div.appendChild($select), setNearby($row, {
+ } else $div.appendChild($select), setNearby($row, {
focus: $select
});
$row.appendChild($label), $row.appendChild($div), $remap.appendChild($row);
@@ -5753,10 +5396,8 @@ var BxExposed = {
modifyTitleInfo: (titleInfo) => {
titleInfo = deepClone(titleInfo);
let supportedInputTypes = titleInfo.details.supportedInputTypes;
- if (BX_FLAGS.ForceNativeMkbTitles?.includes(titleInfo.details.productId))
- supportedInputTypes.push("MKB");
- if (getPref("native_mkb_enabled") === "off")
- supportedInputTypes = supportedInputTypes.filter((i) => i !== "MKB");
+ if (BX_FLAGS.ForceNativeMkbTitles?.includes(titleInfo.details.productId)) supportedInputTypes.push("MKB");
+ if (getPref("native_mkb_enabled") === "off") supportedInputTypes = supportedInputTypes.filter((i) => i !== "MKB");
if (titleInfo.details.hasMkbSupport = supportedInputTypes.includes("MKB"), STATES.userAgent.capabilities.touch) {
let touchControllerAvailability = getPref("stream_touch_controller");
if (touchControllerAvailability !== "off" && getPref("stream_touch_controller_auto_off")) {
@@ -5769,20 +5410,16 @@ var BxExposed = {
}
gamepadFound && (touchControllerAvailability = "off");
}
- if (touchControllerAvailability === "off")
- supportedInputTypes = supportedInputTypes.filter((i) => i !== "CustomTouchOverlay" && i !== "GenericTouch"), titleInfo.details.supportedTabs = [];
- if (titleInfo.details.hasNativeTouchSupport = supportedInputTypes.includes("NativeTouch"), titleInfo.details.hasTouchSupport = titleInfo.details.hasNativeTouchSupport || supportedInputTypes.includes("CustomTouchOverlay") || supportedInputTypes.includes("GenericTouch"), !titleInfo.details.hasTouchSupport && touchControllerAvailability === "all")
- titleInfo.details.hasFakeTouchSupport = !0, supportedInputTypes.push("GenericTouch");
+ if (touchControllerAvailability === "off") supportedInputTypes = supportedInputTypes.filter((i) => i !== "CustomTouchOverlay" && i !== "GenericTouch"), titleInfo.details.supportedTabs = [];
+ if (titleInfo.details.hasNativeTouchSupport = supportedInputTypes.includes("NativeTouch"), titleInfo.details.hasTouchSupport = titleInfo.details.hasNativeTouchSupport || supportedInputTypes.includes("CustomTouchOverlay") || supportedInputTypes.includes("GenericTouch"), !titleInfo.details.hasTouchSupport && touchControllerAvailability === "all") titleInfo.details.hasFakeTouchSupport = !0, supportedInputTypes.push("GenericTouch");
}
return titleInfo.details.supportedInputTypes = supportedInputTypes, STATES.currentStream.titleInfo = titleInfo, BxEvent.dispatch(window, BxEvent.TITLE_INFO_READY), titleInfo;
},
setupGainNode: ($media, audioStream) => {
- if ($media instanceof HTMLAudioElement)
- $media.muted = !0, $media.addEventListener("playing", (e) => {
+ if ($media instanceof HTMLAudioElement) $media.muted = !0, $media.addEventListener("playing", (e) => {
$media.muted = !0, $media.pause();
});
- else
- $media.muted = !0, $media.addEventListener("playing", (e) => {
+ else $media.muted = !0, $media.addEventListener("playing", (e) => {
$media.muted = !0;
});
try {
@@ -5830,13 +5467,11 @@ function localRedirect(path) {
window.localRedirect = localRedirect;
function getPreferredServerRegion(shortName = !1) {
let preferredRegion = getPref("server_region");
- if (preferredRegion in STATES.serverRegions)
- if (shortName && STATES.serverRegions[preferredRegion].shortName) return STATES.serverRegions[preferredRegion].shortName;
+ if (preferredRegion in STATES.serverRegions) if (shortName && STATES.serverRegions[preferredRegion].shortName) return STATES.serverRegions[preferredRegion].shortName;
else return preferredRegion;
for (let regionName in STATES.serverRegions) {
const region = STATES.serverRegions[regionName];
- if (!region.isDefault)
- continue;
+ if (!region.isDefault) continue;
if (shortName && region.shortName) return region.shortName;
else return regionName;
}
@@ -5867,14 +5502,12 @@ class HeaderSection {
if (!$parent) return;
const PREF_LATEST_VERSION = getPref("version_latest"), $btnSettings = HeaderSection.#$settingsBtn;
if (isElementVisible(HeaderSection.#$buttonsWrapper)) return;
- if ($btnSettings.querySelector("span").textContent = getPreferredServerRegion(!0) || t("better-xcloud"), !SCRIPT_VERSION.includes("beta") && PREF_LATEST_VERSION && PREF_LATEST_VERSION !== SCRIPT_VERSION)
- $btnSettings.setAttribute("data-update-available", "true");
+ if ($btnSettings.querySelector("span").textContent = getPreferredServerRegion(!0) || t("better-xcloud"), !SCRIPT_VERSION.includes("beta") && PREF_LATEST_VERSION && PREF_LATEST_VERSION !== SCRIPT_VERSION) $btnSettings.setAttribute("data-update-available", "true");
$parent.appendChild(HeaderSection.#$buttonsWrapper);
}
static checkHeader() {
let $target = document.querySelector("#PageContent div[class*=EdgewaterHeader-module__rightSectionSpacing]");
- if (!$target)
- $target = document.querySelector("div[class^=UnsupportedMarketPage-module__buttons]");
+ if (!$target) $target = document.querySelector("div[class^=UnsupportedMarketPage-module__buttons]");
$target && HeaderSection.#injectSettingsButton($target);
}
static showRemotePlayButton() {
@@ -5891,8 +5524,7 @@ class HeaderSection {
class RemotePlayNavigationDialog extends NavigationDialog {
static instance;
static getInstance() {
- if (!RemotePlayNavigationDialog.instance)
- RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog;
+ if (!RemotePlayNavigationDialog.instance) RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog;
return RemotePlayNavigationDialog.instance;
}
STATE_LABELS = {
@@ -5909,8 +5541,7 @@ class RemotePlayNavigationDialog extends NavigationDialog {
setupDialog() {
const $fragment = CE("div", { class: "bx-remote-play-container" }), $settingNote = CE("p", {}), currentResolution = getPref("xhome_resolution");
let $resolutions = CE("select", {}, CE("option", { value: "1080p" }, "1080p"), CE("option", { value: "720p" }, "720p"));
- if (getPref("ui_controller_friendly"))
- $resolutions = BxSelectElement.wrap($resolutions);
+ if (getPref("ui_controller_friendly")) $resolutions = BxSelectElement.wrap($resolutions);
$resolutions.addEventListener("input", (e) => {
const value = e.target.value;
$settingNote.textContent = value === "1080p" ? "✅ " + t("can-stream-xbox-360-games") : "❌ " + t("cant-stream-xbox-360-games"), setPref("xhome_resolution", value);
@@ -5962,8 +5593,7 @@ var LOG_TAG5 = "RemotePlay";
class RemotePlayManager {
static instance;
static getInstance() {
- if (!this.instance)
- this.instance = new RemotePlayManager;
+ if (!this.instance) this.instance = new RemotePlayManager;
return this.instance;
}
isInitialized = !1;
@@ -6002,12 +5632,10 @@ class RemotePlayManager {
} catch (e) {
for (let i = 0;i < localStorage.length; i++) {
const key = localStorage.key(i);
- if (!key.startsWith("Auth.User."))
- continue;
+ if (!key.startsWith("Auth.User.")) continue;
const json = JSON.parse(localStorage.getItem(key));
for (let token of json.tokens) {
- if (!token.relyingParty.includes("gssv.xboxlive.com"))
- continue;
+ if (!token.relyingParty.includes("gssv.xboxlive.com")) continue;
GSSV_TOKEN = token.tokenData.token;
break;
}
@@ -6042,18 +5670,15 @@ class RemotePlayManager {
for (let region of this.regions)
try {
const request = new Request(`${region.baseUri}/v6/servers/home?mr=50`, options), json = await (await fetch(request)).json();
- if (json.results.length === 0)
- continue;
+ if (json.results.length === 0) continue;
this.consoles = json.results, STATES.remotePlay.server = region.baseUri;
break;
} catch (e) {}
- if (!STATES.remotePlay.server)
- this.consoles = [];
+ if (!STATES.remotePlay.server) this.consoles = [];
callback();
}
play(serverId, resolution) {
- if (resolution)
- setPref("xhome_resolution", resolution);
+ if (resolution) setPref("xhome_resolution", resolution);
STATES.remotePlay.config = {
serverId
}, window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config, localRedirect("/launch/fortnite/BT5P2X999VH2#remote-play");
@@ -6075,10 +5700,8 @@ class RemotePlayManager {
}
static detect() {
if (!getPref("xhome_enabled")) return;
- if (STATES.remotePlay.isPlaying = window.location.pathname.includes("/launch/") && window.location.hash.startsWith("#remote-play"), STATES.remotePlay?.isPlaying)
- window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config, window.history.replaceState({ origin: "better-xcloud" }, "", "https://www.xbox.com/" + location.pathname.substring(1, 6) + "/play");
- else
- window.BX_REMOTE_PLAY_CONFIG = null;
+ if (STATES.remotePlay.isPlaying = window.location.pathname.includes("/launch/") && window.location.hash.startsWith("#remote-play"), STATES.remotePlay?.isPlaying) window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config, window.history.replaceState({ origin: "better-xcloud" }, "", "https://www.xbox.com/" + location.pathname.substring(1, 6) + "/play");
+ else window.BX_REMOTE_PLAY_CONFIG = null;
}
isReady() {
return this.consoles !== null;
@@ -6146,12 +5769,9 @@ class XhomeInterceptor {
const ports = new Set;
return port && ports.add(port), ports.add(9002), Array.from(ports);
}, serverDetails = obj.serverDetails;
- if (serverDetails.ipAddress)
- XhomeInterceptor.#consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
- if (serverDetails.ipV4Address)
- XhomeInterceptor.#consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
- if (serverDetails.ipV6Address)
- XhomeInterceptor.#consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
+ if (serverDetails.ipAddress) XhomeInterceptor.#consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
+ if (serverDetails.ipV4Address) XhomeInterceptor.#consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
+ if (serverDetails.ipV6Address) XhomeInterceptor.#consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
}
static async#handleInputConfigs(request, opts) {
@@ -6165,12 +5785,10 @@ class XhomeInterceptor {
const supportedInputTypes = inputConfigs.supportedInputTypes;
hasTouchSupport = supportedInputTypes.includes("NativeTouch") || supportedInputTypes.includes("CustomTouchOverlay");
}
- if (hasTouchSupport)
- TouchController.disable(), BxEvent.dispatch(window, BxEvent.CUSTOM_TOUCH_LAYOUTS_LOADED, {
+ if (hasTouchSupport) TouchController.disable(), BxEvent.dispatch(window, BxEvent.CUSTOM_TOUCH_LAYOUTS_LOADED, {
data: null
});
- else
- TouchController.enable(), TouchController.requestCustomLayouts(xboxTitleId);
+ else TouchController.enable(), TouchController.requestCustomLayouts(xboxTitleId);
return response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
}
static async#handleTitles(request) {
@@ -6198,15 +5816,13 @@ class XhomeInterceptor {
headers[pair[0]] = pair[1];
headers.authorization = `Bearer ${RemotePlayManager.getInstance().xhomeToken}`;
const deviceInfo = XhomeInterceptor.BASE_DEVICE_INFO;
- if (getPref("xhome_resolution") === "720p")
- deviceInfo.dev.os.name = "android";
+ if (getPref("xhome_resolution") === "720p") deviceInfo.dev.os.name = "android";
headers["x-ms-device-info"] = JSON.stringify(deviceInfo);
const opts = {
method: clone.method,
headers
};
- if (clone.method === "POST")
- opts.body = await clone.text();
+ if (clone.method === "POST") opts.body = await clone.text();
let newUrl = request.url;
if (!newUrl.includes("/servers/home")) {
const index = request.url.indexOf(".xboxlive.com");
@@ -6239,27 +5855,22 @@ class LoadingScreen {
const $bgStyle = CE("style");
document.documentElement.appendChild($bgStyle), LoadingScreen.#$bgStyle = $bgStyle;
}
- if (LoadingScreen.#setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide")
- LoadingScreen.#hideRocket();
+ if (LoadingScreen.#setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide") LoadingScreen.#hideRocket();
}
static #hideRocket() {
let $bgStyle = LoadingScreen.#$bgStyle;
- const css = "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
$bgStyle.textContent += "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
}
static #setBackground(imageUrl) {
let $bgStyle = LoadingScreen.#$bgStyle;
- imageUrl = imageUrl + "?w=1920";
- const css = '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
- $bgStyle.textContent += css;
+ imageUrl = imageUrl + "?w=1920", $bgStyle.textContent += '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
const bg = new Image;
bg.onload = (e) => {
$bgStyle.textContent += '#game-stream rect[width="800"]{opacity:0 !important}';
}, bg.src = imageUrl;
}
static setupWaitTime(waitTime) {
- if (getPref("ui_loading_screen_rocket") === "hide-queue")
- LoadingScreen.#hideRocket();
+ if (getPref("ui_loading_screen_rocket") === "hide-queue") LoadingScreen.#hideRocket();
let secondsLeft = waitTime, $countDown, $estimated;
LoadingScreen.#orgWebTitle = document.title;
const endDate = new Date, timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
@@ -6267,13 +5878,10 @@ class LoadingScreen {
let endDateStr = endDate.toISOString().slice(0, 19);
endDateStr = endDateStr.substring(0, 10) + " " + endDateStr.substring(11, 19), endDateStr += ` (${LoadingScreen.#secondsToString(waitTime)})`;
let $waitTimeBox = LoadingScreen.#$waitTimeBox;
- if (!$waitTimeBox)
- $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.#$waitTimeBox = $waitTimeBox;
- else
- $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
+ if (!$waitTimeBox) $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.#$waitTimeBox = $waitTimeBox;
+ else $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
$estimated.textContent = endDateStr, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, LoadingScreen.#waitTimeInterval = window.setInterval(() => {
- if (secondsLeft--, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, secondsLeft <= 0)
- LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
+ if (secondsLeft--, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, secondsLeft <= 0) LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
}, 1000);
}
static hide() {
@@ -6301,8 +5909,7 @@ var StreamBadgeIcon = {
class StreamBadges {
static instance;
static getInstance() {
- if (!StreamBadges.instance)
- StreamBadges.instance = new StreamBadges;
+ if (!StreamBadges.instance) StreamBadges.instance = new StreamBadges;
return StreamBadges.instance;
}
#ipv6 = !1;
@@ -6322,8 +5929,7 @@ class StreamBadges {
#renderBadge(name, value, color) {
let $badge;
if (this.#cachedDoms[name]) return $badge = this.#cachedDoms[name], $badge.lastElementChild.textContent = value, $badge;
- if ($badge = CE("div", { class: "bx-badge", title: t(`badge-${name}`) }, CE("span", { class: "bx-badge-name" }, createSvgIcon(StreamBadgeIcon[name])), CE("span", { class: "bx-badge-value", style: `background-color: ${color}` }, value)), name === "battery")
- $badge.classList.add("bx-badge-battery");
+ if ($badge = CE("div", { class: "bx-badge", title: t(`badge-${name}`) }, CE("span", { class: "bx-badge-name" }, createSvgIcon(StreamBadgeIcon[name])), CE("span", { class: "bx-badge-value", style: `background-color: ${color}` }, value)), name === "battery") $badge.classList.add("bx-badge-battery");
return this.#cachedDoms[name] = $badge, $badge;
}
async#updateBadges(forceUpdate = !1) {
@@ -6334,8 +5940,7 @@ class StreamBadges {
let now = +new Date;
const diffSeconds = Math.ceil((now - this.startTimestamp) / 1000), playtime = this.#secondsToHm(diffSeconds);
let batteryLevel = "100%", batteryLevelInt = 100, isCharging = !1;
- if (STATES.browser.capabilities.batteryApi)
- try {
+ if (STATES.browser.capabilities.batteryApi) try {
const bm = await navigator.getBattery();
if (isCharging = bm.charging, batteryLevelInt = Math.round(bm.level * 100), batteryLevel = `${batteryLevelInt}%`, batteryLevelInt != this.startBatteryLevel) {
const diffLevel = Math.round(batteryLevelInt - this.startBatteryLevel), sign = diffLevel > 0 ? "+" : "";
@@ -6345,8 +5950,7 @@ class StreamBadges {
const stats = await STATES.currentStream.peerConnection?.getStats();
let totalIn = 0, totalOut = 0;
stats.forEach((stat) => {
- if (stat.type === "candidate-pair" && stat.packetsReceived > 0 && stat.state === "succeeded")
- totalIn += stat.bytesReceived, totalOut += stat.bytesSent;
+ if (stat.type === "candidate-pair" && stat.packetsReceived > 0 && stat.state === "succeeded") totalIn += stat.bytesReceived, totalOut += stat.bytesSent;
});
const badges = {
in: totalIn ? this.#humanFileSize(totalIn) : null,
@@ -6357,14 +5961,10 @@ class StreamBadges {
let name;
for (name in badges) {
const value = badges[name];
- if (value === null)
- continue;
+ if (value === null) continue;
const $elm = this.#cachedDoms[name];
- if ($elm && ($elm.lastElementChild.textContent = value), name === "battery")
- if (this.startBatteryLevel === 100 && batteryLevelInt === 100)
- $elm.classList.add("bx-gone");
- else
- $elm.dataset.charging = isCharging.toString(), $elm.classList.remove("bx-gone");
+ if ($elm && ($elm.lastElementChild.textContent = value), name === "battery") if (this.startBatteryLevel === 100 && batteryLevelInt === 100) $elm.classList.add("bx-gone");
+ else $elm.dataset.charging = isCharging.toString(), $elm.classList.remove("bx-gone");
}
}
async#start() {
@@ -6375,8 +5975,7 @@ class StreamBadges {
}
#secondsToHm(seconds) {
let h = Math.floor(seconds / 3600), m = Math.floor(seconds % 3600 / 60) + 1;
- if (m === 60)
- h += 1, m = 0;
+ if (m === 60) h += 1, m = 0;
const output = [];
return h > 0 && output.push(`${h}h`), m > 0 && output.push(`${m}m`), output.join(" ");
}
@@ -6388,18 +5987,14 @@ class StreamBadges {
if (this.#$container) return this.#start(), this.#$container;
await this.#getServerStats();
let video = "";
- if (this.#resolution)
- video = `${this.#resolution.height}p`;
+ if (this.#resolution) video = `${this.#resolution.height}p`;
if (this.#video) {
if (video && (video += "/"), video += this.#video.codec, this.#video.profile) {
const profile = this.#video.profile;
let quality = profile;
- if (profile.startsWith("4d"))
- quality = t("visual-quality-high");
- else if (profile.startsWith("42e"))
- quality = t("visual-quality-normal");
- else if (profile.startsWith("420"))
- quality = t("visual-quality-low");
+ if (profile.startsWith("4d")) quality = t("visual-quality-high");
+ else if (profile.startsWith("42e")) quality = t("visual-quality-normal");
+ else if (profile.startsWith("420")) quality = t("visual-quality-low");
video += ` (${quality})`;
}
}
@@ -6410,8 +6005,7 @@ class StreamBadges {
audio += ` (${bitrate} kHz)`;
}
let batteryLevel = "";
- if (STATES.browser.capabilities.batteryApi)
- batteryLevel = "100%";
+ if (STATES.browser.capabilities.batteryApi) batteryLevel = "100%";
let server = this.#region;
server += "@" + (this.#ipv6 ? "IPv6" : "IPv4");
const BADGES = [
@@ -6439,19 +6033,13 @@ class StreamBadges {
if (stats.forEach((stat) => {
if (stat.type === "codec") {
const mimeType = stat.mimeType.split("/")[0];
- if (mimeType === "video")
- allVideoCodecs[stat.id] = stat;
- else if (mimeType === "audio")
- allAudioCodecs[stat.id] = stat;
+ if (mimeType === "video") allVideoCodecs[stat.id] = stat;
+ else if (mimeType === "audio") allAudioCodecs[stat.id] = stat;
} else if (stat.type === "inbound-rtp" && stat.packetsReceived > 0) {
- if (stat.kind === "video")
- videoCodecId = stat.codecId;
- else if (stat.kind === "audio")
- audioCodecId = stat.codecId;
- } else if (stat.type === "candidate-pair" && stat.packetsReceived > 0 && stat.state === "succeeded")
- candidateId = stat.remoteCandidateId;
- else if (stat.type === "remote-candidate")
- allCandidates[stat.id] = stat.address;
+ if (stat.kind === "video") videoCodecId = stat.codecId;
+ else if (stat.kind === "audio") audioCodecId = stat.codecId;
+ } else if (stat.type === "candidate-pair" && stat.packetsReceived > 0 && stat.state === "succeeded") candidateId = stat.remoteCandidateId;
+ else if (stat.type === "remote-candidate") allCandidates[stat.id] = stat.address;
}), videoCodecId) {
const videoStat = allVideoCodecs[videoCodecId], video = {
codec: videoStat.mimeType.substring(6)
@@ -6469,8 +6057,7 @@ class StreamBadges {
bitrate: audioStat.clockRate
};
}
- if (candidateId)
- BxLogger.info("candidate", candidateId, allCandidates), this.#ipv6 = allCandidates[candidateId].includes(":");
+ if (candidateId) BxLogger.info("candidate", candidateId, allCandidates), this.#ipv6 = allCandidates[candidateId].includes(":");
}
static setupEvents() {
window.addEventListener(BxEvent.STREAM_PLAYING, (e) => {
@@ -6517,12 +6104,10 @@ class XcloudInterceptor {
for (let region of obj.offeringSettings.regions) {
const regionName = region.name;
let shortName = region.name;
- if (region.isDefault)
- STATES.selectedRegion = Object.assign({}, region);
+ if (region.isDefault) STATES.selectedRegion = Object.assign({}, region);
let match = serverRegex.exec(region.baseUri);
if (match) {
- if (shortName = match[1], serverEmojis[regionName])
- shortName = serverEmojis[regionName] + " " + shortName;
+ if (shortName = match[1], serverEmojis[regionName]) shortName = serverEmojis[regionName] + " " + shortName;
}
region.shortName = shortName.toUpperCase(), STATES.serverRegions[region.name] = Object.assign({}, region);
}
@@ -6550,8 +6135,7 @@ class XcloudInterceptor {
const osName = PREF_STREAM_TARGET_RESOLUTION === "720p" ? "android" : "windows";
body.settings.osName = osName;
}
- if (PREF_STREAM_PREFERRED_LOCALE !== "default")
- body.settings.locale = PREF_STREAM_PREFERRED_LOCALE;
+ if (PREF_STREAM_PREFERRED_LOCALE !== "default") body.settings.locale = PREF_STREAM_PREFERRED_LOCALE;
const newRequest = new Request(request, {
body: JSON.stringify(body)
});
@@ -6561,37 +6145,28 @@ class XcloudInterceptor {
const response = await NATIVE_FETCH(request, init);
if (getPref("ui_loading_screen_wait_time")) {
const json = await response.clone().json();
- if (json.estimatedAllocationTimeInSeconds > 0)
- LoadingScreen.setupWaitTime(json.estimatedTotalWaitTimeInSeconds);
+ if (json.estimatedAllocationTimeInSeconds > 0) LoadingScreen.setupWaitTime(json.estimatedTotalWaitTimeInSeconds);
}
return response;
}
static async#handleConfiguration(request, init) {
if (request.method !== "GET") return NATIVE_FETCH(request, init);
- if (getPref("stream_touch_controller") === "all")
- if (STATES.currentStream.titleInfo?.details.hasTouchSupport)
- TouchController.disable();
- else
- TouchController.enable();
+ if (getPref("stream_touch_controller") === "all") if (STATES.currentStream.titleInfo?.details.hasTouchSupport) TouchController.disable();
+ else TouchController.enable();
const response = await NATIVE_FETCH(request, init), text = await response.clone().text();
if (!text.length) return response;
const obj = JSON.parse(text);
let overrides = JSON.parse(obj.clientStreamingConfigOverrides || "{}") || {};
overrides.inputConfiguration = overrides.inputConfiguration || {}, overrides.inputConfiguration.enableVibration = !0;
let overrideMkb = null;
- if (getPref("native_mkb_enabled") === "on" || STATES.currentStream.titleInfo && BX_FLAGS.ForceNativeMkbTitles?.includes(STATES.currentStream.titleInfo.details.productId))
- overrideMkb = !0;
- if (getPref("native_mkb_enabled") === "off")
- overrideMkb = !1;
- if (overrideMkb !== null)
- overrides.inputConfiguration = Object.assign(overrides.inputConfiguration, {
+ if (getPref("native_mkb_enabled") === "on" || STATES.currentStream.titleInfo && BX_FLAGS.ForceNativeMkbTitles?.includes(STATES.currentStream.titleInfo.details.productId)) overrideMkb = !0;
+ if (getPref("native_mkb_enabled") === "off") overrideMkb = !1;
+ if (overrideMkb !== null) overrides.inputConfiguration = Object.assign(overrides.inputConfiguration, {
enableMouseInput: overrideMkb,
enableKeyboardInput: overrideMkb
});
- if (TouchController.isEnabled())
- overrides.inputConfiguration.enableTouchInput = !0, overrides.inputConfiguration.maxTouchPoints = 10;
- if (getPref("audio_mic_on_playing"))
- overrides.audioConfiguration = overrides.audioConfiguration || {}, overrides.audioConfiguration.enableMicrophone = !0;
+ if (TouchController.isEnabled()) overrides.inputConfiguration.enableTouchInput = !0, overrides.inputConfiguration.maxTouchPoints = 10;
+ if (getPref("audio_mic_on_playing")) overrides.audioConfiguration = overrides.audioConfiguration || {}, overrides.audioConfiguration.enableMicrophone = !0;
return obj.clientStreamingConfigOverrides = JSON.stringify(overrides), response.json = () => Promise.resolve(obj), response.text = () => Promise.resolve(JSON.stringify(obj)), response;
}
static async handle(request, init) {
@@ -6625,13 +6200,11 @@ function clearAllLogs() {
function updateIceCandidates(candidates, options) {
const pattern = new RegExp(/a=candidate:(?\d+) (?\d+) UDP (?\d+) (?[^\s]+) (?\d+) (?.*)/), lst = [];
for (let item2 of candidates) {
- if (item2.candidate == "a=end-of-candidates")
- continue;
+ if (item2.candidate == "a=end-of-candidates") continue;
const groups = pattern.exec(item2.candidate).groups;
lst.push(groups);
}
- if (options.preferIpv6Server)
- lst.sort((a, b) => {
+ if (options.preferIpv6Server) lst.sort((a, b) => {
const firstIp = a.ip, secondIp = b.ip;
return !firstIp.includes(":") && secondIp.includes(":") ? 1 : -1;
});
@@ -6665,15 +6238,13 @@ async function patchIceCandidates(request, consoleAddrs) {
}
function interceptHttpRequests() {
let BLOCKED_URLS = [];
- if (getPref("block_tracking"))
- clearAllLogs(), BLOCKED_URLS = BLOCKED_URLS.concat([
+ if (getPref("block_tracking")) clearAllLogs(), BLOCKED_URLS = BLOCKED_URLS.concat([
"https://arc.msn.com",
"https://browser.events.data.microsoft.com",
"https://dc.services.visualstudio.com",
"https://2c06dea3f26c40c69b8456d319791fd0@o427368.ingest.sentry.io"
]);
- if (getPref("block_social_features"))
- BLOCKED_URLS = BLOCKED_URLS.concat([
+ if (getPref("block_social_features")) BLOCKED_URLS = BLOCKED_URLS.concat([
"https://peoplehub.xboxlive.com/users/me/people/social",
"https://peoplehub.xboxlive.com/users/me/people/recommendations",
"https://xblmessaging.xboxlive.com/network/xbox/users/me/inbox"
@@ -6684,8 +6255,7 @@ function interceptHttpRequests() {
}, xhrPrototype.send = function(...arg) {
for (let blocked of BLOCKED_URLS)
if (this._url.startsWith(blocked)) {
- if (blocked === "https://dc.services.visualstudio.com")
- window.setTimeout(clearAllLogs, 1000);
+ if (blocked === "https://dc.services.visualstudio.com") window.setTimeout(clearAllLogs, 1000);
return !1;
}
return nativeXhrSend.apply(this, arguments);
@@ -6694,22 +6264,17 @@ function interceptHttpRequests() {
window.BX_FETCH = window.fetch = async (request, init) => {
let url = typeof request === "string" ? request : request.url;
for (let blocked of BLOCKED_URLS) {
- if (!url.startsWith(blocked))
- continue;
+ if (!url.startsWith(blocked)) continue;
return new Response('{"acc":1,"webResult":{}}', {
status: 200,
statusText: "200 OK"
});
}
- if (url.endsWith("/play"))
- BxEvent.dispatch(window, BxEvent.STREAM_LOADING);
- if (url.endsWith("/configuration"))
- BxEvent.dispatch(window, BxEvent.STREAM_STARTING);
- if (url.startsWith("https://emerald.xboxservices.com/xboxcomfd/experimentation"))
- try {
+ if (url.endsWith("/play")) BxEvent.dispatch(window, BxEvent.STREAM_LOADING);
+ if (url.endsWith("/configuration")) BxEvent.dispatch(window, BxEvent.STREAM_STARTING);
+ if (url.startsWith("https://emerald.xboxservices.com/xboxcomfd/experimentation")) try {
const response = await NATIVE_FETCH(request, init), json = await response.json();
- if (json && json.exp && json.exp.treatments)
- for (let key in FeatureGates)
+ if (json && json.exp && json.exp.treatments) for (let key in FeatureGates)
json.exp.treatments[key] = FeatureGates[key];
return response.json = () => Promise.resolve(json), response;
} catch (e) {
@@ -6717,11 +6282,9 @@ function interceptHttpRequests() {
}
if (STATES.userAgent.capabilities.touch && url.includes("catalog.gamepass.com/sigls/")) {
const response = await NATIVE_FETCH(request, init), obj = await response.clone().json();
- if (url.includes("29a81209-df6f-41fd-a528-2ae6b91f719c"))
- for (let i = 1;i < obj.length; i++)
+ if (url.includes("29a81209-df6f-41fd-a528-2ae6b91f719c")) for (let i = 1;i < obj.length; i++)
gamepassAllGames.push(obj[i].id);
- else if (url.includes("9c86f07a-f3e8-45ad-82a0-a1f759597059"))
- try {
+ else if (url.includes("9c86f07a-f3e8-45ad-82a0-a1f759597059")) try {
let customList = TouchController.getCustomList();
customList = customList.filter((id2) => gamepassAllGames.includes(id2));
const newCustomList = customList.map((item2) => ({ id: item2 }));
@@ -6742,10 +6305,8 @@ function interceptHttpRequests() {
return response.json = () => Promise.resolve(obj), response;
}
let requestType;
- if (url.includes("/sessions/home") || url.includes("xhome.") || STATES.remotePlay.isPlaying && url.endsWith("/inputconfigs"))
- requestType = "xhome";
- else
- requestType = "xcloud";
+ if (url.includes("/sessions/home") || url.includes("xhome.") || STATES.remotePlay.isPlaying && url.endsWith("/inputconfigs")) requestType = "xhome";
+ else requestType = "xcloud";
if (requestType === "xhome") return XhomeInterceptor.handle(request);
return XcloudInterceptor.handle(request, init);
};
@@ -6754,42 +6315,28 @@ function showGamepadToast(gamepad) {
if (gamepad.id === EmulatedMkbHandler.VIRTUAL_GAMEPAD_ID) return;
BxLogger.info("Gamepad", gamepad);
let text = "🎮";
- if (getPref("local_co_op_enabled"))
- text += ` #${gamepad.index + 1}`;
+ if (getPref("local_co_op_enabled")) text += ` #${gamepad.index + 1}`;
const gamepadId = gamepad.id.replace(/ \(.*?Vendor: \w+ Product: \w+\)$/, "");
text += ` - ${gamepadId}`;
let status;
- if (gamepad.connected)
- status = (gamepad.vibrationActuator ? "✅" : "❌") + " " + t("vibration-status");
- else
- status = t("disconnected");
+ if (gamepad.connected) status = (gamepad.vibrationActuator ? "✅" : "❌") + " " + t("vibration-status");
+ else status = t("disconnected");
Toast.show(text, status, { instant: !1 });
}
function addCss() {
let css = `:root{--bx-title-font:Bahnschrift,Arial,Helvetica,sans-serif;--bx-title-font-semibold:Bahnschrift Semibold,Arial,Helvetica,sans-serif;--bx-normal-font:"Segoe UI",Arial,Helvetica,sans-serif;--bx-monospaced-font:Consolas,"Courier New",Courier,monospace;--bx-promptfont-font:promptfont;--bx-button-height:40px;--bx-default-button-color:#2d3036;--bx-default-button-rgb:45,48,54;--bx-default-button-hover-color:#515863;--bx-default-button-hover-rgb:81,88,99;--bx-default-button-active-color:#222428;--bx-default-button-active-rgb:34,36,40;--bx-default-button-disabled-color:#8e8e8e;--bx-default-button-disabled-rgb:142,142,142;--bx-primary-button-color:#008746;--bx-primary-button-rgb:0,135,70;--bx-primary-button-hover-color:#04b358;--bx-primary-button-hover-rgb:4,179,88;--bx-primary-button-active-color:#044e2a;--bx-primary-button-active-rgb:4,78,42;--bx-primary-button-disabled-color:#448262;--bx-primary-button-disabled-rgb:68,130,98;--bx-danger-button-color:#c10404;--bx-danger-button-rgb:193,4,4;--bx-danger-button-hover-color:#e61d1d;--bx-danger-button-hover-rgb:230,29,29;--bx-danger-button-active-color:#a26c6c;--bx-danger-button-active-rgb:162,108,108;--bx-danger-button-disabled-color:#df5656;--bx-danger-button-disabled-rgb:223,86,86;--bx-fullscreen-text-z-index:99999;--bx-toast-z-index:60000;--bx-dialog-z-index:50000;--bx-dialog-overlay-z-index:40200;--bx-stats-bar-z-index:40100;--bx-mkb-pointer-lock-msg-z-index:40000;--bx-navigation-dialog-z-index:30100;--bx-navigation-dialog-overlay-z-index:30000;--bx-game-bar-z-index:10000;--bx-screenshot-animation-z-index:9000;--bx-wait-time-box-z-index:1000}@font-face{font-family:'promptfont';src:url("https://redphx.github.io/better-xcloud/fonts/promptfont.otf")}div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module__hiddenContainer]){opacity:0;pointer-events:none !important;position:absolute;top:-9999px;left:-9999px}@media screen and (max-width:640px){header a[href="/play"]{display:none}}.bx-full-width{width:100% !important}.bx-full-height{height:100% !important}.bx-no-scroll{overflow:hidden !important}.bx-hide-scroll-bar{scrollbar-width:none}.bx-hide-scroll-bar::-webkit-scrollbar{display:none}.bx-gone{display:none !important}.bx-offscreen{position:absolute !important;top:-9999px !important;left:-9999px !important;visibility:hidden !important}.bx-hidden{visibility:hidden !important}.bx-invisible{opacity:0}.bx-unclickable{pointer-events:none}.bx-pixel{width:1px !important;height:1px !important}.bx-no-margin{margin:0 !important}.bx-no-padding{padding:0 !important}.bx-prompt{font-family:var(--bx-promptfont-font)}.bx-line-through{text-decoration:line-through !important}.bx-normal-case{text-transform:none !important}.bx-normal-link{text-transform:none !important;text-align:left !important;font-weight:400 !important;font-family:var(--bx-normal-font) !important}select[multiple]{overflow:auto}#headerArea,#uhfSkipToMain,.uhf-footer{display:none}div[class*=NotFocusedDialog]{position:absolute !important;top:-9999px !important;left:-9999px !important;width:0 !important;height:0 !important}#game-stream video:not([src]){visibility:hidden}div[class*=SupportedInputsBadge]:not(:has(:nth-child(2))),div[class*=SupportedInputsBadge] svg:first-of-type{display:none}.bx-game-tile-wait-time{position:absolute;top:0;left:0;z-index:1;background:rgba(0,0,0,0.549);display:flex;border-radius:4px 0 4px 0;align-items:center;padding:4px 8px}.bx-game-tile-wait-time svg{width:14px;height:16px;margin-right:2px}.bx-game-tile-wait-time span{display:inline-block;height:16px;line-height:16px;font-size:12px;font-weight:bold;margin-left:2px}.bx-fullscreen-text{position:fixed;top:0;bottom:0;left:0;right:0;background:rgba(0,0,0,0.8);z-index:var(--bx-fullscreen-text-z-index);line-height:100vh;color:#fff;text-align:center;font-weight:400;font-family:var(--bx-normal-font);font-size:1.3rem;user-select:none;-webkit-user-select:none}#root section[class*=DeviceCodePage-module__page]{margin-left:20px !important;margin-right:20px !important;margin-top:20px !important;max-width:800px !important}#root div[class*=DeviceCodePage-module__back]{display:none}.bx-button{--button-rgb:var(--bx-default-button-rgb);--button-hover-rgb:var(--bx-default-button-hover-rgb);--button-active-rgb:var(--bx-default-button-active-rgb);--button-disabled-rgb:var(--bx-default-button-disabled-rgb);background-color:rgb(var(--button-rgb));user-select:none;-webkit-user-select:none;color:#fff;font-family:var(--bx-title-font-semibold);font-size:14px;border:none;font-weight:400;height:var(--bx-button-height);border-radius:4px;padding:0 8px;text-transform:uppercase;cursor:pointer;overflow:hidden}.bx-button:not([disabled]):active{background-color:rgb(var(--button-active-rgb))}.bx-button:focus{outline:none !important}.bx-button:not([disabled]):not(:active):hover,.bx-button:not([disabled]):not(:active).bx-focusable:focus{background-color:rgb(var(--button-hover-rgb))}.bx-button:disabled{cursor:default;background-color:rgb(var(--button-disabled-rgb))}.bx-button.bx-ghost{background-color:transparent}.bx-button.bx-ghost:not([disabled]):not(:active):hover,.bx-button.bx-ghost:not([disabled]):not(:active).bx-focusable:focus{background-color:rgb(var(--button-hover-rgb))}.bx-button.bx-primary{--button-rgb:var(--bx-primary-button-rgb)}.bx-button.bx-primary:not([disabled]):active{--button-active-rgb:var(--bx-primary-button-active-rgb)}.bx-button.bx-primary:not([disabled]):not(:active):hover,.bx-button.bx-primary:not([disabled]):not(:active).bx-focusable:focus{--button-hover-rgb:var(--bx-primary-button-hover-rgb)}.bx-button.bx-primary:disabled{--button-disabled-rgb:var(--bx-primary-button-disabled-rgb)}.bx-button.bx-danger{--button-rgb:var(--bx-danger-button-rgb)}.bx-button.bx-danger:not([disabled]):active{--button-active-rgb:var(--bx-danger-button-active-rgb)}.bx-button.bx-danger:not([disabled]):not(:active):hover,.bx-button.bx-danger:not([disabled]):not(:active).bx-focusable:focus{--button-hover-rgb:var(--bx-danger-button-hover-rgb)}.bx-button.bx-danger:disabled{--button-disabled-rgb:var(--bx-danger-button-disabled-rgb)}.bx-button.bx-frosted{--button-alpha:.2;background-color:rgba(var(--button-rgb), var(--button-alpha));backdrop-filter:blur(4px) brightness(1.5)}.bx-button.bx-frosted:not([disabled]):not(:active):hover,.bx-button.bx-frosted:not([disabled]):not(:active).bx-focusable:focus{background-color:rgba(var(--button-hover-rgb), var(--button-alpha))}.bx-button.bx-drop-shadow{box-shadow:0 0 4px rgba(0,0,0,0.502)}.bx-button.bx-tall{height:calc(var(--bx-button-height) * 1.5) !important}.bx-button.bx-circular{border-radius:var(--bx-button-height);height:var(--bx-button-height)}.bx-button svg{display:inline-block;width:16px;height:var(--bx-button-height)}.bx-button span{display:inline-block;line-height:var(--bx-button-height);vertical-align:middle;color:#fff;overflow:hidden;white-space:nowrap}.bx-button span:not(:only-child){margin-left:10px}.bx-focusable{position:relative;overflow:visible}.bx-focusable::after{border:2px solid transparent;border-radius:10px}.bx-focusable:focus::after{content:'';border-color:#fff;position:absolute;top:-6px;left:-6px;right:-6px;bottom:-6px}html[data-active-input=touch] .bx-focusable:focus::after,html[data-active-input=mouse] .bx-focusable:focus::after{border-color:transparent !important}.bx-focusable.bx-circular::after{border-radius:var(--bx-button-height)}a.bx-button{display:inline-block}a.bx-button.bx-full-width{text-align:center}button.bx-inactive{pointer-events:none;opacity:.2;background:transparent !important}.bx-button-shortcut{max-width:max-content;margin:10px 0 0 0;flex:1 0 auto}@media (min-width:568px) and (max-height:480px){.bx-button-shortcut{margin:8px 0 0 10px}}.bx-header-remote-play-button{height:auto;margin-right:8px !important}.bx-header-remote-play-button svg{width:24px;height:24px}.bx-header-settings-button{line-height:30px;font-size:14px;text-transform:uppercase;position:relative}.bx-header-settings-button[data-update-available]::before{content:'🌟' !important;line-height:var(--bx-button-height);display:inline-block;margin-left:4px}.bx-dialog-overlay{position:fixed;inset:0;z-index:var(--bx-dialog-overlay-z-index);background:#000;opacity:50%}.bx-dialog{display:flex;flex-flow:column;max-height:90vh;position:fixed;top:50%;left:50%;margin-right:-50%;transform:translate(-50%,-50%);min-width:420px;padding:20px;border-radius:8px;z-index:var(--bx-dialog-z-index);background:#1a1b1e;color:#fff;font-weight:400;font-size:16px;font-family:var(--bx-normal-font);box-shadow:0 0 6px #000;user-select:none;-webkit-user-select:none}.bx-dialog *:focus{outline:none !important}.bx-dialog h2{display:flex;margin-bottom:12px}.bx-dialog h2 b{flex:1;color:#fff;display:block;font-family:var(--bx-title-font);font-size:26px;font-weight:400;line-height:var(--bx-button-height)}.bx-dialog.bx-binding-dialog h2 b{font-family:var(--bx-promptfont-font) !important}.bx-dialog > div{overflow:auto;padding:2px 0}.bx-dialog > button{padding:8px 32px;margin:10px auto 0;border:none;border-radius:4px;display:block;background-color:#2d3036;text-align:center;color:#fff;text-transform:uppercase;font-family:var(--bx-title-font);font-weight:400;line-height:18px;font-size:14px}@media (hover:hover){.bx-dialog > button:hover{background-color:#515863}}.bx-dialog > button:focus{background-color:#515863}@media screen and (max-width:450px){.bx-dialog{min-width:100%}}.bx-navigation-dialog{position:absolute;z-index:var(--bx-navigation-dialog-z-index);font-family:var(--bx-title-font)}.bx-navigation-dialog *:focus{outline:none !important}.bx-navigation-dialog-overlay{position:fixed;background:rgba(11,11,11,0.89);top:0;left:0;right:0;bottom:0;z-index:var(--bx-navigation-dialog-overlay-z-index)}.bx-navigation-dialog-overlay[data-is-playing="true"]{background:transparent}.bx-settings-dialog{display:flex;position:fixed;top:0;right:0;bottom:0;opacity:.98;user-select:none;-webkit-user-select:none}.bx-settings-dialog .bx-focusable::after{border-radius:4px}.bx-settings-dialog .bx-focusable:focus::after{top:0;left:0;right:0;bottom:0}.bx-settings-dialog .bx-settings-reload-note{font-size:.8rem;display:block;padding:8px;font-style:italic;font-weight:normal;height:var(--bx-button-height)}.bx-settings-dialog input{accent-color:var(--bx-primary-button-color)}.bx-settings-dialog input:focus{accent-color:var(--bx-danger-button-color)}.bx-settings-dialog select:disabled{-webkit-appearance:none;background:transparent;text-align-last:right;border:none;color:#fff}.bx-settings-dialog select option:disabled{display:none}.bx-settings-dialog input[type=checkbox]:focus,.bx-settings-dialog select:focus{filter:drop-shadow(1px 0 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 1px 0 #fff) drop-shadow(0 -1px 0 #fff)}.bx-settings-dialog a{color:#1c9d1c;text-decoration:none}.bx-settings-dialog a:hover,.bx-settings-dialog a:focus{color:#5dc21e}.bx-settings-tabs-container{position:fixed;width:48px;max-height:100vh;display:flex;flex-direction:column}.bx-settings-tabs-container > div:last-of-type{display:flex;flex-direction:column;align-items:end}.bx-settings-tabs-container > div:last-of-type button{flex-shrink:0;border-top-right-radius:0;border-bottom-right-radius:0;margin-top:8px;height:unset;padding:8px 10px}.bx-settings-tabs-container > div:last-of-type button svg{width:16px;height:16px}.bx-settings-tabs{display:flex;flex-direction:column;border-radius:0 0 0 8px;box-shadow:0 0 6px #000;overflow:overlay;flex:1}.bx-settings-tabs svg{width:24px;height:24px;padding:10px;flex-shrink:0;box-sizing:content-box;background:#131313;cursor:pointer;border-left:4px solid #1e1e1e}.bx-settings-tabs svg.bx-active{background:#222;border-color:#008746}.bx-settings-tabs svg:not(.bx-active):hover{background:#2f2f2f;border-color:#484848}.bx-settings-tabs svg:focus{border-color:#fff}.bx-settings-tabs svg[data-group=global][data-need-refresh=true]{background:var(--bx-danger-button-color) !important}.bx-settings-tabs svg[data-group=global][data-need-refresh=true]:hover{background:var(--bx-danger-button-hover-color) !important}.bx-settings-tab-contents{flex-direction:column;padding:10px;margin-left:48px;width:450px;max-width:calc(100vw - tabsWidth);background:#1a1b1e;color:#fff;font-weight:400;font-size:16px;font-family:var(--bx-title-font);text-align:center;box-shadow:0 0 6px #000;overflow:overlay;z-index:1}.bx-settings-tab-contents > div[data-tab-group=mkb]{display:flex;flex-direction:column;height:100%;overflow:hidden}.bx-settings-tab-contents > div[data-tab-group=shortcuts] > div[data-has-gamepad=true] > div:first-of-type{display:none}.bx-settings-tab-contents > div[data-tab-group=shortcuts] > div[data-has-gamepad=true] > div:last-of-type{display:block}.bx-settings-tab-contents > div[data-tab-group=shortcuts] > div[data-has-gamepad=false] > div:first-of-type{display:block}.bx-settings-tab-contents > div[data-tab-group=shortcuts] > div[data-has-gamepad=false] > div:last-of-type{display:none}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-profile{width:100%;height:36px;display:block}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-note{margin-top:10px;font-size:14px}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-row{display:flex;margin-bottom:10px}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-row label.bx-prompt{flex:1;font-size:26px;margin-bottom:0}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-row .bx-shortcut-actions{flex:2;position:relative}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-row .bx-shortcut-actions select{position:absolute;width:100%;height:100%;display:block}.bx-settings-tab-contents > div[data-tab-group=shortcuts] .bx-shortcut-row .bx-shortcut-actions select:last-of-type{opacity:0;z-index:calc(var(--bx-settings-z-index) + 1)}.bx-settings-tab-contents .bx-top-buttons{display:flex;flex-direction:column;gap:8px;margin-bottom:8px}.bx-settings-tab-contents .bx-top-buttons .bx-button{display:block}.bx-settings-tab-contents h2{margin:16px 0 8px 0;display:flex;align-items:center}.bx-settings-tab-contents h2:first-of-type{margin-top:0}.bx-settings-tab-contents h2 span{display:inline-block;font-size:20px;font-weight:bold;text-align:left;flex:1;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}@media (max-width:500px){.bx-settings-tab-contents{width:calc(100vw - 48px)}}.bx-settings-row{display:flex;gap:10px;padding:16px 10px;margin:0;background:#2a2a2a;border-bottom:1px solid #343434}.bx-settings-row:hover,.bx-settings-row:focus-within{background-color:#242424}.bx-settings-row:not(:has(> input[type=checkbox])){flex-wrap:wrap}.bx-settings-row > span.bx-settings-label{font-size:14px;display:block;text-align:left;align-self:center;margin-bottom:0 !important;flex:1}.bx-settings-row > span.bx-settings-label + *{margin:0 0 0 auto}.bx-settings-dialog-note{display:block;color:#afafb0;font-size:12px;font-weight:lighter;font-style:italic}.bx-settings-dialog-note:not(:has(a)){margin-top:4px}.bx-settings-dialog-note a{display:inline-block;padding:4px}.bx-settings-custom-user-agent{display:block;width:100%;padding:6px}.bx-donation-link{display:block;text-align:center;text-decoration:none;height:20px;line-height:20px;font-size:14px;margin-top:10px}.bx-debug-info button{margin-top:10px}.bx-debug-info pre{margin-top:10px;cursor:copy;color:#fff;padding:8px;border:1px solid #2d2d2d;background:#212121;white-space:break-spaces;text-align:left}.bx-debug-info pre:hover{background:#272727}.bx-settings-app-version{margin-top:10px;text-align:center;color:#747474;font-size:12px}.bx-note-unsupported{display:block;font-size:12px;font-style:italic;font-weight:normal;color:#828282}.bx-settings-tab-contents > div *:not(.bx-settings-row):has(+ .bx-settings-row) + .bx-settings-row:has(+ .bx-settings-row){border-top-left-radius:10px;border-top-right-radius:10px}.bx-settings-tab-contents > div .bx-settings-row:not(:has(+ .bx-settings-row)){border:none;border-bottom-left-radius:10px;border-bottom-right-radius:10px}.bx-settings-tab-contents > div *:not(.bx-settings-row):has(+ .bx-settings-row) + .bx-settings-row:not(:has(+ .bx-settings-row)){border:none;border-radius:10px}.bx-suggest-toggler{text-align:left;display:flex;border-radius:4px;overflow:hidden;background:#003861}.bx-suggest-toggler label{flex:1;margin-bottom:0;padding:10px;background:#004f87}.bx-suggest-toggler span{display:inline-block;align-self:center;padding:10px;width:40px;text-align:center}.bx-suggest-toggler:hover,.bx-suggest-toggler:focus{cursor:pointer;background:#005da1}.bx-suggest-toggler:hover label,.bx-suggest-toggler:focus label{background:#006fbe}.bx-suggest-toggler[bx-open] span{transform:rotate(90deg)}.bx-suggest-toggler[bx-open]+ .bx-suggest-box{display:block}.bx-suggest-box{display:none;background:#161616;padding:10px;box-shadow:0 0 12px #0f0f0f inset;border-radius:10px}.bx-suggest-wrapper{display:flex;flex-direction:column;gap:10px;margin:10px}.bx-suggest-note{font-size:11px;color:#8c8c8c;font-style:italic;font-weight:100}.bx-suggest-link{font-size:14px;display:inline-block;margin-top:4px;padding:4px}.bx-suggest-row{display:flex;flex-direction:row;gap:10px}.bx-suggest-row label{flex:1;overflow:overlay;border-radius:4px}.bx-suggest-row label .bx-suggest-label{background:#323232;padding:4px 10px;font-size:12px;text-align:left}.bx-suggest-row label .bx-suggest-value{padding:6px;font-size:14px}.bx-suggest-row label .bx-suggest-value.bx-suggest-change{background-color:var(--bx-warning-color)}.bx-suggest-row.bx-suggest-ok input{visibility:hidden}.bx-suggest-row.bx-suggest-ok .bx-suggest-label{background-color:#008114}.bx-suggest-row.bx-suggest-ok .bx-suggest-value{background-color:#13a72a}.bx-suggest-row.bx-suggest-change .bx-suggest-label{background-color:#a65e08}.bx-suggest-row.bx-suggest-change .bx-suggest-value{background-color:#d57f18}.bx-suggest-row.bx-suggest-change:hover label{cursor:pointer}.bx-suggest-row.bx-suggest-change:hover .bx-suggest-label{background-color:#995707}.bx-suggest-row.bx-suggest-change:hover .bx-suggest-value{background-color:#bd7115}.bx-suggest-row.bx-suggest-change input:not(:checked) + label{opacity:.5}.bx-suggest-row.bx-suggest-change input:not(:checked) + label .bx-suggest-label{background-color:#2a2a2a}.bx-suggest-row.bx-suggest-change input:not(:checked) + label .bx-suggest-value{background-color:#393939}.bx-suggest-row.bx-suggest-change:hover input:not(:checked) + label{opacity:1}.bx-suggest-row.bx-suggest-change:hover input:not(:checked) + label .bx-suggest-label{background-color:#202020}.bx-suggest-row.bx-suggest-change:hover input:not(:checked) + label .bx-suggest-value{background-color:#303030}.bx-toast{user-select:none;-webkit-user-select:none;position:fixed;left:50%;top:24px;transform:translate(-50%,0);background:#000;border-radius:16px;color:#fff;z-index:var(--bx-toast-z-index);font-family:var(--bx-normal-font);border:2px solid #fff;display:flex;align-items:center;opacity:0;overflow:clip;transition:opacity .2s ease-in}.bx-toast.bx-show{opacity:.85}.bx-toast.bx-hide{opacity:0;pointer-events:none}.bx-toast-msg{font-size:14px;display:inline-block;padding:12px 16px;white-space:pre}.bx-toast-status{font-weight:bold;font-size:14px;text-transform:uppercase;display:inline-block;background:#515863;padding:12px 16px;color:#fff;white-space:pre}.bx-wait-time-box{position:fixed;top:0;right:0;background-color:rgba(0,0,0,0.8);color:#fff;z-index:var(--bx-wait-time-box-z-index);padding:12px;border-radius:0 0 0 8px}.bx-wait-time-box label{display:block;text-transform:uppercase;text-align:right;font-size:12px;font-weight:bold;margin:0}.bx-wait-time-box span{display:block;font-family:var(--bx-monospaced-font);text-align:right;font-size:16px;margin-bottom:10px}.bx-wait-time-box span:last-of-type{margin-bottom:0}.bx-remote-play-container{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);color:#fff;background:#1a1b1e;border-radius:10px;width:420px;max-width:calc(100vw - 20px);margin:0 0 0 auto;padding:20px}.bx-remote-play-container > .bx-button{display:table;margin:0 0 0 auto}.bx-remote-play-settings{margin-bottom:12px;padding-bottom:12px;border-bottom:1px solid #2d2d2d}.bx-remote-play-settings > div{display:flex}.bx-remote-play-settings label{flex:1}.bx-remote-play-settings label p{margin:4px 0 0;padding:0;color:#888;font-size:12px}.bx-remote-play-resolution{display:block}.bx-remote-play-resolution input[type="radio"]{accent-color:var(--bx-primary-button-color);margin-right:6px}.bx-remote-play-resolution input[type="radio"]:focus{accent-color:var(--bx-primary-button-hover-color)}.bx-remote-play-device-wrapper{display:flex;margin-bottom:12px}.bx-remote-play-device-wrapper:last-child{margin-bottom:2px}.bx-remote-play-device-info{flex:1;padding:4px 0}.bx-remote-play-device-name{font-size:20px;font-weight:bold;display:inline-block;vertical-align:middle}.bx-remote-play-console-type{font-size:12px;background:#004c87;color:#fff;display:inline-block;border-radius:14px;padding:2px 10px;margin-left:8px;vertical-align:middle}.bx-remote-play-power-state{color:#888;font-size:12px}.bx-remote-play-connect-button{min-height:100%;margin:4px 0}.bx-remote-play-buttons{display:flex;justify-content:space-between}.bx-select{display:flex;align-items:center;flex:0 1 auto}.bx-select select{position:absolute !important;top:-9999px !important;left:-9999px !important;visibility:hidden !important}.bx-select > div,.bx-select button.bx-select-value{min-width:120px;text-align:left;margin:0 8px;line-height:24px;vertical-align:middle;background:#fff;color:#000;border-radius:4px;padding:2px 8px;flex:1}.bx-select > div{display:inline-block}.bx-select > div input{display:inline-block;margin-right:8px}.bx-select > div label{margin-bottom:0;font-size:14px;width:100%}.bx-select > div label span{display:block;font-size:10px;font-weight:bold;text-align:left;line-height:initial}.bx-select button.bx-select-value{border:none;display:inline-flex;cursor:pointer;min-height:30px;font-size:.9rem;align-items:center}.bx-select button.bx-select-value span{flex:1;text-align:left;display:inline-block}.bx-select button.bx-select-value input{margin:0 4px;accent-color:var(--bx-primary-button-color)}.bx-select button.bx-select-value:hover input,.bx-select button.bx-select-value:focus input{accent-color:var(--bx-danger-button-color)}.bx-select button.bx-select-value:hover::after,.bx-select button.bx-select-value:focus::after{border-color:#4d4d4d !important}.bx-select button.bx-button{border:none;height:24px;width:24px;padding:0;line-height:24px;color:#fff;border-radius:4px;font-weight:bold;font-size:12px;font-family:var(--bx-monospaced-font);flex-shrink:0}.bx-select button.bx-button span{line-height:unset}.bx-guide-home-achievements-progress{display:flex;gap:10px;flex-direction:row}.bx-guide-home-achievements-progress .bx-button{margin-bottom:0 !important}html[data-xds-platform=tv] .bx-guide-home-achievements-progress{flex-direction:column}html:not([data-xds-platform=tv]) .bx-guide-home-achievements-progress{flex-direction:row}html:not([data-xds-platform=tv]) .bx-guide-home-achievements-progress > button:first-of-type{flex:1}html:not([data-xds-platform=tv]) .bx-guide-home-achievements-progress > button:last-of-type{width:40px}html:not([data-xds-platform=tv]) .bx-guide-home-achievements-progress > button:last-of-type span{display:none}.bx-guide-home-buttons > div{display:flex;flex-direction:row;gap:12px}html[data-xds-platform=tv] .bx-guide-home-buttons > div{flex-direction:column}html[data-xds-platform=tv] .bx-guide-home-buttons > div button{margin-bottom:0 !important}html:not([data-xds-platform=tv]) .bx-guide-home-buttons > div button span{display:none}.bx-guide-home-buttons[data-is-playing="true"] button[data-state='normal']{display:none}.bx-guide-home-buttons[data-is-playing="false"] button[data-state='playing']{display:none}div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]{overflow:visible}.bx-stream-menu-button-on{fill:#000 !important;background-color:#2d2d2d !important;color:#000 !important}.bx-stream-refresh-button{top:calc(env(safe-area-inset-top, 0px) + 10px + 50px) !important}body[data-media-type=default] .bx-stream-refresh-button{left:calc(env(safe-area-inset-left, 0px) + 11px) !important}body[data-media-type=tv] .bx-stream-refresh-button{top:calc(var(--gds-focus-borderSize) + 80px) !important}.bx-stream-home-button{top:calc(env(safe-area-inset-top, 0px) + 10px + 50px * 2) !important}body[data-media-type=default] .bx-stream-home-button{left:calc(env(safe-area-inset-left, 0px) + 12px) !important}body[data-media-type=tv] .bx-stream-home-button{top:calc(var(--gds-focus-borderSize) + 80px * 2) !important}div[data-testid=media-container]{display:flex}div[data-testid=media-container].bx-taking-screenshot:before{animation:bx-anim-taking-screenshot .5s ease;content:' ';position:absolute;width:100%;height:100%;z-index:var(--bx-screenshot-animation-z-index)}#game-stream video{margin:auto;align-self:center;background:#000}#game-stream canvas{position:absolute;align-self:center;margin:auto;left:0;right:0}#gamepass-dialog-root div[class^=Guide-module__guide] .bx-button{overflow:visible;margin-bottom:12px}@-moz-keyframes bx-anim-taking-screenshot{0%{border:0 solid rgba(255,255,255,0.502)}50%{border:8px solid rgba(255,255,255,0.502)}100%{border:0 solid rgba(255,255,255,0.502)}}@-webkit-keyframes bx-anim-taking-screenshot{0%{border:0 solid rgba(255,255,255,0.502)}50%{border:8px solid rgba(255,255,255,0.502)}100%{border:0 solid rgba(255,255,255,0.502)}}@-o-keyframes bx-anim-taking-screenshot{0%{border:0 solid rgba(255,255,255,0.502)}50%{border:8px solid rgba(255,255,255,0.502)}100%{border:0 solid rgba(255,255,255,0.502)}}@keyframes bx-anim-taking-screenshot{0%{border:0 solid rgba(255,255,255,0.502)}50%{border:8px solid rgba(255,255,255,0.502)}100%{border:0 solid rgba(255,255,255,0.502)}}.bx-number-stepper{text-align:center}.bx-number-stepper span{display:inline-block;min-width:40px;font-family:var(--bx-monospaced-font);font-size:12px;margin:0 4px}.bx-number-stepper button{border:none;width:24px;height:24px;margin:0;line-height:24px;background-color:var(--bx-default-button-color);color:#fff;border-radius:4px;font-weight:bold;font-size:14px;font-family:var(--bx-monospaced-font)}@media (hover:hover){.bx-number-stepper button:hover{background-color:var(--bx-default-button-hover-color)}}.bx-number-stepper button:active{background-color:var(--bx-default-button-hover-color)}.bx-number-stepper button:disabled + span{font-family:var(--bx-title-font)}.bx-number-stepper input[type="range"]{display:block;margin:12px auto 2px;width:180px;color:#959595 !important}.bx-number-stepper input[type=range]:disabled,.bx-number-stepper button:disabled{display:none}.bx-number-stepper[data-disabled=true] input[type=range],.bx-number-stepper[data-disabled=true] button{display:none}#bx-game-bar{z-index:var(--bx-game-bar-z-index);position:fixed;bottom:0;width:40px;height:90px;overflow:visible;cursor:pointer}#bx-game-bar > svg{display:none;pointer-events:none;position:absolute;height:28px;margin-top:16px}@media (hover:hover){#bx-game-bar:hover > svg{display:block}}#bx-game-bar .bx-game-bar-container{opacity:0;position:absolute;display:flex;overflow:hidden;background:rgba(26,27,30,0.91);box-shadow:0 0 6px #1c1c1c;transition:opacity .1s ease-in}#bx-game-bar .bx-game-bar-container.bx-show{opacity:.9}#bx-game-bar .bx-game-bar-container.bx-show + svg{display:none !important}#bx-game-bar .bx-game-bar-container.bx-hide{opacity:0;pointer-events:none}#bx-game-bar .bx-game-bar-container button{width:60px;height:60px;border-radius:0}#bx-game-bar .bx-game-bar-container button svg{width:28px;height:28px;transition:transform .08s ease 0s}#bx-game-bar .bx-game-bar-container button:hover{border-radius:0}#bx-game-bar .bx-game-bar-container button:active svg{transform:scale(.75)}#bx-game-bar .bx-game-bar-container button.bx-activated{background-color:#fff}#bx-game-bar .bx-game-bar-container button.bx-activated svg{filter:invert(1)}#bx-game-bar .bx-game-bar-container div[data-enabled] button{display:none}#bx-game-bar .bx-game-bar-container div[data-enabled='true'] button:first-of-type{display:block}#bx-game-bar .bx-game-bar-container div[data-enabled='false'] button:last-of-type{display:block}#bx-game-bar[data-position="bottom-left"]{left:0;direction:ltr}#bx-game-bar[data-position="bottom-left"] .bx-game-bar-container{border-radius:0 10px 10px 0}#bx-game-bar[data-position="bottom-right"]{right:0;direction:rtl}#bx-game-bar[data-position="bottom-right"] .bx-game-bar-container{direction:ltr;border-radius:10px 0 0 10px}.bx-badges{margin-left:0;user-select:none;-webkit-user-select:none}.bx-badge{border:none;display:inline-block;line-height:24px;color:#fff;font-family:var(--bx-title-font-semibold);font-size:14px;font-weight:400;margin:0 8px 8px 0;box-shadow:0 0 6px #000;border-radius:4px}.bx-badge-name{background-color:#2d3036;border-radius:4px 0 0 4px}.bx-badge-name svg{width:16px;height:16px}.bx-badge-value{background-color:#808080;border-radius:0 4px 4px 0}.bx-badge-name,.bx-badge-value{display:inline-block;padding:0 8px;line-height:30px;vertical-align:bottom}.bx-badge-battery[data-charging=true] span:first-of-type::after{content:' ⚡️'}div[class^=StreamMenu-module__container] .bx-badges{position:absolute;max-width:500px}#gamepass-dialog-root .bx-badges{position:fixed;top:60px;left:460px;max-width:500px}@media (min-width:568px) and (max-height:480px){#gamepass-dialog-root .bx-badges{position:unset;top:unset;left:unset;margin:8px 0}}.bx-stats-bar{display:block;user-select:none;-webkit-user-select:none;position:fixed;top:0;background-color:#000;color:#fff;font-family:var(--bx-monospaced-font);font-size:.9rem;padding-left:8px;z-index:var(--bx-stats-bar-z-index);text-wrap:nowrap}.bx-stats-bar[data-stats*="[fps]"] > .bx-stat-fps,.bx-stats-bar[data-stats*="[ping]"] > .bx-stat-ping,.bx-stats-bar[data-stats*="[btr]"] > .bx-stat-btr,.bx-stats-bar[data-stats*="[dt]"] > .bx-stat-dt,.bx-stats-bar[data-stats*="[pl]"] > .bx-stat-pl,.bx-stats-bar[data-stats*="[fl]"] > .bx-stat-fl{display:inline-block}.bx-stats-bar[data-stats$="[fps]"] > .bx-stat-fps,.bx-stats-bar[data-stats$="[ping]"] > .bx-stat-ping,.bx-stats-bar[data-stats$="[btr]"] > .bx-stat-btr,.bx-stats-bar[data-stats$="[dt]"] > .bx-stat-dt,.bx-stats-bar[data-stats$="[pl]"] > .bx-stat-pl,.bx-stats-bar[data-stats$="[fl]"] > .bx-stat-fl{margin-right:0;border-right:none}.bx-stats-bar::before{display:none;content:'👀';vertical-align:middle;margin-right:8px}.bx-stats-bar[data-display=glancing]::before{display:inline-block}.bx-stats-bar[data-position=top-left]{left:0;border-radius:0 0 4px 0}.bx-stats-bar[data-position=top-right]{right:0;border-radius:0 0 0 4px}.bx-stats-bar[data-position=top-center]{transform:translate(-50%,0);left:50%;border-radius:0 0 4px 4px}.bx-stats-bar[data-transparent=true]{background:none;filter:drop-shadow(1px 0 0 rgba(0,0,0,0.941)) drop-shadow(-1px 0 0 rgba(0,0,0,0.941)) drop-shadow(0 1px 0 rgba(0,0,0,0.941)) drop-shadow(0 -1px 0 rgba(0,0,0,0.941))}.bx-stats-bar > div{display:none;margin-right:8px;border-right:1px solid #fff;padding-right:8px}.bx-stats-bar label{margin:0 8px 0 0;font-family:var(--bx-title-font);font-size:inherit;font-weight:bold;vertical-align:middle;cursor:help}.bx-stats-bar span{min-width:60px;display:inline-block;text-align:right;vertical-align:middle}.bx-stats-bar span[data-grade=good]{color:#6bffff}.bx-stats-bar span[data-grade=ok]{color:#fff16b}.bx-stats-bar span[data-grade=bad]{color:#ff5f5f}.bx-stats-bar span:first-of-type{min-width:22px}.bx-mkb-settings{display:flex;flex-direction:column;flex:1;padding-bottom:10px;overflow:hidden}.bx-mkb-settings select:disabled{-webkit-appearance:none;background:transparent;text-align-last:right;text-align:right;border:none;color:#fff}.bx-mkb-pointer-lock-msg{user-select:none;-webkit-user-select:none;position:fixed;left:50%;top:50%;transform:translateX(-50%) translateY(-50%);margin:auto;background:#151515;z-index:var(--bx-mkb-pointer-lock-msg-z-index);color:#fff;text-align:center;font-weight:400;font-family:"Segoe UI",Arial,Helvetica,sans-serif;font-size:1.3rem;padding:12px;border-radius:8px;align-items:center;box-shadow:0 0 6px #000;min-width:220px;opacity:.9}.bx-mkb-pointer-lock-msg:hover{opacity:1}.bx-mkb-pointer-lock-msg > div:first-of-type{display:flex;flex-direction:column;text-align:left}.bx-mkb-pointer-lock-msg p{margin:0}.bx-mkb-pointer-lock-msg p:first-child{font-size:22px;margin-bottom:4px;font-weight:bold}.bx-mkb-pointer-lock-msg p:last-child{font-size:12px;font-style:italic}.bx-mkb-pointer-lock-msg > div:last-of-type{margin-top:10px}.bx-mkb-pointer-lock-msg > div:last-of-type[data-type='native'] button:first-of-type{margin-bottom:8px}.bx-mkb-pointer-lock-msg > div:last-of-type[data-type='virtual'] div{display:flex;flex-flow:row;margin-top:8px}.bx-mkb-pointer-lock-msg > div:last-of-type[data-type='virtual'] div button{flex:1}.bx-mkb-pointer-lock-msg > div:last-of-type[data-type='virtual'] div button:first-of-type{margin-right:5px}.bx-mkb-pointer-lock-msg > div:last-of-type[data-type='virtual'] div button:last-of-type{margin-left:5px}.bx-mkb-preset-tools{display:flex;margin-bottom:12px}.bx-mkb-preset-tools select{flex:1}.bx-mkb-preset-tools button{margin-left:6px}.bx-mkb-settings-rows{flex:1;overflow:scroll}.bx-mkb-key-row{display:flex;margin-bottom:10px;align-items:center}.bx-mkb-key-row label{margin-bottom:0;font-family:var(--bx-promptfont-font);font-size:26px;text-align:center;width:26px;height:32px;line-height:32px}.bx-mkb-key-row button{flex:1;height:32px;line-height:32px;margin:0 0 0 10px;background:transparent;border:none;color:#fff;border-radius:0;border-left:1px solid #373737}.bx-mkb-key-row button:hover{background:transparent;cursor:default}.bx-mkb-settings.bx-editing .bx-mkb-key-row button{background:#393939;border-radius:4px;border:none}.bx-mkb-settings.bx-editing .bx-mkb-key-row button:hover{background:#333;cursor:pointer}.bx-mkb-action-buttons > div{text-align:right;display:none}.bx-mkb-action-buttons button{margin-left:8px}.bx-mkb-settings:not(.bx-editing) .bx-mkb-action-buttons > div:first-child{display:block}.bx-mkb-settings.bx-editing .bx-mkb-action-buttons > div:last-child{display:block}.bx-mkb-note{display:block;margin:16px 0 10px;font-size:12px}.bx-mkb-note:first-of-type{margin-top:0}`;
const PREF_HIDE_SECTIONS = getPref("ui_hide_sections"), selectorToHide = [];
- if (PREF_HIDE_SECTIONS.includes("news"))
- selectorToHide.push("#BodyContent > div[class*=CarouselRow-module]");
- if (PREF_HIDE_SECTIONS.includes("all-games"))
- selectorToHide.push("#BodyContent div[class*=AllGamesRow-module__gridContainer]"), selectorToHide.push("#BodyContent div[class*=AllGamesRow-module__rowHeader]");
- if (PREF_HIDE_SECTIONS.includes("most-popular"))
- selectorToHide.push('#BodyContent div[class*=HomePage-module__bottomSpacing]:has(a[href="/play/gallery/popular"])');
- if (PREF_HIDE_SECTIONS.includes("touch"))
- selectorToHide.push('#BodyContent div[class*=HomePage-module__bottomSpacing]:has(a[href="/play/gallery/touch"])');
- if (getPref("block_social_features"))
- selectorToHide.push("#gamepass-dialog-root div[class^=AchievementsPreview-module__container] + button[class*=HomeLandingPage-module__button]");
- if (selectorToHide)
- css += selectorToHide.join(",") + "{ display: none; }";
- if (getPref("reduce_animations"))
- css += "div[class*=GameCard-module__gameTitleInnerWrapper],div[class*=GameCard-module__card],div[class*=ScrollArrows-module]{transition:none !important}";
- if (getPref("hide_dots_icon"))
- css += "div[class*=Grip-module__container]{visibility:hidden}@media (hover:hover){button[class*=GripHandle-module__container]:hover div[class*=Grip-module__container]{visibility:visible}}button[class*=GripHandle-module__container][aria-expanded=true] div[class*=Grip-module__container]{visibility:visible}button[class*=GripHandle-module__container][aria-expanded=false]{background-color:transparent !important}div[class*=StreamHUD-module__buttonsContainer]{padding:0 !important}";
- if (css += "div[class*=StreamMenu-module__menu]{min-width:100vw !important}", getPref("stream_simplify_menu"))
- css += "div[class*=Menu-module__scrollable]{--bxStreamMenuItemSize:80px;--streamMenuItemSize:calc(var(--bxStreamMenuItemSize) + 40px) !important}.bx-badges{top:calc(var(--streamMenuItemSize) - 20px)}body[data-media-type=tv] .bx-badges{top:calc(var(--streamMenuItemSize) - 10px) !important}button[class*=MenuItem-module__container]{min-width:auto !important;min-height:auto !important;width:var(--bxStreamMenuItemSize) !important;height:var(--bxStreamMenuItemSize) !important}div[class*=MenuItem-module__label]{display:none !important}svg[class*=MenuItem-module__icon]{width:36px;height:100% !important;padding:0 !important;margin:0 !important}";
- else
- css += "body[data-media-type=tv] .bx-badges{top:calc(var(--streamMenuItemSize) + 30px)}body:not([data-media-type=tv]) .bx-badges{top:calc(var(--streamMenuItemSize) + 20px)}body:not([data-media-type=tv]) button[class*=MenuItem-module__container]{min-width:auto !important;width:100px !important}body:not([data-media-type=tv]) button[class*=MenuItem-module__container]:nth-child(n+2){margin-left:10px !important}body:not([data-media-type=tv]) div[class*=MenuItem-module__label]{margin-left:8px !important;margin-right:8px !important}";
- if (getPref("ui_scrollbar_hide"))
- css += "html{scrollbar-width:none}body::-webkit-scrollbar{display:none}";
+ if (PREF_HIDE_SECTIONS.includes("news")) selectorToHide.push("#BodyContent > div[class*=CarouselRow-module]");
+ if (PREF_HIDE_SECTIONS.includes("all-games")) selectorToHide.push("#BodyContent div[class*=AllGamesRow-module__gridContainer]"), selectorToHide.push("#BodyContent div[class*=AllGamesRow-module__rowHeader]");
+ if (PREF_HIDE_SECTIONS.includes("most-popular")) selectorToHide.push('#BodyContent div[class*=HomePage-module__bottomSpacing]:has(a[href="/play/gallery/popular"])');
+ if (PREF_HIDE_SECTIONS.includes("touch")) selectorToHide.push('#BodyContent div[class*=HomePage-module__bottomSpacing]:has(a[href="/play/gallery/touch"])');
+ if (getPref("block_social_features")) selectorToHide.push("#gamepass-dialog-root div[class^=AchievementsPreview-module__container] + button[class*=HomeLandingPage-module__button]");
+ if (selectorToHide) css += selectorToHide.join(",") + "{ display: none; }";
+ if (getPref("reduce_animations")) css += "div[class*=GameCard-module__gameTitleInnerWrapper],div[class*=GameCard-module__card],div[class*=ScrollArrows-module]{transition:none !important}";
+ if (getPref("hide_dots_icon")) css += "div[class*=Grip-module__container]{visibility:hidden}@media (hover:hover){button[class*=GripHandle-module__container]:hover div[class*=Grip-module__container]{visibility:visible}}button[class*=GripHandle-module__container][aria-expanded=true] div[class*=Grip-module__container]{visibility:visible}button[class*=GripHandle-module__container][aria-expanded=false]{background-color:transparent !important}div[class*=StreamHUD-module__buttonsContainer]{padding:0 !important}";
+ if (css += "div[class*=StreamMenu-module__menu]{min-width:100vw !important}", getPref("stream_simplify_menu")) css += "div[class*=Menu-module__scrollable]{--bxStreamMenuItemSize:80px;--streamMenuItemSize:calc(var(--bxStreamMenuItemSize) + 40px) !important}.bx-badges{top:calc(var(--streamMenuItemSize) - 20px)}body[data-media-type=tv] .bx-badges{top:calc(var(--streamMenuItemSize) - 10px) !important}button[class*=MenuItem-module__container]{min-width:auto !important;min-height:auto !important;width:var(--bxStreamMenuItemSize) !important;height:var(--bxStreamMenuItemSize) !important}div[class*=MenuItem-module__label]{display:none !important}svg[class*=MenuItem-module__icon]{width:36px;height:100% !important;padding:0 !important;margin:0 !important}";
+ else css += "body[data-media-type=tv] .bx-badges{top:calc(var(--streamMenuItemSize) + 30px)}body:not([data-media-type=tv]) .bx-badges{top:calc(var(--streamMenuItemSize) + 20px)}body:not([data-media-type=tv]) button[class*=MenuItem-module__container]{min-width:auto !important;width:100px !important}body:not([data-media-type=tv]) button[class*=MenuItem-module__container]:nth-child(n+2){margin-left:10px !important}body:not([data-media-type=tv]) div[class*=MenuItem-module__label]{margin-left:8px !important;margin-right:8px !important}";
+ if (getPref("ui_scrollbar_hide")) css += "html{scrollbar-width:none}body::-webkit-scrollbar{display:none}";
const $style = CE("style", {}, css);
document.documentElement.appendChild($style);
}
@@ -6834,8 +6381,7 @@ function onHistoryChanged(e) {
if (e && e.arguments && e.arguments[0] && e.arguments[0].origin === "better-xcloud") return;
window.setTimeout(RemotePlayManager.detect, 10);
const $settings = document.querySelector(".bx-settings-container");
- if ($settings)
- $settings.classList.add("bx-gone");
+ if ($settings) $settings.classList.add("bx-gone");
NavigationDialogManager.getInstance().hide(), LoadingScreen.reset(), window.setTimeout(HeaderSection.watchHeader, 2000), BxEvent.dispatch(window, BxEvent.STREAM_STOPPED);
}
function overridePreloadState() {
@@ -6851,21 +6397,18 @@ function overridePreloadState() {
} catch (e) {
BxLogger.error(LOG_TAG6, e);
}
- if (STATES.userAgent.capabilities.touch)
- try {
+ if (STATES.userAgent.capabilities.touch) try {
const sigls = state.xcloud.sigls;
if ("9c86f07a-f3e8-45ad-82a0-a1f759597059" in sigls) {
let customList = TouchController.getCustomList();
const allGames = sigls["29a81209-df6f-41fd-a528-2ae6b91f719c"].data.products;
customList = customList.filter((id2) => allGames.includes(id2)), sigls["9c86f07a-f3e8-45ad-82a0-a1f759597059"]?.data.products.push(...customList);
}
- if (BX_FLAGS.ForceNativeMkbTitles && "8fa264dd-124f-4af3-97e8-596fcdf4b486" in sigls)
- sigls["8fa264dd-124f-4af3-97e8-596fcdf4b486"]?.data.products.push(...BX_FLAGS.ForceNativeMkbTitles);
+ if (BX_FLAGS.ForceNativeMkbTitles && "8fa264dd-124f-4af3-97e8-596fcdf4b486" in sigls) sigls["8fa264dd-124f-4af3-97e8-596fcdf4b486"]?.data.products.push(...BX_FLAGS.ForceNativeMkbTitles);
} catch (e) {
BxLogger.error(LOG_TAG6, e);
}
- if (getPref("ui_home_context_menu_disabled"))
- try {
+ if (getPref("ui_home_context_menu_disabled")) try {
state.experiments.experimentationInfo.data.treatments.EnableHomeContextMenu = !1;
} catch (e) {
BxLogger.error(LOG_TAG6, e);
@@ -6879,15 +6422,13 @@ function setCodecPreferences(sdp, preferredCodec) {
const h264Pattern = /a=fmtp:(\d+).*profile-level-id=([0-9a-f]{6})/g, profilePrefix = preferredCodec === "high" ? "4d" : preferredCodec === "low" ? "420" : "42e", preferredCodecIds = [], matches = sdp.matchAll(h264Pattern) || [];
for (let match of matches) {
const id2 = match[1];
- if (match[2].startsWith(profilePrefix))
- preferredCodecIds.push(id2);
+ if (match[2].startsWith(profilePrefix)) preferredCodecIds.push(id2);
}
if (!preferredCodecIds.length) return sdp;
const lines = sdp.split("\r\n");
for (let lineIndex = 0;lineIndex < lines.length; lineIndex++) {
const line = lines[lineIndex];
- if (!line.startsWith("m=video"))
- continue;
+ if (!line.startsWith("m=video")) continue;
const tmp = line.trim().split(" ");
let ids = tmp.slice(3);
ids = ids.filter((item2) => !preferredCodecIds.includes(item2)), ids = preferredCodecIds.concat(ids), lines[lineIndex] = tmp.slice(0, 3).concat(ids).join(" ");
@@ -6904,19 +6445,16 @@ function patchSdpBitrate(sdp, video, audio) {
};
for (let lineNumber = 0;lineNumber < lines.length; lineNumber++) {
let media = "", line = lines[lineNumber];
- if (!line.startsWith("m="))
- continue;
+ if (!line.startsWith("m=")) continue;
for (let m of mediaSet)
if (line.startsWith(`m=${m}`)) {
media = m, mediaSet.delete(media);
break;
}
- if (!media)
- continue;
+ if (!media) continue;
const bLine = `b=AS:${bitrate[media]}`;
while (lineNumber++, lineNumber < lines.length) {
- if (line = lines[lineNumber], line.startsWith("i=") || line.startsWith("c="))
- continue;
+ if (line = lines[lineNumber], line.startsWith("i=") || line.startsWith("c=")) continue;
if (line.startsWith("b=AS:")) {
lines[lineNumber] = bLine;
break;
@@ -6986,8 +6524,7 @@ class WebGL2Player {
if (this.#stopped) return;
this.drawFrame(), this.#animFrameId = $video.requestVideoFrameCallback(animate);
}, this.#animFrameId = $video.requestVideoFrameCallback(animate);
- } else
- animate = () => {
+ } else animate = () => {
if (this.#stopped) return;
this.drawFrame(), this.#animFrameId = requestAnimationFrame(animate);
}, this.#animFrameId = requestAnimationFrame(animate);
@@ -7006,8 +6543,7 @@ class WebGL2Player {
const fShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fShader, clarity_boost_default2), gl.compileShader(fShader);
const program = gl.createProgram();
- if (this.#program = program, gl.attachShader(program, vShader), gl.attachShader(program, fShader), gl.linkProgram(program), gl.useProgram(program), !gl.getProgramParameter(program, gl.LINK_STATUS))
- console.error(`Link failed: ${gl.getProgramInfoLog(program)}`), console.error(`vs info-log: ${gl.getShaderInfoLog(vShader)}`), console.error(`fs info-log: ${gl.getShaderInfoLog(fShader)}`);
+ if (this.#program = program, gl.attachShader(program, vShader), gl.attachShader(program, fShader), gl.linkProgram(program), gl.useProgram(program), !gl.getProgramParameter(program, gl.LINK_STATUS)) console.error(`Link failed: ${gl.getProgramInfoLog(program)}`), console.error(`vs info-log: ${gl.getShaderInfoLog(vShader)}`), console.error(`fs info-log: ${gl.getShaderInfoLog(fShader)}`);
this.updateCanvas();
const buffer = gl.createBuffer();
this.#resources.push(buffer), gl.bindBuffer(gl.ARRAY_BUFFER, buffer), gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
@@ -7032,10 +6568,8 @@ class WebGL2Player {
}
stop() {
if (BxLogger.info(LOG_TAG7, "Stop"), this.#$canvas.classList.add("bx-gone"), this.#stopped = !0, this.#animFrameId) {
- if ("requestVideoFrameCallback" in HTMLVideoElement.prototype)
- this.#$video.cancelVideoFrameCallback(this.#animFrameId);
- else
- cancelAnimationFrame(this.#animFrameId);
+ if ("requestVideoFrameCallback" in HTMLVideoElement.prototype) this.#$video.cancelVideoFrameCallback(this.#animFrameId);
+ else cancelAnimationFrame(this.#animFrameId);
this.#animFrameId = null;
}
}
@@ -7045,18 +6579,13 @@ class WebGL2Player {
if (gl) {
gl.getExtension("WEBGL_lose_context")?.loseContext();
for (let resource of this.#resources)
- if (resource instanceof WebGLProgram)
- gl.useProgram(null), gl.deleteProgram(resource);
- else if (resource instanceof WebGLShader)
- gl.deleteShader(resource);
- else if (resource instanceof WebGLTexture)
- gl.deleteTexture(resource);
- else if (resource instanceof WebGLBuffer)
- gl.deleteBuffer(resource);
+ if (resource instanceof WebGLProgram) gl.useProgram(null), gl.deleteProgram(resource);
+ else if (resource instanceof WebGLShader) gl.deleteShader(resource);
+ else if (resource instanceof WebGLTexture) gl.deleteTexture(resource);
+ else if (resource instanceof WebGLBuffer) gl.deleteBuffer(resource);
this.#gl = null;
}
- if (this.#$canvas.isConnected)
- this.#$canvas.parentElement?.removeChild(this.#$canvas);
+ if (this.#$canvas.isConnected) this.#$canvas.parentElement?.removeChild(this.#$canvas);
this.#$canvas.width = 1, this.#$canvas.height = 1;
}
}
@@ -7098,48 +6627,35 @@ class StreamPlayer {
this.#$usmMatrix?.setAttributeNS(null, "kernelMatrix", matrix), filters.push("url(#bx-filter-usm)");
}
const saturation = this.#options.saturation || 100;
- if (saturation != 100)
- filters.push(`saturate(${saturation}%)`);
+ if (saturation != 100) filters.push(`saturate(${saturation}%)`);
const contrast = this.#options.contrast || 100;
- if (contrast != 100)
- filters.push(`contrast(${contrast}%)`);
+ if (contrast != 100) filters.push(`contrast(${contrast}%)`);
const brightness = this.#options.brightness || 100;
- if (brightness != 100)
- filters.push(`brightness(${brightness}%)`);
+ if (brightness != 100) filters.push(`brightness(${brightness}%)`);
return filters.join(" ");
}
#resizePlayer() {
const PREF_RATIO = getPref("video_ratio"), $video = this.#$video, isNativeTouchGame = STATES.currentStream.titleInfo?.details.hasNativeTouchSupport;
let $webGL2Canvas;
- if (this.#playerType == "webgl2")
- $webGL2Canvas = this.#webGL2Player?.getCanvas();
+ if (this.#playerType == "webgl2") $webGL2Canvas = this.#webGL2Player?.getCanvas();
let targetWidth, targetHeight, targetObjectFit;
if (PREF_RATIO.includes(":")) {
const tmp = PREF_RATIO.split(":"), videoRatio = parseFloat(tmp[0]) / parseFloat(tmp[1]);
let width = 0, height = 0;
const parentRect = $video.parentElement.getBoundingClientRect();
- if (parentRect.width / parentRect.height > videoRatio)
- height = parentRect.height, width = height * videoRatio;
- else
- width = parentRect.width, height = width / videoRatio;
+ if (parentRect.width / parentRect.height > videoRatio) height = parentRect.height, width = height * videoRatio;
+ else width = parentRect.width, height = width / videoRatio;
width = Math.ceil(Math.min(parentRect.width, width)), height = Math.ceil(Math.min(parentRect.height, height)), $video.dataset.width = width.toString(), $video.dataset.height = height.toString(), targetWidth = `${width}px`, targetHeight = `${height}px`, targetObjectFit = PREF_RATIO === "16:9" ? "contain" : "fill";
- } else
- targetWidth = "100%", targetHeight = "100%", targetObjectFit = PREF_RATIO, $video.dataset.width = window.innerWidth.toString(), $video.dataset.height = window.innerHeight.toString();
- if ($video.style.width = targetWidth, $video.style.height = targetHeight, $video.style.objectFit = targetObjectFit, $webGL2Canvas)
- $webGL2Canvas.style.width = targetWidth, $webGL2Canvas.style.height = targetHeight, $webGL2Canvas.style.objectFit = targetObjectFit;
- if (isNativeTouchGame && this.#playerType == "webgl2")
- window.BX_EXPOSED.streamSession.updateDimensions();
+ } else targetWidth = "100%", targetHeight = "100%", targetObjectFit = PREF_RATIO, $video.dataset.width = window.innerWidth.toString(), $video.dataset.height = window.innerHeight.toString();
+ if ($video.style.width = targetWidth, $video.style.height = targetHeight, $video.style.objectFit = targetObjectFit, $webGL2Canvas) $webGL2Canvas.style.width = targetWidth, $webGL2Canvas.style.height = targetHeight, $webGL2Canvas.style.objectFit = targetObjectFit;
+ if (isNativeTouchGame && this.#playerType == "webgl2") window.BX_EXPOSED.streamSession.updateDimensions();
}
setPlayerType(type, refreshPlayer = !1) {
- if (this.#playerType !== type)
- if (type === "webgl2") {
- if (!this.#webGL2Player)
- this.#webGL2Player = new WebGL2Player(this.#$video);
- else
- this.#webGL2Player.resume();
+ if (this.#playerType !== type) if (type === "webgl2") {
+ if (!this.#webGL2Player) this.#webGL2Player = new WebGL2Player(this.#$video);
+ else this.#webGL2Player.resume();
this.#$videoCss.textContent = "", this.#$video.classList.add("bx-pixel");
- } else
- this.#webGL2Player?.stop(), this.#$video.classList.remove("bx-pixel");
+ } else this.#webGL2Player?.stop(), this.#$video.classList.remove("bx-pixel");
this.#playerType = type, refreshPlayer && this.refreshPlayer();
}
setOptions(options, refreshPlayer = !1) {
@@ -7149,8 +6665,7 @@ class StreamPlayer {
this.#options = Object.assign(this.#options, options), refreshPlayer && this.refreshPlayer();
}
getPlayerElement(playerType) {
- if (typeof playerType === "undefined")
- playerType = this.#playerType;
+ if (typeof playerType === "undefined") playerType = this.#playerType;
if (playerType === "webgl2") return this.#webGL2Player?.getCanvas();
return this.#$video;
}
@@ -7160,20 +6675,15 @@ class StreamPlayer {
refreshPlayer() {
if (this.#playerType === "webgl2") {
const options = this.#options, webGL2Player = this.#webGL2Player;
- if (options.processing === "usm")
- webGL2Player.setFilter(1);
- else
- webGL2Player.setFilter(2);
+ if (options.processing === "usm") webGL2Player.setFilter(1);
+ else webGL2Player.setFilter(2);
Screenshot.updateCanvasFilters("none"), webGL2Player.setSharpness(options.sharpness || 0), webGL2Player.setSaturation(options.saturation || 100), webGL2Player.setContrast(options.contrast || 100), webGL2Player.setBrightness(options.brightness || 100);
} else {
let filters = this.#getVideoPlayerFilterStyle(), videoCss = "";
- if (filters)
- videoCss += `filter: ${filters} !important;`;
- if (getPref("screenshot_apply_filters"))
- Screenshot.updateCanvasFilters(filters);
+ if (filters) videoCss += `filter: ${filters} !important;`;
+ if (getPref("screenshot_apply_filters")) Screenshot.updateCanvasFilters(filters);
let css = "";
- if (videoCss)
- css = `#game-stream video { ${videoCss} }`;
+ if (videoCss) css = `#game-stream video { ${videoCss} }`;
this.#$videoCss.textContent = css;
}
this.#resizePlayer();
@@ -7208,8 +6718,7 @@ function patchVideoApi() {
return nativePlay.apply(this);
}
const $parent = this.parentElement;
- if (!this.src && $parent.dataset.testid === "media-container")
- this.addEventListener("loadedmetadata", showFunc, { once: !0 });
+ if (!this.src && $parent.dataset.testid === "media-container") this.addEventListener("loadedmetadata", showFunc, { once: !0 });
return nativePlay.apply(this);
};
}
@@ -7229,11 +6738,9 @@ function patchRtcPeerConnection() {
if (codec !== "default" || maxVideoBitrate > 0) {
const nativeSetLocalDescription = RTCPeerConnection.prototype.setLocalDescription;
RTCPeerConnection.prototype.setLocalDescription = function(description) {
- if (codec !== "default")
- arguments[0].sdp = setCodecPreferences(arguments[0].sdp, codec);
+ if (codec !== "default") arguments[0].sdp = setCodecPreferences(arguments[0].sdp, codec);
try {
- if (maxVideoBitrate > 0 && description)
- arguments[0].sdp = patchSdpBitrate(arguments[0].sdp, Math.round(maxVideoBitrate / 1000));
+ if (maxVideoBitrate > 0 && description) arguments[0].sdp = patchSdpBitrate(arguments[0].sdp, Math.round(maxVideoBitrate / 1000));
} catch (e) {
BxLogger.error("setLocalDescription", e);
}
@@ -7251,8 +6758,7 @@ function patchRtcPeerConnection() {
function patchAudioContext() {
const OrgAudioContext = window.AudioContext, nativeCreateGain = OrgAudioContext.prototype.createGain;
window.AudioContext = function(options) {
- if (options && options.latencyHint)
- options.latencyHint = 0;
+ if (options && options.latencyHint) options.latencyHint = 0;
const ctx = new OrgAudioContext(options);
return BxLogger.info("patchAudioContext", ctx, options), ctx.createGain = function() {
const gainNode = nativeCreateGain.apply(this);
@@ -7280,8 +6786,7 @@ function patchMeControl() {
return target[prop];
},
set(obj, prop, value) {
- if (prop === "MeControl" && value.Config)
- value.Config = Object.assign(value.Config, overrideConfigs);
+ if (prop === "MeControl" && value.Config) value.Config = Object.assign(value.Config, overrideConfigs);
return obj[prop] = value, !0;
}
}, MeControlHandler = {
@@ -7289,8 +6794,7 @@ function patchMeControl() {
return target[prop];
},
set(obj, prop, value) {
- if (prop === "Config")
- value = Object.assign(value, overrideConfigs);
+ if (prop === "Config") value = Object.assign(value, overrideConfigs);
return obj[prop] = value, !0;
}
};
@@ -7304,8 +6808,7 @@ function patchCanvasContext() {
HTMLCanvasElement.prototype.getContext = function(contextType, contextAttributes) {
if (contextType.includes("webgl")) {
if (contextAttributes = contextAttributes || {}, !contextAttributes.isBx) {
- if (contextAttributes.antialias = !1, contextAttributes.powerPreference === "high-performance")
- contextAttributes.powerPreference = "low-power";
+ if (contextAttributes.antialias = !1, contextAttributes.powerPreference === "high-performance") contextAttributes.powerPreference = "low-power";
}
}
return nativeGetContext.apply(this, [contextType, contextAttributes]);
@@ -7440,10 +6943,8 @@ class TrueAchievements {
});
static updateIds(xboxTitleId, id2) {
const { $link, $button } = TrueAchievements;
- if (clearDataSet($link), clearDataSet($button), xboxTitleId)
- $link.dataset.xboxTitleId = xboxTitleId, $button.dataset.xboxTitleId = xboxTitleId;
- if (id2)
- $link.dataset.id = id2, $button.dataset.id = id2;
+ if (clearDataSet($link), clearDataSet($button), xboxTitleId) $link.dataset.xboxTitleId = xboxTitleId, $button.dataset.xboxTitleId = xboxTitleId;
+ if (id2) $link.dataset.id = id2, $button.dataset.id = id2;
}
static injectAchievementsProgress($elm) {
const $parent = $elm.parentElement, $div = CE("div", {
@@ -7452,17 +6953,12 @@ class TrueAchievements {
let xboxTitleId;
try {
const $container = $parent.closest("div[class*=AchievementsPreview-module__container]");
- if ($container)
- xboxTitleId = getReactProps($container).children.props.data.data.xboxTitleId;
+ if ($container) xboxTitleId = getReactProps($container).children.props.data.data.xboxTitleId;
} catch (e) {}
- if (!xboxTitleId)
- xboxTitleId = TrueAchievements.getStreamXboxTitleId();
- if (typeof xboxTitleId !== "undefined")
- xboxTitleId = xboxTitleId.toString();
- if (TrueAchievements.updateIds(xboxTitleId), document.documentElement.dataset.xdsPlatform === "tv")
- $div.appendChild(TrueAchievements.$link);
- else
- $div.appendChild(TrueAchievements.$button);
+ if (!xboxTitleId) xboxTitleId = TrueAchievements.getStreamXboxTitleId();
+ if (typeof xboxTitleId !== "undefined") xboxTitleId = xboxTitleId.toString();
+ if (TrueAchievements.updateIds(xboxTitleId), document.documentElement.dataset.xdsPlatform === "tv") $div.appendChild(TrueAchievements.$link);
+ else $div.appendChild(TrueAchievements.$button);
$parent.appendChild($div);
}
static injectAchievementDetailPage($parent) {
@@ -7476,24 +6972,21 @@ class TrueAchievements {
id2 = achiev.id, xboxTitleId = achiev.title.id;
break;
}
- if (id2)
- TrueAchievements.updateIds(xboxTitleId, id2), $parent.appendChild(TrueAchievements.$link);
+ if (id2) TrueAchievements.updateIds(xboxTitleId, id2), $parent.appendChild(TrueAchievements.$link);
} catch (e) {}
}
static getStreamXboxTitleId() {
return STATES.currentStream.xboxTitleId || STATES.currentStream.titleInfo?.details.xboxTitleId;
}
static open(override, xboxTitleId, id2) {
- if (!xboxTitleId || xboxTitleId === "undefined")
- xboxTitleId = TrueAchievements.getStreamXboxTitleId();
+ if (!xboxTitleId || xboxTitleId === "undefined") xboxTitleId = TrueAchievements.getStreamXboxTitleId();
if (AppInterface && AppInterface.openTrueAchievementsLink) {
AppInterface.openTrueAchievementsLink(override, xboxTitleId?.toString(), id2?.toString());
return;
}
let url = "https://www.trueachievements.com";
if (xboxTitleId) {
- if (url += `/deeplink/${xboxTitleId}`, id2)
- url += `/${id2}`;
+ if (url += `/deeplink/${xboxTitleId}`, id2) url += `/${id2}`;
}
TrueAchievements.$hiddenLink.href = url, TrueAchievements.$hiddenLink.click();
}
@@ -7547,8 +7040,7 @@ class SpeakerAction extends BaseGameBarAction {
class GameBar {
static instance;
static getInstance() {
- if (!GameBar.instance)
- GameBar.instance = new GameBar;
+ if (!GameBar.instance) GameBar.instance = new GameBar;
return GameBar.instance;
}
static VISIBLE_DURATION = 2000;
@@ -7574,8 +7066,7 @@ class GameBar {
$container.classList.contains("bx-show") ? this.hideBar() : this.showBar();
}), window.addEventListener(BxEvent.GAME_BAR_ACTION_ACTIVATED, this.hideBar.bind(this)), $container.addEventListener("pointerover", this.clearHideTimeout.bind(this)), $container.addEventListener("pointerout", this.beginHideTimeout.bind(this)), $container.addEventListener("transitionend", (e) => {
const classList = $container.classList;
- if (classList.contains("bx-hide"))
- classList.remove("bx-hide"), classList.add("bx-offscreen");
+ if (classList.contains("bx-hide")) classList.remove("bx-hide"), classList.add("bx-offscreen");
}), document.documentElement.appendChild($gameBar), this.$gameBar = $gameBar, this.$container = $container, getPref("game_bar_position") !== "off" && window.addEventListener(BxEvent.XCLOUD_POLLING_MODE_CHANGED, ((e) => {
if (!STATES.isPlaying) {
this.disable();
@@ -7640,10 +7131,8 @@ class GuideMenu {
title: t("reload-page"),
style: 64 | 32,
onClick: (e) => {
- if (STATES.isPlaying)
- confirm(t("confirm-reload-stream")) && window.location.reload();
- else
- window.location.reload();
+ if (STATES.isPlaying) confirm(t("confirm-reload-stream")) && window.location.reload();
+ else window.location.reload();
window.BX_EXPOSED.dialogRoutes.closeAll();
}
}),
@@ -7674,10 +7163,8 @@ class GuideMenu {
]
];
for (let $button of buttons) {
- if (!$button)
- continue;
- if ($button instanceof HTMLElement)
- $div.appendChild($button);
+ if (!$button) continue;
+ if ($button instanceof HTMLElement) $div.appendChild($button);
else if (Array.isArray($button)) {
const $wrapper = CE("div", {});
for (let $child of $button)
@@ -7689,8 +7176,7 @@ class GuideMenu {
}
static #injectHome($root, isPlaying = !1) {
const $achievementsProgress = $root.querySelector("button[class*=AchievementsButton-module__progressBarContainer]");
- if ($achievementsProgress)
- TrueAchievements.injectAchievementsProgress($achievementsProgress);
+ if ($achievementsProgress) TrueAchievements.injectAchievementsProgress($achievementsProgress);
let $target = null;
if (isPlaying) {
$target = $root.querySelector("a[class*=QuitGameButton]");
@@ -7698,8 +7184,7 @@ class GuideMenu {
$btnXcloudHome && ($btnXcloudHome.style.display = "none");
} else {
const $dividers = $root.querySelectorAll("div[class*=Divider-module__divider]");
- if ($dividers)
- $target = $dividers[$dividers.length - 1];
+ if ($dividers) $target = $dividers[$dividers.length - 1];
}
if (!$target) return !1;
const $buttons = GuideMenu.#renderButtons();
@@ -7731,16 +7216,14 @@ class GuideMenu {
let $elm = $selectedTab, index;
for (index = 0;$elm = $elm?.previousElementSibling; index++)
;
- if (index === 0)
- BxEvent.dispatch(window, BxEvent.XCLOUD_GUIDE_MENU_SHOWN, { where: "home" });
+ if (index === 0) BxEvent.dispatch(window, BxEvent.XCLOUD_GUIDE_MENU_SHOWN, { where: "home" });
}
}
}
class XcloudApi {
static instance;
static getInstance() {
- if (!XcloudApi.instance)
- XcloudApi.instance = new XcloudApi;
+ if (!XcloudApi.instance) XcloudApi.instance = new XcloudApi;
return XcloudApi.instance;
}
#CACHE_TITLES = {};
@@ -7792,8 +7275,7 @@ class GameTile {
seconds %= 3600;
let m = Math.floor(seconds / 60), s = seconds % 60;
const output = [];
- if (h > 0 && output.push(`${h}h`), m > 0 && output.push(`${m}m`), s > 0 || output.length === 0)
- output.push(`${s}s`);
+ if (h > 0 && output.push(`${h}h`), m > 0 && output.push(`${m}m`), s > 0 || output.length === 0) output.push(`${s}s`);
return output.join(" ");
}
static async#showWaitTime($elm, productId) {
@@ -7803,8 +7285,7 @@ class GameTile {
const api = XcloudApi.getInstance(), info = await api.getTitleInfo(productId);
if (info) {
const waitTime = await api.getWaitTime(info.titleId);
- if (waitTime)
- totalWaitTime = waitTime.estimatedAllocationTimeInSeconds;
+ if (waitTime) totalWaitTime = waitTime.estimatedAllocationTimeInSeconds;
}
if (typeof totalWaitTime === "number" && isElementVisible($elm)) {
const $div = CE("div", { class: "bx-game-tile-wait-time" }, createSvgIcon(BxIcon.PLAYTIME), CE("span", {}, GameTile.#secondsToHms(totalWaitTime)));
@@ -7821,17 +7302,12 @@ class GameTile {
try {
if ($elm.tagName === "BUTTON" && $elm.className.includes("MruGameCard") || $elm.tagName === "A" && $elm.className.includes("GameCard")) {
let props = getReactProps($elm.parentElement);
- if (Array.isArray(props.children))
- productId = props.children[0].props.productId;
- else
- productId = props.children.props.productId;
+ if (Array.isArray(props.children)) productId = props.children[0].props.productId;
+ else productId = props.children.props.productId;
} else if ($elm.tagName === "A" && $elm.className.includes("GameItem")) {
let props = getReactProps($elm.parentElement);
- if (props = props.children.props, props.location !== "NonStreamableGameItem")
- if ("productId" in props)
- productId = props.productId;
- else
- productId = props.children.props.productId;
+ if (props = props.children.props, props.location !== "NonStreamableGameItem") if ("productId" in props) productId = props.productId;
+ else productId = props.children.props.productId;
}
} catch (e) {}
return productId;
@@ -7841,8 +7317,7 @@ class GameTile {
const $elm = e.element;
if (($elm.className || "").includes("MruGameCard")) {
const $ol = $elm.closest("ol");
- if ($ol && !$ol.hasWaitTime)
- $ol.hasWaitTime = !0, $ol.querySelectorAll("button[class*=MruGameCard]").forEach(($elm2) => {
+ if ($ol && !$ol.hasWaitTime) $ol.hasWaitTime = !0, $ol.querySelectorAll("button[class*=MruGameCard]").forEach(($elm2) => {
const productId = GameTile.#findProductId($elm2);
productId && GameTile.#showWaitTime($elm2, productId);
});
@@ -7886,8 +7361,7 @@ class ProductDetailsPage {
const $container = document.querySelector("div[class*=ActionButtons-module__container]");
if ($container && $container.parentElement) {
const fragment = document.createDocumentFragment();
- if (BX_FLAGS.DeviceInfo.deviceType === "android")
- fragment.appendChild(ProductDetailsPage.$btnShortcut);
+ if (BX_FLAGS.DeviceInfo.deviceType === "android") fragment.appendChild(ProductDetailsPage.$btnShortcut);
fragment.appendChild(ProductDetailsPage.$btnWallpaper), $container.parentElement.appendChild(fragment);
}
}, 500);
@@ -7937,16 +7411,13 @@ class StreamUiHandler {
const $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", () => {
+ 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", () => {
+ 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);
+ 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) {
@@ -7959,14 +7430,12 @@ class StreamUiHandler {
$gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click(), $gripHandle.dispatchEvent(new PointerEvent("pointerdown")), $gripHandle.click();
};
let $btnStreamSettings = StreamUiHandler.$btnStreamSettings;
- if (typeof $btnStreamSettings === "undefined")
- $btnStreamSettings = StreamUiHandler.cloneStreamHudButton($orgButton, t("better-xcloud"), BxIcon.BETTER_XCLOUD), $btnStreamSettings?.addEventListener("click", (e) => {
+ if (typeof $btnStreamSettings === "undefined") $btnStreamSettings = StreamUiHandler.cloneStreamHudButton($orgButton, t("better-xcloud"), BxIcon.BETTER_XCLOUD), $btnStreamSettings?.addEventListener("click", (e) => {
hideGripHandle(), e.preventDefault(), SettingsNavigationDialog.getInstance().show();
}), StreamUiHandler.$btnStreamSettings = $btnStreamSettings;
const streamStats = StreamStats.getInstance();
let $btnStreamStats = StreamUiHandler.$btnStreamStats;
- if (typeof $btnStreamStats === "undefined")
- $btnStreamStats = StreamUiHandler.cloneStreamHudButton($orgButton, t("stream-stats"), BxIcon.STREAM_STATS), $btnStreamStats?.addEventListener("click", (e) => {
+ if (typeof $btnStreamStats === "undefined") $btnStreamStats = StreamUiHandler.cloneStreamHudButton($orgButton, t("stream-stats"), BxIcon.STREAM_STATS), $btnStreamStats?.addEventListener("click", (e) => {
hideGripHandle(), e.preventDefault(), streamStats.toggle();
const btnStreamStatsOn = !streamStats.isHidden() && !streamStats.isGlancing();
$btnStreamStats.classList.toggle("bx-stream-menu-button-on", btnStreamStatsOn);
@@ -8002,8 +7471,7 @@ class StreamUiHandler {
StreamUiHandler.handleStreamMenu();
return;
}
- if (className.startsWith("Overlay-module_") || className.startsWith("InProgressScreen"))
- $elm = $elm.querySelector("#StreamHud");
+ if (className.startsWith("Overlay-module_") || className.startsWith("InProgressScreen")) $elm = $elm.querySelector("#StreamHud");
if (!$elm || ($elm.id || "") !== "StreamHud") return;
StreamUiHandler.handleSystemMenu($elm);
});
@@ -8031,26 +7499,22 @@ function observeRootDialog($root) {
let beingShown = !1;
new MutationObserver((mutationList) => {
for (let mutation of mutationList) {
- if (mutation.type !== "childList")
- continue;
+ if (mutation.type !== "childList") continue;
if (BX_FLAGS.Debug && BxLogger.warning("RootDialog", "added", mutation.addedNodes), mutation.addedNodes.length === 1) {
const $addedElm = mutation.addedNodes[0];
if ($addedElm instanceof HTMLElement && $addedElm.className) {
- if ($root.querySelector("div[class*=GuideDialog]"))
- GuideMenu.observe($addedElm);
+ if ($root.querySelector("div[class*=GuideDialog]")) GuideMenu.observe($addedElm);
}
}
const shown = !!($root.firstElementChild && $root.firstElementChild.childElementCount > 0);
- if (shown !== beingShown)
- beingShown = shown, BxEvent.dispatch(window, shown ? BxEvent.XCLOUD_DIALOG_SHOWN : BxEvent.XCLOUD_DIALOG_DISMISSED);
+ if (shown !== beingShown) beingShown = shown, BxEvent.dispatch(window, shown ? BxEvent.XCLOUD_DIALOG_SHOWN : BxEvent.XCLOUD_DIALOG_DISMISSED);
}
}).observe($root, { subtree: !0, childList: !0 });
}
function waitForRootDialog() {
const observer = new MutationObserver((mutationList) => {
for (let mutation of mutationList) {
- if (mutation.type !== "childList")
- continue;
+ if (mutation.type !== "childList") continue;
const $target = mutation.target;
if ($target.id && $target.id === "gamepass-dialog-root") {
observer.disconnect(), observeRootDialog($target);
@@ -8061,16 +7525,11 @@ function waitForRootDialog() {
observer.observe(document.documentElement, { subtree: !0, childList: !0 });
}
function main() {
- if (waitForRootDialog(), patchRtcPeerConnection(), patchRtcCodecs(), interceptHttpRequests(), patchVideoApi(), patchCanvasContext(), AppInterface && patchPointerLockApi(), getPref("audio_enable_volume_control") && patchAudioContext(), getPref("block_tracking"))
- patchMeControl(), disableAdobeAudienceManager();
- if (STATES.userAgent.capabilities.touch && TouchController.updateCustomList(), overridePreloadState(), VibrationManager.initialSetup(), BX_FLAGS.CheckForUpdate && checkForUpdate(), addCss(), Toast.setup(), getPref("game_bar_position") !== "off" && GameBar.getInstance(), Screenshot.setup(), GuideMenu.addEventListeners(), StreamBadges.setupEvents(), StreamStats.setupEvents(), EmulatedMkbHandler.setupEvents(), Patcher.init(), disablePwa(), getPref("controller_show_connection_status"))
- window.addEventListener("gamepadconnected", (e) => showGamepadToast(e.gamepad)), window.addEventListener("gamepaddisconnected", (e) => showGamepadToast(e.gamepad));
- if (getPref("xhome_enabled"))
- RemotePlayManager.detect();
- if (getPref("stream_touch_controller") === "all")
- TouchController.setup();
- if (getPref("mkb_enabled") && AppInterface)
- STATES.pointerServerPort = AppInterface.startPointerServer() || 9269, BxLogger.info("startPointerServer", "Port", STATES.pointerServerPort.toString());
+ if (waitForRootDialog(), patchRtcPeerConnection(), patchRtcCodecs(), interceptHttpRequests(), patchVideoApi(), patchCanvasContext(), AppInterface && patchPointerLockApi(), getPref("audio_enable_volume_control") && patchAudioContext(), getPref("block_tracking")) patchMeControl(), disableAdobeAudienceManager();
+ if (STATES.userAgent.capabilities.touch && TouchController.updateCustomList(), overridePreloadState(), VibrationManager.initialSetup(), BX_FLAGS.CheckForUpdate && checkForUpdate(), addCss(), Toast.setup(), getPref("game_bar_position") !== "off" && GameBar.getInstance(), Screenshot.setup(), GuideMenu.addEventListeners(), StreamBadges.setupEvents(), StreamStats.setupEvents(), EmulatedMkbHandler.setupEvents(), Patcher.init(), disablePwa(), getPref("controller_show_connection_status")) window.addEventListener("gamepadconnected", (e) => showGamepadToast(e.gamepad)), window.addEventListener("gamepaddisconnected", (e) => showGamepadToast(e.gamepad));
+ if (getPref("xhome_enabled")) RemotePlayManager.detect();
+ if (getPref("stream_touch_controller") === "all") TouchController.setup();
+ if (getPref("mkb_enabled") && AppInterface) STATES.pointerServerPort = AppInterface.startPointerServer() || 9269, BxLogger.info("startPointerServer", "Port", STATES.pointerServerPort.toString());
getPref("ui_game_card_show_wait_time") && GameTile.setup();
}
if (window.location.pathname.includes("/auth/msa")) {
@@ -8087,32 +7546,29 @@ if (window.location.pathname.includes("/auth/msa")) {
BxLogger.info("readyState", document.readyState);
if (BX_FLAGS.SafariWorkaround && document.readyState !== "loading") {
window.stop();
- const css = '.bx-reload-overlay{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;background:rgba(0,0,0,0.8);z-index:9999;color:#fff;text-align:center;font-weight:400;font-family:"Segoe UI",Arial,Helvetica,sans-serif;font-size:1.3rem}.bx-reload-overlay *:focus{outline:none !important}.bx-reload-overlay > div{margin:0 auto}.bx-reload-overlay a{text-decoration:none;display:inline-block;background:#107c10;color:#fff;border-radius:4px;padding:6px}', isSafari = UserAgent.isSafari();
+ let css = "";
+ css += '.bx-reload-overlay{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;background:rgba(0,0,0,0.8);z-index:9999;color:#fff;text-align:center;font-weight:400;font-family:"Segoe UI",Arial,Helvetica,sans-serif;font-size:1.3rem}.bx-reload-overlay *:focus{outline:none !important}.bx-reload-overlay > div{margin:0 auto}.bx-reload-overlay a{text-decoration:none;display:inline-block;background:#107c10;color:#fff;border-radius:4px;padding:6px}';
+ const isSafari = UserAgent.isSafari();
let $secondaryAction;
- if (isSafari)
- $secondaryAction = CE("p", {}, t("settings-reloading"));
- else
- $secondaryAction = CE("a", {
+ if (isSafari) $secondaryAction = CE("p", {}, t("settings-reloading"));
+ else $secondaryAction = CE("a", {
href: "https://better-xcloud.github.io/troubleshooting",
target: "_blank"
}, "🤓 " + t("how-to-fix"));
const $fragment = document.createDocumentFragment();
- throw $fragment.appendChild(CE("style", {}, '.bx-reload-overlay{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:center;background:rgba(0,0,0,0.8);z-index:9999;color:#fff;text-align:center;font-weight:400;font-family:"Segoe UI",Arial,Helvetica,sans-serif;font-size:1.3rem}.bx-reload-overlay *:focus{outline:none !important}.bx-reload-overlay > div{margin:0 auto}.bx-reload-overlay a{text-decoration:none;display:inline-block;background:#107c10;color:#fff;border-radius:4px;padding:6px}')), $fragment.appendChild(CE("div", {
+ throw $fragment.appendChild(CE("style", {}, css)), $fragment.appendChild(CE("div", {
class: "bx-reload-overlay"
}, CE("div", {}, CE("p", {}, t("load-failed-message")), $secondaryAction))), document.documentElement.appendChild($fragment), isSafari && window.location.reload(!0), new Error("[Better xCloud] Executing workaround for Safari");
}
window.addEventListener("load", (e) => {
window.setTimeout(() => {
- if (document.body.classList.contains("legacyBackground"))
- window.stop(), window.location.reload(!0);
+ if (document.body.classList.contains("legacyBackground")) window.stop(), window.location.reload(!0);
}, 3000);
});
document.addEventListener("readystatechange", (e) => {
if (document.readyState !== "interactive") return;
- if (STATES.isSignedIn = !!window.xbcUser?.isSignedIn, STATES.isSignedIn)
- getPref("xhome_enabled") && RemotePlayManager.getInstance().initialize();
- else
- window.setTimeout(HeaderSection.watchHeader, 2000);
+ if (STATES.isSignedIn = !!window.xbcUser?.isSignedIn, STATES.isSignedIn) getPref("xhome_enabled") && RemotePlayManager.getInstance().initialize();
+ else window.setTimeout(HeaderSection.watchHeader, 2000);
if (getPref("ui_hide_sections").includes("friends")) {
const $parent = document.querySelector("div[class*=PlayWithFriendsSkeleton]")?.closest("div[class*=HomePage-module]");
$parent && ($parent.style.display = "none");
@@ -8131,15 +7587,12 @@ window.addEventListener(BxEvent.XCLOUD_SERVERS_READY, (e) => {
STATES.isSignedIn = !0, window.setTimeout(HeaderSection.watchHeader, 2000);
});
window.addEventListener(BxEvent.STREAM_LOADING, (e) => {
- if (window.location.pathname.includes("/launch/") && STATES.currentStream.titleInfo)
- STATES.currentStream.titleSlug = productTitleToSlug(STATES.currentStream.titleInfo.product.title);
- else
- STATES.currentStream.titleSlug = "remote-play";
+ if (window.location.pathname.includes("/launch/") && STATES.currentStream.titleInfo) STATES.currentStream.titleSlug = productTitleToSlug(STATES.currentStream.titleInfo.product.title);
+ else STATES.currentStream.titleSlug = "remote-play";
});
getPref("ui_loading_screen_game_art") && window.addEventListener(BxEvent.TITLE_INFO_READY, LoadingScreen.setup);
window.addEventListener(BxEvent.STREAM_STARTING, (e) => {
- if (LoadingScreen.hide(), !getPref("mkb_enabled") && getPref("mkb_hide_idle_cursor"))
- MouseCursorHider.start(), MouseCursorHider.hide();
+ if (LoadingScreen.hide(), !getPref("mkb_enabled") && getPref("mkb_hide_idle_cursor")) MouseCursorHider.start(), MouseCursorHider.hide();
});
window.addEventListener(BxEvent.STREAM_PLAYING, (e) => {
if (STATES.isPlaying = !0, StreamUiHandler.observe(), getPref("game_bar_position") !== "off") {
@@ -8153,8 +7606,7 @@ window.addEventListener(BxEvent.STREAM_ERROR_PAGE, (e) => {
BxEvent.dispatch(window, BxEvent.STREAM_STOPPED);
});
window.addEventListener(BxEvent.XCLOUD_RENDERING_COMPONENT, (e) => {
- if (e.component === "product-details")
- ProductDetailsPage.injectButtons();
+ if (e.component === "product-details") ProductDetailsPage.injectButtons();
});
window.addEventListener(BxEvent.DATA_CHANNEL_CREATED, (e) => {
const dataChannel = e.dataChannel;
@@ -8166,8 +7618,7 @@ window.addEventListener(BxEvent.DATA_CHANNEL_CREATED, (e) => {
if (STATES.currentStream.xboxTitleId = xboxTitleId, STATES.remotePlay.isPlaying) {
if (STATES.currentStream.titleSlug = "remote-play", json.focused) {
const productTitle = await XboxApi.getProductTitle(xboxTitleId);
- if (productTitle)
- STATES.currentStream.titleSlug = productTitleToSlug(productTitle);
+ if (productTitle) STATES.currentStream.titleSlug = productTitleToSlug(productTitle);
}
}
}