Update dist

This commit is contained in:
redphx 2024-10-14 17:17:32 +07:00
parent 8e88af5f8c
commit 82ee00b4ae
2 changed files with 12678 additions and 12762 deletions

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud (Lite) // @name Better xCloud (Lite)
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 5.8.4 // @version 5.8.5-beta
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@ -111,7 +111,7 @@ function deepClone(obj) {
if (!obj) return {}; if (!obj) return {};
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
} }
var SCRIPT_VERSION = "5.8.4", SCRIPT_VARIANT = "lite", AppInterface = window.AppInterface; var SCRIPT_VERSION = "5.8.5-beta", SCRIPT_VARIANT = "lite", AppInterface = window.AppInterface;
UserAgent.init(); UserAgent.init();
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, supportMkb = AppInterface || !userAgent.match(/(android|iphone|ipad)/), STATES = { var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, supportMkb = AppInterface || !userAgent.match(/(android|iphone|ipad)/), STATES = {
supportedRegion: !0, supportedRegion: !0,
@ -936,10 +936,7 @@ class BaseSettingsStore {
} }
class StreamStatsCollector { class StreamStatsCollector {
static instance; static instance;
static getInstance() { static getInstance = () => StreamStatsCollector.instance ?? (StreamStatsCollector.instance = new StreamStatsCollector);
if (!StreamStatsCollector.instance) StreamStatsCollector.instance = new StreamStatsCollector;
return StreamStatsCollector.instance;
}
static INTERVAL_BACKGROUND = 60000; static INTERVAL_BACKGROUND = 60000;
calculateGrade(value, grades) { calculateGrade(value, grades) {
return value > grades[2] ? "bad" : value > grades[1] ? "ok" : value > grades[0] ? "good" : ""; return value > grades[2] ? "bad" : value > grades[1] ? "ok" : value > grades[0] ? "good" : "";
@ -1807,10 +1804,7 @@ var MouseMapTo;
})(MouseMapTo ||= {}); })(MouseMapTo ||= {});
class StreamStats { class StreamStats {
static instance; static instance;
static getInstance() { static getInstance = () => StreamStats.instance ?? (StreamStats.instance = new StreamStats);
if (!StreamStats.instance) StreamStats.instance = new StreamStats;
return StreamStats.instance;
}
intervalId; intervalId;
REFRESH_INTERVAL = 1000; REFRESH_INTERVAL = 1000;
stats = { stats = {
@ -2141,14 +2135,13 @@ function onChangeVideoPlayerType() {
else if ($videoProcessing.value = "usm", setPref("video_processing", "usm"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0; 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"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), updateVideoPlayer(); $videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), updateVideoPlayer();
} }
function limitVideoPlayerFps() { function limitVideoPlayerFps(targetFps) {
const targetFps = getPref("video_max_fps");
STATES.currentStream.streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps); STATES.currentStream.streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps);
} }
function updateVideoPlayer() { function updateVideoPlayer() {
const streamPlayer = STATES.currentStream.streamPlayer; const streamPlayer = STATES.currentStream.streamPlayer;
if (!streamPlayer) return; if (!streamPlayer) return;
limitVideoPlayerFps(); limitVideoPlayerFps(getPref("video_max_fps"));
const options = { const options = {
processing: getPref("video_processing"), processing: getPref("video_processing"),
sharpness: getPref("video_sharpness"), sharpness: getPref("video_sharpness"),
@ -2381,10 +2374,7 @@ class KeyHelper {
var LOG_TAG = "PointerClient"; var LOG_TAG = "PointerClient";
class PointerClient { class PointerClient {
static instance; static instance;
static getInstance() { static getInstance = () => PointerClient.instance ?? (PointerClient.instance = new PointerClient);
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
return PointerClient.instance;
}
socket; socket;
mkbHandler; mkbHandler;
start(port, mkbHandler) { start(port, mkbHandler) {
@ -2516,11 +2506,8 @@ class PointerLockMouseDataProvider extends MouseDataProvider {
#disableContextMenu = (e) => e.preventDefault(); #disableContextMenu = (e) => e.preventDefault();
} }
class EmulatedMkbHandler extends MkbHandler { class EmulatedMkbHandler extends MkbHandler {
static #instance; static instance;
static getInstance() { static getInstance = () => EmulatedMkbHandler.instance ?? (EmulatedMkbHandler.instance = new EmulatedMkbHandler);
if (!EmulatedMkbHandler.#instance) EmulatedMkbHandler.#instance = new EmulatedMkbHandler;
return EmulatedMkbHandler.#instance;
}
#CURRENT_PRESET_DATA = MkbPreset.convert(MkbPreset.DEFAULT_PRESET); #CURRENT_PRESET_DATA = MkbPreset.convert(MkbPreset.DEFAULT_PRESET);
static DEFAULT_PANNING_SENSITIVITY = 0.001; static DEFAULT_PANNING_SENSITIVITY = 0.001;
static DEFAULT_DEADZONE_COUNTERWEIGHT = 0.01; static DEFAULT_DEADZONE_COUNTERWEIGHT = 0.01;
@ -2798,10 +2785,7 @@ class NavigationDialog {
} }
class NavigationDialogManager { class NavigationDialogManager {
static instance; static instance;
static getInstance() { static getInstance = () => NavigationDialogManager.instance ?? (NavigationDialogManager.instance = new NavigationDialogManager);
if (!NavigationDialogManager.instance) NavigationDialogManager.instance = new NavigationDialogManager;
return NavigationDialogManager.instance;
}
static GAMEPAD_POLLING_INTERVAL = 50; static GAMEPAD_POLLING_INTERVAL = 50;
static GAMEPAD_KEYS = [ static GAMEPAD_KEYS = [
12, 12,
@ -3171,10 +3155,7 @@ if (getPref("block_social_features")) FeatureGates.EnableGuideChatTab = !1;
if (BX_FLAGS.FeatureGates) FeatureGates = Object.assign(BX_FLAGS.FeatureGates, FeatureGates); if (BX_FLAGS.FeatureGates) FeatureGates = Object.assign(BX_FLAGS.FeatureGates, FeatureGates);
class FullscreenText { class FullscreenText {
static instance; static instance;
static getInstance() { static getInstance = () => FullscreenText.instance ?? (FullscreenText.instance = new FullscreenText);
if (!FullscreenText.instance) FullscreenText.instance = new FullscreenText;
return FullscreenText.instance;
}
$text; $text;
constructor() { constructor() {
this.$text = CE("div", { this.$text = CE("div", {
@ -3190,10 +3171,7 @@ class FullscreenText {
} }
class SettingsNavigationDialog extends NavigationDialog { class SettingsNavigationDialog extends NavigationDialog {
static instance; static instance;
static getInstance() { static getInstance = () => SettingsNavigationDialog.instance ?? (SettingsNavigationDialog.instance = new SettingsNavigationDialog);
if (!SettingsNavigationDialog.instance) SettingsNavigationDialog.instance = new SettingsNavigationDialog;
return SettingsNavigationDialog.instance;
}
$container; $container;
$tabs; $tabs;
$settings; $settings;
@ -3458,7 +3436,9 @@ class SettingsNavigationDialog extends NavigationDialog {
onChange: onChangeVideoPlayerType onChange: onChangeVideoPlayerType
}, { }, {
pref: "video_max_fps", pref: "video_max_fps",
onChange: limitVideoPlayerFps onChange: (e) => {
limitVideoPlayerFps(parseInt(e.target.value));
}
}, { }, {
pref: "video_power_preference", pref: "video_power_preference",
onChange: () => { onChange: () => {
@ -4185,10 +4165,7 @@ class HeaderSection {
} }
class RemotePlayNavigationDialog extends NavigationDialog { class RemotePlayNavigationDialog extends NavigationDialog {
static instance; static instance;
static getInstance() { static getInstance = () => RemotePlayNavigationDialog.instance ?? (RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog);
if (!RemotePlayNavigationDialog.instance) RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog;
return RemotePlayNavigationDialog.instance;
}
STATE_LABELS = { STATE_LABELS = {
On: t("powered-on"), On: t("powered-on"),
Off: t("powered-off"), Off: t("powered-off"),
@ -4254,10 +4231,7 @@ class RemotePlayNavigationDialog extends NavigationDialog {
var LOG_TAG2 = "RemotePlay"; var LOG_TAG2 = "RemotePlay";
class RemotePlayManager { class RemotePlayManager {
static instance; static instance;
static getInstance() { static getInstance = () => RemotePlayManager.instance ?? (RemotePlayManager.instance = new RemotePlayManager);
if (!this.instance) this.instance = new RemotePlayManager;
return this.instance;
}
isInitialized = !1; isInitialized = !1;
XCLOUD_TOKEN; XCLOUD_TOKEN;
XHOME_TOKEN; XHOME_TOKEN;
@ -4544,10 +4518,7 @@ class GuideMenu {
} }
class StreamBadges { class StreamBadges {
static instance; static instance;
static getInstance() { static getInstance = () => StreamBadges.instance ?? (StreamBadges.instance = new StreamBadges);
if (!StreamBadges.instance) StreamBadges.instance = new StreamBadges;
return StreamBadges.instance;
}
serverInfo = {}; serverInfo = {};
badges = { badges = {
playtime: { playtime: {
@ -5107,7 +5078,7 @@ class WebGL2Player {
this.options.saturation = 1 + (saturation - 100) / 100, update && this.updateCanvas(); this.options.saturation = 1 + (saturation - 100) / 100, update && this.updateCanvas();
} }
setTargetFps(target) { setTargetFps(target) {
this.targetFps = target, this.frameInterval = Math.ceil(1000 / target); this.targetFps = target, this.lastFrameTime = 0, this.frameInterval = target ? Math.floor(1000 / target) : 0;
} }
getCanvas() { getCanvas() {
return this.$canvas; return this.$canvas;
@ -5117,6 +5088,7 @@ class WebGL2Player {
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), this.options.filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpenFactor), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation); gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), this.options.filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpenFactor), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation);
} }
drawFrame() { drawFrame() {
if (this.targetFps === 0) return;
if (this.targetFps < 60) { if (this.targetFps < 60) {
const currentTime = performance.now(); const currentTime = performance.now();
if (currentTime - this.lastFrameTime < this.frameInterval) return; if (currentTime - this.lastFrameTime < this.frameInterval) return;
@ -5171,9 +5143,9 @@ class WebGL2Player {
BxLogger.info(this.LOG_TAG, "Destroy"), this.stop(); BxLogger.info(this.LOG_TAG, "Destroy"), this.stop();
const gl = this.gl; const gl = this.gl;
if (gl) { if (gl) {
gl.getExtension("WEBGL_lose_context")?.loseContext(); gl.getExtension("WEBGL_lose_context")?.loseContext(), gl.useProgram(null);
for (let resource of this.resources) for (let resource of this.resources)
if (resource instanceof WebGLProgram) gl.useProgram(null), gl.deleteProgram(resource); if (resource instanceof WebGLProgram) gl.deleteProgram(resource);
else if (resource instanceof WebGLShader) gl.deleteShader(resource); else if (resource instanceof WebGLShader) gl.deleteShader(resource);
else if (resource instanceof WebGLTexture) gl.deleteTexture(resource); else if (resource instanceof WebGLTexture) gl.deleteTexture(resource);
else if (resource instanceof WebGLBuffer) gl.deleteBuffer(resource); else if (resource instanceof WebGLBuffer) gl.deleteBuffer(resource);

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud // @name Better xCloud
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 5.8.4 // @version 5.8.5-beta
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@ -113,7 +113,7 @@ function deepClone(obj) {
if (!obj) return {}; if (!obj) return {};
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
} }
var SCRIPT_VERSION = "5.8.4", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface; var SCRIPT_VERSION = "5.8.5-beta", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
UserAgent.init(); UserAgent.init();
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, supportMkb = AppInterface || !userAgent.match(/(android|iphone|ipad)/), STATES = { var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, supportMkb = AppInterface || !userAgent.match(/(android|iphone|ipad)/), STATES = {
supportedRegion: !0, supportedRegion: !0,
@ -963,10 +963,7 @@ class BaseSettingsStore {
} }
class StreamStatsCollector { class StreamStatsCollector {
static instance; static instance;
static getInstance() { static getInstance = () => StreamStatsCollector.instance ?? (StreamStatsCollector.instance = new StreamStatsCollector);
if (!StreamStatsCollector.instance) StreamStatsCollector.instance = new StreamStatsCollector;
return StreamStatsCollector.instance;
}
static INTERVAL_BACKGROUND = 60000; static INTERVAL_BACKGROUND = 60000;
calculateGrade(value, grades) { calculateGrade(value, grades) {
return value > grades[2] ? "bad" : value > grades[1] ? "ok" : value > grades[0] ? "good" : ""; return value > grades[2] ? "bad" : value > grades[1] ? "ok" : value > grades[0] ? "good" : "";
@ -1878,10 +1875,7 @@ var MouseMapTo;
})(MouseMapTo ||= {}); })(MouseMapTo ||= {});
class StreamStats { class StreamStats {
static instance; static instance;
static getInstance() { static getInstance = () => StreamStats.instance ?? (StreamStats.instance = new StreamStats);
if (!StreamStats.instance) StreamStats.instance = new StreamStats;
return StreamStats.instance;
}
intervalId; intervalId;
REFRESH_INTERVAL = 1000; REFRESH_INTERVAL = 1000;
stats = { stats = {
@ -2258,14 +2252,13 @@ function onChangeVideoPlayerType() {
else if ($videoProcessing.value = "usm", setPref("video_processing", "usm"), $optCas && ($optCas.disabled = !0), UserAgent.isSafari()) isDisabled = !0; 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"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), updateVideoPlayer(); $videoProcessing.disabled = isDisabled, $videoSharpness.dataset.disabled = isDisabled.toString(), $videoPowerPreference.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), $videoMaxFps.closest(".bx-settings-row").classList.toggle("bx-gone", playerType !== "webgl2"), updateVideoPlayer();
} }
function limitVideoPlayerFps() { function limitVideoPlayerFps(targetFps) {
const targetFps = getPref("video_max_fps");
STATES.currentStream.streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps); STATES.currentStream.streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps);
} }
function updateVideoPlayer() { function updateVideoPlayer() {
const streamPlayer = STATES.currentStream.streamPlayer; const streamPlayer = STATES.currentStream.streamPlayer;
if (!streamPlayer) return; if (!streamPlayer) return;
limitVideoPlayerFps(); limitVideoPlayerFps(getPref("video_max_fps"));
const options = { const options = {
processing: getPref("video_processing"), processing: getPref("video_processing"),
sharpness: getPref("video_sharpness"), sharpness: getPref("video_sharpness"),
@ -2498,10 +2491,7 @@ class KeyHelper {
var LOG_TAG = "PointerClient"; var LOG_TAG = "PointerClient";
class PointerClient { class PointerClient {
static instance; static instance;
static getInstance() { static getInstance = () => PointerClient.instance ?? (PointerClient.instance = new PointerClient);
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
return PointerClient.instance;
}
socket; socket;
mkbHandler; mkbHandler;
start(port, mkbHandler) { start(port, mkbHandler) {
@ -2575,6 +2565,7 @@ class MouseDataProvider {
class MkbHandler {} class MkbHandler {}
class NativeMkbHandler extends MkbHandler { class NativeMkbHandler extends MkbHandler {
static instance; static instance;
static getInstance = () => NativeMkbHandler.instance ?? (NativeMkbHandler.instance = new NativeMkbHandler);
#pointerClient; #pointerClient;
#enabled = !1; #enabled = !1;
#mouseButtonsPressed = 0; #mouseButtonsPressed = 0;
@ -2584,10 +2575,6 @@ class NativeMkbHandler extends MkbHandler {
#mouseHorizontalMultiply = 0; #mouseHorizontalMultiply = 0;
#inputSink; #inputSink;
#$message; #$message;
static getInstance() {
if (!NativeMkbHandler.instance) NativeMkbHandler.instance = new NativeMkbHandler;
return NativeMkbHandler.instance;
}
#onKeyboardEvent(e) { #onKeyboardEvent(e) {
if (e.type === "keyup" && e.code === "F8") { if (e.type === "keyup" && e.code === "F8") {
e.preventDefault(), this.toggle(); e.preventDefault(), this.toggle();
@ -2793,11 +2780,8 @@ class PointerLockMouseDataProvider extends MouseDataProvider {
#disableContextMenu = (e) => e.preventDefault(); #disableContextMenu = (e) => e.preventDefault();
} }
class EmulatedMkbHandler extends MkbHandler { class EmulatedMkbHandler extends MkbHandler {
static #instance; static instance;
static getInstance() { static getInstance = () => EmulatedMkbHandler.instance ?? (EmulatedMkbHandler.instance = new EmulatedMkbHandler);
if (!EmulatedMkbHandler.#instance) EmulatedMkbHandler.#instance = new EmulatedMkbHandler;
return EmulatedMkbHandler.#instance;
}
#CURRENT_PRESET_DATA = MkbPreset.convert(MkbPreset.DEFAULT_PRESET); #CURRENT_PRESET_DATA = MkbPreset.convert(MkbPreset.DEFAULT_PRESET);
static DEFAULT_PANNING_SENSITIVITY = 0.001; static DEFAULT_PANNING_SENSITIVITY = 0.001;
static DEFAULT_DEADZONE_COUNTERWEIGHT = 0.01; static DEFAULT_DEADZONE_COUNTERWEIGHT = 0.01;
@ -3081,10 +3065,7 @@ class NavigationDialog {
} }
class NavigationDialogManager { class NavigationDialogManager {
static instance; static instance;
static getInstance() { static getInstance = () => NavigationDialogManager.instance ?? (NavigationDialogManager.instance = new NavigationDialogManager);
if (!NavigationDialogManager.instance) NavigationDialogManager.instance = new NavigationDialogManager;
return NavigationDialogManager.instance;
}
static GAMEPAD_POLLING_INTERVAL = 50; static GAMEPAD_POLLING_INTERVAL = 50;
static GAMEPAD_KEYS = [ static GAMEPAD_KEYS = [
12, 12,
@ -4551,10 +4532,7 @@ class PatcherCache {
} }
class FullscreenText { class FullscreenText {
static instance; static instance;
static getInstance() { static getInstance = () => FullscreenText.instance ?? (FullscreenText.instance = new FullscreenText);
if (!FullscreenText.instance) FullscreenText.instance = new FullscreenText;
return FullscreenText.instance;
}
$text; $text;
constructor() { constructor() {
this.$text = CE("div", { this.$text = CE("div", {
@ -4570,10 +4548,7 @@ class FullscreenText {
} }
class SettingsNavigationDialog extends NavigationDialog { class SettingsNavigationDialog extends NavigationDialog {
static instance; static instance;
static getInstance() { static getInstance = () => SettingsNavigationDialog.instance ?? (SettingsNavigationDialog.instance = new SettingsNavigationDialog);
if (!SettingsNavigationDialog.instance) SettingsNavigationDialog.instance = new SettingsNavigationDialog;
return SettingsNavigationDialog.instance;
}
$container; $container;
$tabs; $tabs;
$settings; $settings;
@ -4838,7 +4813,9 @@ class SettingsNavigationDialog extends NavigationDialog {
onChange: onChangeVideoPlayerType onChange: onChangeVideoPlayerType
}, { }, {
pref: "video_max_fps", pref: "video_max_fps",
onChange: limitVideoPlayerFps onChange: (e) => {
limitVideoPlayerFps(parseInt(e.target.value));
}
}, { }, {
pref: "video_power_preference", pref: "video_power_preference",
onChange: () => { onChange: () => {
@ -5832,10 +5809,7 @@ class HeaderSection {
} }
class RemotePlayNavigationDialog extends NavigationDialog { class RemotePlayNavigationDialog extends NavigationDialog {
static instance; static instance;
static getInstance() { static getInstance = () => RemotePlayNavigationDialog.instance ?? (RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog);
if (!RemotePlayNavigationDialog.instance) RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog;
return RemotePlayNavigationDialog.instance;
}
STATE_LABELS = { STATE_LABELS = {
On: t("powered-on"), On: t("powered-on"),
Off: t("powered-off"), Off: t("powered-off"),
@ -5901,10 +5875,7 @@ class RemotePlayNavigationDialog extends NavigationDialog {
var LOG_TAG5 = "RemotePlay"; var LOG_TAG5 = "RemotePlay";
class RemotePlayManager { class RemotePlayManager {
static instance; static instance;
static getInstance() { static getInstance = () => RemotePlayManager.instance ?? (RemotePlayManager.instance = new RemotePlayManager);
if (!this.instance) this.instance = new RemotePlayManager;
return this.instance;
}
isInitialized = !1; isInitialized = !1;
XCLOUD_TOKEN; XCLOUD_TOKEN;
XHOME_TOKEN; XHOME_TOKEN;
@ -6413,10 +6384,7 @@ class GuideMenu {
} }
class StreamBadges { class StreamBadges {
static instance; static instance;
static getInstance() { static getInstance = () => StreamBadges.instance ?? (StreamBadges.instance = new StreamBadges);
if (!StreamBadges.instance) StreamBadges.instance = new StreamBadges;
return StreamBadges.instance;
}
serverInfo = {}; serverInfo = {};
badges = { badges = {
playtime: { playtime: {
@ -7015,7 +6983,7 @@ class WebGL2Player {
this.options.saturation = 1 + (saturation - 100) / 100, update && this.updateCanvas(); this.options.saturation = 1 + (saturation - 100) / 100, update && this.updateCanvas();
} }
setTargetFps(target) { setTargetFps(target) {
this.targetFps = target, this.frameInterval = Math.ceil(1000 / target); this.targetFps = target, this.lastFrameTime = 0, this.frameInterval = target ? Math.floor(1000 / target) : 0;
} }
getCanvas() { getCanvas() {
return this.$canvas; return this.$canvas;
@ -7025,6 +6993,7 @@ class WebGL2Player {
gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), this.options.filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpenFactor), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation); gl.uniform2f(gl.getUniformLocation(program, "iResolution"), this.$canvas.width, this.$canvas.height), gl.uniform1i(gl.getUniformLocation(program, "filterId"), this.options.filterId), gl.uniform1f(gl.getUniformLocation(program, "sharpenFactor"), this.options.sharpenFactor), gl.uniform1f(gl.getUniformLocation(program, "brightness"), this.options.brightness), gl.uniform1f(gl.getUniformLocation(program, "contrast"), this.options.contrast), gl.uniform1f(gl.getUniformLocation(program, "saturation"), this.options.saturation);
} }
drawFrame() { drawFrame() {
if (this.targetFps === 0) return;
if (this.targetFps < 60) { if (this.targetFps < 60) {
const currentTime = performance.now(); const currentTime = performance.now();
if (currentTime - this.lastFrameTime < this.frameInterval) return; if (currentTime - this.lastFrameTime < this.frameInterval) return;
@ -7079,9 +7048,9 @@ class WebGL2Player {
BxLogger.info(this.LOG_TAG, "Destroy"), this.stop(); BxLogger.info(this.LOG_TAG, "Destroy"), this.stop();
const gl = this.gl; const gl = this.gl;
if (gl) { if (gl) {
gl.getExtension("WEBGL_lose_context")?.loseContext(); gl.getExtension("WEBGL_lose_context")?.loseContext(), gl.useProgram(null);
for (let resource of this.resources) for (let resource of this.resources)
if (resource instanceof WebGLProgram) gl.useProgram(null), gl.deleteProgram(resource); if (resource instanceof WebGLProgram) gl.deleteProgram(resource);
else if (resource instanceof WebGLShader) gl.deleteShader(resource); else if (resource instanceof WebGLShader) gl.deleteShader(resource);
else if (resource instanceof WebGLTexture) gl.deleteTexture(resource); else if (resource instanceof WebGLTexture) gl.deleteTexture(resource);
else if (resource instanceof WebGLBuffer) gl.deleteBuffer(resource); else if (resource instanceof WebGLBuffer) gl.deleteBuffer(resource);
@ -7343,6 +7312,9 @@ class BaseGameBarAction {
onClick(e) { onClick(e) {
BxEvent.dispatch(window, BxEvent.GAME_BAR_ACTION_ACTIVATED); BxEvent.dispatch(window, BxEvent.GAME_BAR_ACTION_ACTIVATED);
} }
render() {
return this.$content;
}
} }
class ScreenshotAction extends BaseGameBarAction { class ScreenshotAction extends BaseGameBarAction {
$content; $content;
@ -7358,9 +7330,6 @@ class ScreenshotAction extends BaseGameBarAction {
onClick(e) { onClick(e) {
super.onClick(e), Screenshot.takeScreenshot(); super.onClick(e), Screenshot.takeScreenshot();
} }
render() {
return this.$content;
}
} }
class TouchControlAction extends BaseGameBarAction { class TouchControlAction extends BaseGameBarAction {
$content; $content;
@ -7378,23 +7347,19 @@ class TouchControlAction extends BaseGameBarAction {
onClick: this.onClick.bind(this), onClick: this.onClick.bind(this),
classes: ["bx-activated"] classes: ["bx-activated"]
}); });
this.$content = CE("div", {}, $btnEnable, $btnDisable), this.reset(); this.$content = CE("div", {}, $btnEnable, $btnDisable);
} }
onClick(e) { onClick(e) {
super.onClick(e); super.onClick(e);
const isVisible = TouchController.toggleVisibility(); const isVisible = TouchController.toggleVisibility();
this.$content.dataset.activated = (!isVisible).toString(); this.$content.dataset.activated = (!isVisible).toString();
} }
render() {
return this.$content;
}
reset() { reset() {
this.$content.dataset.activated = "false"; this.$content.dataset.activated = "false";
} }
} }
class MicrophoneAction extends BaseGameBarAction { class MicrophoneAction extends BaseGameBarAction {
$content; $content;
visible = !1;
constructor() { constructor() {
super(); super();
const $btnDefault = createButton({ const $btnDefault = createButton({
@ -7407,7 +7372,7 @@ class MicrophoneAction extends BaseGameBarAction {
icon: BxIcon.MICROPHONE_MUTED, icon: BxIcon.MICROPHONE_MUTED,
onClick: this.onClick.bind(this) onClick: this.onClick.bind(this)
}); });
this.$content = CE("div", {}, $btnMuted, $btnDefault), this.reset(), window.addEventListener(BxEvent.MICROPHONE_STATE_CHANGED, (e) => { this.$content = CE("div", {}, $btnMuted, $btnDefault), window.addEventListener(BxEvent.MICROPHONE_STATE_CHANGED, (e) => {
const enabled = e.microphoneState === "Enabled"; const enabled = e.microphoneState === "Enabled";
this.$content.dataset.activated = enabled.toString(), this.$content.classList.remove("bx-gone"); this.$content.dataset.activated = enabled.toString(), this.$content.classList.remove("bx-gone");
}); });
@ -7417,11 +7382,8 @@ class MicrophoneAction extends BaseGameBarAction {
const enabled = MicrophoneShortcut.toggle(!1); const enabled = MicrophoneShortcut.toggle(!1);
this.$content.dataset.activated = enabled.toString(); this.$content.dataset.activated = enabled.toString();
} }
render() {
return this.$content;
}
reset() { reset() {
this.visible = !1, this.$content.classList.add("bx-gone"), this.$content.dataset.activated = "false"; this.$content.classList.add("bx-gone"), this.$content.dataset.activated = "false";
} }
} }
class TrueAchievementsAction extends BaseGameBarAction { class TrueAchievementsAction extends BaseGameBarAction {
@ -7431,16 +7393,12 @@ class TrueAchievementsAction extends BaseGameBarAction {
this.$content = createButton({ this.$content = createButton({
style: 4, style: 4,
icon: BxIcon.TRUE_ACHIEVEMENTS, icon: BxIcon.TRUE_ACHIEVEMENTS,
title: t("true-achievements"),
onClick: this.onClick.bind(this) onClick: this.onClick.bind(this)
}); });
} }
onClick(e) { onClick(e) {
super.onClick(e), TrueAchievements.open(!1); super.onClick(e), TrueAchievements.open(!1);
} }
render() {
return this.$content;
}
} }
class SpeakerAction extends BaseGameBarAction { class SpeakerAction extends BaseGameBarAction {
$content; $content;
@ -7456,7 +7414,7 @@ class SpeakerAction extends BaseGameBarAction {
onClick: this.onClick.bind(this), onClick: this.onClick.bind(this),
classes: ["bx-activated"] classes: ["bx-activated"]
}); });
this.$content = CE("div", {}, $btnEnable, $btnMuted), this.reset(), window.addEventListener(BxEvent.SPEAKER_STATE_CHANGED, (e) => { this.$content = CE("div", {}, $btnEnable, $btnMuted), window.addEventListener(BxEvent.SPEAKER_STATE_CHANGED, (e) => {
const enabled = e.speakerState === 0; const enabled = e.speakerState === 0;
this.$content.dataset.activated = (!enabled).toString(); this.$content.dataset.activated = (!enabled).toString();
}); });
@ -7464,9 +7422,6 @@ class SpeakerAction extends BaseGameBarAction {
onClick(e) { onClick(e) {
super.onClick(e), SoundShortcut.muteUnmute(); super.onClick(e), SoundShortcut.muteUnmute();
} }
render() {
return this.$content;
}
reset() { reset() {
this.$content.dataset.activated = "false"; this.$content.dataset.activated = "false";
} }
@ -7475,7 +7430,9 @@ class RendererShortcut {
static toggleVisibility() { static toggleVisibility() {
const $mediaContainer = document.querySelector('#game-stream div[data-testid="media-container"]'); const $mediaContainer = document.querySelector('#game-stream div[data-testid="media-container"]');
if (!$mediaContainer) return !0; if (!$mediaContainer) return !0;
return $mediaContainer.classList.toggle("bx-gone"), !$mediaContainer.classList.contains("bx-gone"); $mediaContainer.classList.toggle("bx-gone");
const isShowing = !$mediaContainer.classList.contains("bx-gone");
return limitVideoPlayerFps(isShowing ? getPref("video_max_fps") : 0), isShowing;
} }
} }
class RendererAction extends BaseGameBarAction { class RendererAction extends BaseGameBarAction {
@ -7492,26 +7449,20 @@ class RendererAction extends BaseGameBarAction {
onClick: this.onClick.bind(this), onClick: this.onClick.bind(this),
classes: ["bx-activated"] classes: ["bx-activated"]
}); });
this.$content = CE("div", {}, $btnDefault, $btnActivated), this.reset(); this.$content = CE("div", {}, $btnDefault, $btnActivated);
} }
onClick(e) { onClick(e) {
super.onClick(e); super.onClick(e);
const isVisible = RendererShortcut.toggleVisibility(); const isVisible = RendererShortcut.toggleVisibility();
this.$content.dataset.activated = (!isVisible).toString(); this.$content.dataset.activated = (!isVisible).toString();
} }
render() {
return this.$content;
}
reset() { reset() {
this.$content.dataset.activated = "false"; this.$content.dataset.activated = "false";
} }
} }
class GameBar { class GameBar {
static instance; static instance;
static getInstance() { static getInstance = () => GameBar.instance ?? (GameBar.instance = new GameBar);
if (!GameBar.instance) GameBar.instance = new GameBar;
return GameBar.instance;
}
static VISIBLE_DURATION = 2000; static VISIBLE_DURATION = 2000;
$gameBar; $gameBar;
$container; $container;
@ -7535,8 +7486,7 @@ class GameBar {
if (e.target !== $gameBar) return; if (e.target !== $gameBar) return;
$container.classList.contains("bx-show") ? this.hideBar() : this.showBar(); $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) => { }), 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; $container.classList.replace("bx-hide", "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) => { }), 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) { if (!STATES.isPlaying) {
this.disable(); this.disable();
@ -7554,30 +7504,24 @@ class GameBar {
this.timeoutId && clearTimeout(this.timeoutId), this.timeoutId = null; this.timeoutId && clearTimeout(this.timeoutId), this.timeoutId = null;
} }
enable() { enable() {
this.$gameBar && this.$gameBar.classList.remove("bx-gone"); this.$gameBar.classList.remove("bx-gone");
} }
disable() { disable() {
this.hideBar(), this.$gameBar && this.$gameBar.classList.add("bx-gone"); this.hideBar(), this.$gameBar.classList.add("bx-gone");
} }
showBar() { showBar() {
if (!this.$container) return;
this.$container.classList.remove("bx-offscreen", "bx-hide", "bx-gone"), this.$container.classList.add("bx-show"), this.beginHideTimeout(); this.$container.classList.remove("bx-offscreen", "bx-hide", "bx-gone"), this.$container.classList.add("bx-show"), this.beginHideTimeout();
} }
hideBar() { hideBar() {
if (this.clearHideTimeout(), clearFocus(), !this.$container) return; this.clearHideTimeout(), clearFocus(), this.$container.classList.replace("bx-show", "bx-hide");
this.$container.classList.remove("bx-show"), this.$container.classList.add("bx-hide");
} }
reset() { reset() {
for (let action of this.actions) this.actions.forEach((action) => action.reset());
action.reset();
} }
} }
class XcloudApi { class XcloudApi {
static instance; static instance;
static getInstance() { static getInstance = () => XcloudApi.instance ?? (XcloudApi.instance = new XcloudApi);
if (!XcloudApi.instance) XcloudApi.instance = new XcloudApi;
return XcloudApi.instance;
}
CACHE_TITLES = {}; CACHE_TITLES = {};
CACHE_WAIT_TIME = {}; CACHE_WAIT_TIME = {};
async getTitleInfo(id2) { async getTitleInfo(id2) {