Prepare for webOS & Tizen support

This commit is contained in:
redphx
2024-07-01 17:26:04 +07:00
parent 64d60aedfa
commit c1502b5552
29 changed files with 801 additions and 598 deletions

View File

@@ -1,6 +1,6 @@
import { ControllerShortcut } from "@/modules/controller-shortcut";
import { BxEvent } from "@utils/bx-event";
import { STATES } from "@utils/global";
import { deepClone, STATES } from "@utils/global";
import { getPref, PrefKey } from "@utils/preferences";
import { BxLogger } from "./bx-logger";
import { BX_FLAGS } from "./bx-flags";
@@ -19,7 +19,7 @@ export const BxExposed = {
modifyTitleInfo: (titleInfo: XcloudTitleInfo): XcloudTitleInfo => {
// Clone the object since the original is read-only
titleInfo = structuredClone(titleInfo);
titleInfo = deepClone(titleInfo);
let supportedInputTypes = titleInfo.details.supportedInputTypes;

View File

@@ -9,6 +9,8 @@ type BxFlags = Partial<{
ForceNativeMkbTitles: string[];
FeatureGates: {[key: string]: boolean} | null,
ScriptUi: 'default' | 'tv',
}>
// Setup flags
@@ -23,6 +25,8 @@ const DEFAULT_FLAGS: BxFlags = {
ForceNativeMkbTitles: [],
FeatureGates: null,
ScriptUi: 'default',
}
export const BX_FLAGS: BxFlags = Object.assign(DEFAULT_FLAGS, window.BX_FLAGS || {});

View File

@@ -140,3 +140,16 @@ body::-webkit-scrollbar {
const $style = CE('style', {}, css);
document.documentElement.appendChild($style);
}
export function preloadFonts() {
const $link = CE<HTMLLinkElement>('link', {
rel: 'preload',
href: 'https://redphx.github.io/better-xcloud/fonts/promptfont.otf',
as: 'font',
type: 'font/otf',
crossorigin: '',
});
document.querySelector('head')?.appendChild($link);
}

View File

@@ -24,3 +24,15 @@ export const STATES: BxStates = {
pointerServerPort: 9269,
};
export function deepClone(obj: any): any {
if ('structuredClone' in window) {
return structuredClone(obj);
}
if (!obj) {
return obj;
}
return JSON.parse(JSON.stringify(obj));
}

View File

@@ -9,6 +9,7 @@ type BxButton = {
title?: string;
disabled?: boolean;
onClick?: EventListener;
attributes?: {[key: string]: any},
}
type ButtonStyle = {[index: string]: number} & {[index: number]: string};
@@ -94,6 +95,12 @@ export const createButton = <T=HTMLButtonElement>(options: BxButton): T => {
options.disabled && (($btn as HTMLButtonElement).disabled = true);
options.onClick && $btn.addEventListener('click', options.onClick);
for (const key in options.attributes) {
if (!$btn.hasOwnProperty(key)) {
$btn.setAttribute(key, options.attributes[key]);
}
}
return $btn as T;
}

View File

@@ -576,8 +576,10 @@ export function interceptHttpRequests() {
const response = await NATIVE_FETCH(request, init);
const json = await response.json();
for (const key in FeatureGates) {
json.exp.treatments[key] = FeatureGates[key]
if (json && json.exp && json.treatments) {
for (const key in FeatureGates) {
json.exp.treatments[key] = FeatureGates[key]
}
}
response.json = () => Promise.resolve(json);

View File

@@ -570,7 +570,7 @@ export class Preferences {
[UserAgentProfile.SMARTTV_GENERIC]: 'Smart TV',
[UserAgentProfile.SMARTTV_TIZEN]: 'Samsung Smart TV',
[UserAgentProfile.VR_OCULUS]: 'Meta Quest VR',
[UserAgentProfile.ANDROID_KIWI_V123]: 'Kiwi Browser v123',
[UserAgentProfile.ANDROID_KIWI_V123]: 'Kiwi Browser v124 Fix',
[UserAgentProfile.CUSTOM]: t('custom'),
},
},

View File

@@ -1,4 +1,4 @@
import { STATES } from "@utils/global";
import { deepClone, STATES } from "@utils/global";
import { BxLogger } from "./bx-logger";
import { TouchController } from "@modules/touch-controller";
import { GamePassCloudGallery } from "../enums/game-pass-gallery";
@@ -59,7 +59,7 @@ export function overridePreloadState() {
// @ts-ignore
_state = state;
STATES.appContext = structuredClone(state.appContext);
STATES.appContext = deepClone(state.appContext);
}
});
}

View File

@@ -38,7 +38,7 @@ export class SettingElement {
}
$control.value = currentValue;
onChange && $control.addEventListener('change', e => {
onChange && $control.addEventListener('input', e => {
const target = e.target as HTMLSelectElement;
const value = (setting.type && setting.type === 'number') ? parseInt(target.value) : target.value;
onChange(e, value);
@@ -76,7 +76,7 @@ export class SettingElement {
const $parent = target.parentElement!;
$parent.focus();
$parent.dispatchEvent(new Event('change'));
$parent.dispatchEvent(new Event('input'));
});
$control.appendChild($option);
@@ -90,7 +90,7 @@ export class SettingElement {
$control.addEventListener('mousemove', e => e.preventDefault());
onChange && $control.addEventListener('change', (e: Event) => {
onChange && $control.addEventListener('input', (e: Event) => {
const target = e.target as HTMLSelectElement
const values = Array.from(target.selectedOptions).map(i => i.value);
onChange(e, values);

View File

@@ -377,8 +377,12 @@ export class Translations {
const resp = await NATIVE_FETCH(`https://raw.githubusercontent.com/redphx/better-xcloud/gh-pages/translations/${locale}.json`);
const translations = await resp.json();
window.localStorage.setItem(Translations.#KEY_TRANSLATIONS, JSON.stringify(translations));
Translations.#foreignTranslations = translations;
// Prevent saving incorrect translations
let currentLocale = localStorage.getItem(Translations.#KEY_LOCALE);
if (currentLocale === locale) {
window.localStorage.setItem(Translations.#KEY_TRANSLATIONS, JSON.stringify(translations));
Translations.#foreignTranslations = translations;
}
return true;
} catch (e) {
debugger;

View File

@@ -1,4 +1,5 @@
import { UserAgentProfile } from "@enums/user-agent";
import { deepClone } from "./global";
type UserAgentConfig = {
profile: UserAgentProfile,
@@ -45,7 +46,7 @@ export class UserAgent {
}
static updateStorage(profile: UserAgentProfile, custom?: string) {
const clonedConfig = structuredClone(UserAgent.#config);
const clonedConfig = deepClone(UserAgent.#config);
clonedConfig.profile = profile;
if (typeof custom !== 'undefined') {