mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-07-08 23:31:43 +02:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
96de61c301 | |||
54a3e144a6 | |||
277a830d99 | |||
0ef8fe18ac | |||
706665713f |
2
dist/better-xcloud.meta.js
vendored
2
dist/better-xcloud.meta.js
vendored
@ -1,5 +1,5 @@
|
||||
// ==UserScript==
|
||||
// @name Better xCloud
|
||||
// @namespace https://github.com/redphx
|
||||
// @version 6.3.0
|
||||
// @version 6.3.1
|
||||
// ==/UserScript==
|
||||
|
40
dist/better-xcloud.pretty.user.js
vendored
40
dist/better-xcloud.pretty.user.js
vendored
@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name Better xCloud
|
||||
// @namespace https://github.com/redphx
|
||||
// @version 6.3.0
|
||||
// @version 6.3.1
|
||||
// @description Improve Xbox Cloud Gaming (xCloud) experience
|
||||
// @author redphx
|
||||
// @license MIT
|
||||
@ -190,7 +190,7 @@ class UserAgent {
|
||||
});
|
||||
}
|
||||
}
|
||||
var SCRIPT_VERSION = "6.3.0", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||
var SCRIPT_VERSION = "6.3.1", SCRIPT_VARIANT = "full", AppInterface = window.AppInterface;
|
||||
UserAgent.init();
|
||||
var userAgent = window.navigator.userAgent.toLowerCase(), isTv = userAgent.includes("smart-tv") || userAgent.includes("smarttv") || /\baft.*\b/.test(userAgent), isVr = window.navigator.userAgent.includes("VR") && window.navigator.userAgent.includes("OculusBrowser"), browserHasTouchSupport = "ontouchstart" in window || navigator.maxTouchPoints > 0, userAgentHasTouchSupport = !isTv && !isVr && browserHasTouchSupport, STATES = {
|
||||
supportedRegion: !0,
|
||||
@ -1167,7 +1167,7 @@ class BaseSettingsStorage {
|
||||
this.storage = window.localStorage, this.storageKey = storageKey;
|
||||
for (let [_, setting] of Object.entries(definitions)) {
|
||||
if (typeof setting.requiredVariants === "string") setting.requiredVariants = [setting.requiredVariants];
|
||||
setting.ready && setting.ready.call(this, setting);
|
||||
if (setting.ready) setting.ready.call(this, setting), delete setting.ready;
|
||||
}
|
||||
this.definitions = definitions, this._settings = null;
|
||||
}
|
||||
@ -1944,6 +1944,9 @@ class GameSettingsStorage extends BaseSettingsStorage {
|
||||
constructor(id) {
|
||||
super(`${"BetterXcloud.Stream"}.${id}`, StreamSettingsStorage.DEFINITIONS);
|
||||
}
|
||||
isEmpty() {
|
||||
return Object.keys(this.settings).length === 0;
|
||||
}
|
||||
deleteSetting(pref) {
|
||||
if (this.hasSetting(pref)) return delete this.settings[pref], this.saveSettings(), !0;
|
||||
return !1;
|
||||
@ -3688,7 +3691,7 @@ class StreamSettings {
|
||||
StreamSettings.settings.deviceVibrationIntensity = intensity, BxEventBus.Stream.emit("deviceVibration.updated", {});
|
||||
}
|
||||
static async refreshMkbSettings() {
|
||||
let settings = StreamSettings.settings, presetId = getStreamPref("mkb.p1.preset.mappingId"), orgPreset = await MkbMappingPresetsTable.getInstance().getPreset(presetId), orgPresetData = orgPreset.data, converted = {
|
||||
let settings = StreamSettings.settings, presetId = getStreamPref("mkb.p1.preset.mappingId"), orgPresetData = (await MkbMappingPresetsTable.getInstance().getPreset(presetId)).data, converted = {
|
||||
mapping: {},
|
||||
mouse: Object.assign({}, orgPresetData.mouse)
|
||||
}, key;
|
||||
@ -3699,20 +3702,20 @@ class StreamSettings {
|
||||
if (typeof keyName === "string") converted.mapping[keyName] = buttonIndex;
|
||||
}
|
||||
let mouse = converted.mouse;
|
||||
mouse["sensitivityX"] *= 0.001, mouse["sensitivityY"] *= 0.001, mouse["deadzoneCounterweight"] *= 0.01, settings.mkbPreset = converted, setStreamPref("mkb.p1.preset.mappingId", orgPreset.id, "direct"), BxEventBus.Stream.emit("mkb.setting.updated", {});
|
||||
mouse["sensitivityX"] *= 0.001, mouse["sensitivityY"] *= 0.001, mouse["deadzoneCounterweight"] *= 0.01, settings.mkbPreset = converted, BxEventBus.Stream.emit("mkb.setting.updated", {});
|
||||
}
|
||||
static async refreshKeyboardShortcuts() {
|
||||
let settings = StreamSettings.settings, presetId = getStreamPref("keyboardShortcuts.preset.inGameId");
|
||||
if (presetId === 0) {
|
||||
settings.keyboardShortcuts = null, setStreamPref("keyboardShortcuts.preset.inGameId", presetId, "direct"), BxEventBus.Stream.emit("keyboardShortcuts.updated", {});
|
||||
settings.keyboardShortcuts = null, BxEventBus.Stream.emit("keyboardShortcuts.updated", {});
|
||||
return;
|
||||
}
|
||||
let orgPreset = await KeyboardShortcutsTable.getInstance().getPreset(presetId), orgPresetData = orgPreset.data.mapping, converted = {}, action;
|
||||
let orgPresetData = (await KeyboardShortcutsTable.getInstance().getPreset(presetId)).data.mapping, converted = {}, action;
|
||||
for (action in orgPresetData) {
|
||||
let info = orgPresetData[action], key = `${info.code}:${info.modifiers || 0}`;
|
||||
converted[key] = action;
|
||||
}
|
||||
settings.keyboardShortcuts = converted, setStreamPref("keyboardShortcuts.preset.inGameId", orgPreset.id, "direct"), BxEventBus.Stream.emit("keyboardShortcuts.updated", {});
|
||||
settings.keyboardShortcuts = converted, BxEventBus.Stream.emit("keyboardShortcuts.updated", {});
|
||||
}
|
||||
static async refreshAllSettings() {
|
||||
window.BX_STREAM_SETTINGS = StreamSettings.settings, await StreamSettings.refreshControllerSettings(), await StreamSettings.refreshMkbSettings(), await StreamSettings.refreshKeyboardShortcuts();
|
||||
@ -4118,11 +4121,14 @@ class XboxApi {
|
||||
static CACHED_TITLES = {};
|
||||
static async getProductTitle(xboxTitleId) {
|
||||
if (xboxTitleId = xboxTitleId.toString(), XboxApi.CACHED_TITLES[xboxTitleId]) return XboxApi.CACHED_TITLES[xboxTitleId];
|
||||
let title;
|
||||
try {
|
||||
let url = `https://displaycatalog.mp.microsoft.com/v7.0/products/lookup?market=US&languages=en&value=${xboxTitleId}&alternateId=XboxTitleId&fieldsTemplate=browse`, productTitle = (await (await NATIVE_FETCH(url)).json()).Products[0].LocalizedProperties[0].ProductTitle;
|
||||
return XboxApi.CACHED_TITLES[xboxTitleId] = productTitle, productTitle;
|
||||
} catch (e) {}
|
||||
return;
|
||||
let url = `https://displaycatalog.mp.microsoft.com/v7.0/products/lookup?market=US&languages=en&value=${xboxTitleId}&alternateId=XboxTitleId&fieldsTemplate=browse`;
|
||||
title = (await (await NATIVE_FETCH(url)).json()).Products[0].LocalizedProperties[0].ProductTitle;
|
||||
} catch (e) {
|
||||
title = "Unknown Game #" + xboxTitleId;
|
||||
}
|
||||
return XboxApi.CACHED_TITLES[xboxTitleId] = title, title;
|
||||
}
|
||||
}
|
||||
class SettingsManager {
|
||||
@ -4304,7 +4310,9 @@ class SettingsManager {
|
||||
class: "bx-stream-settings-selection bx-gone",
|
||||
_nearby: { orientation: "vertical" }
|
||||
}, CE("div", !1, $select), this.$tips), BxEventBus.Stream.on("xboxTitleId.changed", async ({ id }) => {
|
||||
this.playingGameId = id, setGameIdPref(id);
|
||||
this.playingGameId = id;
|
||||
let gameSettings = STORAGE.Stream.getGameSettings(id), selectedId = gameSettings && !gameSettings.isEmpty() ? id : -1;
|
||||
setGameIdPref(selectedId);
|
||||
let $optGroup = $select.querySelector("optgroup");
|
||||
while ($optGroup.childElementCount > 1)
|
||||
$optGroup.lastElementChild?.remove();
|
||||
@ -4312,9 +4320,9 @@ class SettingsManager {
|
||||
let title = id === 0 ? "Xbox" : await XboxApi.getProductTitle(id);
|
||||
$optGroup.appendChild(CE("option", {
|
||||
value: id
|
||||
}, title)), $select.value = id.toString();
|
||||
} else $select.value = "-1";
|
||||
BxEventBus.Stream.emit("gameSettings.switched", { id });
|
||||
}, title));
|
||||
}
|
||||
$select.value = selectedId.toString(), BxEventBus.Stream.emit("gameSettings.switched", { id: selectedId });
|
||||
});
|
||||
}
|
||||
getStreamSettingsSelection() {
|
||||
|
14
dist/better-xcloud.user.js
vendored
14
dist/better-xcloud.user.js
vendored
File diff suppressed because one or more lines are too long
@ -270,7 +270,6 @@ BxEventBus.Stream.on('state.playing', payload => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateVideoPlayer();
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { limitVideoPlayerFps, onChangeVideoPlayerType, updateVideoPlayer } from
|
||||
import { StreamStats } from "./stream/stream-stats";
|
||||
import { SoundShortcut } from "./shortcuts/sound-shortcut";
|
||||
import { STATES } from "@/utils/global";
|
||||
import { getGamePref, getStreamPref, hasGamePref, isStreamPref, setGameIdPref } from "@/utils/pref-utils";
|
||||
import { getGamePref, getStreamPref, hasGamePref, isStreamPref, setGameIdPref, STORAGE } from "@/utils/pref-utils";
|
||||
import { BxExposed } from "@/utils/bx-exposed";
|
||||
import { StreamSettings } from "@/utils/stream-settings";
|
||||
import { NativeMkbHandler } from "./mkb/native-mkb-handler";
|
||||
@ -311,10 +311,16 @@ export class SettingsManager {
|
||||
|
||||
BxEventBus.Stream.on('xboxTitleId.changed', async ({ id }) => {
|
||||
this.playingGameId = id;
|
||||
setGameIdPref(id);
|
||||
const $optGroup = $select.querySelector('optgroup')!;
|
||||
|
||||
// Only switch to game settings if it's not empty
|
||||
const gameSettings = STORAGE.Stream.getGameSettings(id);
|
||||
const customSettings = gameSettings && !gameSettings.isEmpty();
|
||||
const selectedId = customSettings ? id : -1;
|
||||
|
||||
setGameIdPref(selectedId);
|
||||
|
||||
// Remove every options except the first one (All games)
|
||||
const $optGroup = $select.querySelector('optgroup')!;
|
||||
while ($optGroup.childElementCount > 1) {
|
||||
$optGroup.lastElementChild?.remove();
|
||||
}
|
||||
@ -325,13 +331,12 @@ export class SettingsManager {
|
||||
$optGroup.appendChild(CE('option', {
|
||||
value: id,
|
||||
}, title));
|
||||
|
||||
$select.value = id.toString();
|
||||
} else {
|
||||
$select.value = '-1';
|
||||
}
|
||||
|
||||
BxEventBus.Stream.emit('gameSettings.switched', { id });
|
||||
// Activate custom settings
|
||||
|
||||
$select.value = selectedId.toString();
|
||||
BxEventBus.Stream.emit('gameSettings.switched', { id: selectedId });
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,10 @@ export class BaseSettingsStorage<T extends AnyPref> {
|
||||
}
|
||||
*/
|
||||
|
||||
setting.ready && setting.ready.call(this, setting);
|
||||
if (setting.ready) {
|
||||
setting.ready.call(this, setting);
|
||||
delete setting.ready;
|
||||
}
|
||||
}
|
||||
this.definitions = definitions;
|
||||
|
||||
|
@ -7,6 +7,10 @@ export class GameSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
||||
super(`${StorageKey.STREAM}.${id}`, StreamSettingsStorage.DEFINITIONS);
|
||||
}
|
||||
|
||||
isEmpty() {
|
||||
return Object.keys(this.settings).length === 0;
|
||||
}
|
||||
|
||||
deleteSetting(pref: StreamPref) {
|
||||
if (this.hasSetting(pref)) {
|
||||
delete this.settings[pref];
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BypassServers } from "@/enums/bypass-servers";
|
||||
import { GlobalPref, StorageKey, type GlobalPrefTypeMap } from "@/enums/pref-keys";
|
||||
import { GlobalPref, StorageKey } from "@/enums/pref-keys";
|
||||
import { UserAgentProfile } from "@/enums/user-agent";
|
||||
import { type SettingDefinition } from "@/types/setting-definition";
|
||||
import { type SettingDefinition, type SettingDefinitions } from "@/types/setting-definition";
|
||||
import { BX_FLAGS } from "../bx-flags";
|
||||
import { STATES, AppInterface } from "../global";
|
||||
import { CE } from "../html";
|
||||
@ -71,7 +71,7 @@ function getSupportedCodecProfiles() {
|
||||
}
|
||||
|
||||
export class GlobalSettingsStorage extends BaseSettingsStorage<GlobalPref> {
|
||||
private static readonly DEFINITIONS: Record<keyof GlobalPrefTypeMap, SettingDefinition> = {
|
||||
private static readonly DEFINITIONS: SettingDefinitions<GlobalPref> = {
|
||||
[GlobalPref.VERSION_LAST_CHECK]: {
|
||||
default: 0,
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { StreamPref, StorageKey, type StreamPrefTypeMap, type PrefTypeMap } from "@/enums/pref-keys";
|
||||
import { StreamPref, StorageKey, type PrefTypeMap } from "@/enums/pref-keys";
|
||||
import { DeviceVibrationMode, StreamPlayerType, StreamVideoProcessing, VideoPowerPreference, VideoRatio, VideoPosition, StreamStat, StreamStatPosition } from "@/enums/pref-values";
|
||||
import { STATES } from "../global";
|
||||
import { KeyboardShortcutDefaultId } from "../local-db/keyboard-shortcuts-table";
|
||||
@ -6,7 +6,7 @@ import { MkbMappingDefaultPresetId } from "../local-db/mkb-mapping-presets-table
|
||||
import { t } from "../translation";
|
||||
import { BaseSettingsStorage } from "./base-settings-storage";
|
||||
import { CE } from "../html";
|
||||
import type { SettingActionOrigin, SettingDefinition } from "@/types/setting-definition";
|
||||
import type { SettingActionOrigin, SettingDefinitions } from "@/types/setting-definition";
|
||||
import { BxIcon } from "../bx-icon";
|
||||
import { GameSettingsStorage } from "./game-settings-storage";
|
||||
import { BxLogger } from "../bx-logger";
|
||||
@ -15,7 +15,7 @@ import { ControllerShortcutDefaultId } from "../local-db/controller-shortcuts-ta
|
||||
|
||||
|
||||
export class StreamSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
||||
static readonly DEFINITIONS: Record<keyof StreamPrefTypeMap, SettingDefinition> = {
|
||||
static readonly DEFINITIONS: SettingDefinitions<StreamPref> = {
|
||||
[StreamPref.DEVICE_VIBRATION_MODE]: {
|
||||
requiredVariants: 'full',
|
||||
label: t('device-vibration'),
|
||||
@ -132,7 +132,7 @@ export class StreamSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
||||
max: 4,
|
||||
params: {
|
||||
hideSlider: true,
|
||||
customTextValue(value) {
|
||||
customTextValue(value: any) {
|
||||
value = parseInt(value);
|
||||
return (value === 0) ? t('off') : value.toString();
|
||||
},
|
||||
@ -302,7 +302,7 @@ export class StreamSettingsStorage extends BaseSettingsStorage<StreamPref> {
|
||||
params: {
|
||||
size: 0,
|
||||
},
|
||||
ready: setting => {
|
||||
ready: (setting: any) => {
|
||||
// Remove Battery option in unsupported browser
|
||||
const multipleOptions = (setting as any).multipleOptions;
|
||||
if (!STATES.browser.capabilities.batteryApi) {
|
||||
|
@ -13,7 +13,7 @@ import { ShortcutAction } from "@/enums/shortcut-actions";
|
||||
import { KeyHelper } from "@/modules/mkb/key-helper";
|
||||
import { BxEventBus } from "./bx-event-bus";
|
||||
import { ControllerCustomizationsTable } from "./local-db/controller-customizations-table";
|
||||
import { getStreamPref, setStreamPref, STORAGE } from "@/utils/pref-utils";
|
||||
import { getStreamPref, STORAGE } from "@/utils/pref-utils";
|
||||
|
||||
|
||||
export type StreamSettingsData = {
|
||||
@ -191,7 +191,6 @@ export class StreamSettings {
|
||||
|
||||
settings.mkbPreset = converted;
|
||||
|
||||
setStreamPref(StreamPref.MKB_P1_MAPPING_PRESET_ID, orgPreset.id, 'direct');
|
||||
BxEventBus.Stream.emit('mkb.setting.updated', {});
|
||||
}
|
||||
|
||||
@ -202,7 +201,6 @@ export class StreamSettings {
|
||||
if (presetId === KeyboardShortcutDefaultId.OFF) {
|
||||
settings.keyboardShortcuts = null;
|
||||
|
||||
setStreamPref(StreamPref.KEYBOARD_SHORTCUTS_IN_GAME_PRESET_ID, presetId, 'direct');
|
||||
BxEventBus.Stream.emit('keyboardShortcuts.updated', {});
|
||||
return;
|
||||
}
|
||||
@ -222,7 +220,6 @@ export class StreamSettings {
|
||||
|
||||
settings.keyboardShortcuts = converted;
|
||||
|
||||
setStreamPref(StreamPref.KEYBOARD_SHORTCUTS_IN_GAME_PRESET_ID, orgPreset.id, 'direct');
|
||||
BxEventBus.Stream.emit('keyboardShortcuts.updated', {});
|
||||
}
|
||||
|
||||
|
@ -9,17 +9,18 @@ export class XboxApi {
|
||||
return XboxApi.CACHED_TITLES[xboxTitleId];
|
||||
}
|
||||
|
||||
let title: string;
|
||||
try {
|
||||
const url = `https://displaycatalog.mp.microsoft.com/v7.0/products/lookup?market=US&languages=en&value=${xboxTitleId}&alternateId=XboxTitleId&fieldsTemplate=browse`;
|
||||
const resp = await NATIVE_FETCH(url);
|
||||
const json = await resp.json();
|
||||
|
||||
const productTitle = json['Products'][0]['LocalizedProperties'][0]['ProductTitle'];
|
||||
XboxApi.CACHED_TITLES[xboxTitleId] = productTitle;
|
||||
title = json['Products'][0]['LocalizedProperties'][0]['ProductTitle'];
|
||||
} catch (e) {
|
||||
title = 'Unknown Game #' + xboxTitleId;
|
||||
}
|
||||
|
||||
return productTitle;
|
||||
} catch (e) {}
|
||||
|
||||
return;
|
||||
XboxApi.CACHED_TITLES[xboxTitleId] = title;
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user