mirror of
				https://github.com/redphx/better-xcloud.git
				synced 2025-11-04 16:04:04 +01:00 
			
		
		
		
	Show touch icon on games with custom layouts
This commit is contained in:
		@@ -22,7 +22,7 @@ import { Patcher } from "@modules/patcher";
 | 
			
		||||
import { RemotePlay } from "@modules/remote-play";
 | 
			
		||||
import { onHistoryChanged, patchHistoryMethod } from "@utils/history";
 | 
			
		||||
import { VibrationManager } from "@modules/vibration-manager";
 | 
			
		||||
import { PreloadedState } from "@utils/titles-info";
 | 
			
		||||
import { overridePreloadState } from "@utils/preload-state";
 | 
			
		||||
import { patchAudioContext, patchCanvasContext, patchMeControl, patchRtcCodecs, patchRtcPeerConnection, patchVideoApi } from "@utils/monkey-patches";
 | 
			
		||||
import { STATES } from "@utils/global";
 | 
			
		||||
import { injectStreamMenuButtons } from "@modules/stream/stream-ui";
 | 
			
		||||
@@ -220,7 +220,7 @@ function main() {
 | 
			
		||||
    getPref(PrefKey.AUDIO_ENABLE_VOLUME_CONTROL) && patchAudioContext();
 | 
			
		||||
    getPref(PrefKey.BLOCK_TRACKING) && patchMeControl();
 | 
			
		||||
 | 
			
		||||
    PreloadedState.override();
 | 
			
		||||
    overridePreloadState();
 | 
			
		||||
 | 
			
		||||
    VibrationManager.initialSetup();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { BX_FLAGS } from "@utils/bx-flags";
 | 
			
		||||
import { getPref, PrefKey } from "@utils/preferences";
 | 
			
		||||
import { VibrationManager } from "@modules/vibration-manager";
 | 
			
		||||
import { BxLogger } from "@utils/bx-logger";
 | 
			
		||||
import { hashCode } from "@/utils/utils";
 | 
			
		||||
import { hashCode } from "@utils/utils";
 | 
			
		||||
 | 
			
		||||
type PatchArray = (keyof typeof PATCHES)[];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ import { BxLogger } from "@utils/bx-logger";
 | 
			
		||||
 | 
			
		||||
const LOG_TAG = 'TouchController';
 | 
			
		||||
 | 
			
		||||
export const GALLERY_TOUCH_GAMES = '9c86f07a-f3e8-45ad-82a0-a1f759597059';
 | 
			
		||||
 | 
			
		||||
export class TouchController {
 | 
			
		||||
    static readonly #EVENT_SHOW_DEFAULT_CONTROLLER = new MessageEvent('message', {
 | 
			
		||||
            data: '{"content":"{\\"layoutId\\":\\"\\"}","target":"/streaming/touchcontrols/showlayoutv2","type":"Message"}',
 | 
			
		||||
@@ -184,6 +186,18 @@ export class TouchController {
 | 
			
		||||
        }, delay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static updateCustomList() {
 | 
			
		||||
        NATIVE_FETCH('https://raw.githubusercontent.com/redphx/better-xcloud/gh-pages/touch-layouts/ids.json')
 | 
			
		||||
            .then(response => response.json())
 | 
			
		||||
            .then(json => {
 | 
			
		||||
                window.localStorage.setItem('better_xcloud_custom_touch_layouts', JSON.stringify(json));
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static getCustomList(): string[] {
 | 
			
		||||
        return JSON.parse(window.localStorage.getItem('better_xcloud_custom_touch_layouts') || '[]');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static setup() {
 | 
			
		||||
        // Function for testing touch control
 | 
			
		||||
        window.BX_EXPOSED.test_touch_control = (layout: any) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import { LoadingScreen } from "@modules/loading-screen";
 | 
			
		||||
import { PrefKey, getPref } from "@utils/preferences";
 | 
			
		||||
import { RemotePlay } from "@modules/remote-play";
 | 
			
		||||
import { StreamBadges } from "@modules/stream/stream-badges";
 | 
			
		||||
import { TouchController } from "@modules/touch-controller";
 | 
			
		||||
import { GALLERY_TOUCH_GAMES, TouchController } from "@modules/touch-controller";
 | 
			
		||||
import { STATES } from "@utils/global";
 | 
			
		||||
import { getPreferredServerRegion } from "@utils/region";
 | 
			
		||||
 | 
			
		||||
@@ -549,6 +549,20 @@ export function interceptHttpRequests() {
 | 
			
		||||
            BxEvent.dispatch(window, BxEvent.STREAM_STARTING);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add list of games with custom layouts to the official list
 | 
			
		||||
        if (url.includes('catalog.gamepass.com') && url.includes(GALLERY_TOUCH_GAMES)) {
 | 
			
		||||
            const response = await NATIVE_FETCH(request, init);
 | 
			
		||||
            const obj = await response.clone().json();
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                const customList = TouchController.getCustomList().map(item => ({ id: item }));
 | 
			
		||||
                obj.push(...customList);
 | 
			
		||||
            } catch (e) {}
 | 
			
		||||
 | 
			
		||||
            response.json = () => Promise.resolve(obj);
 | 
			
		||||
            return response;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let requestType: RequestType;
 | 
			
		||||
        if (url.includes('/sessions/home') || url.includes('xhome.') || (STATES.remotePlay.isPlaying && url.endsWith('/inputconfigs'))) {
 | 
			
		||||
            requestType = RequestType.XHOME;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								src/utils/preload-state.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/utils/preload-state.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
import { STATES } from "@utils/global";
 | 
			
		||||
import { UserAgent } from "@utils/user-agent";
 | 
			
		||||
import { BxLogger } from "./bx-logger";
 | 
			
		||||
import { GALLERY_TOUCH_GAMES, TouchController } from "@modules/touch-controller";
 | 
			
		||||
 | 
			
		||||
const LOG_TAG = 'PreloadState';
 | 
			
		||||
 | 
			
		||||
export function overridePreloadState() {
 | 
			
		||||
    let _state: any;
 | 
			
		||||
 | 
			
		||||
    Object.defineProperty(window, '__PRELOADED_STATE__', {
 | 
			
		||||
        configurable: true,
 | 
			
		||||
        get: () => {
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            return _state;
 | 
			
		||||
        },
 | 
			
		||||
        set: state => {
 | 
			
		||||
            // Override User-Agent
 | 
			
		||||
            const userAgent = UserAgent.spoof();
 | 
			
		||||
            if (userAgent) {
 | 
			
		||||
                try {
 | 
			
		||||
                    // @ts-ignore
 | 
			
		||||
                    state.appContext.requestInfo.userAgent = userAgent;
 | 
			
		||||
                } catch (e) {
 | 
			
		||||
                    BxLogger.error(LOG_TAG, e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Add list of games with custom layouts to the official list
 | 
			
		||||
            if (STATES.hasTouchSupport) {
 | 
			
		||||
                TouchController.updateCustomList();
 | 
			
		||||
                const customList = TouchController.getCustomList();
 | 
			
		||||
 | 
			
		||||
                try {
 | 
			
		||||
                    state.xcloud.sigls[GALLERY_TOUCH_GAMES]?.data.products.push(...customList);
 | 
			
		||||
                } catch (e) {
 | 
			
		||||
                    BxLogger.error(LOG_TAG, e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // @ts-ignore
 | 
			
		||||
            _state = state;
 | 
			
		||||
            STATES.appContext = structuredClone(state.appContext);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
@@ -1,24 +0,0 @@
 | 
			
		||||
import { STATES } from "@utils/global";
 | 
			
		||||
import { UserAgent } from "@utils/user-agent";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export class PreloadedState {
 | 
			
		||||
    static override() {
 | 
			
		||||
        Object.defineProperty(window, '__PRELOADED_STATE__', {
 | 
			
		||||
            configurable: true,
 | 
			
		||||
            get: () => {
 | 
			
		||||
                // Override User-Agent
 | 
			
		||||
                const userAgent = UserAgent.spoof();
 | 
			
		||||
                if (userAgent) {
 | 
			
		||||
                    (this as any)._state.appContext.requestInfo.userAgent = userAgent;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return (this as any)._state;
 | 
			
		||||
            },
 | 
			
		||||
            set: state => {
 | 
			
		||||
                (this as any)._state = state;
 | 
			
		||||
                STATES.appContext = structuredClone(state.appContext);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user