Compare commits

...

17 Commits

18 changed files with 146 additions and 71 deletions

View File

@ -4,6 +4,13 @@ title: "[Bug] "
labels: labels:
- bug - bug
body: body:
- type: markdown
attributes:
value: |
> [!note]
> - Use `Discussions` if you want to ask for question.
> - Non-English reports will be deleted. No exceptions.
- type: checkboxes - type: checkboxes
id: checklist id: checklist
attributes: attributes:
@ -15,17 +22,37 @@ body:
required: true required: true
- label: I will describe the problem with as much detail as possible. - label: I will describe the problem with as much detail as possible.
required: true required: true
- type: checkboxes
id: questions - type: dropdown
id: question_01
attributes: attributes:
label: Questions label: xCloud officially supports your country/region
options: options:
- label: xCloud officially supports my country/region. - "No"
required: false - "Yes"
- label: "The bug doesn't happen when I disable Better xCloud script." validations:
required: false required: true
- label: "The bug didn't happen in previous Better xCloud version (name which one)."
required: false - type: dropdown
id: question_02
attributes:
label: "The bug doesn't happen when you disable Better xCloud script"
options:
- "No"
- "Yes"
validations:
required: true
- type: dropdown
id: question_03
attributes:
label: "Previous Better xCloud versions didn't have this bug (name which one)"
options:
- "No"
- "Yes"
validations:
required: true
- type: dropdown - type: dropdown
id: device_type id: device_type
attributes: attributes:
@ -40,6 +67,7 @@ body:
multiple: false multiple: false
validations: validations:
required: true required: true
- type: input - type: input
id: device_name id: device_name
attributes: attributes:
@ -48,6 +76,7 @@ body:
placeholder: "e.g., Google Pixel 8" placeholder: "e.g., Google Pixel 8"
validations: validations:
required: true required: true
- type: input - type: input
id: os id: os
attributes: attributes:
@ -56,6 +85,7 @@ body:
placeholder: "e.g., Android 14" placeholder: "e.g., Android 14"
validations: validations:
required: true required: true
- type: input - type: input
id: browser_version id: browser_version
attributes: attributes:
@ -64,6 +94,7 @@ body:
placeholder: "e.g., Chrome 124.0, Android app 0.15.0" placeholder: "e.g., Chrome 124.0, Android app 0.15.0"
validations: validations:
required: true required: true
- type: input - type: input
id: extension_version id: extension_version
attributes: attributes:
@ -72,6 +103,7 @@ body:
placeholder: "e.g., 3.5.0" placeholder: "e.g., 3.5.0"
validations: validations:
required: true required: true
- type: input - type: input
id: game_list id: game_list
attributes: attributes:
@ -80,6 +112,7 @@ body:
placeholder: "e.g., Halo" placeholder: "e.g., Halo"
validations: validations:
required: false required: false
- type: textarea - type: textarea
id: reproduction id: reproduction
attributes: attributes:
@ -93,6 +126,7 @@ body:
3. Error 3. Error
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: media id: media
attributes: attributes:

File diff suppressed because one or more lines are too long

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 6.0.4 // @version 6.0.7
// ==/UserScript== // ==/UserScript==

File diff suppressed because one or more lines are too long

View File

@ -7,11 +7,11 @@
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
body[data-media-type=tv] & { body[data-bx-media-type=tv] & {
flex-direction: column; flex-direction: column;
} }
body:not([data-media-type=tv]) & { body:not([data-bx-media-type=tv]) & {
flex-direction: row; flex-direction: row;
> button:first-of-type { > button:first-of-type {
@ -34,7 +34,7 @@
flex-direction: row; flex-direction: row;
gap: 12px; gap: 12px;
body[data-media-type=tv] & { body[data-bx-media-type=tv] & {
flex-direction: column; flex-direction: column;
button { button {
@ -42,7 +42,7 @@
} }
} }
body:not([data-media-type=tv]) & { body:not([data-bx-media-type=tv]) & {
button { button {
span { span {
display: none; display: none;

View File

@ -194,7 +194,7 @@ div[class*=SupportedInputsBadge] {
top: 0; top: 0;
left: 0; left: 0;
z-index: 1; z-index: 1;
background: #0000008c; background: rgba(0, 0, 0, 0.5);
display: flex; display: flex;
border-radius: 4px 0 4px 0; border-radius: 4px 0 4px 0;
align-items: center; align-items: center;
@ -214,6 +214,18 @@ div[class*=SupportedInputsBadge] {
font-weight: bold; font-weight: bold;
margin-left: 2px; margin-left: 2px;
} }
&[data-duration=short] {
background-color: rgba(0, 133, 133, 0.75);
}
&[data-duration=medium] {
background-color: rgba(213, 133, 0, 0.75);
}
&[data-duration=long] {
background-color: rgba(150, 0, 0, 0.75);
}
} }

View File

@ -1,5 +1,6 @@
export enum GamePassCloudGallery { export enum GamePassCloudGallery {
ALL = 'ce573635-7c18-4d0c-9d68-90b932393470', ALL = '29a81209-df6f-41fd-a528-2ae6b91f719c',
ALL_WITH_BYGO = 'ce573635-7c18-4d0c-9d68-90b932393470',
MOST_POPULAR = 'e7590b22-e299-44db-ae22-25c61405454c', MOST_POPULAR = 'e7590b22-e299-44db-ae22-25c61405454c',
NATIVE_MKB = '8fa264dd-124f-4af3-97e8-596fcdf4b486', NATIVE_MKB = '8fa264dd-124f-4af3-97e8-596fcdf4b486',
TOUCH = '9c86f07a-f3e8-45ad-82a0-a1f759597059', TOUCH = '9c86f07a-f3e8-45ad-82a0-a1f759597059',

View File

@ -191,7 +191,7 @@ window.addEventListener('popstate', onHistoryChanged);
window.history.pushState = patchHistoryMethod('pushState'); window.history.pushState = patchHistoryMethod('pushState');
window.history.replaceState = patchHistoryMethod('replaceState'); window.history.replaceState = patchHistoryMethod('replaceState');
BxEventBus.Script.once('xcloudServerUnavailable', () => { BxEventBus.Script.once('xcloud.server.unavailable', () => {
STATES.supportedRegion = false; STATES.supportedRegion = false;
window.setTimeout(HeaderSection.watchHeader, 2000); window.setTimeout(HeaderSection.watchHeader, 2000);

View File

@ -440,7 +440,9 @@ export class EmulatedMkbHandler extends MkbHandler {
} }
if (this.enabled) { if (this.enabled) {
document.body.requestPointerLock(); document.body.requestPointerLock({
unadjustedMovement: true,
});
} else { } else {
document.pointerLockElement && document.exitPointerLock(); document.pointerLockElement && document.exitPointerLock();
} }

View File

@ -541,12 +541,12 @@ BxLogger.info('patchRemotePlayMkb', ${configsVar});
}, },
patchShowSensorControls(str: string) { patchShowSensorControls(str: string) {
let text = '{shouldShowSensorControls:'; let text = ',{shouldShowSensorControls:';
if (!str.includes(text)) { if (!str.includes(text)) {
return false; return false;
} }
const newCode = `{shouldShowSensorControls: (window.BX_EXPOSED && window.BX_EXPOSED.shouldShowSensorControls) ||`; const newCode = `,{shouldShowSensorControls: (window.BX_EXPOSED && window.BX_EXPOSED.shouldShowSensorControls) ||`;
str = str.replace(text, newCode); str = str.replace(text, newCode);
return str; return str;
@ -835,9 +835,9 @@ if (this.baseStorageKey in window.BX_EXPOSED.overrideSettings) {
return str; return str;
}, },
// 24225.js#4127, 24.17.11 // 49851.js#4083, 27.0.4
patchSetCurrentlyFocusedInteractable(str: string) { patchSetCurrentFocus(str: string) {
let index = str.indexOf('.setCurrentlyFocusedInteractable=('); let index = str.indexOf('.setCurrentFocus=(');
if (index < 0) { if (index < 0) {
return false; return false;
} }
@ -1017,7 +1017,7 @@ let PATCH_ORDERS = PatcherUtils.filterPatches([
'supportLocalCoOp', 'supportLocalCoOp',
'overrideStorageGetSettings', 'overrideStorageGetSettings',
getPref(PrefKey.UI_GAME_CARD_SHOW_WAIT_TIME) && 'patchSetCurrentlyFocusedInteractable', getPref(PrefKey.UI_GAME_CARD_SHOW_WAIT_TIME) && 'patchSetCurrentFocus',
getPref<UiLayout>(PrefKey.UI_LAYOUT) !== UiLayout.DEFAULT && 'websiteLayout', getPref<UiLayout>(PrefKey.UI_LAYOUT) !== UiLayout.DEFAULT && 'websiteLayout',
getPref(PrefKey.GAME_FORTNITE_FORCE_CONSOLE) && 'forceFortniteConsole', getPref(PrefKey.GAME_FORTNITE_FORCE_CONSOLE) && 'forceFortniteConsole',
@ -1090,7 +1090,7 @@ let STREAM_PAGE_PATCH_ORDERS = PatcherUtils.filterPatches([
getPref<TouchControllerMode>(PrefKey.TOUCH_CONTROLLER_MODE) === TouchControllerMode.ALL && 'exposeTouchLayoutManager', getPref<TouchControllerMode>(PrefKey.TOUCH_CONTROLLER_MODE) === TouchControllerMode.ALL && 'exposeTouchLayoutManager',
(getPref<TouchControllerMode>(PrefKey.TOUCH_CONTROLLER_MODE) === TouchControllerMode.OFF || getPref(PrefKey.TOUCH_CONTROLLER_AUTO_OFF)) && 'disableTakRenderer', (getPref<TouchControllerMode>(PrefKey.TOUCH_CONTROLLER_MODE) === TouchControllerMode.OFF || getPref(PrefKey.TOUCH_CONTROLLER_AUTO_OFF)) && 'disableTakRenderer',
getPref<TouchControllerDefaultOpacity>(PrefKey.TOUCH_CONTROLLER_DEFAULT_OPACITY) !== 100 && 'patchTouchControlDefaultOpacity', getPref<TouchControllerDefaultOpacity>(PrefKey.TOUCH_CONTROLLER_DEFAULT_OPACITY) !== 100 && 'patchTouchControlDefaultOpacity',
'patchBabylonRendererClass', (getPref<TouchControllerMode>(PrefKey.TOUCH_CONTROLLER_MODE) !== TouchControllerMode.OFF && (getPref(PrefKey.MKB_ENABLED) || getPref<NativeMkbMode>(PrefKey.NATIVE_MKB_MODE) === NativeMkbMode.ON)) && 'patchBabylonRendererClass',
] : []), ] : []),
BX_FLAGS.EnableXcloudLogging && 'enableConsoleLogging', BX_FLAGS.EnableXcloudLogging && 'enableConsoleLogging',

View File

@ -1,6 +1,6 @@
import { BxEvent } from "@/utils/bx-event"; import { BxEvent } from "@/utils/bx-event";
import { BxIcon } from "@/utils/bx-icon"; import { BxIcon } from "@/utils/bx-icon";
import { CE, createSvgIcon, getReactProps, isElementVisible, secondsToHms } from "@/utils/html"; import { CE, createSvgIcon, getReactProps, isElementVisible, secondsToHm } from "@/utils/html";
import { XcloudApi } from "@/utils/xcloud-api"; import { XcloudApi } from "@/utils/xcloud-api";
interface GameTimeElement extends HTMLElement { interface GameTimeElement extends HTMLElement {
@ -30,8 +30,14 @@ export class GameTile {
if (typeof totalWaitTime === 'number' && isElementVisible($elm)) { if (typeof totalWaitTime === 'number' && isElementVisible($elm)) {
const $div = CE('div', { class: 'bx-game-tile-wait-time' }, const $div = CE('div', { class: 'bx-game-tile-wait-time' },
createSvgIcon(BxIcon.PLAYTIME), createSvgIcon(BxIcon.PLAYTIME),
CE('span', {}, secondsToHms(totalWaitTime)), CE('span', {}, totalWaitTime < 60 ? totalWaitTime + 's' : secondsToHm(totalWaitTime)),
); );
const duration = (totalWaitTime >= 15 * 60) ? 'long' : (totalWaitTime >= 10 * 60) ? 'medium' : (totalWaitTime >= 5 * 60 ) ? 'short' : '';
if (duration) {
$div.dataset.duration = duration;
}
$elm.insertAdjacentElement('afterbegin', $div); $elm.insertAdjacentElement('afterbegin', $div);
} }
} }

View File

@ -8,6 +8,9 @@ import { SettingsDialog } from "./dialog/settings-dialog";
import { TrueAchievements } from "@/utils/true-achievements"; import { TrueAchievements } from "@/utils/true-achievements";
import { BxIcon } from "@/utils/bx-icon"; import { BxIcon } from "@/utils/bx-icon";
import { BxEventBus } from "@/utils/bx-event-bus"; import { BxEventBus } from "@/utils/bx-event-bus";
import { getPref } from "@/utils/settings-storages/global-settings-storage";
import { UiLayout } from "@/enums/pref-values";
import { PrefKey } from "@/enums/pref-keys";
export enum GuideMenuTab { export enum GuideMenuTab {
HOME = 'home', HOME = 'home',
@ -41,7 +44,7 @@ export class GuideMenu {
style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE | ButtonStyle.PRIMARY, style: ButtonStyle.FULL_WIDTH | ButtonStyle.FOCUSABLE | ButtonStyle.PRIMARY,
onClick: () => { onClick: () => {
// Wait until the Guide dialog is closed // Wait until the Guide dialog is closed
BxEventBus.Script.once('xcloudDialogDismissed', () => { BxEventBus.Script.once('dialog.dismissed', () => {
setTimeout(() => SettingsDialog.getInstance().show(), 50); setTimeout(() => SettingsDialog.getInstance().show(), 50);
}); });
@ -111,6 +114,11 @@ export class GuideMenu {
class: 'bx-guide-home-buttons', class: 'bx-guide-home-buttons',
}); });
// Set TV tag
if (STATES.userAgent.isTv || getPref<UiLayout>(PrefKey.UI_LAYOUT) === UiLayout.TV) {
document.body.dataset.bxMediaType = 'tv';
}
for (const $button of buttonsLayout) { for (const $button of buttonsLayout) {
if (!$button) { if (!$button) {
continue; continue;

View File

@ -78,7 +78,7 @@ export class BxEventBus<TEvents extends Record<string, any>> {
BX_FLAGS.Debug && BxLogger.warning('EventBus', 'on', event, callback); BX_FLAGS.Debug && BxLogger.warning('EventBus', 'on', event, callback);
} }
once<K extends keyof TEvents>(event: string, callback: EventCallback<TEvents[K]>): void { once<K extends keyof TEvents>(event: K, callback: EventCallback<TEvents[K]>): void {
const wrapper = (...args: any[]) => { const wrapper = (...args: any[]) => {
// @ts-ignore // @ts-ignore
callback(...args); callback(...args);

View File

@ -54,7 +54,7 @@ export namespace BxEvent {
target.dispatchEvent(event); target.dispatchEvent(event);
AppInterface && AppInterface.onEvent(eventName); AppInterface && AppInterface.onEvent(eventName);
BX_FLAGS.Debug && BxLogger.warning('BxEvent', 'dispatch', eventName, data); BX_FLAGS.Debug && BxLogger.warning('BxEvent', 'dispatch', target, eventName, data);
} }
} }

View File

@ -54,11 +54,16 @@ export const BxExposed = {
let customList = TouchController.getCustomList(); let customList = TouchController.getCustomList();
// Remove non-cloud games from the official list // Remove non-cloud games from the official list
const allGames = sigls[GamePassCloudGallery.ALL].data.products; const siglId = GamePassCloudGallery.ALL_WITH_BYGO;
if (siglId in sigls) {
const allGames = sigls[siglId].data.products;
customList = customList.filter(id => allGames.includes(id)); customList = customList.filter(id => allGames.includes(id));
// Add to the official touchlist // Add to the official touchlist
sigls[GamePassCloudGallery.TOUCH]?.data.products.push(...customList); sigls[GamePassCloudGallery.TOUCH]?.data.products.push(...customList);
} else {
BxLogger.warning(LOG_TAG, 'Sigl not found: ' + siglId);
}
} }
} catch (e) { } catch (e) {
BxLogger.error(LOG_TAG, e); BxLogger.error(LOG_TAG, e);

View File

@ -8,6 +8,7 @@ export let FeatureGates: { [key: string]: boolean } = {
EnableWifiWarnings: false, EnableWifiWarnings: false,
EnableUpdateRequiredPage: false, EnableUpdateRequiredPage: false,
ShowForcedUpdateScreen: false, ShowForcedUpdateScreen: false,
EnableTakControlResizing: true, // Experimenting
}; };
// Enable Native Mouse & Keyboard // Enable Native Mouse & Keyboard

View File

@ -253,7 +253,7 @@ export function interceptHttpRequests() {
const response = await NATIVE_FETCH(request, init); const response = await NATIVE_FETCH(request, init);
const obj = await response.clone().json(); const obj = await response.clone().json();
if (url.includes(GamePassCloudGallery.ALL)) { if (url.includes(GamePassCloudGallery.ALL) || url.includes(GamePassCloudGallery.ALL_WITH_BYGO)) {
for (let i = 1; i < obj.length; i++) { for (let i = 1; i < obj.length; i++) {
gamepassAllGames.push(obj[i].id); gamepassAllGames.push(obj[i].id);
} }

View File

@ -114,6 +114,7 @@ export class BxNumberStepper extends HTMLInputElement implements BxHtmlSettingEl
self.$range = $range; self.$range = $range;
options.hideSlider && $range.classList.add('bx-gone'); options.hideSlider && $range.classList.add('bx-gone');
$range.addEventListener('input', self.onRangeInput);
self.addEventListener('input', self.onRangeInput); self.addEventListener('input', self.onRangeInput);
self.appendChild($range); self.appendChild($range);