mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-25 08:53:04 +02:00
Migrate Remote Play popup to Navigation dialog
This commit is contained in:
parent
df266d32fc
commit
784a31ce43
@ -1,6 +1,11 @@
|
|||||||
.bx-navigation-dialog {
|
.bx-navigation-dialog {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: var(--bx-navigation-dialog-z-index);
|
z-index: var(--bx-navigation-dialog-z-index);
|
||||||
|
font-family: var(--bx-title-font);
|
||||||
|
|
||||||
|
*:focus {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bx-navigation-dialog-overlay {
|
.bx-navigation-dialog-overlay {
|
||||||
|
@ -1,36 +1,16 @@
|
|||||||
.bx-remote-play-popup {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 1920px;
|
|
||||||
margin: auto;
|
|
||||||
position: relative;
|
|
||||||
height: 0.1px;
|
|
||||||
overflow: visible;
|
|
||||||
z-index: var(--bx-remote-play-popup-z-index);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bx-remote-play-container {
|
.bx-remote-play-container {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
right: 10px;
|
top: 50%;
|
||||||
top: 0;
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
color: white;
|
||||||
background: #1a1b1e;
|
background: #1a1b1e;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 420px;
|
width: 420px;
|
||||||
max-width: calc(100vw - 20px);
|
max-width: calc(100vw - 20px);
|
||||||
margin: 0 0 0 auto;
|
margin: 0 0 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-shadow: #00000080 0px 0px 12px 0px;
|
|
||||||
|
|
||||||
@media (min-width:480px) and (min-height:calc(480px + 1px)) {
|
|
||||||
right: calc(env(safe-area-inset-right, 0px) + 32px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width:768px) and (min-height:calc(480px + 1px)) {
|
|
||||||
right: calc(env(safe-area-inset-right, 0px) + 48px);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width:1920px) and (min-height:calc(480px + 1px)) {
|
|
||||||
right: calc(env(safe-area-inset-right, 0px) + 80px);
|
|
||||||
}
|
|
||||||
|
|
||||||
> .bx-button {
|
> .bx-button {
|
||||||
display: table;
|
display: table;
|
||||||
@ -121,3 +101,8 @@
|
|||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bx-remote-play-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
@ -37,8 +37,6 @@ button_color(name, normal, hover, active, disabled)
|
|||||||
--bx-navigation-dialog-z-index: 30100;
|
--bx-navigation-dialog-z-index: 30100;
|
||||||
--bx-navigation-dialog-overlay-z-index: 30000;
|
--bx-navigation-dialog-overlay-z-index: 30000;
|
||||||
|
|
||||||
--bx-remote-play-popup-z-index: 20000;
|
|
||||||
|
|
||||||
--bx-game-bar-z-index: 10000;
|
--bx-game-bar-z-index: 10000;
|
||||||
--bx-screenshot-animation-z-index: 9000;
|
--bx-screenshot-animation-z-index: 9000;
|
||||||
--bx-wait-time-box-z-index: 1000;
|
--bx-wait-time-box-z-index: 1000;
|
||||||
|
@ -130,7 +130,6 @@
|
|||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: #fff;
|
border-color: #fff;
|
||||||
outline: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&[data-group=global] {
|
&[data-group=global] {
|
||||||
@ -234,11 +233,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus,
|
|
||||||
*:focus {
|
|
||||||
outline: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bx-top-buttons {
|
.bx-top-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -16,7 +16,7 @@ import { MouseCursorHider } from "@modules/mkb/mouse-cursor-hider";
|
|||||||
import { TouchController } from "@modules/touch-controller";
|
import { TouchController } from "@modules/touch-controller";
|
||||||
import { checkForUpdate, disablePwa, productTitleToSlug } from "@utils/utils";
|
import { checkForUpdate, disablePwa, productTitleToSlug } from "@utils/utils";
|
||||||
import { Patcher } from "@modules/patcher";
|
import { Patcher } from "@modules/patcher";
|
||||||
import { RemotePlay } from "@modules/remote-play";
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
import { onHistoryChanged, patchHistoryMethod } from "@utils/history";
|
import { onHistoryChanged, patchHistoryMethod } from "@utils/history";
|
||||||
import { VibrationManager } from "@modules/vibration-manager";
|
import { VibrationManager } from "@modules/vibration-manager";
|
||||||
import { overridePreloadState } from "@utils/preload-state";
|
import { overridePreloadState } from "@utils/preload-state";
|
||||||
@ -157,7 +157,7 @@ document.addEventListener('readystatechange', e => {
|
|||||||
|
|
||||||
if (STATES.isSignedIn) {
|
if (STATES.isSignedIn) {
|
||||||
// Preload Remote Play
|
// Preload Remote Play
|
||||||
getPref(PrefKey.REMOTE_PLAY_ENABLED) && RemotePlay.preload();
|
getPref(PrefKey.REMOTE_PLAY_ENABLED) && RemotePlayManager.getInstance().initialize();
|
||||||
} else {
|
} else {
|
||||||
// Show Settings button in the header when not signed in
|
// Show Settings button in the header when not signed in
|
||||||
window.setTimeout(HeaderSection.watchHeader, 2000);
|
window.setTimeout(HeaderSection.watchHeader, 2000);
|
||||||
@ -413,7 +413,7 @@ function main() {
|
|||||||
|
|
||||||
// Preload Remote Play
|
// Preload Remote Play
|
||||||
if (getPref(PrefKey.REMOTE_PLAY_ENABLED)) {
|
if (getPref(PrefKey.REMOTE_PLAY_ENABLED)) {
|
||||||
RemotePlay.detect();
|
RemotePlayManager.detect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === StreamTouchController.ALL) {
|
if (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) === StreamTouchController.ALL) {
|
||||||
|
276
src/modules/remote-play-manager.ts
Normal file
276
src/modules/remote-play-manager.ts
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
import { STATES, AppInterface } from "@utils/global";
|
||||||
|
import { Toast } from "@utils/toast";
|
||||||
|
import { BxEvent } from "@utils/bx-event";
|
||||||
|
import { t } from "@utils/translation";
|
||||||
|
import { localRedirect } from "@modules/ui/ui";
|
||||||
|
import { BxLogger } from "@utils/bx-logger";
|
||||||
|
import { HeaderSection } from "./ui/header";
|
||||||
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
|
import { getPref, setPref } from "@/utils/settings-storages/global-settings-storage";
|
||||||
|
import { RemotePlayNavigationDialog } from "./ui/dialog/remote-play-dialog";
|
||||||
|
|
||||||
|
const LOG_TAG = 'RemotePlay';
|
||||||
|
|
||||||
|
export const enum RemotePlayConsoleState {
|
||||||
|
ON = 'On',
|
||||||
|
OFF = 'Off',
|
||||||
|
STANDBY = 'ConnectedStandby',
|
||||||
|
UNKNOWN = 'Unknown',
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemotePlayRegion = {
|
||||||
|
name: string;
|
||||||
|
baseUri: string;
|
||||||
|
isDefault: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
type RemotePlayConsole = {
|
||||||
|
deviceName: string;
|
||||||
|
serverId: string;
|
||||||
|
powerState: RemotePlayConsoleState;
|
||||||
|
consoleType: string;
|
||||||
|
// playPath: string;
|
||||||
|
// outOfHomeWarning: string;
|
||||||
|
// wirelessWarning: string;
|
||||||
|
// isDevKit: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class RemotePlayManager {
|
||||||
|
private static instance: RemotePlayManager;
|
||||||
|
public static getInstance(): RemotePlayManager {
|
||||||
|
if (!this.instance) {
|
||||||
|
this.instance = new RemotePlayManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isInitialized = false;
|
||||||
|
|
||||||
|
private XCLOUD_TOKEN!: string;
|
||||||
|
private XHOME_TOKEN!: string;
|
||||||
|
|
||||||
|
private consoles!: Array<RemotePlayConsole>;
|
||||||
|
private regions: Array<RemotePlayRegion> = [];
|
||||||
|
|
||||||
|
static readonly BASE_DEVICE_INFO = {
|
||||||
|
appInfo: {
|
||||||
|
env: {
|
||||||
|
clientAppId: window.location.host,
|
||||||
|
clientAppType: 'browser',
|
||||||
|
clientAppVersion: '24.17.36',
|
||||||
|
clientSdkVersion: '10.1.14',
|
||||||
|
httpEnvironment: 'prod',
|
||||||
|
sdkInstallId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dev: {
|
||||||
|
displayInfo: {
|
||||||
|
dimensions: {
|
||||||
|
widthInPixels: 1920,
|
||||||
|
heightInPixels: 1080,
|
||||||
|
},
|
||||||
|
pixelDensity: {
|
||||||
|
dpiX: 1,
|
||||||
|
dpiY: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hw: {
|
||||||
|
make: 'Microsoft',
|
||||||
|
model: 'unknown',
|
||||||
|
sdktype: 'web',
|
||||||
|
},
|
||||||
|
os: {
|
||||||
|
name: 'windows',
|
||||||
|
ver: '22631.2715',
|
||||||
|
platform: 'desktop',
|
||||||
|
},
|
||||||
|
browser: {
|
||||||
|
browserName: 'chrome',
|
||||||
|
browserVersion: '125.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
if (this.isInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isInitialized = true;
|
||||||
|
|
||||||
|
this.getXhomeToken(() => {
|
||||||
|
this.getConsolesList(() => {
|
||||||
|
BxLogger.info(LOG_TAG, 'Consoles', this.consoles);
|
||||||
|
|
||||||
|
STATES.supportedRegion && HeaderSection.showRemotePlayButton();
|
||||||
|
BxEvent.dispatch(window, BxEvent.REMOTE_PLAY_READY);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get xcloudToken() {
|
||||||
|
return this.XCLOUD_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
set xcloudToken(token: string) {
|
||||||
|
this.XCLOUD_TOKEN = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
get xhomeToken() {
|
||||||
|
return this.XHOME_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
getConsoles() {
|
||||||
|
return this.consoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private getXhomeToken(callback: any) {
|
||||||
|
if (this.XHOME_TOKEN) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let GSSV_TOKEN;
|
||||||
|
try {
|
||||||
|
GSSV_TOKEN = JSON.parse(localStorage.getItem('xboxcom_xbl_user_info')!).tokens['http://gssv.xboxlive.com/'].token;
|
||||||
|
} catch (e) {
|
||||||
|
for (let i = 0; i < localStorage.length; i++){
|
||||||
|
const key = localStorage.key(i)!;
|
||||||
|
if (!key.startsWith('Auth.User.')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const json = JSON.parse(localStorage.getItem(key)!);
|
||||||
|
for (const token of json.tokens) {
|
||||||
|
if (!token.relyingParty.includes('gssv.xboxlive.com')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GSSV_TOKEN = token.tokenData.token;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = new Request('https://xhome.gssv-play-prod.xboxlive.com/v2/login/user', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
offeringId: 'xhome',
|
||||||
|
token: GSSV_TOKEN,
|
||||||
|
}),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(request).then(resp => resp.json())
|
||||||
|
.then(json => {
|
||||||
|
this.regions = json.offeringSettings.regions;
|
||||||
|
this.XHOME_TOKEN = json.gsToken;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getConsolesList(callback: any) {
|
||||||
|
if (this.consoles) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${this.XHOME_TOKEN}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test servers one by one
|
||||||
|
for (const region of this.regions) {
|
||||||
|
try {
|
||||||
|
const request = new Request(`${region.baseUri}/v6/servers/home?mr=50`, options);
|
||||||
|
const resp = await fetch(request);
|
||||||
|
|
||||||
|
const json = await resp.json();
|
||||||
|
if (json.results.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.consoles = json.results;
|
||||||
|
|
||||||
|
// Store working server
|
||||||
|
STATES.remotePlay.server = region.baseUri;
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
if (this.consoles) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of the servers worked
|
||||||
|
if (!STATES.remotePlay.server) {
|
||||||
|
this.consoles = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
play(serverId: string, resolution?: string) {
|
||||||
|
if (resolution) {
|
||||||
|
setPref(PrefKey.REMOTE_PLAY_RESOLUTION, resolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
STATES.remotePlay.config = {
|
||||||
|
serverId: serverId,
|
||||||
|
};
|
||||||
|
window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config;
|
||||||
|
|
||||||
|
localRedirect('/launch/fortnite/BT5P2X999VH2#remote-play');
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePopup(force = null) {
|
||||||
|
if (!this.isReady()) {
|
||||||
|
Toast.show(t('getting-consoles-list'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.consoles.length === 0) {
|
||||||
|
Toast.show(t('no-consoles-found'), '', {instant: true});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show native dialog in Android app
|
||||||
|
if (AppInterface && AppInterface.showRemotePlayDialog) {
|
||||||
|
AppInterface.showRemotePlayDialog(JSON.stringify(this.consoles));
|
||||||
|
(document.activeElement as HTMLElement).blur();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemotePlayNavigationDialog.getInstance().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
static detect() {
|
||||||
|
if (!getPref(PrefKey.REMOTE_PLAY_ENABLED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATES.remotePlay.isPlaying = window.location.pathname.includes('/launch/') && window.location.hash.startsWith('#remote-play');
|
||||||
|
if (STATES.remotePlay?.isPlaying) {
|
||||||
|
window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config;
|
||||||
|
// Remove /launch/... from URL
|
||||||
|
window.history.replaceState({origin: 'better-xcloud'}, '', 'https://www.xbox.com/' + location.pathname.substring(1, 6) + '/play');
|
||||||
|
} else {
|
||||||
|
window.BX_REMOTE_PLAY_CONFIG = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private isReady() {
|
||||||
|
return this.consoles !== null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,368 +0,0 @@
|
|||||||
import { STATES, AppInterface } from "@utils/global";
|
|
||||||
import { CE, createButton, ButtonStyle } from "@utils/html";
|
|
||||||
import { BxIcon } from "@utils/bx-icon";
|
|
||||||
import { Toast } from "@utils/toast";
|
|
||||||
import { BxEvent } from "@utils/bx-event";
|
|
||||||
import { t } from "@utils/translation";
|
|
||||||
import { localRedirect } from "@modules/ui/ui";
|
|
||||||
import { BxLogger } from "@utils/bx-logger";
|
|
||||||
import { HeaderSection } from "./ui/header";
|
|
||||||
import { PrefKey } from "@/enums/pref-keys";
|
|
||||||
import { getPref, setPref } from "@/utils/settings-storages/global-settings-storage";
|
|
||||||
|
|
||||||
const LOG_TAG = 'RemotePlay';
|
|
||||||
|
|
||||||
const enum RemotePlayConsoleState {
|
|
||||||
ON = 'On',
|
|
||||||
OFF = 'Off',
|
|
||||||
STANDBY = 'ConnectedStandby',
|
|
||||||
UNKNOWN = 'Unknown',
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemotePlayRegion = {
|
|
||||||
name: string;
|
|
||||||
baseUri: string;
|
|
||||||
isDefault: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type RemotePlayConsole = {
|
|
||||||
deviceName: string;
|
|
||||||
serverId: string;
|
|
||||||
powerState: RemotePlayConsoleState;
|
|
||||||
consoleType: string;
|
|
||||||
// playPath: string;
|
|
||||||
// outOfHomeWarning: string;
|
|
||||||
// wirelessWarning: string;
|
|
||||||
// isDevKit: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class RemotePlay {
|
|
||||||
static XCLOUD_TOKEN: string;
|
|
||||||
static XHOME_TOKEN: string;
|
|
||||||
static #CONSOLES: Array<RemotePlayConsole>;
|
|
||||||
static #REGIONS: Array<RemotePlayRegion>;
|
|
||||||
|
|
||||||
static readonly #STATE_LABELS: {[key in RemotePlayConsoleState]: string} = {
|
|
||||||
[RemotePlayConsoleState.ON]: t('powered-on'),
|
|
||||||
[RemotePlayConsoleState.OFF]: t('powered-off'),
|
|
||||||
[RemotePlayConsoleState.STANDBY]: t('standby'),
|
|
||||||
[RemotePlayConsoleState.UNKNOWN]: t('unknown'),
|
|
||||||
};
|
|
||||||
|
|
||||||
static readonly BASE_DEVICE_INFO = {
|
|
||||||
appInfo: {
|
|
||||||
env: {
|
|
||||||
clientAppId: window.location.host,
|
|
||||||
clientAppType: 'browser',
|
|
||||||
clientAppVersion: '24.17.36',
|
|
||||||
clientSdkVersion: '10.1.14',
|
|
||||||
httpEnvironment: 'prod',
|
|
||||||
sdkInstallId: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dev: {
|
|
||||||
displayInfo: {
|
|
||||||
dimensions: {
|
|
||||||
widthInPixels: 1920,
|
|
||||||
heightInPixels: 1080,
|
|
||||||
},
|
|
||||||
pixelDensity: {
|
|
||||||
dpiX: 1,
|
|
||||||
dpiY: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hw: {
|
|
||||||
make: 'Microsoft',
|
|
||||||
model: 'unknown',
|
|
||||||
sdktype: 'web',
|
|
||||||
},
|
|
||||||
os: {
|
|
||||||
name: 'windows',
|
|
||||||
ver: '22631.2715',
|
|
||||||
platform: 'desktop',
|
|
||||||
},
|
|
||||||
browser: {
|
|
||||||
browserName: 'chrome',
|
|
||||||
browserVersion: '125.0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static #$content: HTMLElement;
|
|
||||||
|
|
||||||
static #initialize() {
|
|
||||||
if (RemotePlay.#$content) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemotePlay.#$content = CE('div', {}, t('getting-consoles-list'));
|
|
||||||
RemotePlay.#getXhomeToken(() => {
|
|
||||||
RemotePlay.#getConsolesList(() => {
|
|
||||||
BxLogger.info(LOG_TAG, 'Consoles', RemotePlay.#CONSOLES);
|
|
||||||
if (RemotePlay.#CONSOLES && RemotePlay.#CONSOLES.length > 0) {
|
|
||||||
STATES.supportedRegion && HeaderSection.showRemotePlayButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
RemotePlay.#renderConsoles();
|
|
||||||
BxEvent.dispatch(window, BxEvent.REMOTE_PLAY_READY);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static #renderConsoles() {
|
|
||||||
const $fragment = CE('div', {'class': 'bx-remote-play-container'});
|
|
||||||
|
|
||||||
if (!RemotePlay.#CONSOLES || RemotePlay.#CONSOLES.length === 0) {
|
|
||||||
$fragment.appendChild(CE('span', {}, t('no-consoles-found')));
|
|
||||||
RemotePlay.#$content = CE('div', {}, $fragment);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $settingNote = CE('p', {});
|
|
||||||
|
|
||||||
const resolutions = [1080, 720];
|
|
||||||
const currentResolution = getPref(PrefKey.REMOTE_PLAY_RESOLUTION);
|
|
||||||
const $resolutionGroup = CE('div', {});
|
|
||||||
for (const resolution of resolutions) {
|
|
||||||
const value = `${resolution}p`;
|
|
||||||
const id = `bx_radio_xhome_resolution_${resolution}`;
|
|
||||||
|
|
||||||
const $radio = CE<HTMLInputElement>('input', {
|
|
||||||
'type': 'radio',
|
|
||||||
'value': value,
|
|
||||||
'id': id,
|
|
||||||
'name': 'bx_radio_xhome_resolution',
|
|
||||||
}, value);
|
|
||||||
|
|
||||||
$radio.addEventListener('change', e => {
|
|
||||||
const value = (e.target as HTMLInputElement).value;
|
|
||||||
|
|
||||||
$settingNote.textContent = value === '1080p' ? '✅ ' + t('can-stream-xbox-360-games') : '❌ ' + t('cant-stream-xbox-360-games');
|
|
||||||
setPref(PrefKey.REMOTE_PLAY_RESOLUTION, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
const $label = CE('label', {
|
|
||||||
'for': id,
|
|
||||||
'class': 'bx-remote-play-resolution',
|
|
||||||
}, $radio, `${resolution}p`);
|
|
||||||
|
|
||||||
$resolutionGroup.appendChild($label);
|
|
||||||
|
|
||||||
if (currentResolution === value) {
|
|
||||||
$radio.checked = true;
|
|
||||||
$radio.dispatchEvent(new Event('change'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const $qualitySettings = CE('div', {'class': 'bx-remote-play-settings'},
|
|
||||||
CE('div', {},
|
|
||||||
CE('label', {}, t('target-resolution'), $settingNote),
|
|
||||||
$resolutionGroup,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$fragment.appendChild($qualitySettings);
|
|
||||||
|
|
||||||
// Render concoles list
|
|
||||||
for (let con of RemotePlay.#CONSOLES) {
|
|
||||||
const $child = CE('div', {'class': 'bx-remote-play-device-wrapper'},
|
|
||||||
CE('div', {'class': 'bx-remote-play-device-info'},
|
|
||||||
CE('div', {},
|
|
||||||
CE('span', {'class': 'bx-remote-play-device-name'}, con.deviceName),
|
|
||||||
CE('span', {'class': 'bx-remote-play-console-type'}, con.consoleType.replace('Xbox', ''))
|
|
||||||
),
|
|
||||||
CE('div', {'class': 'bx-remote-play-power-state'}, RemotePlay.#STATE_LABELS[con.powerState]),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Connect button
|
|
||||||
createButton({
|
|
||||||
classes: ['bx-remote-play-connect-button'],
|
|
||||||
label: t('console-connect'),
|
|
||||||
style: ButtonStyle.PRIMARY | ButtonStyle.FOCUSABLE,
|
|
||||||
onClick: e => {
|
|
||||||
RemotePlay.play(con.serverId);
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
$fragment.appendChild($child);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Help button
|
|
||||||
$fragment.appendChild(createButton({
|
|
||||||
icon: BxIcon.QUESTION,
|
|
||||||
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE,
|
|
||||||
url: 'https://better-xcloud.github.io/remote-play',
|
|
||||||
label: t('help'),
|
|
||||||
}));
|
|
||||||
|
|
||||||
RemotePlay.#$content = CE('div', {}, $fragment);
|
|
||||||
}
|
|
||||||
|
|
||||||
static #getXhomeToken(callback: any) {
|
|
||||||
if (RemotePlay.XHOME_TOKEN) {
|
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let GSSV_TOKEN;
|
|
||||||
try {
|
|
||||||
GSSV_TOKEN = JSON.parse(localStorage.getItem('xboxcom_xbl_user_info')!).tokens['http://gssv.xboxlive.com/'].token;
|
|
||||||
} catch (e) {
|
|
||||||
for (let i = 0; i < localStorage.length; i++){
|
|
||||||
const key = localStorage.key(i)!;
|
|
||||||
if (!key.startsWith('Auth.User.')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const json = JSON.parse(localStorage.getItem(key)!);
|
|
||||||
for (const token of json.tokens) {
|
|
||||||
if (!token.relyingParty.includes('gssv.xboxlive.com')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GSSV_TOKEN = token.tokenData.token;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const request = new Request('https://xhome.gssv-play-prod.xboxlive.com/v2/login/user', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({
|
|
||||||
offeringId: 'xhome',
|
|
||||||
token: GSSV_TOKEN,
|
|
||||||
}),
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json; charset=utf-8',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
fetch(request).then(resp => resp.json())
|
|
||||||
.then(json => {
|
|
||||||
RemotePlay.#REGIONS = json.offeringSettings.regions;
|
|
||||||
RemotePlay.XHOME_TOKEN = json.gsToken;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static async #getConsolesList(callback: any) {
|
|
||||||
if (RemotePlay.#CONSOLES) {
|
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${RemotePlay.XHOME_TOKEN}`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Test servers one by one
|
|
||||||
for (const region of RemotePlay.#REGIONS) {
|
|
||||||
try {
|
|
||||||
const request = new Request(`${region.baseUri}/v6/servers/home?mr=50`, options);
|
|
||||||
const resp = await fetch(request);
|
|
||||||
|
|
||||||
const json = await resp.json();
|
|
||||||
if (json.results.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemotePlay.#CONSOLES = json.results;
|
|
||||||
|
|
||||||
// Store working server
|
|
||||||
STATES.remotePlay.server = region.baseUri;
|
|
||||||
|
|
||||||
callback();
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
if (RemotePlay.#CONSOLES && RemotePlay.#CONSOLES.length > 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// None of the servers worked
|
|
||||||
if (!STATES.remotePlay.server) {
|
|
||||||
RemotePlay.#CONSOLES = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static play(serverId: string, resolution?: string) {
|
|
||||||
if (resolution) {
|
|
||||||
setPref(PrefKey.REMOTE_PLAY_RESOLUTION, resolution);
|
|
||||||
}
|
|
||||||
|
|
||||||
STATES.remotePlay.config = {
|
|
||||||
serverId: serverId,
|
|
||||||
};
|
|
||||||
window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config;
|
|
||||||
|
|
||||||
localRedirect('/launch/fortnite/BT5P2X999VH2#remote-play');
|
|
||||||
RemotePlay.detachPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
static preload() {
|
|
||||||
RemotePlay.#initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
static detachPopup() {
|
|
||||||
// Detach popup from body
|
|
||||||
const $popup = document.querySelector('.bx-remote-play-popup');
|
|
||||||
$popup && $popup.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
static togglePopup(force = null) {
|
|
||||||
if (!getPref(PrefKey.REMOTE_PLAY_ENABLED) || !RemotePlay.isReady()) {
|
|
||||||
Toast.show(t('getting-consoles-list'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RemotePlay.#initialize();
|
|
||||||
|
|
||||||
if (AppInterface && AppInterface.showRemotePlayDialog) {
|
|
||||||
AppInterface.showRemotePlayDialog(JSON.stringify(RemotePlay.#CONSOLES));
|
|
||||||
(document.activeElement as HTMLElement).blur();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.querySelector('.bx-remote-play-popup')) {
|
|
||||||
if (force === false) {
|
|
||||||
RemotePlay.#$content.classList.add('bx-gone');
|
|
||||||
} else {
|
|
||||||
RemotePlay.#$content.classList.toggle('bx-gone');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $header = document.querySelector('#gamepass-root header')!;
|
|
||||||
|
|
||||||
const group = $header.firstElementChild!.getAttribute('data-group')!;
|
|
||||||
RemotePlay.#$content.setAttribute('data-group', group);
|
|
||||||
RemotePlay.#$content.classList.add('bx-remote-play-popup');
|
|
||||||
RemotePlay.#$content.classList.remove('bx-gone');
|
|
||||||
|
|
||||||
$header.insertAdjacentElement('afterend', RemotePlay.#$content);
|
|
||||||
}
|
|
||||||
|
|
||||||
static detect() {
|
|
||||||
if (!getPref(PrefKey.REMOTE_PLAY_ENABLED)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATES.remotePlay.isPlaying = window.location.pathname.includes('/launch/') && window.location.hash.startsWith('#remote-play');
|
|
||||||
if (STATES.remotePlay?.isPlaying) {
|
|
||||||
window.BX_REMOTE_PLAY_CONFIG = STATES.remotePlay.config;
|
|
||||||
// Remove /launch/... from URL
|
|
||||||
window.history.replaceState({origin: 'better-xcloud'}, '', 'https://www.xbox.com/' + location.pathname.substring(1, 6) + '/play');
|
|
||||||
} else {
|
|
||||||
window.BX_REMOTE_PLAY_CONFIG = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static isReady() {
|
|
||||||
return RemotePlay.#CONSOLES !== null && RemotePlay.#CONSOLES.length > 0;
|
|
||||||
}
|
|
||||||
}
|
|
148
src/modules/ui/dialog/remote-play-dialog.ts
Normal file
148
src/modules/ui/dialog/remote-play-dialog.ts
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import { ButtonStyle, CE, createButton } from "@/utils/html";
|
||||||
|
import { NavigationDialog } from "./navigation-dialog";
|
||||||
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
|
import { BxIcon } from "@/utils/bx-icon";
|
||||||
|
import { getPref, setPref } from "@/utils/settings-storages/global-settings-storage";
|
||||||
|
import { t } from "@/utils/translation";
|
||||||
|
import { RemotePlayConsoleState, RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
|
|
||||||
|
|
||||||
|
export class RemotePlayNavigationDialog extends NavigationDialog {
|
||||||
|
private static instance: RemotePlayNavigationDialog;
|
||||||
|
public static getInstance(): RemotePlayNavigationDialog {
|
||||||
|
if (!RemotePlayNavigationDialog.instance) {
|
||||||
|
RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog();
|
||||||
|
}
|
||||||
|
return RemotePlayNavigationDialog.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly STATE_LABELS: Record<RemotePlayConsoleState, string> = {
|
||||||
|
[RemotePlayConsoleState.ON]: t('powered-on'),
|
||||||
|
[RemotePlayConsoleState.OFF]: t('powered-off'),
|
||||||
|
[RemotePlayConsoleState.STANDBY]: t('standby'),
|
||||||
|
[RemotePlayConsoleState.UNKNOWN]: t('unknown'),
|
||||||
|
};
|
||||||
|
|
||||||
|
$container!: HTMLElement;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setupDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupDialog() {
|
||||||
|
const $fragment = CE('div', {'class': 'bx-remote-play-container'});
|
||||||
|
|
||||||
|
const $settingNote = CE('p', {});
|
||||||
|
|
||||||
|
const resolutions = [1080, 720];
|
||||||
|
const currentResolution = getPref(PrefKey.REMOTE_PLAY_RESOLUTION);
|
||||||
|
const $resolutionGroup = CE('div', {});
|
||||||
|
|
||||||
|
const onResolutionChange = (e: Event) => {
|
||||||
|
const value = (e.target as HTMLInputElement).value;
|
||||||
|
|
||||||
|
$settingNote.textContent = value === '1080p' ? '✅ ' + t('can-stream-xbox-360-games') : '❌ ' + t('cant-stream-xbox-360-games');
|
||||||
|
setPref(PrefKey.REMOTE_PLAY_RESOLUTION, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const resolution of resolutions) {
|
||||||
|
const value = `${resolution}p`;
|
||||||
|
const id = `bx_radio_xhome_resolution_${resolution}`;
|
||||||
|
|
||||||
|
const $radio = CE<HTMLInputElement>('input', {
|
||||||
|
type: 'radio',
|
||||||
|
value: value,
|
||||||
|
id: id,
|
||||||
|
name: 'bx_radio_xhome_resolution',
|
||||||
|
}, value);
|
||||||
|
|
||||||
|
$radio.addEventListener('input', onResolutionChange);
|
||||||
|
|
||||||
|
const $label = CE('label', {
|
||||||
|
for: id,
|
||||||
|
class: 'bx-remote-play-resolution',
|
||||||
|
}, $radio, `${resolution}p`);
|
||||||
|
|
||||||
|
$resolutionGroup.appendChild($label);
|
||||||
|
|
||||||
|
if (currentResolution === value) {
|
||||||
|
$radio.checked = true;
|
||||||
|
$radio.dispatchEvent(new Event('input'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const $qualitySettings = CE('div', {
|
||||||
|
class: 'bx-remote-play-settings',
|
||||||
|
}, CE('div', {},
|
||||||
|
CE('label', {}, t('target-resolution'), $settingNote),
|
||||||
|
$resolutionGroup,
|
||||||
|
));
|
||||||
|
|
||||||
|
$fragment.appendChild($qualitySettings);
|
||||||
|
|
||||||
|
// Render consoles list
|
||||||
|
const manager = RemotePlayManager.getInstance();
|
||||||
|
const consoles = manager.getConsoles();
|
||||||
|
|
||||||
|
for (let con of consoles) {
|
||||||
|
const $child = CE('div', {class: 'bx-remote-play-device-wrapper'},
|
||||||
|
CE('div', {class: 'bx-remote-play-device-info'},
|
||||||
|
CE('div', {},
|
||||||
|
CE('span', {class: 'bx-remote-play-device-name'}, con.deviceName),
|
||||||
|
CE('span', {class: 'bx-remote-play-console-type'}, con.consoleType.replace('Xbox', ''))
|
||||||
|
),
|
||||||
|
CE('div', {class: 'bx-remote-play-power-state'}, this.STATE_LABELS[con.powerState]),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Connect button
|
||||||
|
createButton({
|
||||||
|
classes: ['bx-remote-play-connect-button'],
|
||||||
|
label: t('console-connect'),
|
||||||
|
style: ButtonStyle.PRIMARY | ButtonStyle.FOCUSABLE,
|
||||||
|
onClick: e => manager.play(con.serverId),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
$fragment.appendChild($child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add buttons
|
||||||
|
$fragment.appendChild(
|
||||||
|
CE('div', {
|
||||||
|
class: 'bx-remote-play-buttons',
|
||||||
|
_nearby: {
|
||||||
|
orientation: 'horizontal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
createButton({
|
||||||
|
icon: BxIcon.QUESTION,
|
||||||
|
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE,
|
||||||
|
url: 'https://better-xcloud.github.io/remote-play',
|
||||||
|
label: t('help'),
|
||||||
|
}),
|
||||||
|
|
||||||
|
createButton({
|
||||||
|
icon: BxIcon.CLOSE,
|
||||||
|
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE,
|
||||||
|
label: t('close'),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$container = $fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDialog(): NavigationDialog {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getContent(): HTMLElement {
|
||||||
|
return this.$container;
|
||||||
|
}
|
||||||
|
|
||||||
|
focusIfNeeded(): void {
|
||||||
|
const $btnConnect = this.$container.querySelector('.bx-remote-play-device-wrapper button') as HTMLElement;
|
||||||
|
$btnConnect && $btnConnect.focus();
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@ import { SCRIPT_VERSION } from "@utils/global";
|
|||||||
import { createButton, ButtonStyle, CE, isElementVisible } from "@utils/html";
|
import { createButton, ButtonStyle, CE, isElementVisible } from "@utils/html";
|
||||||
import { BxIcon } from "@utils/bx-icon";
|
import { BxIcon } from "@utils/bx-icon";
|
||||||
import { getPreferredServerRegion } from "@utils/region";
|
import { getPreferredServerRegion } from "@utils/region";
|
||||||
import { RemotePlay } from "@modules/remote-play";
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
import { t } from "@utils/translation";
|
import { t } from "@utils/translation";
|
||||||
import { SettingsNavigationDialog } from "./dialog/settings-dialog";
|
import { SettingsNavigationDialog } from "./dialog/settings-dialog";
|
||||||
import { PrefKey } from "@/enums/pref-keys";
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
@ -15,7 +15,7 @@ export class HeaderSection {
|
|||||||
title: t('remote-play'),
|
title: t('remote-play'),
|
||||||
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE | ButtonStyle.CIRCULAR,
|
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE | ButtonStyle.CIRCULAR,
|
||||||
onClick: e => {
|
onClick: e => {
|
||||||
RemotePlay.togglePopup();
|
RemotePlayManager.getInstance().togglePopup();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BxEvent } from "@utils/bx-event";
|
import { BxEvent } from "@utils/bx-event";
|
||||||
import { LoadingScreen } from "@modules/loading-screen";
|
import { LoadingScreen } from "@modules/loading-screen";
|
||||||
import { RemotePlay } from "@modules/remote-play";
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
import { HeaderSection } from "@/modules/ui/header";
|
import { HeaderSection } from "@/modules/ui/header";
|
||||||
import { NavigationDialogManager } from "@/modules/ui/dialog/navigation-dialog";
|
import { NavigationDialogManager } from "@/modules/ui/dialog/navigation-dialog";
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export function onHistoryChanged(e: PopStateEvent) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.setTimeout(RemotePlay.detect, 10);
|
window.setTimeout(RemotePlayManager.detect, 10);
|
||||||
|
|
||||||
// Hide Global settings
|
// Hide Global settings
|
||||||
const $settings = document.querySelector('.bx-settings-container');
|
const $settings = document.querySelector('.bx-settings-container');
|
||||||
@ -35,9 +35,6 @@ export function onHistoryChanged(e: PopStateEvent) {
|
|||||||
// Hide Navigation dialog
|
// Hide Navigation dialog
|
||||||
NavigationDialogManager.getInstance().hide();
|
NavigationDialogManager.getInstance().hide();
|
||||||
|
|
||||||
// Hide Remote Play popup
|
|
||||||
RemotePlay.detachPopup();
|
|
||||||
|
|
||||||
LoadingScreen.reset();
|
LoadingScreen.reset();
|
||||||
window.setTimeout(HeaderSection.watchHeader, 2000);
|
window.setTimeout(HeaderSection.watchHeader, 2000);
|
||||||
|
|
||||||
|
@ -254,6 +254,7 @@ export function patchPointerLockApi() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// const nativeRequestPointerLock = HTMLElement.prototype.requestPointerLock;
|
// const nativeRequestPointerLock = HTMLElement.prototype.requestPointerLock;
|
||||||
|
// @ts-ignore
|
||||||
HTMLElement.prototype.requestPointerLock = function() {
|
HTMLElement.prototype.requestPointerLock = function() {
|
||||||
pointerLockElement = document.documentElement;
|
pointerLockElement = document.documentElement;
|
||||||
window.dispatchEvent(new Event(BxEvent.POINTER_LOCK_REQUESTED));
|
window.dispatchEvent(new Event(BxEvent.POINTER_LOCK_REQUESTED));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { LoadingScreen } from "@modules/loading-screen";
|
import { LoadingScreen } from "@modules/loading-screen";
|
||||||
import { RemotePlay } from "@modules/remote-play";
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
import { StreamBadges } from "@modules/stream/stream-badges";
|
import { StreamBadges } from "@modules/stream/stream-badges";
|
||||||
import { TouchController } from "@modules/touch-controller";
|
import { TouchController } from "@modules/touch-controller";
|
||||||
import { BxEvent } from "./bx-event";
|
import { BxEvent } from "./bx-event";
|
||||||
@ -30,7 +30,7 @@ class XcloudInterceptor {
|
|||||||
const obj = await response.clone().json();
|
const obj = await response.clone().json();
|
||||||
|
|
||||||
// Store xCloud token
|
// Store xCloud token
|
||||||
RemotePlay.XCLOUD_TOKEN = obj.gsToken;
|
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
||||||
|
|
||||||
// Get server list
|
// Get server list
|
||||||
const serverEmojis = {
|
const serverEmojis = {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { RemotePlay } from "@/modules/remote-play";
|
|
||||||
import { TouchController } from "@/modules/touch-controller";
|
import { TouchController } from "@/modules/touch-controller";
|
||||||
import { BxEvent } from "./bx-event";
|
import { BxEvent } from "./bx-event";
|
||||||
import { SupportedInputType } from "./bx-exposed";
|
import { SupportedInputType } from "./bx-exposed";
|
||||||
@ -8,6 +7,7 @@ import { patchIceCandidates } from "./network";
|
|||||||
import { PrefKey } from "@/enums/pref-keys";
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
import { getPref, StreamResolution, StreamTouchController } from "./settings-storages/global-settings-storage";
|
import { getPref, StreamResolution, StreamTouchController } from "./settings-storages/global-settings-storage";
|
||||||
import type { RemotePlayConsoleAddresses } from "@/types/network";
|
import type { RemotePlayConsoleAddresses } from "@/types/network";
|
||||||
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
|
|
||||||
export class XhomeInterceptor {
|
export class XhomeInterceptor {
|
||||||
static #consoleAddrs: RemotePlayConsoleAddresses = {};
|
static #consoleAddrs: RemotePlayConsoleAddresses = {};
|
||||||
@ -111,7 +111,7 @@ export class XhomeInterceptor {
|
|||||||
for (const pair of (clone.headers as any).entries()) {
|
for (const pair of (clone.headers as any).entries()) {
|
||||||
headers[pair[0]] = pair[1];
|
headers[pair[0]] = pair[1];
|
||||||
}
|
}
|
||||||
headers.authorization = `Bearer ${RemotePlay.XCLOUD_TOKEN}`;
|
headers.authorization = `Bearer ${RemotePlayManager.getInstance().xcloudToken}`;
|
||||||
|
|
||||||
const index = request.url.indexOf('.xboxlive.com');
|
const index = request.url.indexOf('.xboxlive.com');
|
||||||
request = new Request('https://wus.core.gssv-play-prod' + request.url.substring(index), {
|
request = new Request('https://wus.core.gssv-play-prod' + request.url.substring(index), {
|
||||||
@ -146,10 +146,10 @@ export class XhomeInterceptor {
|
|||||||
headers[pair[0]] = pair[1];
|
headers[pair[0]] = pair[1];
|
||||||
}
|
}
|
||||||
// Add xHome token to headers
|
// Add xHome token to headers
|
||||||
headers.authorization = `Bearer ${RemotePlay.XHOME_TOKEN}`;
|
headers.authorization = `Bearer ${RemotePlayManager.getInstance().xhomeToken}`;
|
||||||
|
|
||||||
// Patch resolution
|
// Patch resolution
|
||||||
const deviceInfo = RemotePlay.BASE_DEVICE_INFO;
|
const deviceInfo = RemotePlayManager.BASE_DEVICE_INFO;
|
||||||
if (getPref(PrefKey.REMOTE_PLAY_RESOLUTION) === StreamResolution.DIM_720P) {
|
if (getPref(PrefKey.REMOTE_PLAY_RESOLUTION) === StreamResolution.DIM_720P) {
|
||||||
deviceInfo.dev.os.name = 'android';
|
deviceInfo.dev.os.name = 'android';
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user