mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-07-05 13:51:43 +02:00
Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
fa19a5a68e | |||
3f834f74b6 | |||
749d5d720e | |||
b969d52a3c | |||
e5bd7e64a7 | |||
82ee00b4ae | |||
8e88af5f8c | |||
927eae3f2f | |||
9f440e9cf4 | |||
1acb30e3af | |||
34159fad22 |
9
build.ts
9
build.ts
@ -87,6 +87,15 @@ const postProcess = (str: string): string => {
|
|||||||
return p1.toUpperCase();
|
return p1.toUpperCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Replace " (e) =>" to " e =>"
|
||||||
|
// str = str.replaceAll(/ \(([^\s,.$()]+)\) =>/g, ' $1 =>');
|
||||||
|
|
||||||
|
// Set indent to 1 space
|
||||||
|
str = str.replaceAll(/\n(\s+)/g, (match, p1) => {
|
||||||
|
const len = p1.length / 2;
|
||||||
|
return '\n' + ' '.repeat(len);
|
||||||
|
});
|
||||||
|
|
||||||
assert(str.includes('/* ADDITIONAL CODE */'));
|
assert(str.includes('/* ADDITIONAL CODE */'));
|
||||||
assert(str.includes('window.BX_EXPOSED = BxExposed'));
|
assert(str.includes('window.BX_EXPOSED = BxExposed'));
|
||||||
assert(str.includes('window.BxEvent = BxEvent'));
|
assert(str.includes('window.BxEvent = BxEvent'));
|
||||||
|
10586
dist/better-xcloud.lite.user.js
vendored
10586
dist/better-xcloud.lite.user.js
vendored
File diff suppressed because one or more lines are too long
2
dist/better-xcloud.meta.js
vendored
2
dist/better-xcloud.meta.js
vendored
@ -1,5 +1,5 @@
|
|||||||
// ==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
|
||||||
// ==/UserScript==
|
// ==/UserScript==
|
||||||
|
14858
dist/better-xcloud.user.js
vendored
14858
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,8 @@
|
|||||||
import { BxEvent } from "@/utils/bx-event";
|
import { BxEvent } from "@/utils/bx-event";
|
||||||
|
|
||||||
export abstract class BaseGameBarAction {
|
export abstract class BaseGameBarAction {
|
||||||
|
abstract $content: HTMLElement;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
reset() {}
|
reset() {}
|
||||||
|
|
||||||
@ -8,5 +10,7 @@ export abstract class BaseGameBarAction {
|
|||||||
BxEvent.dispatch(window, BxEvent.GAME_BAR_ACTION_ACTIVATED);
|
BxEvent.dispatch(window, BxEvent.GAME_BAR_ACTION_ACTIVATED);
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract render(): HTMLElement;
|
render(): HTMLElement {
|
||||||
|
return this.$content;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import { MicrophoneShortcut, MicrophoneState } from "../shortcuts/shortcut-micro
|
|||||||
export class MicrophoneAction extends BaseGameBarAction {
|
export class MicrophoneAction extends BaseGameBarAction {
|
||||||
$content: HTMLElement;
|
$content: HTMLElement;
|
||||||
|
|
||||||
visible: boolean = false;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -26,12 +24,7 @@ export class MicrophoneAction extends BaseGameBarAction {
|
|||||||
onClick: this.onClick.bind(this),
|
onClick: this.onClick.bind(this),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$content = CE('div', {},
|
this.$content = CE('div', {}, $btnMuted, $btnDefault);
|
||||||
$btnMuted,
|
|
||||||
$btnDefault,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
window.addEventListener(BxEvent.MICROPHONE_STATE_CHANGED, e => {
|
window.addEventListener(BxEvent.MICROPHONE_STATE_CHANGED, e => {
|
||||||
const microphoneState = (e as any).microphoneState;
|
const microphoneState = (e as any).microphoneState;
|
||||||
@ -49,12 +42,7 @@ export class MicrophoneAction extends BaseGameBarAction {
|
|||||||
this.$content.dataset.activated = enabled.toString();
|
this.$content.dataset.activated = enabled.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.visible = false;
|
|
||||||
this.$content.classList.add('bx-gone');
|
this.$content.classList.add('bx-gone');
|
||||||
this.$content.dataset.activated = 'false';
|
this.$content.dataset.activated = 'false';
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,7 @@ export class RendererAction extends BaseGameBarAction {
|
|||||||
classes: ['bx-activated'],
|
classes: ['bx-activated'],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$content = CE('div', {},
|
this.$content = CE('div', {}, $btnDefault, $btnActivated);
|
||||||
$btnDefault,
|
|
||||||
$btnActivated,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(e: Event) {
|
onClick(e: Event) {
|
||||||
@ -37,10 +32,6 @@ export class RendererAction extends BaseGameBarAction {
|
|||||||
this.$content.dataset.activated = (!isVisible).toString();
|
this.$content.dataset.activated = (!isVisible).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.$content.dataset.activated = 'false';
|
this.$content.dataset.activated = 'false';
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,4 @@ export class ScreenshotAction extends BaseGameBarAction {
|
|||||||
super.onClick(e);
|
super.onClick(e);
|
||||||
Screenshot.takeScreenshot();
|
Screenshot.takeScreenshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,7 @@ export class SpeakerAction extends BaseGameBarAction {
|
|||||||
classes: ['bx-activated'],
|
classes: ['bx-activated'],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$content = CE('div', {},
|
this.$content = CE('div', {}, $btnEnable, $btnMuted);
|
||||||
$btnEnable,
|
|
||||||
$btnMuted,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
|
|
||||||
window.addEventListener(BxEvent.SPEAKER_STATE_CHANGED, e => {
|
window.addEventListener(BxEvent.SPEAKER_STATE_CHANGED, e => {
|
||||||
const speakerState = (e as any).speakerState;
|
const speakerState = (e as any).speakerState;
|
||||||
@ -44,10 +39,6 @@ export class SpeakerAction extends BaseGameBarAction {
|
|||||||
SoundShortcut.muteUnmute();
|
SoundShortcut.muteUnmute();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.$content.dataset.activated = 'false';
|
this.$content.dataset.activated = 'false';
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,7 @@ export class TouchControlAction extends BaseGameBarAction {
|
|||||||
classes: ['bx-activated'],
|
classes: ['bx-activated'],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$content = CE('div', {},
|
this.$content = CE('div', {}, $btnEnable, $btnDisable);
|
||||||
$btnEnable,
|
|
||||||
$btnDisable,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(e: Event) {
|
onClick(e: Event) {
|
||||||
@ -39,10 +34,6 @@ export class TouchControlAction extends BaseGameBarAction {
|
|||||||
this.$content.dataset.activated = (!isVisible).toString();
|
this.$content.dataset.activated = (!isVisible).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
|
|
||||||
reset(): void {
|
reset(): void {
|
||||||
this.$content.dataset.activated = 'false';
|
this.$content.dataset.activated = 'false';
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { BxIcon } from "@/utils/bx-icon";
|
import { BxIcon } from "@/utils/bx-icon";
|
||||||
import { createButton, ButtonStyle } from "@/utils/html";
|
import { createButton, ButtonStyle } from "@/utils/html";
|
||||||
import { t } from "@/utils/translation";
|
|
||||||
import { BaseGameBarAction } from "./action-base";
|
import { BaseGameBarAction } from "./action-base";
|
||||||
import { TrueAchievements } from "@/utils/true-achievements";
|
import { TrueAchievements } from "@/utils/true-achievements";
|
||||||
|
|
||||||
@ -13,7 +12,6 @@ export class TrueAchievementsAction extends BaseGameBarAction {
|
|||||||
this.$content = createButton({
|
this.$content = createButton({
|
||||||
style: ButtonStyle.GHOST,
|
style: ButtonStyle.GHOST,
|
||||||
icon: BxIcon.TRUE_ACHIEVEMENTS,
|
icon: BxIcon.TRUE_ACHIEVEMENTS,
|
||||||
title: t('true-achievements'),
|
|
||||||
onClick: this.onClick.bind(this),
|
onClick: this.onClick.bind(this),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -22,8 +20,4 @@ export class TrueAchievementsAction extends BaseGameBarAction {
|
|||||||
super.onClick(e);
|
super.onClick(e);
|
||||||
TrueAchievements.open(false);
|
TrueAchievements.open(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): HTMLElement {
|
|
||||||
return this.$content;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import type { BaseGameBarAction } from "./action-base";
|
|||||||
import { STATES } from "@utils/global";
|
import { STATES } from "@utils/global";
|
||||||
import { MicrophoneAction } from "./action-microphone";
|
import { MicrophoneAction } from "./action-microphone";
|
||||||
import { PrefKey } from "@/enums/pref-keys";
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
import { getPref, StreamTouchController } from "@/utils/settings-storages/global-settings-storage";
|
import { getPref, StreamTouchController, type GameBarPosition } from "@/utils/settings-storages/global-settings-storage";
|
||||||
import { TrueAchievementsAction } from "./action-true-achievements";
|
import { TrueAchievementsAction } from "./action-true-achievements";
|
||||||
import { SpeakerAction } from "./action-speaker";
|
import { SpeakerAction } from "./action-speaker";
|
||||||
import { RendererAction } from "./action-renderer";
|
import { RendererAction } from "./action-renderer";
|
||||||
@ -15,13 +15,7 @@ import { RendererAction } from "./action-renderer";
|
|||||||
|
|
||||||
export class GameBar {
|
export class GameBar {
|
||||||
private static instance: GameBar;
|
private static instance: GameBar;
|
||||||
public static getInstance(): GameBar {
|
public static getInstance = () => GameBar.instance ?? (GameBar.instance = new GameBar());
|
||||||
if (!GameBar.instance) {
|
|
||||||
GameBar.instance = new GameBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
return GameBar.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly VISIBLE_DURATION = 2000;
|
private static readonly VISIBLE_DURATION = 2000;
|
||||||
|
|
||||||
@ -35,12 +29,12 @@ export class GameBar {
|
|||||||
private constructor() {
|
private constructor() {
|
||||||
let $container;
|
let $container;
|
||||||
|
|
||||||
const position = getPref(PrefKey.GAME_BAR_POSITION);
|
const position = getPref(PrefKey.GAME_BAR_POSITION) as GameBarPosition;
|
||||||
|
|
||||||
const $gameBar = CE('div', {id: 'bx-game-bar', class: 'bx-gone', 'data-position': position},
|
const $gameBar = CE('div', {id: 'bx-game-bar', class: 'bx-gone', 'data-position': position},
|
||||||
$container = CE('div', {class: 'bx-game-bar-container bx-offscreen'}),
|
$container = CE('div', {class: 'bx-game-bar-container bx-offscreen'}),
|
||||||
createSvgIcon(position === 'bottom-left' ? BxIcon.CARET_RIGHT : BxIcon.CARET_LEFT),
|
createSvgIcon(position === 'bottom-left' ? BxIcon.CARET_RIGHT : BxIcon.CARET_LEFT),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.actions = [
|
this.actions = [
|
||||||
new ScreenshotAction(),
|
new ScreenshotAction(),
|
||||||
@ -78,11 +72,7 @@ export class GameBar {
|
|||||||
|
|
||||||
// Add animation when hiding game bar
|
// Add animation when hiding game bar
|
||||||
$container.addEventListener('transitionend', e => {
|
$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);
|
document.documentElement.appendChild($gameBar);
|
||||||
@ -106,9 +96,9 @@ export class GameBar {
|
|||||||
this.clearHideTimeout();
|
this.clearHideTimeout();
|
||||||
|
|
||||||
this.timeoutId = window.setTimeout(() => {
|
this.timeoutId = window.setTimeout(() => {
|
||||||
this.timeoutId = null;
|
this.timeoutId = null;
|
||||||
this.hideBar();
|
this.hideBar();
|
||||||
}, GameBar.VISIBLE_DURATION);
|
}, GameBar.VISIBLE_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearHideTimeout() {
|
private clearHideTimeout() {
|
||||||
@ -117,19 +107,15 @@ export class GameBar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enable() {
|
enable() {
|
||||||
this.$gameBar && this.$gameBar.classList.remove('bx-gone');
|
this.$gameBar.classList.remove('bx-gone');
|
||||||
}
|
}
|
||||||
|
|
||||||
disable() {
|
disable() {
|
||||||
this.hideBar();
|
this.hideBar();
|
||||||
this.$gameBar && this.$gameBar.classList.add('bx-gone');
|
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.remove('bx-offscreen', 'bx-hide' , 'bx-gone');
|
||||||
this.$container.classList.add('bx-show');
|
this.$container.classList.add('bx-show');
|
||||||
|
|
||||||
@ -142,18 +128,11 @@ export class GameBar {
|
|||||||
// Stop focusing Game Bar
|
// Stop focusing Game Bar
|
||||||
clearFocus();
|
clearFocus();
|
||||||
|
|
||||||
if (!this.$container) {
|
this.$container.classList.replace('bx-show', 'bx-hide');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$container.classList.remove('bx-show');
|
|
||||||
this.$container.classList.add('bx-hide');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset all states
|
// Reset all states
|
||||||
reset() {
|
reset() {
|
||||||
for (const action of this.actions) {
|
this.actions.forEach(action => action.reset());
|
||||||
action.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,14 +124,8 @@ This class uses some code from Yuzu emulator to handle mouse's movements
|
|||||||
Source: https://github.com/yuzu-emu/yuzu-mainline/blob/master/src/input_common/drivers/mouse.cpp
|
Source: https://github.com/yuzu-emu/yuzu-mainline/blob/master/src/input_common/drivers/mouse.cpp
|
||||||
*/
|
*/
|
||||||
export class EmulatedMkbHandler extends MkbHandler {
|
export class EmulatedMkbHandler extends MkbHandler {
|
||||||
static #instance: EmulatedMkbHandler;
|
private static instance: EmulatedMkbHandler;
|
||||||
public static getInstance(): EmulatedMkbHandler {
|
public 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);
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ type XcloudInputSink = {
|
|||||||
|
|
||||||
export class NativeMkbHandler extends MkbHandler {
|
export class NativeMkbHandler extends MkbHandler {
|
||||||
private static instance: NativeMkbHandler;
|
private static instance: NativeMkbHandler;
|
||||||
|
public static getInstance = () => NativeMkbHandler.instance ?? (NativeMkbHandler.instance = new NativeMkbHandler());
|
||||||
|
|
||||||
#pointerClient: PointerClient | undefined;
|
#pointerClient: PointerClient | undefined;
|
||||||
#enabled: boolean = false;
|
#enabled: boolean = false;
|
||||||
|
|
||||||
@ -37,14 +39,6 @@ export class NativeMkbHandler extends MkbHandler {
|
|||||||
|
|
||||||
#$message?: HTMLElement;
|
#$message?: HTMLElement;
|
||||||
|
|
||||||
public static getInstance(): NativeMkbHandler {
|
|
||||||
if (!NativeMkbHandler.instance) {
|
|
||||||
NativeMkbHandler.instance = new NativeMkbHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NativeMkbHandler.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
#onKeyboardEvent(e: KeyboardEvent) {
|
#onKeyboardEvent(e: KeyboardEvent) {
|
||||||
if (e.type === 'keyup' && e.code === 'F8') {
|
if (e.type === 'keyup' && e.code === 'F8') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -15,13 +15,7 @@ enum PointerAction {
|
|||||||
|
|
||||||
export class PointerClient {
|
export class PointerClient {
|
||||||
private static instance: PointerClient;
|
private static instance: PointerClient;
|
||||||
public static getInstance(): PointerClient {
|
public static getInstance = () => PointerClient.instance ?? (PointerClient.instance = new PointerClient());
|
||||||
if (!PointerClient.instance) {
|
|
||||||
PointerClient.instance = new PointerClient();
|
|
||||||
}
|
|
||||||
|
|
||||||
return PointerClient.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private socket: WebSocket | undefined | null;
|
private socket: WebSocket | undefined | null;
|
||||||
private mkbHandler: MkbHandler | undefined;
|
private mkbHandler: MkbHandler | undefined;
|
||||||
|
@ -632,12 +632,12 @@ true` + text;
|
|||||||
},
|
},
|
||||||
|
|
||||||
skipFeedbackDialog(str: string) {
|
skipFeedbackDialog(str: string) {
|
||||||
let text = '&&this.shouldTransitionToFeedback(';
|
let text = 'shouldTransitionToFeedback(e){';
|
||||||
if (!str.includes(text)) {
|
if (!str.includes(text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str.replace(text, '&& false ' + text);
|
str = str.replace(text, text + 'return !1;');
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ export class WebGL2Player {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private targetFps = 60;
|
private targetFps = 60;
|
||||||
private frameInterval = Math.ceil(1000 / this.targetFps);
|
private frameInterval = 0;
|
||||||
private lastFrameTime = 0;
|
private lastFrameTime = 0;
|
||||||
|
|
||||||
private animFrameId: number | null = null;
|
private animFrameId: number | null = null;
|
||||||
@ -73,7 +73,8 @@ export class WebGL2Player {
|
|||||||
|
|
||||||
setTargetFps(target: number) {
|
setTargetFps(target: number) {
|
||||||
this.targetFps = target;
|
this.targetFps = target;
|
||||||
this.frameInterval = Math.ceil(1000 / target);
|
this.lastFrameTime = 0;
|
||||||
|
this.frameInterval = target ? Math.floor(1000 / target) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCanvas() {
|
getCanvas() {
|
||||||
@ -94,6 +95,11 @@ export class WebGL2Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawFrame() {
|
drawFrame() {
|
||||||
|
// Don't draw when FPS is 0
|
||||||
|
if (this.targetFps === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Limit FPS
|
// Limit FPS
|
||||||
if (this.targetFps < 60) {
|
if (this.targetFps < 60) {
|
||||||
const currentTime = performance.now();
|
const currentTime = performance.now();
|
||||||
@ -233,10 +239,10 @@ export class WebGL2Player {
|
|||||||
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 (const resource of this.resources) {
|
for (const resource of this.resources) {
|
||||||
if (resource instanceof WebGLProgram) {
|
if (resource instanceof WebGLProgram) {
|
||||||
gl.useProgram(null);
|
|
||||||
gl.deleteProgram(resource);
|
gl.deleteProgram(resource);
|
||||||
} else if (resource instanceof WebGLShader) {
|
} else if (resource instanceof WebGLShader) {
|
||||||
gl.deleteShader(resource);
|
gl.deleteShader(resource);
|
||||||
|
@ -37,13 +37,7 @@ type RemotePlayConsole = {
|
|||||||
|
|
||||||
export class RemotePlayManager {
|
export class RemotePlayManager {
|
||||||
private static instance: RemotePlayManager;
|
private static instance: RemotePlayManager;
|
||||||
public static getInstance(): RemotePlayManager {
|
public static getInstance = () => RemotePlayManager.instance ?? (RemotePlayManager.instance = new RemotePlayManager());
|
||||||
if (!this.instance) {
|
|
||||||
this.instance = new RemotePlayManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isInitialized = false;
|
private isInitialized = false;
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
|
import { getPref } from "@/utils/settings-storages/global-settings-storage";
|
||||||
|
import { limitVideoPlayerFps } from "../stream/stream-settings-utils";
|
||||||
|
|
||||||
export class RendererShortcut {
|
export class RendererShortcut {
|
||||||
static toggleVisibility(): boolean {
|
static toggleVisibility(): boolean {
|
||||||
const $mediaContainer = document.querySelector('#game-stream div[data-testid="media-container"]');
|
const $mediaContainer = document.querySelector('#game-stream div[data-testid="media-container"]');
|
||||||
@ -6,6 +10,9 @@ export class RendererShortcut {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$mediaContainer.classList.toggle('bx-gone');
|
$mediaContainer.classList.toggle('bx-gone');
|
||||||
return !$mediaContainer.classList.contains('bx-gone');
|
const isShowing = !$mediaContainer.classList.contains('bx-gone');
|
||||||
|
// Switch FPS
|
||||||
|
limitVideoPlayerFps(isShowing ? getPref(PrefKey.VIDEO_MAX_FPS) : 0);
|
||||||
|
return isShowing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +50,7 @@ enum StreamBadge {
|
|||||||
|
|
||||||
export class StreamBadges {
|
export class StreamBadges {
|
||||||
private static instance: StreamBadges;
|
private static instance: StreamBadges;
|
||||||
public static getInstance(): StreamBadges {
|
public static getInstance = () => StreamBadges.instance ?? (StreamBadges.instance = new StreamBadges());
|
||||||
if (!StreamBadges.instance) {
|
|
||||||
StreamBadges.instance = new StreamBadges();
|
|
||||||
}
|
|
||||||
|
|
||||||
return StreamBadges.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private serverInfo: StreamServerInfo = {};
|
private serverInfo: StreamServerInfo = {};
|
||||||
|
|
||||||
|
@ -45,8 +45,7 @@ export function onChangeVideoPlayerType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function limitVideoPlayerFps() {
|
export function limitVideoPlayerFps(targetFps: number) {
|
||||||
const targetFps = getPref(PrefKey.VIDEO_MAX_FPS);
|
|
||||||
const streamPlayer = STATES.currentStream.streamPlayer;
|
const streamPlayer = STATES.currentStream.streamPlayer;
|
||||||
streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps);
|
streamPlayer?.getWebGL2Player()?.setTargetFps(targetFps);
|
||||||
}
|
}
|
||||||
@ -58,7 +57,7 @@ export function updateVideoPlayer() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
limitVideoPlayerFps();
|
limitVideoPlayerFps(getPref(PrefKey.VIDEO_MAX_FPS));
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
processing: getPref(PrefKey.VIDEO_PROCESSING),
|
processing: getPref(PrefKey.VIDEO_PROCESSING),
|
||||||
|
@ -9,13 +9,7 @@ import { StreamStat, StreamStatsCollector, type StreamStatGrade } from "@/utils/
|
|||||||
|
|
||||||
export class StreamStats {
|
export class StreamStats {
|
||||||
private static instance: StreamStats;
|
private static instance: StreamStats;
|
||||||
public static getInstance(): StreamStats {
|
public static getInstance = () => StreamStats.instance ?? (StreamStats.instance = new StreamStats());
|
||||||
if (!StreamStats.instance) {
|
|
||||||
StreamStats.instance = new StreamStats();
|
|
||||||
}
|
|
||||||
|
|
||||||
return StreamStats.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private intervalId?: number | null;
|
private intervalId?: number | null;
|
||||||
private readonly REFRESH_INTERVAL = 1 * 1000;
|
private readonly REFRESH_INTERVAL = 1 * 1000;
|
||||||
|
@ -88,12 +88,7 @@ export abstract class NavigationDialog {
|
|||||||
|
|
||||||
export class NavigationDialogManager {
|
export class NavigationDialogManager {
|
||||||
private static instance: NavigationDialogManager;
|
private static instance: NavigationDialogManager;
|
||||||
public static getInstance(): NavigationDialogManager {
|
public static getInstance = () => NavigationDialogManager.instance ?? (NavigationDialogManager.instance = new NavigationDialogManager());
|
||||||
if (!NavigationDialogManager.instance) {
|
|
||||||
NavigationDialogManager.instance = new NavigationDialogManager();
|
|
||||||
}
|
|
||||||
return NavigationDialogManager.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly GAMEPAD_POLLING_INTERVAL = 50;
|
private static readonly GAMEPAD_POLLING_INTERVAL = 50;
|
||||||
private static readonly GAMEPAD_KEYS = [
|
private static readonly GAMEPAD_KEYS = [
|
||||||
|
@ -11,12 +11,7 @@ import { BxEvent } from "@/utils/bx-event";
|
|||||||
|
|
||||||
export class RemotePlayNavigationDialog extends NavigationDialog {
|
export class RemotePlayNavigationDialog extends NavigationDialog {
|
||||||
private static instance: RemotePlayNavigationDialog;
|
private static instance: RemotePlayNavigationDialog;
|
||||||
public static getInstance(): RemotePlayNavigationDialog {
|
public static getInstance = () => RemotePlayNavigationDialog.instance ?? (RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog());
|
||||||
if (!RemotePlayNavigationDialog.instance) {
|
|
||||||
RemotePlayNavigationDialog.instance = new RemotePlayNavigationDialog();
|
|
||||||
}
|
|
||||||
return RemotePlayNavigationDialog.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly STATE_LABELS: Record<RemotePlayConsoleState, string> = {
|
private readonly STATE_LABELS: Record<RemotePlayConsoleState, string> = {
|
||||||
[RemotePlayConsoleState.ON]: t('powered-on'),
|
[RemotePlayConsoleState.ON]: t('powered-on'),
|
||||||
|
@ -64,12 +64,7 @@ type SettingTab = {
|
|||||||
|
|
||||||
export class SettingsNavigationDialog extends NavigationDialog {
|
export class SettingsNavigationDialog extends NavigationDialog {
|
||||||
private static instance: SettingsNavigationDialog;
|
private static instance: SettingsNavigationDialog;
|
||||||
public static getInstance(): SettingsNavigationDialog {
|
public static getInstance = () => SettingsNavigationDialog.instance ?? (SettingsNavigationDialog.instance = new SettingsNavigationDialog());
|
||||||
if (!SettingsNavigationDialog.instance) {
|
|
||||||
SettingsNavigationDialog.instance = new SettingsNavigationDialog();
|
|
||||||
}
|
|
||||||
return SettingsNavigationDialog.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
$container!: HTMLElement;
|
$container!: HTMLElement;
|
||||||
private $tabs!: HTMLElement;
|
private $tabs!: HTMLElement;
|
||||||
@ -409,7 +404,9 @@ export class SettingsNavigationDialog extends NavigationDialog {
|
|||||||
onChange: onChangeVideoPlayerType,
|
onChange: onChangeVideoPlayerType,
|
||||||
}, {
|
}, {
|
||||||
pref: PrefKey.VIDEO_MAX_FPS,
|
pref: PrefKey.VIDEO_MAX_FPS,
|
||||||
onChange: limitVideoPlayerFps,
|
onChange: e => {
|
||||||
|
limitVideoPlayerFps(parseInt(e.target.value));
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
pref: PrefKey.VIDEO_POWER_PREFERENCE,
|
pref: PrefKey.VIDEO_POWER_PREFERENCE,
|
||||||
onChange: () => {
|
onChange: () => {
|
||||||
|
@ -2,12 +2,7 @@ import { CE } from "@/utils/html";
|
|||||||
|
|
||||||
export class FullscreenText {
|
export class FullscreenText {
|
||||||
private static instance: FullscreenText;
|
private static instance: FullscreenText;
|
||||||
public static getInstance(): FullscreenText {
|
public static getInstance = () => FullscreenText.instance ?? (FullscreenText.instance = new FullscreenText());
|
||||||
if (!FullscreenText.instance) {
|
|
||||||
FullscreenText.instance = new FullscreenText();
|
|
||||||
}
|
|
||||||
return FullscreenText.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
$text: HTMLElement;
|
$text: HTMLElement;
|
||||||
|
|
||||||
|
@ -39,6 +39,10 @@ export const enum ControllerDeviceVibration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type GameBarPosition = 'bottom-left' | 'bottom-right' | 'off';
|
||||||
|
export type GameBarPositionOptions = Record<GameBarPosition, string>;
|
||||||
|
|
||||||
|
|
||||||
function getSupportedCodecProfiles() {
|
function getSupportedCodecProfiles() {
|
||||||
const options: PartialRecord<CodecProfile, string> = {
|
const options: PartialRecord<CodecProfile, string> = {
|
||||||
default: t('default'),
|
default: t('default'),
|
||||||
@ -323,12 +327,12 @@ export class GlobalSettingsStorage extends BaseSettingsStorage {
|
|||||||
[PrefKey.GAME_BAR_POSITION]: {
|
[PrefKey.GAME_BAR_POSITION]: {
|
||||||
requiredVariants: 'full',
|
requiredVariants: 'full',
|
||||||
label: t('position'),
|
label: t('position'),
|
||||||
default: 'bottom-left',
|
default: 'bottom-left' satisfies GameBarPosition,
|
||||||
options: {
|
options: {
|
||||||
'bottom-left': t('bottom-left'),
|
'bottom-left': t('bottom-left'),
|
||||||
'bottom-right': t('bottom-right'),
|
'bottom-right': t('bottom-right'),
|
||||||
'off': t('off'),
|
'off': t('off'),
|
||||||
},
|
} satisfies GameBarPositionOptions,
|
||||||
},
|
},
|
||||||
|
|
||||||
[PrefKey.LOCAL_CO_OP_ENABLED]: {
|
[PrefKey.LOCAL_CO_OP_ENABLED]: {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
import { PrefKey } from "@/enums/pref-keys";
|
||||||
import { BxEvent } from "./bx-event";
|
import { BxEvent } from "./bx-event";
|
||||||
import { STATES } from "./global";
|
import { STATES } from "./global";
|
||||||
import { humanFileSize, secondsToHm } from "./html";
|
import { humanFileSize, secondsToHm } from "./html";
|
||||||
|
import { getPref } from "./settings-storages/global-settings-storage";
|
||||||
|
|
||||||
export enum StreamStat {
|
export enum StreamStat {
|
||||||
PING = 'ping',
|
PING = 'ping',
|
||||||
@ -92,13 +94,7 @@ type CurrentStats = {
|
|||||||
|
|
||||||
export class StreamStatsCollector {
|
export class StreamStatsCollector {
|
||||||
private static instance: StreamStatsCollector;
|
private static instance: StreamStatsCollector;
|
||||||
public static getInstance(): StreamStatsCollector {
|
public static getInstance = () => StreamStatsCollector.instance ?? (StreamStatsCollector.instance = new StreamStatsCollector());
|
||||||
if (!StreamStatsCollector.instance) {
|
|
||||||
StreamStatsCollector.instance = new StreamStatsCollector();
|
|
||||||
}
|
|
||||||
|
|
||||||
return StreamStatsCollector.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect in background - 60 seconds
|
// Collect in background - 60 seconds
|
||||||
static readonly INTERVAL_BACKGROUND = 60 * 1000;
|
static readonly INTERVAL_BACKGROUND = 60 * 1000;
|
||||||
@ -127,7 +123,8 @@ export class StreamStatsCollector {
|
|||||||
[StreamStat.FPS]: {
|
[StreamStat.FPS]: {
|
||||||
current: 0,
|
current: 0,
|
||||||
toString() {
|
toString() {
|
||||||
return this.current.toString();
|
const maxFps = getPref(PrefKey.VIDEO_MAX_FPS);
|
||||||
|
return maxFps < 60 ? `${maxFps}/${this.current}` : this.current.toString();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3,13 +3,7 @@ import { STATES } from "./global";
|
|||||||
|
|
||||||
export class XcloudApi {
|
export class XcloudApi {
|
||||||
private static instance: XcloudApi;
|
private static instance: XcloudApi;
|
||||||
public static getInstance(): XcloudApi {
|
public static getInstance = () => XcloudApi.instance ?? (XcloudApi.instance = new XcloudApi());
|
||||||
if (!XcloudApi.instance) {
|
|
||||||
XcloudApi.instance = new XcloudApi();
|
|
||||||
}
|
|
||||||
|
|
||||||
return XcloudApi.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private CACHE_TITLES: {[key: string]: XcloudTitleInfo} = {};
|
private CACHE_TITLES: {[key: string]: XcloudTitleInfo} = {};
|
||||||
private CACHE_WAIT_TIME: {[key: string]: XcloudWaitTimeInfo} = {};
|
private CACHE_WAIT_TIME: {[key: string]: XcloudWaitTimeInfo} = {};
|
||||||
|
@ -13,9 +13,25 @@ import { BypassServerIps } from "@/enums/bypass-servers";
|
|||||||
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";
|
||||||
|
|
||||||
export
|
export class XcloudInterceptor {
|
||||||
class XcloudInterceptor {
|
private static readonly SERVER_EMOJIS = {
|
||||||
static async #handleLogin(request: RequestInfo | URL, init?: RequestInit) {
|
AustraliaEast: '🇦🇺',
|
||||||
|
AustraliaSouthEast: '🇦🇺',
|
||||||
|
BrazilSouth: '🇧🇷',
|
||||||
|
EastUS: '🇺🇸',
|
||||||
|
EastUS2: '🇺🇸',
|
||||||
|
JapanEast: '🇯🇵',
|
||||||
|
KoreaCentral: '🇰🇷',
|
||||||
|
MexicoCentral: '🇲🇽',
|
||||||
|
NorthCentralUs: '🇺🇸',
|
||||||
|
SouthCentralUS: '🇺🇸',
|
||||||
|
UKSouth: '🇬🇧',
|
||||||
|
WestEurope: '🇪🇺',
|
||||||
|
WestUS: '🇺🇸',
|
||||||
|
WestUS2: '🇺🇸',
|
||||||
|
};
|
||||||
|
|
||||||
|
private static async handleLogin(request: RequestInfo | URL, init?: RequestInit) {
|
||||||
const bypassServer = getPref(PrefKey.SERVER_BYPASS_RESTRICTION);
|
const bypassServer = getPref(PrefKey.SERVER_BYPASS_RESTRICTION);
|
||||||
if (bypassServer !== 'off') {
|
if (bypassServer !== 'off') {
|
||||||
const ip = BypassServerIps[bypassServer as keyof typeof BypassServerIps];
|
const ip = BypassServerIps[bypassServer as keyof typeof BypassServerIps];
|
||||||
@ -35,24 +51,8 @@ class XcloudInterceptor {
|
|||||||
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
RemotePlayManager.getInstance().xcloudToken = obj.gsToken;
|
||||||
|
|
||||||
// Get server list
|
// Get server list
|
||||||
const serverEmojis = {
|
|
||||||
AustraliaEast: '🇦🇺',
|
|
||||||
AustraliaSouthEast: '🇦🇺',
|
|
||||||
BrazilSouth: '🇧🇷',
|
|
||||||
EastUS: '🇺🇸',
|
|
||||||
EastUS2: '🇺🇸',
|
|
||||||
JapanEast: '🇯🇵',
|
|
||||||
KoreaCentral: '🇰🇷',
|
|
||||||
MexicoCentral: '🇲🇽',
|
|
||||||
NorthCentralUs: '🇺🇸',
|
|
||||||
SouthCentralUS: '🇺🇸',
|
|
||||||
UKSouth: '🇬🇧',
|
|
||||||
WestEurope: '🇪🇺',
|
|
||||||
WestUS: '🇺🇸',
|
|
||||||
WestUS2: '🇺🇸',
|
|
||||||
};
|
|
||||||
|
|
||||||
const serverRegex = /\/\/(\w+)\./;
|
const serverRegex = /\/\/(\w+)\./;
|
||||||
|
const serverEmojis = XcloudInterceptor.SERVER_EMOJIS;
|
||||||
|
|
||||||
for (let region of obj.offeringSettings.regions) {
|
for (let region of obj.offeringSettings.regions) {
|
||||||
const regionName = region.name as keyof typeof serverEmojis;
|
const regionName = region.name as keyof typeof serverEmojis;
|
||||||
@ -91,7 +91,7 @@ class XcloudInterceptor {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handlePlay(request: RequestInfo | URL, init?: RequestInit) {
|
private static async handlePlay(request: RequestInfo | URL, init?: RequestInit) {
|
||||||
const PREF_STREAM_TARGET_RESOLUTION = getPref(PrefKey.STREAM_TARGET_RESOLUTION);
|
const PREF_STREAM_TARGET_RESOLUTION = getPref(PrefKey.STREAM_TARGET_RESOLUTION);
|
||||||
const PREF_STREAM_PREFERRED_LOCALE = getPref(PrefKey.STREAM_PREFERRED_LOCALE);
|
const PREF_STREAM_PREFERRED_LOCALE = getPref(PrefKey.STREAM_PREFERRED_LOCALE);
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ class XcloudInterceptor {
|
|||||||
return NATIVE_FETCH(newRequest);
|
return NATIVE_FETCH(newRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handleWaitTime(request: RequestInfo | URL, init?: RequestInit) {
|
private static async handleWaitTime(request: RequestInfo | URL, init?: RequestInit) {
|
||||||
const response = await NATIVE_FETCH(request, init);
|
const response = await NATIVE_FETCH(request, init);
|
||||||
|
|
||||||
if (getPref(PrefKey.UI_LOADING_SCREEN_WAIT_TIME)) {
|
if (getPref(PrefKey.UI_LOADING_SCREEN_WAIT_TIME)) {
|
||||||
@ -143,7 +143,7 @@ class XcloudInterceptor {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handleConfiguration(request: RequestInfo | URL, init?: RequestInit) {
|
private static async handleConfiguration(request: RequestInfo | URL, init?: RequestInit) {
|
||||||
if ((request as Request).method !== 'GET') {
|
if ((request as Request).method !== 'GET') {
|
||||||
return NATIVE_FETCH(request, init);
|
return NATIVE_FETCH(request, init);
|
||||||
}
|
}
|
||||||
@ -213,13 +213,13 @@ class XcloudInterceptor {
|
|||||||
|
|
||||||
// Server list
|
// Server list
|
||||||
if (url.endsWith('/v2/login/user')) {
|
if (url.endsWith('/v2/login/user')) {
|
||||||
return XcloudInterceptor.#handleLogin(request, init);
|
return XcloudInterceptor.handleLogin(request, init);
|
||||||
} else if (url.endsWith('/sessions/cloud/play')) { // Get session
|
} else if (url.endsWith('/sessions/cloud/play')) { // Get session
|
||||||
return XcloudInterceptor.#handlePlay(request, init);
|
return XcloudInterceptor.handlePlay(request, init);
|
||||||
} else if (url.includes('xboxlive.com') && url.includes('/waittime/')) {
|
} else if (url.includes('xboxlive.com') && url.includes('/waittime/')) {
|
||||||
return XcloudInterceptor.#handleWaitTime(request, init);
|
return XcloudInterceptor.handleWaitTime(request, init);
|
||||||
} else if (url.endsWith('/configuration')) {
|
} else if (url.endsWith('/configuration')) {
|
||||||
return XcloudInterceptor.#handleConfiguration(request, init);
|
return XcloudInterceptor.handleConfiguration(request, init);
|
||||||
} else if (url && url.endsWith('/ice') && url.includes('/sessions/') && (request as Request).method === 'GET') {
|
} else if (url && url.endsWith('/ice') && url.includes('/sessions/') && (request as Request).method === 'GET') {
|
||||||
return patchIceCandidates(request as Request);
|
return patchIceCandidates(request as Request);
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import type { RemotePlayConsoleAddresses } from "@/types/network";
|
|||||||
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
import { RemotePlayManager } from "@/modules/remote-play-manager";
|
||||||
|
|
||||||
export class XhomeInterceptor {
|
export class XhomeInterceptor {
|
||||||
static #consoleAddrs: RemotePlayConsoleAddresses = {};
|
private static consoleAddrs: RemotePlayConsoleAddresses = {};
|
||||||
|
|
||||||
private static readonly BASE_DEVICE_INFO = {
|
private static readonly BASE_DEVICE_INFO = {
|
||||||
appInfo: {
|
appInfo: {
|
||||||
@ -52,7 +52,7 @@ export class XhomeInterceptor {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static async #handleLogin(request: Request) {
|
private static async handleLogin(request: Request) {
|
||||||
try {
|
try {
|
||||||
const clone = (request as Request).clone();
|
const clone = (request as Request).clone();
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ export class XhomeInterceptor {
|
|||||||
return NATIVE_FETCH(request);
|
return NATIVE_FETCH(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handleConfiguration(request: Request | URL) {
|
private static async handleConfiguration(request: Request | URL) {
|
||||||
const response = await NATIVE_FETCH(request);
|
const response = await NATIVE_FETCH(request);
|
||||||
|
|
||||||
const obj = await response.clone().json()
|
const obj = await response.clone().json()
|
||||||
@ -90,15 +90,15 @@ export class XhomeInterceptor {
|
|||||||
|
|
||||||
const serverDetails = obj.serverDetails;
|
const serverDetails = obj.serverDetails;
|
||||||
if (serverDetails.ipAddress) {
|
if (serverDetails.ipAddress) {
|
||||||
XhomeInterceptor.#consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
|
XhomeInterceptor.consoleAddrs[serverDetails.ipAddress] = processPorts(serverDetails.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverDetails.ipV4Address) {
|
if (serverDetails.ipV4Address) {
|
||||||
XhomeInterceptor.#consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
|
XhomeInterceptor.consoleAddrs[serverDetails.ipV4Address] = processPorts(serverDetails.ipV4Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverDetails.ipV6Address) {
|
if (serverDetails.ipV6Address) {
|
||||||
XhomeInterceptor.#consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
|
XhomeInterceptor.consoleAddrs[serverDetails.ipV6Address] = processPorts(serverDetails.ipV6Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.json = () => Promise.resolve(obj);
|
response.json = () => Promise.resolve(obj);
|
||||||
@ -107,7 +107,7 @@ export class XhomeInterceptor {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handleInputConfigs(request: Request | URL, opts: {[index: string]: any}) {
|
private static async handleInputConfigs(request: Request | URL, opts: {[index: string]: any}) {
|
||||||
const response = await NATIVE_FETCH(request);
|
const response = await NATIVE_FETCH(request);
|
||||||
|
|
||||||
if (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) !== StreamTouchController.ALL) {
|
if (getPref(PrefKey.STREAM_TOUCH_CONTROLLER) !== StreamTouchController.ALL) {
|
||||||
@ -144,7 +144,7 @@ export class XhomeInterceptor {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handleTitles(request: Request) {
|
private static async handleTitles(request: Request) {
|
||||||
const clone = request.clone();
|
const clone = request.clone();
|
||||||
|
|
||||||
const headers: {[index: string]: any} = {};
|
const headers: {[index: string]: any} = {};
|
||||||
@ -163,7 +163,7 @@ export class XhomeInterceptor {
|
|||||||
return NATIVE_FETCH(request);
|
return NATIVE_FETCH(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #handlePlay(request: RequestInfo | URL) {
|
private static async handlePlay(request: RequestInfo | URL) {
|
||||||
const clone = (request as Request).clone();
|
const clone = (request as Request).clone();
|
||||||
const body = await clone.json();
|
const body = await clone.json();
|
||||||
|
|
||||||
@ -216,17 +216,17 @@ export class XhomeInterceptor {
|
|||||||
|
|
||||||
// Get console IP
|
// Get console IP
|
||||||
if (url.includes('/configuration')) {
|
if (url.includes('/configuration')) {
|
||||||
return XhomeInterceptor.#handleConfiguration(request);
|
return XhomeInterceptor.handleConfiguration(request);
|
||||||
} else if (url.endsWith('/sessions/home/play')) {
|
} else if (url.endsWith('/sessions/home/play')) {
|
||||||
return XhomeInterceptor.#handlePlay(request);
|
return XhomeInterceptor.handlePlay(request);
|
||||||
} else if (url.includes('inputconfigs')) {
|
} else if (url.includes('inputconfigs')) {
|
||||||
return XhomeInterceptor.#handleInputConfigs(request, opts);
|
return XhomeInterceptor.handleInputConfigs(request, opts);
|
||||||
} else if (url.includes('/login/user')) {
|
} else if (url.includes('/login/user')) {
|
||||||
return XhomeInterceptor.#handleLogin(request);
|
return XhomeInterceptor.handleLogin(request);
|
||||||
} else if (url.endsWith('/titles')) {
|
} else if (url.endsWith('/titles')) {
|
||||||
return XhomeInterceptor.#handleTitles(request);
|
return XhomeInterceptor.handleTitles(request);
|
||||||
} else if (url && url.endsWith('/ice') && url.includes('/sessions/') && (request as Request).method === 'GET') {
|
} else if (url && url.endsWith('/ice') && url.includes('/sessions/') && (request as Request).method === 'GET') {
|
||||||
return patchIceCandidates(request, XhomeInterceptor.#consoleAddrs);
|
return patchIceCandidates(request, XhomeInterceptor.consoleAddrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await NATIVE_FETCH(request);
|
return await NATIVE_FETCH(request);
|
||||||
|
Reference in New Issue
Block a user