Compare commits

..

5 Commits

Author SHA1 Message Date
redphx
a34ae75131 Bump version to 5.7.3 2024-09-07 18:36:05 +07:00
redphx
139543aaa5 Update better-xcloud.user.js 2024-09-07 18:29:45 +07:00
redphx
8099115959 Set Achievements list's default filter to "Locked" 2024-09-07 18:15:04 +07:00
redphx
21efa5ffdc Minor fix in Game Bar 2024-09-07 17:27:23 +07:00
redphx
07ebf3926b Update script in app when clicking on the "Version x available" button 2024-09-07 16:43:56 +07:00
8 changed files with 112 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud // @name Better xCloud
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 5.7.2 // @version 5.7.3
// ==/UserScript== // ==/UserScript==

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.7.2 // @version 5.7.3
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@@ -139,7 +139,7 @@ function deepClone(obj) {
return {}; return {};
return JSON.parse(JSON.stringify(obj)); return JSON.parse(JSON.stringify(obj));
} }
var SCRIPT_VERSION = "5.7.2", AppInterface = window.AppInterface; var SCRIPT_VERSION = "5.7.3", 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, 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, STATES = {
supportedRegion: !0, supportedRegion: !0,
@@ -327,6 +327,7 @@ var SUPPORTED_LANGUAGES = {
"badge-playtime": "Playtime", "badge-playtime": "Playtime",
"badge-server": "Server", "badge-server": "Server",
"badge-video": "Video", "badge-video": "Video",
"battery-saving": "Battery saving",
"better-xcloud": "Better xCloud", "better-xcloud": "Better xCloud",
"bitrate-audio-maximum": "Maximum audio bitrate", "bitrate-audio-maximum": "Maximum audio bitrate",
"bitrate-video-maximum": "Maximum video bitrate", "bitrate-video-maximum": "Maximum video bitrate",
@@ -422,7 +423,6 @@ var SUPPORTED_LANGUAGES = {
"load-failed-message": "Failed to run Better xCloud", "load-failed-message": "Failed to run Better xCloud",
"loading-screen": "Loading screen", "loading-screen": "Loading screen",
"local-co-op": "Local co-op", "local-co-op": "Local co-op",
"low-power": "Low power",
"lowest-quality": "Lowest quality", "lowest-quality": "Lowest quality",
"map-mouse-to": "Map mouse to", "map-mouse-to": "Map mouse to",
"may-not-work-properly": "May not work properly!", "may-not-work-properly": "May not work properly!",
@@ -437,6 +437,27 @@ var SUPPORTED_LANGUAGES = {
name: "Name", name: "Name",
"native-mkb": "Native Mouse & Keyboard", "native-mkb": "Native Mouse & Keyboard",
new: "New", new: "New",
"new-version-available": [
(e) => `Version ${e.version} available`,
,
,
,
,
,
,
,
(e) => `Ver ${e.version} が利用可能です`,
(e) => `${e.version} 버전 사용가능`,
,
,
,
,
,
,
(e) => `Đã có phiên bản ${e.version}`,
,
,
],
"no-consoles-found": "No consoles found", "no-consoles-found": "No consoles found",
normal: "Normal", normal: "Normal",
off: "Off", off: "Off",
@@ -479,7 +500,7 @@ var SUPPORTED_LANGUAGES = {
recommended: "Recommended", recommended: "Recommended",
"recommended-settings-for-device": [ "recommended-settings-for-device": [
(e) => `Recommended settings for ${e.device}`, (e) => `Recommended settings for ${e.device}`,
, (e) => `Configuració recomanada per a ${e.device}`,
, ,
(e) => `Empfohlene Einstellungen für ${e.device}`, (e) => `Empfohlene Einstellungen für ${e.device}`,
, ,
@@ -1622,7 +1643,7 @@ class GlobalSettingsStorage extends BaseSettingsStore {
default: "default", default: "default",
options: { options: {
default: t("default"), default: t("default"),
"low-power": t("low-power"), "low-power": t("battery-saving"),
"high-performance": t("high-performance") "high-performance": t("high-performance")
}, },
suggest: { suggest: {
@@ -4197,6 +4218,14 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
if (index = PatcherUtils.lastIndexOf(str, "return", index, 100), index < 0) if (index = PatcherUtils.lastIndexOf(str, "return", index, 100), index < 0)
return !1; return !1;
return str = PatcherUtils.insertAt(str, index, "window.BxEvent.dispatch(window, window.BxEvent.XCLOUD_ROUTER_HISTORY_READY, {history: this.history});"), str; return str = PatcherUtils.insertAt(str, index, "window.BxEvent.dispatch(window, window.BxEvent.XCLOUD_ROUTER_HISTORY_READY, {history: this.history});"), str;
},
guideAchievementsDefaultLocked(str) {
let index = str.indexOf("FilterButton-module__container");
if (index >= 0 && (index = PatcherUtils.lastIndexOf(str, ".All", index, 150)), index < 0)
return !1;
if (str = PatcherUtils.replaceWith(str, index, ".All", ".Locked"), index = str.indexOf('"Guide_Achievements_Unlocked_Empty","Guide_Achievements_Locked_Empty"'), index >= 0 && (index = PatcherUtils.indexOf(str, ".All", index, 250)), index < 0)
return !1;
return str = PatcherUtils.replaceWith(str, index, ".All", ".Locked"), str;
} }
}, PATCH_ORDERS = [ }, PATCH_ORDERS = [
...getPref("native_mkb_enabled") === "on" ? [ ...getPref("native_mkb_enabled") === "on" ? [
@@ -4213,6 +4242,7 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
"patchGamepadPolling", "patchGamepadPolling",
"exposeStreamSession", "exposeStreamSession",
"exposeDialogRoutes", "exposeDialogRoutes",
"guideAchievementsDefaultLocked",
"enableTvRoutes", "enableTvRoutes",
AppInterface && "detectProductDetailsPage", AppInterface && "detectProductDetailsPage",
"overrideStorageGetSettings", "overrideStorageGetSettings",
@@ -4433,12 +4463,17 @@ class SettingsNavigationDialog extends NavigationDialog {
items: [ items: [
($parent) => { ($parent) => {
const PREF_LATEST_VERSION = getPref("version_latest"), topButtons = []; const PREF_LATEST_VERSION = getPref("version_latest"), topButtons = [];
if (!SCRIPT_VERSION.includes("beta") && PREF_LATEST_VERSION && PREF_LATEST_VERSION != SCRIPT_VERSION) if (!SCRIPT_VERSION.includes("beta") && PREF_LATEST_VERSION && PREF_LATEST_VERSION != SCRIPT_VERSION) {
topButtons.push(createButton({ const opts = {
label: `🌟 Version ${PREF_LATEST_VERSION} available`, label: "🌟 " + t("new-version-available", { version: PREF_LATEST_VERSION }),
style: 1 | 32 | 64, style: 1 | 32 | 64
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) if (AppInterface)
topButtons.push(createButton({ topButtons.push(createButton({
label: t("app-settings"), label: t("app-settings"),
@@ -7873,7 +7908,7 @@ class GameBar {
}), 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; const classList = $container.classList;
if (classList.contains("bx-hide")) if (classList.contains("bx-hide"))
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"); 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();
@@ -7902,7 +7937,7 @@ class GameBar {
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 (clearFocus(), !this.$container) if (this.clearHideTimeout(), clearFocus(), !this.$container)
return; return;
this.$container.classList.remove("bx-show"), this.$container.classList.add("bx-hide"); this.$container.classList.remove("bx-show"), this.$container.classList.add("bx-hide");
} }

View File

@@ -78,7 +78,7 @@ export class GameBar {
$container.addEventListener('transitionend', e => { $container.addEventListener('transitionend', e => {
const classList = $container.classList; const classList = $container.classList;
if (classList.contains('bx-hide')) { if (classList.contains('bx-hide')) {
classList.remove('bx-offscreen', 'bx-hide'); classList.remove('bx-hide');
classList.add('bx-offscreen'); classList.add('bx-offscreen');
} }
}); });
@@ -135,6 +135,8 @@ export class GameBar {
} }
hideBar() { hideBar() {
this.clearHideTimeout();
// Stop focusing Game Bar // Stop focusing Game Bar
clearFocus(); clearFocus();

View File

@@ -912,6 +912,26 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
str = PatcherUtils.insertAt(str, index, 'window.BxEvent.dispatch(window, window.BxEvent.XCLOUD_ROUTER_HISTORY_READY, {history: this.history});'); str = PatcherUtils.insertAt(str, index, 'window.BxEvent.dispatch(window, window.BxEvent.XCLOUD_ROUTER_HISTORY_READY, {history: this.history});');
return str; return str;
}, },
// Set Achievements list's filter default to "Locked"
guideAchievementsDefaultLocked(str: string) {
let index = str.indexOf('FilterButton-module__container');
index >= 0 && (index = PatcherUtils.lastIndexOf(str, '.All', index, 150));
if (index < 0) {
return false;
}
str = PatcherUtils.replaceWith(str, index, '.All', '.Locked');
index = str.indexOf('"Guide_Achievements_Unlocked_Empty","Guide_Achievements_Locked_Empty"');
index >= 0 && (index = PatcherUtils.indexOf(str, '.All', index, 250));
if (index < 0) {
return false;
}
str = PatcherUtils.replaceWith(str, index, '.All', '.Locked');
return str;
}
}; };
let PATCH_ORDERS: PatchArray = [ let PATCH_ORDERS: PatchArray = [
@@ -933,6 +953,8 @@ let PATCH_ORDERS: PatchArray = [
'exposeStreamSession', 'exposeStreamSession',
'exposeDialogRoutes', 'exposeDialogRoutes',
'guideAchievementsDefaultLocked',
'enableTvRoutes', 'enableTvRoutes',
AppInterface && 'detectProductDetailsPage', AppInterface && 'detectProductDetailsPage',

View File

@@ -1,5 +1,5 @@
import { onChangeVideoPlayerType, updateVideoPlayer } from "@/modules/stream/stream-settings-utils"; import { onChangeVideoPlayerType, updateVideoPlayer } from "@/modules/stream/stream-settings-utils";
import { ButtonStyle, CE, createButton, createSvgIcon, removeChildElements } from "@/utils/html"; import { ButtonStyle, CE, createButton, createSvgIcon, removeChildElements, type BxButton } from "@/utils/html";
import { NavigationDialog, NavigationDirection } from "./navigation-dialog"; import { NavigationDialog, NavigationDirection } from "./navigation-dialog";
import { ControllerShortcut } from "@/modules/controller-shortcut"; import { ControllerShortcut } from "@/modules/controller-shortcut";
import { MkbRemapper } from "@/modules/mkb/mkb-remapper"; import { MkbRemapper } from "@/modules/mkb/mkb-remapper";
@@ -97,12 +97,19 @@ export class SettingsNavigationDialog extends NavigationDialog {
// "New version available" button // "New version available" button
if (!SCRIPT_VERSION.includes('beta') && PREF_LATEST_VERSION && PREF_LATEST_VERSION != SCRIPT_VERSION) { if (!SCRIPT_VERSION.includes('beta') && PREF_LATEST_VERSION && PREF_LATEST_VERSION != SCRIPT_VERSION) {
// Show new version indicator // Show new version button
topButtons.push(createButton({ const opts = {
label: `🌟 Version ${PREF_LATEST_VERSION} available`, label: '🌟 ' + t('new-version-available', {version: PREF_LATEST_VERSION}),
style: ButtonStyle.PRIMARY | ButtonStyle.FOCUSABLE | ButtonStyle.FULL_WIDTH, style: ButtonStyle.PRIMARY | ButtonStyle.FOCUSABLE | ButtonStyle.FULL_WIDTH,
url: 'https://github.com/redphx/better-xcloud/releases/latest', } as BxButton;
}));
if (AppInterface && AppInterface.updateLatestScript) {
opts.onClick = e => AppInterface.updateLatestScript();
} else {
opts.url = 'https://github.com/redphx/better-xcloud/releases/latest';
}
topButtons.push(createButton(opts));
} }
// Buttons for Android app // Buttons for Android app

View File

@@ -32,7 +32,7 @@ const ButtonStyleClass = {
[ButtonStyle.NORMAL_LINK]: 'bx-normal-link', [ButtonStyle.NORMAL_LINK]: 'bx-normal-link',
} }
type BxButton = { export type BxButton = {
style?: ButtonStyle; style?: ButtonStyle;
url?: string; url?: string;
classes?: string[]; classes?: string[];

View File

@@ -584,7 +584,7 @@ export class GlobalSettingsStorage extends BaseSettingsStorage {
default: 'default', default: 'default',
options: { options: {
'default': t('default'), 'default': t('default'),
'low-power': t('low-power'), 'low-power': t('battery-saving'),
'high-performance': t('high-performance'), 'high-performance': t('high-performance'),
}, },
suggest: { suggest: {

View File

@@ -47,6 +47,7 @@ const Texts = {
"badge-playtime": "Playtime", "badge-playtime": "Playtime",
"badge-server": "Server", "badge-server": "Server",
"badge-video": "Video", "badge-video": "Video",
"battery-saving": "Battery saving",
"better-xcloud": "Better xCloud", "better-xcloud": "Better xCloud",
"bitrate-audio-maximum": "Maximum audio bitrate", "bitrate-audio-maximum": "Maximum audio bitrate",
"bitrate-video-maximum": "Maximum video bitrate", "bitrate-video-maximum": "Maximum video bitrate",
@@ -142,7 +143,6 @@ const Texts = {
"load-failed-message": "Failed to run Better xCloud", "load-failed-message": "Failed to run Better xCloud",
"loading-screen": "Loading screen", "loading-screen": "Loading screen",
"local-co-op": "Local co-op", "local-co-op": "Local co-op",
"low-power": "Low power",
"lowest-quality": "Lowest quality", "lowest-quality": "Lowest quality",
"map-mouse-to": "Map mouse to", "map-mouse-to": "Map mouse to",
"may-not-work-properly": "May not work properly!", "may-not-work-properly": "May not work properly!",
@@ -157,6 +157,27 @@ const Texts = {
"name": "Name", "name": "Name",
"native-mkb": "Native Mouse & Keyboard", "native-mkb": "Native Mouse & Keyboard",
"new": "New", "new": "New",
"new-version-available": [
(e: any) => `Version ${e.version} available`,
,
,
,
,
,
,
,
(e: any) => `Ver ${e.version} が利用可能です`,
(e: any) => `${e.version} 버전 사용가능`,
,
,
,
,
,
,
(e: any) => `Đã có phiên bản ${e.version}`,
,
,
],
"no-consoles-found": "No consoles found", "no-consoles-found": "No consoles found",
"normal": "Normal", "normal": "Normal",
"off": "Off", "off": "Off",
@@ -199,7 +220,7 @@ const Texts = {
"recommended": "Recommended", "recommended": "Recommended",
"recommended-settings-for-device": [ "recommended-settings-for-device": [
(e: any) => `Recommended settings for ${e.device}`, (e: any) => `Recommended settings for ${e.device}`,
, (e: any) => `Configuració recomanada per a ${e.device}`,
, ,
(e: any) => `Empfohlene Einstellungen für ${e.device}`, (e: any) => `Empfohlene Einstellungen für ${e.device}`,
, ,