mirror of
https://github.com/redphx/better-xcloud.git
synced 2025-06-06 15:47:18 +02:00
Replace "#" with "private"
This commit is contained in:
parent
2eea9ce8f5
commit
e4d73f9e36
124
dist/better-xcloud.lite.user.js
vendored
124
dist/better-xcloud.lite.user.js
vendored
@ -1960,43 +1960,43 @@ class StreamStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Toast {
|
class Toast {
|
||||||
static #$wrapper;
|
static $wrapper;
|
||||||
static #$msg;
|
static $msg;
|
||||||
static #$status;
|
static $status;
|
||||||
static #stack = [];
|
static stack = [];
|
||||||
static #isShowing = !1;
|
static isShowing = !1;
|
||||||
static #timeout;
|
static timeout;
|
||||||
static #DURATION = 3000;
|
static DURATION = 3000;
|
||||||
static show(msg, status, options = {}) {
|
static show(msg, status, options = {}) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
const args = Array.from(arguments);
|
const args = Array.from(arguments);
|
||||||
if (options.instant) Toast.#stack = [args], Toast.#showNext();
|
if (options.instant) Toast.stack = [args], Toast.showNext();
|
||||||
else Toast.#stack.push(args), !Toast.#isShowing && Toast.#showNext();
|
else Toast.stack.push(args), !Toast.isShowing && Toast.showNext();
|
||||||
}
|
}
|
||||||
static #showNext() {
|
static showNext() {
|
||||||
if (!Toast.#stack.length) {
|
if (!Toast.stack.length) {
|
||||||
Toast.#isShowing = !1;
|
Toast.isShowing = !1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Toast.#isShowing = !0, Toast.#timeout && clearTimeout(Toast.#timeout), Toast.#timeout = window.setTimeout(Toast.#hide, Toast.#DURATION);
|
Toast.isShowing = !0, Toast.timeout && clearTimeout(Toast.timeout), Toast.timeout = window.setTimeout(Toast.hide, Toast.DURATION);
|
||||||
const [msg, status, options] = Toast.#stack.shift();
|
const [msg, status, options] = Toast.stack.shift();
|
||||||
if (options && options.html) Toast.#$msg.innerHTML = msg;
|
if (options && options.html) Toast.$msg.innerHTML = msg;
|
||||||
else Toast.#$msg.textContent = msg;
|
else Toast.$msg.textContent = msg;
|
||||||
if (status) Toast.#$status.classList.remove("bx-gone"), Toast.#$status.textContent = status;
|
if (status) Toast.$status.classList.remove("bx-gone"), Toast.$status.textContent = status;
|
||||||
else Toast.#$status.classList.add("bx-gone");
|
else Toast.$status.classList.add("bx-gone");
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-show");
|
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-show");
|
||||||
}
|
}
|
||||||
static #hide() {
|
static hide() {
|
||||||
Toast.#timeout = null;
|
Toast.timeout = null;
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove("bx-show"), classList.add("bx-hide");
|
classList.remove("bx-show"), classList.add("bx-hide");
|
||||||
}
|
}
|
||||||
static setup() {
|
static setup() {
|
||||||
Toast.#$wrapper = CE("div", { class: "bx-toast bx-offscreen" }, Toast.#$msg = CE("span", { class: "bx-toast-msg" }), Toast.#$status = CE("span", { class: "bx-toast-status" })), Toast.#$wrapper.addEventListener("transitionend", (e) => {
|
Toast.$wrapper = CE("div", { class: "bx-toast bx-offscreen" }, Toast.$msg = CE("span", { class: "bx-toast-msg" }), Toast.$status = CE("span", { class: "bx-toast-status" })), Toast.$wrapper.addEventListener("transitionend", (e) => {
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
if (classList.contains("bx-hide")) classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.#showNext();
|
if (classList.contains("bx-hide")) classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.showNext();
|
||||||
}), document.documentElement.appendChild(Toast.#$wrapper);
|
}), document.documentElement.appendChild(Toast.$wrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function ceilToNearest(value, interval) {
|
function ceilToNearest(value, interval) {
|
||||||
@ -2392,17 +2392,17 @@ class PointerClient {
|
|||||||
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
|
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
|
||||||
return PointerClient.instance;
|
return PointerClient.instance;
|
||||||
}
|
}
|
||||||
#socket;
|
socket;
|
||||||
#mkbHandler;
|
mkbHandler;
|
||||||
start(port, mkbHandler) {
|
start(port, mkbHandler) {
|
||||||
if (!port) throw new Error("PointerServer port is 0");
|
if (!port) throw new Error("PointerServer port is 0");
|
||||||
this.#mkbHandler = mkbHandler, this.#socket = new WebSocket(`ws://localhost:${port}`), this.#socket.binaryType = "arraybuffer", this.#socket.addEventListener("open", (event) => {
|
this.mkbHandler = mkbHandler, this.socket = new WebSocket(`ws://localhost:${port}`), this.socket.binaryType = "arraybuffer", this.socket.addEventListener("open", (event) => {
|
||||||
BxLogger.info(LOG_TAG, "connected");
|
BxLogger.info(LOG_TAG, "connected");
|
||||||
}), this.#socket.addEventListener("error", (event) => {
|
}), this.socket.addEventListener("error", (event) => {
|
||||||
BxLogger.error(LOG_TAG, event), Toast.show("Cannot setup mouse: " + event);
|
BxLogger.error(LOG_TAG, event), Toast.show("Cannot setup mouse: " + event);
|
||||||
}), this.#socket.addEventListener("close", (event) => {
|
}), this.socket.addEventListener("close", (event) => {
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
}), this.#socket.addEventListener("message", (event) => {
|
}), this.socket.addEventListener("message", (event) => {
|
||||||
const dataView = new DataView(event.data);
|
const dataView = new DataView(event.data);
|
||||||
let messageType = dataView.getInt8(0), offset = Int8Array.BYTES_PER_ELEMENT;
|
let messageType = dataView.getInt8(0), offset = Int8Array.BYTES_PER_ELEMENT;
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
@ -2425,14 +2425,14 @@ class PointerClient {
|
|||||||
const x = dataView.getInt16(offset);
|
const x = dataView.getInt16(offset);
|
||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const y = dataView.getInt16(offset);
|
const y = dataView.getInt16(offset);
|
||||||
this.#mkbHandler?.handleMouseMove({
|
this.mkbHandler?.handleMouseMove({
|
||||||
movementX: x,
|
movementX: x,
|
||||||
movementY: y
|
movementY: y
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onPress(messageType, dataView, offset) {
|
onPress(messageType, dataView, offset) {
|
||||||
const button = dataView.getUint8(offset);
|
const button = dataView.getUint8(offset);
|
||||||
this.#mkbHandler?.handleMouseClick({
|
this.mkbHandler?.handleMouseClick({
|
||||||
pointerButton: button,
|
pointerButton: button,
|
||||||
pressed: messageType === 2
|
pressed: messageType === 2
|
||||||
});
|
});
|
||||||
@ -2441,19 +2441,19 @@ class PointerClient {
|
|||||||
const vScroll = dataView.getInt16(offset);
|
const vScroll = dataView.getInt16(offset);
|
||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const hScroll = dataView.getInt16(offset);
|
const hScroll = dataView.getInt16(offset);
|
||||||
this.#mkbHandler?.handleMouseWheel({
|
this.mkbHandler?.handleMouseWheel({
|
||||||
vertical: vScroll,
|
vertical: vScroll,
|
||||||
horizontal: hScroll
|
horizontal: hScroll
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onPointerCaptureChanged(dataView, offset) {
|
onPointerCaptureChanged(dataView, offset) {
|
||||||
dataView.getInt8(offset) !== 1 && this.#mkbHandler?.stop();
|
dataView.getInt8(offset) !== 1 && this.mkbHandler?.stop();
|
||||||
}
|
}
|
||||||
stop() {
|
stop() {
|
||||||
try {
|
try {
|
||||||
this.#socket?.close();
|
this.socket?.close();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MouseDataProvider {
|
class MouseDataProvider {
|
||||||
@ -4375,29 +4375,29 @@ class RemotePlayManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class LoadingScreen {
|
class LoadingScreen {
|
||||||
static #$bgStyle;
|
static $bgStyle;
|
||||||
static #$waitTimeBox;
|
static $waitTimeBox;
|
||||||
static #waitTimeInterval = null;
|
static waitTimeInterval = null;
|
||||||
static #orgWebTitle;
|
static orgWebTitle;
|
||||||
static #secondsToString(seconds) {
|
static secondsToString(seconds) {
|
||||||
const m = Math.floor(seconds / 60), s = Math.floor(seconds % 60), mDisplay = m > 0 ? `${m}m` : "", sDisplay = `${s}s`.padStart(s >= 0 ? 3 : 4, "0");
|
const m = Math.floor(seconds / 60), s = Math.floor(seconds % 60), mDisplay = m > 0 ? `${m}m` : "", sDisplay = `${s}s`.padStart(s >= 0 ? 3 : 4, "0");
|
||||||
return mDisplay + sDisplay;
|
return mDisplay + sDisplay;
|
||||||
}
|
}
|
||||||
static setup() {
|
static setup() {
|
||||||
const titleInfo = STATES.currentStream.titleInfo;
|
const titleInfo = STATES.currentStream.titleInfo;
|
||||||
if (!titleInfo) return;
|
if (!titleInfo) return;
|
||||||
if (!LoadingScreen.#$bgStyle) {
|
if (!LoadingScreen.$bgStyle) {
|
||||||
const $bgStyle = CE("style");
|
const $bgStyle = CE("style");
|
||||||
document.documentElement.appendChild($bgStyle), LoadingScreen.#$bgStyle = $bgStyle;
|
document.documentElement.appendChild($bgStyle), LoadingScreen.$bgStyle = $bgStyle;
|
||||||
}
|
}
|
||||||
if (LoadingScreen.#setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide") LoadingScreen.#hideRocket();
|
if (LoadingScreen.setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide") LoadingScreen.hideRocket();
|
||||||
}
|
}
|
||||||
static #hideRocket() {
|
static hideRocket() {
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
$bgStyle.textContent += "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
|
$bgStyle.textContent += "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
|
||||||
}
|
}
|
||||||
static #setBackground(imageUrl) {
|
static setBackground(imageUrl) {
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
imageUrl = imageUrl + "?w=1920", $bgStyle.textContent += '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
|
imageUrl = imageUrl + "?w=1920", $bgStyle.textContent += '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
|
||||||
const bg = new Image;
|
const bg = new Image;
|
||||||
bg.onload = (e) => {
|
bg.onload = (e) => {
|
||||||
@ -4405,31 +4405,31 @@ class LoadingScreen {
|
|||||||
}, bg.src = imageUrl;
|
}, bg.src = imageUrl;
|
||||||
}
|
}
|
||||||
static setupWaitTime(waitTime) {
|
static setupWaitTime(waitTime) {
|
||||||
if (getPref("ui_loading_screen_rocket") === "hide-queue") LoadingScreen.#hideRocket();
|
if (getPref("ui_loading_screen_rocket") === "hide-queue") LoadingScreen.hideRocket();
|
||||||
let secondsLeft = waitTime, $countDown, $estimated;
|
let secondsLeft = waitTime, $countDown, $estimated;
|
||||||
LoadingScreen.#orgWebTitle = document.title;
|
LoadingScreen.orgWebTitle = document.title;
|
||||||
const endDate = new Date, timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
const endDate = new Date, timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
||||||
endDate.setSeconds(endDate.getSeconds() + waitTime - timeZoneOffsetSeconds);
|
endDate.setSeconds(endDate.getSeconds() + waitTime - timeZoneOffsetSeconds);
|
||||||
let endDateStr = endDate.toISOString().slice(0, 19);
|
let endDateStr = endDate.toISOString().slice(0, 19);
|
||||||
endDateStr = endDateStr.substring(0, 10) + " " + endDateStr.substring(11, 19), endDateStr += ` (${LoadingScreen.#secondsToString(waitTime)})`;
|
endDateStr = endDateStr.substring(0, 10) + " " + endDateStr.substring(11, 19), endDateStr += ` (${LoadingScreen.secondsToString(waitTime)})`;
|
||||||
let $waitTimeBox = LoadingScreen.#$waitTimeBox;
|
let $waitTimeBox = LoadingScreen.$waitTimeBox;
|
||||||
if (!$waitTimeBox) $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.#$waitTimeBox = $waitTimeBox;
|
if (!$waitTimeBox) $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.$waitTimeBox = $waitTimeBox;
|
||||||
else $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
|
else $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
|
||||||
$estimated.textContent = endDateStr, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, LoadingScreen.#waitTimeInterval = window.setInterval(() => {
|
$estimated.textContent = endDateStr, $countDown.textContent = LoadingScreen.secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`, LoadingScreen.waitTimeInterval = window.setInterval(() => {
|
||||||
if (secondsLeft--, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, secondsLeft <= 0) LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
|
if (secondsLeft--, $countDown.textContent = LoadingScreen.secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`, secondsLeft <= 0) LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval), LoadingScreen.waitTimeInterval = null;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
static hide() {
|
static hide() {
|
||||||
if (LoadingScreen.#orgWebTitle && (document.title = LoadingScreen.#orgWebTitle), LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add("bx-gone"), getPref("ui_loading_screen_game_art") && LoadingScreen.#$bgStyle) {
|
if (LoadingScreen.orgWebTitle && (document.title = LoadingScreen.orgWebTitle), LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add("bx-gone"), getPref("ui_loading_screen_game_art") && LoadingScreen.$bgStyle) {
|
||||||
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
||||||
$rocketBg && $rocketBg.addEventListener("transitionend", (e) => {
|
$rocketBg && $rocketBg.addEventListener("transitionend", (e) => {
|
||||||
LoadingScreen.#$bgStyle.textContent += "#game-stream{background:#000 !important}";
|
LoadingScreen.$bgStyle.textContent += "#game-stream{background:#000 !important}";
|
||||||
}), LoadingScreen.#$bgStyle.textContent += '#game-stream rect[width="800"]{opacity:1 !important}';
|
}), LoadingScreen.$bgStyle.textContent += '#game-stream rect[width="800"]{opacity:1 !important}';
|
||||||
}
|
}
|
||||||
setTimeout(LoadingScreen.reset, 2000);
|
setTimeout(LoadingScreen.reset, 2000);
|
||||||
}
|
}
|
||||||
static reset() {
|
static reset() {
|
||||||
LoadingScreen.#$bgStyle && (LoadingScreen.#$bgStyle.textContent = ""), LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add("bx-gone"), LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
|
LoadingScreen.$bgStyle && (LoadingScreen.$bgStyle.textContent = ""), LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add("bx-gone"), LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval), LoadingScreen.waitTimeInterval = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class GuideMenu {
|
class GuideMenu {
|
||||||
|
202
dist/better-xcloud.user.js
vendored
202
dist/better-xcloud.user.js
vendored
@ -2031,43 +2031,43 @@ class StreamStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Toast {
|
class Toast {
|
||||||
static #$wrapper;
|
static $wrapper;
|
||||||
static #$msg;
|
static $msg;
|
||||||
static #$status;
|
static $status;
|
||||||
static #stack = [];
|
static stack = [];
|
||||||
static #isShowing = !1;
|
static isShowing = !1;
|
||||||
static #timeout;
|
static timeout;
|
||||||
static #DURATION = 3000;
|
static DURATION = 3000;
|
||||||
static show(msg, status, options = {}) {
|
static show(msg, status, options = {}) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
const args = Array.from(arguments);
|
const args = Array.from(arguments);
|
||||||
if (options.instant) Toast.#stack = [args], Toast.#showNext();
|
if (options.instant) Toast.stack = [args], Toast.showNext();
|
||||||
else Toast.#stack.push(args), !Toast.#isShowing && Toast.#showNext();
|
else Toast.stack.push(args), !Toast.isShowing && Toast.showNext();
|
||||||
}
|
}
|
||||||
static #showNext() {
|
static showNext() {
|
||||||
if (!Toast.#stack.length) {
|
if (!Toast.stack.length) {
|
||||||
Toast.#isShowing = !1;
|
Toast.isShowing = !1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Toast.#isShowing = !0, Toast.#timeout && clearTimeout(Toast.#timeout), Toast.#timeout = window.setTimeout(Toast.#hide, Toast.#DURATION);
|
Toast.isShowing = !0, Toast.timeout && clearTimeout(Toast.timeout), Toast.timeout = window.setTimeout(Toast.hide, Toast.DURATION);
|
||||||
const [msg, status, options] = Toast.#stack.shift();
|
const [msg, status, options] = Toast.stack.shift();
|
||||||
if (options && options.html) Toast.#$msg.innerHTML = msg;
|
if (options && options.html) Toast.$msg.innerHTML = msg;
|
||||||
else Toast.#$msg.textContent = msg;
|
else Toast.$msg.textContent = msg;
|
||||||
if (status) Toast.#$status.classList.remove("bx-gone"), Toast.#$status.textContent = status;
|
if (status) Toast.$status.classList.remove("bx-gone"), Toast.$status.textContent = status;
|
||||||
else Toast.#$status.classList.add("bx-gone");
|
else Toast.$status.classList.add("bx-gone");
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-show");
|
classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-show");
|
||||||
}
|
}
|
||||||
static #hide() {
|
static hide() {
|
||||||
Toast.#timeout = null;
|
Toast.timeout = null;
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove("bx-show"), classList.add("bx-hide");
|
classList.remove("bx-show"), classList.add("bx-hide");
|
||||||
}
|
}
|
||||||
static setup() {
|
static setup() {
|
||||||
Toast.#$wrapper = CE("div", { class: "bx-toast bx-offscreen" }, Toast.#$msg = CE("span", { class: "bx-toast-msg" }), Toast.#$status = CE("span", { class: "bx-toast-status" })), Toast.#$wrapper.addEventListener("transitionend", (e) => {
|
Toast.$wrapper = CE("div", { class: "bx-toast bx-offscreen" }, Toast.$msg = CE("span", { class: "bx-toast-msg" }), Toast.$status = CE("span", { class: "bx-toast-status" })), Toast.$wrapper.addEventListener("transitionend", (e) => {
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
if (classList.contains("bx-hide")) classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.#showNext();
|
if (classList.contains("bx-hide")) classList.remove("bx-offscreen", "bx-hide"), classList.add("bx-offscreen"), Toast.showNext();
|
||||||
}), document.documentElement.appendChild(Toast.#$wrapper);
|
}), document.documentElement.appendChild(Toast.$wrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MicrophoneShortcut {
|
class MicrophoneShortcut {
|
||||||
@ -2509,17 +2509,17 @@ class PointerClient {
|
|||||||
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
|
if (!PointerClient.instance) PointerClient.instance = new PointerClient;
|
||||||
return PointerClient.instance;
|
return PointerClient.instance;
|
||||||
}
|
}
|
||||||
#socket;
|
socket;
|
||||||
#mkbHandler;
|
mkbHandler;
|
||||||
start(port, mkbHandler) {
|
start(port, mkbHandler) {
|
||||||
if (!port) throw new Error("PointerServer port is 0");
|
if (!port) throw new Error("PointerServer port is 0");
|
||||||
this.#mkbHandler = mkbHandler, this.#socket = new WebSocket(`ws://localhost:${port}`), this.#socket.binaryType = "arraybuffer", this.#socket.addEventListener("open", (event) => {
|
this.mkbHandler = mkbHandler, this.socket = new WebSocket(`ws://localhost:${port}`), this.socket.binaryType = "arraybuffer", this.socket.addEventListener("open", (event) => {
|
||||||
BxLogger.info(LOG_TAG, "connected");
|
BxLogger.info(LOG_TAG, "connected");
|
||||||
}), this.#socket.addEventListener("error", (event) => {
|
}), this.socket.addEventListener("error", (event) => {
|
||||||
BxLogger.error(LOG_TAG, event), Toast.show("Cannot setup mouse: " + event);
|
BxLogger.error(LOG_TAG, event), Toast.show("Cannot setup mouse: " + event);
|
||||||
}), this.#socket.addEventListener("close", (event) => {
|
}), this.socket.addEventListener("close", (event) => {
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
}), this.#socket.addEventListener("message", (event) => {
|
}), this.socket.addEventListener("message", (event) => {
|
||||||
const dataView = new DataView(event.data);
|
const dataView = new DataView(event.data);
|
||||||
let messageType = dataView.getInt8(0), offset = Int8Array.BYTES_PER_ELEMENT;
|
let messageType = dataView.getInt8(0), offset = Int8Array.BYTES_PER_ELEMENT;
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
@ -2542,14 +2542,14 @@ class PointerClient {
|
|||||||
const x = dataView.getInt16(offset);
|
const x = dataView.getInt16(offset);
|
||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const y = dataView.getInt16(offset);
|
const y = dataView.getInt16(offset);
|
||||||
this.#mkbHandler?.handleMouseMove({
|
this.mkbHandler?.handleMouseMove({
|
||||||
movementX: x,
|
movementX: x,
|
||||||
movementY: y
|
movementY: y
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onPress(messageType, dataView, offset) {
|
onPress(messageType, dataView, offset) {
|
||||||
const button = dataView.getUint8(offset);
|
const button = dataView.getUint8(offset);
|
||||||
this.#mkbHandler?.handleMouseClick({
|
this.mkbHandler?.handleMouseClick({
|
||||||
pointerButton: button,
|
pointerButton: button,
|
||||||
pressed: messageType === 2
|
pressed: messageType === 2
|
||||||
});
|
});
|
||||||
@ -2558,19 +2558,19 @@ class PointerClient {
|
|||||||
const vScroll = dataView.getInt16(offset);
|
const vScroll = dataView.getInt16(offset);
|
||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const hScroll = dataView.getInt16(offset);
|
const hScroll = dataView.getInt16(offset);
|
||||||
this.#mkbHandler?.handleMouseWheel({
|
this.mkbHandler?.handleMouseWheel({
|
||||||
vertical: vScroll,
|
vertical: vScroll,
|
||||||
horizontal: hScroll
|
horizontal: hScroll
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onPointerCaptureChanged(dataView, offset) {
|
onPointerCaptureChanged(dataView, offset) {
|
||||||
dataView.getInt8(offset) !== 1 && this.#mkbHandler?.stop();
|
dataView.getInt8(offset) !== 1 && this.mkbHandler?.stop();
|
||||||
}
|
}
|
||||||
stop() {
|
stop() {
|
||||||
try {
|
try {
|
||||||
this.#socket?.close();
|
this.socket?.close();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class MouseDataProvider {
|
class MouseDataProvider {
|
||||||
@ -5513,30 +5513,30 @@ class SettingsNavigationDialog extends NavigationDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class ControllerShortcut {
|
class ControllerShortcut {
|
||||||
static #STORAGE_KEY = "better_xcloud_controller_shortcuts";
|
static STORAGE_KEY = "better_xcloud_controller_shortcuts";
|
||||||
static #buttonsCache = {};
|
static buttonsCache = {};
|
||||||
static #buttonsStatus = {};
|
static buttonsStatus = {};
|
||||||
static #$selectProfile;
|
static $selectProfile;
|
||||||
static #$selectActions = {};
|
static $selectActions = {};
|
||||||
static #$container;
|
static $container;
|
||||||
static #ACTIONS = null;
|
static ACTIONS = null;
|
||||||
static reset(index) {
|
static reset(index) {
|
||||||
ControllerShortcut.#buttonsCache[index] = [], ControllerShortcut.#buttonsStatus[index] = [];
|
ControllerShortcut.buttonsCache[index] = [], ControllerShortcut.buttonsStatus[index] = [];
|
||||||
}
|
}
|
||||||
static handle(gamepad) {
|
static handle(gamepad) {
|
||||||
if (!ControllerShortcut.#ACTIONS) ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
|
if (!ControllerShortcut.ACTIONS) ControllerShortcut.ACTIONS = ControllerShortcut.getActionsFromStorage();
|
||||||
const gamepadIndex = gamepad.index, actions = ControllerShortcut.#ACTIONS[gamepad.id];
|
const gamepadIndex = gamepad.index, actions = ControllerShortcut.ACTIONS[gamepad.id];
|
||||||
if (!actions) return !1;
|
if (!actions) return !1;
|
||||||
ControllerShortcut.#buttonsCache[gamepadIndex] = ControllerShortcut.#buttonsStatus[gamepadIndex].slice(0), ControllerShortcut.#buttonsStatus[gamepadIndex] = [];
|
ControllerShortcut.buttonsCache[gamepadIndex] = ControllerShortcut.buttonsStatus[gamepadIndex].slice(0), ControllerShortcut.buttonsStatus[gamepadIndex] = [];
|
||||||
const pressed = [];
|
const pressed = [];
|
||||||
let otherButtonPressed = !1;
|
let otherButtonPressed = !1;
|
||||||
return gamepad.buttons.forEach((button, index) => {
|
return gamepad.buttons.forEach((button, index) => {
|
||||||
if (button.pressed && index !== 16) {
|
if (button.pressed && index !== 16) {
|
||||||
if (otherButtonPressed = !0, pressed[index] = !0, actions[index] && !ControllerShortcut.#buttonsCache[gamepadIndex][index]) setTimeout(() => ControllerShortcut.#runAction(actions[index]), 0);
|
if (otherButtonPressed = !0, pressed[index] = !0, actions[index] && !ControllerShortcut.buttonsCache[gamepadIndex][index]) setTimeout(() => ControllerShortcut.runAction(actions[index]), 0);
|
||||||
}
|
}
|
||||||
}), ControllerShortcut.#buttonsStatus[gamepadIndex] = pressed, otherButtonPressed;
|
}), ControllerShortcut.buttonsStatus[gamepadIndex] = pressed, otherButtonPressed;
|
||||||
}
|
}
|
||||||
static #runAction(action) {
|
static runAction(action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "bx-settings-show":
|
case "bx-settings-show":
|
||||||
SettingsNavigationDialog.getInstance().show();
|
SettingsNavigationDialog.getInstance().show();
|
||||||
@ -5571,24 +5571,24 @@ class ControllerShortcut {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static #updateAction(profile, button, action) {
|
static updateAction(profile, button, action) {
|
||||||
const actions = ControllerShortcut.#ACTIONS;
|
const actions = ControllerShortcut.ACTIONS;
|
||||||
if (!(profile in actions)) actions[profile] = [];
|
if (!(profile in actions)) actions[profile] = [];
|
||||||
if (!action) action = null;
|
if (!action) action = null;
|
||||||
actions[profile][button] = action;
|
actions[profile][button] = action;
|
||||||
for (let key in ControllerShortcut.#ACTIONS) {
|
for (let key in ControllerShortcut.ACTIONS) {
|
||||||
let empty = !0;
|
let empty = !0;
|
||||||
for (let value of ControllerShortcut.#ACTIONS[key])
|
for (let value of ControllerShortcut.ACTIONS[key])
|
||||||
if (value) {
|
if (value) {
|
||||||
empty = !1;
|
empty = !1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (empty) delete ControllerShortcut.#ACTIONS[key];
|
if (empty) delete ControllerShortcut.ACTIONS[key];
|
||||||
}
|
}
|
||||||
window.localStorage.setItem(ControllerShortcut.#STORAGE_KEY, JSON.stringify(ControllerShortcut.#ACTIONS)), console.log(ControllerShortcut.#ACTIONS);
|
window.localStorage.setItem(ControllerShortcut.STORAGE_KEY, JSON.stringify(ControllerShortcut.ACTIONS)), console.log(ControllerShortcut.ACTIONS);
|
||||||
}
|
}
|
||||||
static #updateProfileList(e) {
|
static updateProfileList(e) {
|
||||||
const $select = ControllerShortcut.#$selectProfile, $container = ControllerShortcut.#$container, $fragment = document.createDocumentFragment();
|
const { $selectProfile: $select, $container } = ControllerShortcut, $fragment = document.createDocumentFragment();
|
||||||
removeChildElements($select);
|
removeChildElements($select);
|
||||||
const gamepads = navigator.getGamepads();
|
const gamepads = navigator.getGamepads();
|
||||||
let hasGamepad = !1;
|
let hasGamepad = !1;
|
||||||
@ -5601,24 +5601,24 @@ class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
if ($container.dataset.hasGamepad = hasGamepad.toString(), hasGamepad) $select.appendChild($fragment), $select.selectedIndex = 0, $select.dispatchEvent(new Event("input"));
|
if ($container.dataset.hasGamepad = hasGamepad.toString(), hasGamepad) $select.appendChild($fragment), $select.selectedIndex = 0, $select.dispatchEvent(new Event("input"));
|
||||||
}
|
}
|
||||||
static #switchProfile(profile) {
|
static switchProfile(profile) {
|
||||||
let actions = ControllerShortcut.#ACTIONS[profile];
|
let actions = ControllerShortcut.ACTIONS[profile];
|
||||||
if (!actions) actions = [];
|
if (!actions) actions = [];
|
||||||
let button;
|
let button;
|
||||||
for (button in ControllerShortcut.#$selectActions) {
|
for (button in ControllerShortcut.$selectActions) {
|
||||||
const $select = ControllerShortcut.#$selectActions[button];
|
const $select = ControllerShortcut.$selectActions[button];
|
||||||
$select.value = actions[button] || "", BxEvent.dispatch($select, "input", {
|
$select.value = actions[button] || "", BxEvent.dispatch($select, "input", {
|
||||||
ignoreOnChange: !0,
|
ignoreOnChange: !0,
|
||||||
manualTrigger: !0
|
manualTrigger: !0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static #getActionsFromStorage() {
|
static getActionsFromStorage() {
|
||||||
return JSON.parse(window.localStorage.getItem(ControllerShortcut.#STORAGE_KEY) || "{}");
|
return JSON.parse(window.localStorage.getItem(ControllerShortcut.STORAGE_KEY) || "{}");
|
||||||
}
|
}
|
||||||
static renderSettings() {
|
static renderSettings() {
|
||||||
const PREF_CONTROLLER_FRIENDLY_UI = getPref("ui_controller_friendly");
|
const PREF_CONTROLLER_FRIENDLY_UI = getPref("ui_controller_friendly");
|
||||||
ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
|
ControllerShortcut.ACTIONS = ControllerShortcut.getActionsFromStorage();
|
||||||
const buttons = new Map;
|
const buttons = new Map;
|
||||||
buttons.set(3, "⇑"), buttons.set(0, "⇓"), buttons.set(1, "⇒"), buttons.set(2, "⇐"), buttons.set(12, "≻"), buttons.set(13, "≽"), buttons.set(14, "≺"), buttons.set(15, "≼"), buttons.set(8, "⇺"), buttons.set(9, "⇻"), buttons.set(4, "↘"), buttons.set(5, "↙"), buttons.set(6, "↖"), buttons.set(7, "↗"), buttons.set(10, "↺"), buttons.set(11, "↻");
|
buttons.set(3, "⇑"), buttons.set(0, "⇓"), buttons.set(1, "⇒"), buttons.set(2, "⇐"), buttons.set(12, "≻"), buttons.set(13, "≽"), buttons.set(14, "≺"), buttons.set(15, "≼"), buttons.set(8, "⇺"), buttons.set(9, "⇻"), buttons.set(4, "↘"), buttons.set(5, "↙"), buttons.set(6, "↖"), buttons.set(7, "↗"), buttons.set(10, "↺"), buttons.set(11, "↻");
|
||||||
const actions = {
|
const actions = {
|
||||||
@ -5669,7 +5669,7 @@ class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
}, $profile), CE("p", { class: "bx-shortcut-note" }, CE("span", { class: "bx-prompt" }, ""), ": " + t("controller-shortcuts-xbox-note"))));
|
}, $profile), CE("p", { class: "bx-shortcut-note" }, CE("span", { class: "bx-prompt" }, ""), ": " + t("controller-shortcuts-xbox-note"))));
|
||||||
$selectProfile.addEventListener("input", (e) => {
|
$selectProfile.addEventListener("input", (e) => {
|
||||||
ControllerShortcut.#switchProfile($selectProfile.value);
|
ControllerShortcut.switchProfile($selectProfile.value);
|
||||||
});
|
});
|
||||||
const onActionChanged = (e) => {
|
const onActionChanged = (e) => {
|
||||||
const $target = e.target, profile = $selectProfile.value, button = $target.dataset.button, action = $target.value;
|
const $target = e.target, profile = $selectProfile.value, button = $target.dataset.button, action = $target.value;
|
||||||
@ -5682,7 +5682,7 @@ class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
$fakeSelect.firstElementChild.text = fakeText;
|
$fakeSelect.firstElementChild.text = fakeText;
|
||||||
}
|
}
|
||||||
!e.ignoreOnChange && ControllerShortcut.#updateAction(profile, button, action);
|
!e.ignoreOnChange && ControllerShortcut.updateAction(profile, button, action);
|
||||||
};
|
};
|
||||||
for (let [button, prompt2] of buttons) {
|
for (let [button, prompt2] of buttons) {
|
||||||
const $row = CE("div", {
|
const $row = CE("div", {
|
||||||
@ -5693,7 +5693,7 @@ class ControllerShortcut {
|
|||||||
$div.appendChild($fakeSelect);
|
$div.appendChild($fakeSelect);
|
||||||
}
|
}
|
||||||
const $select = $baseSelect.cloneNode(!0);
|
const $select = $baseSelect.cloneNode(!0);
|
||||||
if ($select.dataset.button = button.toString(), $select.addEventListener("input", onActionChanged), ControllerShortcut.#$selectActions[button] = $select, PREF_CONTROLLER_FRIENDLY_UI) {
|
if ($select.dataset.button = button.toString(), $select.addEventListener("input", onActionChanged), ControllerShortcut.$selectActions[button] = $select, PREF_CONTROLLER_FRIENDLY_UI) {
|
||||||
const $bxSelect = BxSelectElement.wrap($select);
|
const $bxSelect = BxSelectElement.wrap($select);
|
||||||
$bxSelect.classList.add("bx-full-width"), $div.appendChild($bxSelect), setNearby($row, {
|
$bxSelect.classList.add("bx-full-width"), $div.appendChild($bxSelect), setNearby($row, {
|
||||||
focus: $bxSelect
|
focus: $bxSelect
|
||||||
@ -5703,7 +5703,7 @@ class ControllerShortcut {
|
|||||||
});
|
});
|
||||||
$row.appendChild($label), $row.appendChild($div), $remap.appendChild($row);
|
$row.appendChild($label), $row.appendChild($div), $remap.appendChild($row);
|
||||||
}
|
}
|
||||||
return $container.appendChild($remap), ControllerShortcut.#$selectProfile = $selectProfile, ControllerShortcut.#$container = $container, window.addEventListener("gamepadconnected", ControllerShortcut.#updateProfileList), window.addEventListener("gamepaddisconnected", ControllerShortcut.#updateProfileList), ControllerShortcut.#updateProfileList(), $container;
|
return $container.appendChild($remap), ControllerShortcut.$selectProfile = $selectProfile, ControllerShortcut.$container = $container, window.addEventListener("gamepadconnected", ControllerShortcut.updateProfileList), window.addEventListener("gamepaddisconnected", ControllerShortcut.updateProfileList), ControllerShortcut.updateProfileList(), $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var BxExposed = {
|
var BxExposed = {
|
||||||
@ -6155,29 +6155,29 @@ class XhomeInterceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
class LoadingScreen {
|
class LoadingScreen {
|
||||||
static #$bgStyle;
|
static $bgStyle;
|
||||||
static #$waitTimeBox;
|
static $waitTimeBox;
|
||||||
static #waitTimeInterval = null;
|
static waitTimeInterval = null;
|
||||||
static #orgWebTitle;
|
static orgWebTitle;
|
||||||
static #secondsToString(seconds) {
|
static secondsToString(seconds) {
|
||||||
const m = Math.floor(seconds / 60), s = Math.floor(seconds % 60), mDisplay = m > 0 ? `${m}m` : "", sDisplay = `${s}s`.padStart(s >= 0 ? 3 : 4, "0");
|
const m = Math.floor(seconds / 60), s = Math.floor(seconds % 60), mDisplay = m > 0 ? `${m}m` : "", sDisplay = `${s}s`.padStart(s >= 0 ? 3 : 4, "0");
|
||||||
return mDisplay + sDisplay;
|
return mDisplay + sDisplay;
|
||||||
}
|
}
|
||||||
static setup() {
|
static setup() {
|
||||||
const titleInfo = STATES.currentStream.titleInfo;
|
const titleInfo = STATES.currentStream.titleInfo;
|
||||||
if (!titleInfo) return;
|
if (!titleInfo) return;
|
||||||
if (!LoadingScreen.#$bgStyle) {
|
if (!LoadingScreen.$bgStyle) {
|
||||||
const $bgStyle = CE("style");
|
const $bgStyle = CE("style");
|
||||||
document.documentElement.appendChild($bgStyle), LoadingScreen.#$bgStyle = $bgStyle;
|
document.documentElement.appendChild($bgStyle), LoadingScreen.$bgStyle = $bgStyle;
|
||||||
}
|
}
|
||||||
if (LoadingScreen.#setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide") LoadingScreen.#hideRocket();
|
if (LoadingScreen.setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl), getPref("ui_loading_screen_rocket") === "hide") LoadingScreen.hideRocket();
|
||||||
}
|
}
|
||||||
static #hideRocket() {
|
static hideRocket() {
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
$bgStyle.textContent += "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
|
$bgStyle.textContent += "#game-stream div[class*=RocketAnimation-module__container] > svg{display:none}#game-stream video[class*=RocketAnimationVideo-module__video]{display:none}";
|
||||||
}
|
}
|
||||||
static #setBackground(imageUrl) {
|
static setBackground(imageUrl) {
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
imageUrl = imageUrl + "?w=1920", $bgStyle.textContent += '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
|
imageUrl = imageUrl + "?w=1920", $bgStyle.textContent += '#game-stream{background-color:transparent !important;background-position:center center !important;background-repeat:no-repeat !important;background-size:cover !important}#game-stream rect[width="800"]{transition:opacity .3s ease-in-out !important}' + `#game-stream {background-image: linear-gradient(#00000033, #000000e6), url(${imageUrl}) !important;}`;
|
||||||
const bg = new Image;
|
const bg = new Image;
|
||||||
bg.onload = (e) => {
|
bg.onload = (e) => {
|
||||||
@ -6185,31 +6185,31 @@ class LoadingScreen {
|
|||||||
}, bg.src = imageUrl;
|
}, bg.src = imageUrl;
|
||||||
}
|
}
|
||||||
static setupWaitTime(waitTime) {
|
static setupWaitTime(waitTime) {
|
||||||
if (getPref("ui_loading_screen_rocket") === "hide-queue") LoadingScreen.#hideRocket();
|
if (getPref("ui_loading_screen_rocket") === "hide-queue") LoadingScreen.hideRocket();
|
||||||
let secondsLeft = waitTime, $countDown, $estimated;
|
let secondsLeft = waitTime, $countDown, $estimated;
|
||||||
LoadingScreen.#orgWebTitle = document.title;
|
LoadingScreen.orgWebTitle = document.title;
|
||||||
const endDate = new Date, timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
const endDate = new Date, timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
||||||
endDate.setSeconds(endDate.getSeconds() + waitTime - timeZoneOffsetSeconds);
|
endDate.setSeconds(endDate.getSeconds() + waitTime - timeZoneOffsetSeconds);
|
||||||
let endDateStr = endDate.toISOString().slice(0, 19);
|
let endDateStr = endDate.toISOString().slice(0, 19);
|
||||||
endDateStr = endDateStr.substring(0, 10) + " " + endDateStr.substring(11, 19), endDateStr += ` (${LoadingScreen.#secondsToString(waitTime)})`;
|
endDateStr = endDateStr.substring(0, 10) + " " + endDateStr.substring(11, 19), endDateStr += ` (${LoadingScreen.secondsToString(waitTime)})`;
|
||||||
let $waitTimeBox = LoadingScreen.#$waitTimeBox;
|
let $waitTimeBox = LoadingScreen.$waitTimeBox;
|
||||||
if (!$waitTimeBox) $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.#$waitTimeBox = $waitTimeBox;
|
if (!$waitTimeBox) $waitTimeBox = CE("div", { class: "bx-wait-time-box" }, CE("label", {}, t("server")), CE("span", {}, getPreferredServerRegion()), CE("label", {}, t("wait-time-estimated")), $estimated = CE("span", {}), CE("label", {}, t("wait-time-countdown")), $countDown = CE("span", {})), document.documentElement.appendChild($waitTimeBox), LoadingScreen.$waitTimeBox = $waitTimeBox;
|
||||||
else $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
|
else $waitTimeBox.classList.remove("bx-gone"), $estimated = $waitTimeBox.querySelector(".bx-wait-time-estimated"), $countDown = $waitTimeBox.querySelector(".bx-wait-time-countdown");
|
||||||
$estimated.textContent = endDateStr, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, LoadingScreen.#waitTimeInterval = window.setInterval(() => {
|
$estimated.textContent = endDateStr, $countDown.textContent = LoadingScreen.secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`, LoadingScreen.waitTimeInterval = window.setInterval(() => {
|
||||||
if (secondsLeft--, $countDown.textContent = LoadingScreen.#secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`, secondsLeft <= 0) LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
|
if (secondsLeft--, $countDown.textContent = LoadingScreen.secondsToString(secondsLeft), document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`, secondsLeft <= 0) LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval), LoadingScreen.waitTimeInterval = null;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
static hide() {
|
static hide() {
|
||||||
if (LoadingScreen.#orgWebTitle && (document.title = LoadingScreen.#orgWebTitle), LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add("bx-gone"), getPref("ui_loading_screen_game_art") && LoadingScreen.#$bgStyle) {
|
if (LoadingScreen.orgWebTitle && (document.title = LoadingScreen.orgWebTitle), LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add("bx-gone"), getPref("ui_loading_screen_game_art") && LoadingScreen.$bgStyle) {
|
||||||
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
||||||
$rocketBg && $rocketBg.addEventListener("transitionend", (e) => {
|
$rocketBg && $rocketBg.addEventListener("transitionend", (e) => {
|
||||||
LoadingScreen.#$bgStyle.textContent += "#game-stream{background:#000 !important}";
|
LoadingScreen.$bgStyle.textContent += "#game-stream{background:#000 !important}";
|
||||||
}), LoadingScreen.#$bgStyle.textContent += '#game-stream rect[width="800"]{opacity:1 !important}';
|
}), LoadingScreen.$bgStyle.textContent += '#game-stream rect[width="800"]{opacity:1 !important}';
|
||||||
}
|
}
|
||||||
setTimeout(LoadingScreen.reset, 2000);
|
setTimeout(LoadingScreen.reset, 2000);
|
||||||
}
|
}
|
||||||
static reset() {
|
static reset() {
|
||||||
LoadingScreen.#$bgStyle && (LoadingScreen.#$bgStyle.textContent = ""), LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add("bx-gone"), LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval), LoadingScreen.#waitTimeInterval = null;
|
LoadingScreen.$bgStyle && (LoadingScreen.$bgStyle.textContent = ""), LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add("bx-gone"), LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval), LoadingScreen.waitTimeInterval = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class TrueAchievements {
|
class TrueAchievements {
|
||||||
@ -7558,10 +7558,10 @@ class XcloudApi {
|
|||||||
if (!XcloudApi.instance) XcloudApi.instance = new XcloudApi;
|
if (!XcloudApi.instance) XcloudApi.instance = new XcloudApi;
|
||||||
return XcloudApi.instance;
|
return XcloudApi.instance;
|
||||||
}
|
}
|
||||||
#CACHE_TITLES = {};
|
CACHE_TITLES = {};
|
||||||
#CACHE_WAIT_TIME = {};
|
CACHE_WAIT_TIME = {};
|
||||||
async getTitleInfo(id2) {
|
async getTitleInfo(id2) {
|
||||||
if (id2 in this.#CACHE_TITLES) return this.#CACHE_TITLES[id2];
|
if (id2 in this.CACHE_TITLES) return this.CACHE_TITLES[id2];
|
||||||
const baseUri = STATES.selectedRegion.baseUri;
|
const baseUri = STATES.selectedRegion.baseUri;
|
||||||
if (!baseUri || !STATES.gsToken) return null;
|
if (!baseUri || !STATES.gsToken) return null;
|
||||||
let json;
|
let json;
|
||||||
@ -7580,10 +7580,10 @@ class XcloudApi {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
json = {};
|
json = {};
|
||||||
}
|
}
|
||||||
return this.#CACHE_TITLES[id2] = json, json;
|
return this.CACHE_TITLES[id2] = json, json;
|
||||||
}
|
}
|
||||||
async getWaitTime(id2) {
|
async getWaitTime(id2) {
|
||||||
if (id2 in this.#CACHE_WAIT_TIME) return this.#CACHE_WAIT_TIME[id2];
|
if (id2 in this.CACHE_WAIT_TIME) return this.CACHE_WAIT_TIME[id2];
|
||||||
const baseUri = STATES.selectedRegion.baseUri;
|
const baseUri = STATES.selectedRegion.baseUri;
|
||||||
if (!baseUri || !STATES.gsToken) return null;
|
if (!baseUri || !STATES.gsToken) return null;
|
||||||
let json;
|
let json;
|
||||||
@ -7597,7 +7597,7 @@ class XcloudApi {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
json = {};
|
json = {};
|
||||||
}
|
}
|
||||||
return this.#CACHE_WAIT_TIME[id2] = json, json;
|
return this.CACHE_WAIT_TIME[id2] = json, json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class GameTile {
|
class GameTile {
|
||||||
|
@ -38,37 +38,37 @@ const enum ShortcutAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ControllerShortcut {
|
export class ControllerShortcut {
|
||||||
static readonly #STORAGE_KEY = 'better_xcloud_controller_shortcuts';
|
private static readonly STORAGE_KEY = 'better_xcloud_controller_shortcuts';
|
||||||
|
|
||||||
static #buttonsCache: {[key: string]: boolean[]} = {};
|
private static buttonsCache: {[key: string]: boolean[]} = {};
|
||||||
static #buttonsStatus: {[key: string]: boolean[]} = {};
|
private static buttonsStatus: {[key: string]: boolean[]} = {};
|
||||||
|
|
||||||
static #$selectProfile: HTMLSelectElement;
|
private static $selectProfile: HTMLSelectElement;
|
||||||
static #$selectActions: Partial<{[key in GamepadKey]: HTMLSelectElement}> = {};
|
private static $selectActions: Partial<{[key in GamepadKey]: HTMLSelectElement}> = {};
|
||||||
static #$container: HTMLElement;
|
private static $container: HTMLElement;
|
||||||
|
|
||||||
static #ACTIONS: {[key: string]: (ShortcutAction | null)[]} | null = null;
|
private static ACTIONS: {[key: string]: (ShortcutAction | null)[]} | null = null;
|
||||||
|
|
||||||
static reset(index: number) {
|
static reset(index: number) {
|
||||||
ControllerShortcut.#buttonsCache[index] = [];
|
ControllerShortcut.buttonsCache[index] = [];
|
||||||
ControllerShortcut.#buttonsStatus[index] = [];
|
ControllerShortcut.buttonsStatus[index] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
static handle(gamepad: Gamepad): boolean {
|
static handle(gamepad: Gamepad): boolean {
|
||||||
if (!ControllerShortcut.#ACTIONS) {
|
if (!ControllerShortcut.ACTIONS) {
|
||||||
ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
|
ControllerShortcut.ACTIONS = ControllerShortcut.getActionsFromStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
const gamepadIndex = gamepad.index;
|
const gamepadIndex = gamepad.index;
|
||||||
const actions = ControllerShortcut.#ACTIONS![gamepad.id];
|
const actions = ControllerShortcut.ACTIONS![gamepad.id];
|
||||||
if (!actions) {
|
if (!actions) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the buttons status from the previous frame to the cache
|
// Move the buttons status from the previous frame to the cache
|
||||||
ControllerShortcut.#buttonsCache[gamepadIndex] = ControllerShortcut.#buttonsStatus[gamepadIndex].slice(0);
|
ControllerShortcut.buttonsCache[gamepadIndex] = ControllerShortcut.buttonsStatus[gamepadIndex].slice(0);
|
||||||
// Clear the buttons status
|
// Clear the buttons status
|
||||||
ControllerShortcut.#buttonsStatus[gamepadIndex] = [];
|
ControllerShortcut.buttonsStatus[gamepadIndex] = [];
|
||||||
|
|
||||||
const pressed: boolean[] = [];
|
const pressed: boolean[] = [];
|
||||||
let otherButtonPressed = false;
|
let otherButtonPressed = false;
|
||||||
@ -80,17 +80,17 @@ export class ControllerShortcut {
|
|||||||
pressed[index] = true;
|
pressed[index] = true;
|
||||||
|
|
||||||
// If this is newly pressed button -> run action
|
// If this is newly pressed button -> run action
|
||||||
if (actions[index] && !ControllerShortcut.#buttonsCache[gamepadIndex][index]) {
|
if (actions[index] && !ControllerShortcut.buttonsCache[gamepadIndex][index]) {
|
||||||
setTimeout(() => ControllerShortcut.#runAction(actions[index]!), 0);
|
setTimeout(() => ControllerShortcut.runAction(actions[index]!), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ControllerShortcut.#buttonsStatus[gamepadIndex] = pressed;
|
ControllerShortcut.buttonsStatus[gamepadIndex] = pressed;
|
||||||
return otherButtonPressed;
|
return otherButtonPressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static #runAction(action: ShortcutAction) {
|
private static runAction(action: ShortcutAction) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ShortcutAction.BETTER_XCLOUD_SETTINGS_SHOW:
|
case ShortcutAction.BETTER_XCLOUD_SETTINGS_SHOW:
|
||||||
SettingsNavigationDialog.getInstance().show();
|
SettingsNavigationDialog.getInstance().show();
|
||||||
@ -134,8 +134,8 @@ export class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static #updateAction(profile: string, button: GamepadKey, action: ShortcutAction | null) {
|
private static updateAction(profile: string, button: GamepadKey, action: ShortcutAction | null) {
|
||||||
const actions = ControllerShortcut.#ACTIONS!;
|
const actions = ControllerShortcut.ACTIONS!;
|
||||||
if (!(profile in actions)) {
|
if (!(profile in actions)) {
|
||||||
actions[profile] = [];
|
actions[profile] = [];
|
||||||
}
|
}
|
||||||
@ -147,9 +147,9 @@ export class ControllerShortcut {
|
|||||||
actions[profile][button] = action;
|
actions[profile][button] = action;
|
||||||
|
|
||||||
// Remove empty profiles
|
// Remove empty profiles
|
||||||
for (const key in ControllerShortcut.#ACTIONS) {
|
for (const key in ControllerShortcut.ACTIONS) {
|
||||||
let empty = true;
|
let empty = true;
|
||||||
for (const value of ControllerShortcut.#ACTIONS[key]) {
|
for (const value of ControllerShortcut.ACTIONS[key]) {
|
||||||
if (!!value) {
|
if (!!value) {
|
||||||
empty = false;
|
empty = false;
|
||||||
break;
|
break;
|
||||||
@ -157,19 +157,19 @@ export class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty) {
|
if (empty) {
|
||||||
delete ControllerShortcut.#ACTIONS[key];
|
delete ControllerShortcut.ACTIONS[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to storage
|
// Save to storage
|
||||||
window.localStorage.setItem(ControllerShortcut.#STORAGE_KEY, JSON.stringify(ControllerShortcut.#ACTIONS));
|
window.localStorage.setItem(ControllerShortcut.STORAGE_KEY, JSON.stringify(ControllerShortcut.ACTIONS));
|
||||||
|
|
||||||
console.log(ControllerShortcut.#ACTIONS);
|
console.log(ControllerShortcut.ACTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static #updateProfileList(e?: GamepadEvent) {
|
private static updateProfileList(e?: GamepadEvent) {
|
||||||
const $select = ControllerShortcut.#$selectProfile;
|
const $select = ControllerShortcut.$selectProfile;
|
||||||
const $container = ControllerShortcut.#$container;
|
const $container = ControllerShortcut.$container;
|
||||||
|
|
||||||
const $fragment = document.createDocumentFragment();
|
const $fragment = document.createDocumentFragment();
|
||||||
|
|
||||||
@ -205,16 +205,16 @@ export class ControllerShortcut {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static #switchProfile(profile: string) {
|
private static switchProfile(profile: string) {
|
||||||
let actions = ControllerShortcut.#ACTIONS![profile];
|
let actions = ControllerShortcut.ACTIONS![profile];
|
||||||
if (!actions) {
|
if (!actions) {
|
||||||
actions = [];
|
actions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset selects' values
|
// Reset selects' values
|
||||||
let button: any;
|
let button: any;
|
||||||
for (button in ControllerShortcut.#$selectActions) {
|
for (button in ControllerShortcut.$selectActions) {
|
||||||
const $select = ControllerShortcut.#$selectActions[button as GamepadKey]!;
|
const $select = ControllerShortcut.$selectActions[button as GamepadKey]!;
|
||||||
$select.value = actions[button] || '';
|
$select.value = actions[button] || '';
|
||||||
|
|
||||||
BxEvent.dispatch($select, 'input', {
|
BxEvent.dispatch($select, 'input', {
|
||||||
@ -224,15 +224,15 @@ export class ControllerShortcut {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static #getActionsFromStorage() {
|
private static getActionsFromStorage() {
|
||||||
return JSON.parse(window.localStorage.getItem(ControllerShortcut.#STORAGE_KEY) || '{}');
|
return JSON.parse(window.localStorage.getItem(ControllerShortcut.STORAGE_KEY) || '{}');
|
||||||
}
|
}
|
||||||
|
|
||||||
static renderSettings() {
|
static renderSettings() {
|
||||||
const PREF_CONTROLLER_FRIENDLY_UI = getPref(PrefKey.UI_CONTROLLER_FRIENDLY);
|
const PREF_CONTROLLER_FRIENDLY_UI = getPref(PrefKey.UI_CONTROLLER_FRIENDLY);
|
||||||
|
|
||||||
// Read actions from localStorage
|
// Read actions from localStorage
|
||||||
ControllerShortcut.#ACTIONS = ControllerShortcut.#getActionsFromStorage();
|
ControllerShortcut.ACTIONS = ControllerShortcut.getActionsFromStorage();
|
||||||
|
|
||||||
const buttons: Map<GamepadKey, PrompFont> = new Map();
|
const buttons: Map<GamepadKey, PrompFont> = new Map();
|
||||||
buttons.set(GamepadKey.Y, PrompFont.Y);
|
buttons.set(GamepadKey.Y, PrompFont.Y);
|
||||||
@ -340,7 +340,7 @@ export class ControllerShortcut {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$selectProfile.addEventListener('input', e => {
|
$selectProfile.addEventListener('input', e => {
|
||||||
ControllerShortcut.#switchProfile($selectProfile.value);
|
ControllerShortcut.switchProfile($selectProfile.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onActionChanged = (e: Event) => {
|
const onActionChanged = (e: Event) => {
|
||||||
@ -361,7 +361,7 @@ export class ControllerShortcut {
|
|||||||
($fakeSelect.firstElementChild as HTMLOptionElement).text = fakeText;
|
($fakeSelect.firstElementChild as HTMLOptionElement).text = fakeText;
|
||||||
}
|
}
|
||||||
|
|
||||||
!(e as any).ignoreOnChange && ControllerShortcut.#updateAction(profile, button as GamepadKey, action);
|
!(e as any).ignoreOnChange && ControllerShortcut.updateAction(profile, button as GamepadKey, action);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -387,7 +387,7 @@ export class ControllerShortcut {
|
|||||||
$select.dataset.button = button.toString();
|
$select.dataset.button = button.toString();
|
||||||
$select.addEventListener('input', onActionChanged);
|
$select.addEventListener('input', onActionChanged);
|
||||||
|
|
||||||
ControllerShortcut.#$selectActions[button] = $select;
|
ControllerShortcut.$selectActions[button] = $select;
|
||||||
|
|
||||||
if (PREF_CONTROLLER_FRIENDLY_UI) {
|
if (PREF_CONTROLLER_FRIENDLY_UI) {
|
||||||
const $bxSelect = BxSelectElement.wrap($select);
|
const $bxSelect = BxSelectElement.wrap($select);
|
||||||
@ -412,14 +412,14 @@ export class ControllerShortcut {
|
|||||||
|
|
||||||
$container.appendChild($remap);
|
$container.appendChild($remap);
|
||||||
|
|
||||||
ControllerShortcut.#$selectProfile = $selectProfile;
|
ControllerShortcut.$selectProfile = $selectProfile;
|
||||||
ControllerShortcut.#$container = $container;
|
ControllerShortcut.$container = $container;
|
||||||
|
|
||||||
// Detect when gamepad connected/disconnect
|
// Detect when gamepad connected/disconnect
|
||||||
window.addEventListener('gamepadconnected', ControllerShortcut.#updateProfileList);
|
window.addEventListener('gamepadconnected', ControllerShortcut.updateProfileList);
|
||||||
window.addEventListener('gamepaddisconnected', ControllerShortcut.#updateProfileList);
|
window.addEventListener('gamepaddisconnected', ControllerShortcut.updateProfileList);
|
||||||
|
|
||||||
ControllerShortcut.#updateProfileList();
|
ControllerShortcut.updateProfileList();
|
||||||
|
|
||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ import { getPref } from "@/utils/settings-storages/global-settings-storage";
|
|||||||
import { compressCss } from "@macros/build" with {type: "macro"};
|
import { compressCss } from "@macros/build" with {type: "macro"};
|
||||||
|
|
||||||
export class LoadingScreen {
|
export class LoadingScreen {
|
||||||
static #$bgStyle: HTMLElement;
|
private static $bgStyle: HTMLElement;
|
||||||
static #$waitTimeBox: HTMLElement;
|
private static $waitTimeBox: HTMLElement;
|
||||||
|
|
||||||
static #waitTimeInterval?: number | null = null;
|
private static waitTimeInterval?: number | null = null;
|
||||||
static #orgWebTitle: string;
|
private static orgWebTitle: string;
|
||||||
|
|
||||||
static #secondsToString(seconds: number) {
|
private static secondsToString(seconds: number) {
|
||||||
const m = Math.floor(seconds / 60);
|
const m = Math.floor(seconds / 60);
|
||||||
const s = Math.floor(seconds % 60);
|
const s = Math.floor(seconds % 60);
|
||||||
|
|
||||||
@ -28,21 +28,21 @@ export class LoadingScreen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadingScreen.#$bgStyle) {
|
if (!LoadingScreen.$bgStyle) {
|
||||||
const $bgStyle = CE('style');
|
const $bgStyle = CE('style');
|
||||||
document.documentElement.appendChild($bgStyle);
|
document.documentElement.appendChild($bgStyle);
|
||||||
LoadingScreen.#$bgStyle = $bgStyle;
|
LoadingScreen.$bgStyle = $bgStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadingScreen.#setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl);
|
LoadingScreen.setBackground(titleInfo.product.heroImageUrl || titleInfo.product.titledHeroImageUrl || titleInfo.product.tileImageUrl);
|
||||||
|
|
||||||
if (getPref(PrefKey.UI_LOADING_SCREEN_ROCKET) === 'hide') {
|
if (getPref(PrefKey.UI_LOADING_SCREEN_ROCKET) === 'hide') {
|
||||||
LoadingScreen.#hideRocket();
|
LoadingScreen.hideRocket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static #hideRocket() {
|
private static hideRocket() {
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
|
|
||||||
$bgStyle.textContent! += compressCss(`
|
$bgStyle.textContent! += compressCss(`
|
||||||
#game-stream div[class*=RocketAnimation-module__container] > svg {
|
#game-stream div[class*=RocketAnimation-module__container] > svg {
|
||||||
@ -55,9 +55,9 @@ export class LoadingScreen {
|
|||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static #setBackground(imageUrl: string) {
|
private static setBackground(imageUrl: string) {
|
||||||
// Setup style tag
|
// Setup style tag
|
||||||
let $bgStyle = LoadingScreen.#$bgStyle;
|
let $bgStyle = LoadingScreen.$bgStyle;
|
||||||
|
|
||||||
// Limit max width to reduce image size
|
// Limit max width to reduce image size
|
||||||
imageUrl = imageUrl + '?w=1920';
|
imageUrl = imageUrl + '?w=1920';
|
||||||
@ -89,14 +89,14 @@ export class LoadingScreen {
|
|||||||
static setupWaitTime(waitTime: number) {
|
static setupWaitTime(waitTime: number) {
|
||||||
// Hide rocket when queing
|
// Hide rocket when queing
|
||||||
if (getPref(PrefKey.UI_LOADING_SCREEN_ROCKET) === 'hide-queue') {
|
if (getPref(PrefKey.UI_LOADING_SCREEN_ROCKET) === 'hide-queue') {
|
||||||
LoadingScreen.#hideRocket();
|
LoadingScreen.hideRocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
let secondsLeft = waitTime;
|
let secondsLeft = waitTime;
|
||||||
let $countDown;
|
let $countDown;
|
||||||
let $estimated;
|
let $estimated;
|
||||||
|
|
||||||
LoadingScreen.#orgWebTitle = document.title;
|
LoadingScreen.orgWebTitle = document.title;
|
||||||
|
|
||||||
const endDate = new Date();
|
const endDate = new Date();
|
||||||
const timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
const timeZoneOffsetSeconds = endDate.getTimezoneOffset() * 60;
|
||||||
@ -104,9 +104,9 @@ export class LoadingScreen {
|
|||||||
|
|
||||||
let endDateStr = endDate.toISOString().slice(0, 19);
|
let endDateStr = endDate.toISOString().slice(0, 19);
|
||||||
endDateStr = endDateStr.substring(0, 10) + ' ' + endDateStr.substring(11, 19);
|
endDateStr = endDateStr.substring(0, 10) + ' ' + endDateStr.substring(11, 19);
|
||||||
endDateStr += ` (${LoadingScreen.#secondsToString(waitTime)})`;
|
endDateStr += ` (${LoadingScreen.secondsToString(waitTime)})`;
|
||||||
|
|
||||||
let $waitTimeBox = LoadingScreen.#$waitTimeBox;
|
let $waitTimeBox = LoadingScreen.$waitTimeBox;
|
||||||
if (!$waitTimeBox) {
|
if (!$waitTimeBox) {
|
||||||
$waitTimeBox = CE('div', {'class': 'bx-wait-time-box'},
|
$waitTimeBox = CE('div', {'class': 'bx-wait-time-box'},
|
||||||
CE('label', {}, t('server')),
|
CE('label', {}, t('server')),
|
||||||
@ -118,7 +118,7 @@ export class LoadingScreen {
|
|||||||
);
|
);
|
||||||
|
|
||||||
document.documentElement.appendChild($waitTimeBox);
|
document.documentElement.appendChild($waitTimeBox);
|
||||||
LoadingScreen.#$waitTimeBox = $waitTimeBox;
|
LoadingScreen.$waitTimeBox = $waitTimeBox;
|
||||||
} else {
|
} else {
|
||||||
$waitTimeBox.classList.remove('bx-gone');
|
$waitTimeBox.classList.remove('bx-gone');
|
||||||
$estimated = $waitTimeBox.querySelector('.bx-wait-time-estimated')!;
|
$estimated = $waitTimeBox.querySelector('.bx-wait-time-estimated')!;
|
||||||
@ -126,36 +126,36 @@ export class LoadingScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$estimated.textContent = endDateStr;
|
$estimated.textContent = endDateStr;
|
||||||
$countDown.textContent = LoadingScreen.#secondsToString(secondsLeft);
|
$countDown.textContent = LoadingScreen.secondsToString(secondsLeft);
|
||||||
document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`;
|
document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`;
|
||||||
|
|
||||||
LoadingScreen.#waitTimeInterval = window.setInterval(() => {
|
LoadingScreen.waitTimeInterval = window.setInterval(() => {
|
||||||
secondsLeft--;
|
secondsLeft--;
|
||||||
$countDown.textContent = LoadingScreen.#secondsToString(secondsLeft);
|
$countDown.textContent = LoadingScreen.secondsToString(secondsLeft);
|
||||||
document.title = `[${$countDown.textContent}] ${LoadingScreen.#orgWebTitle}`;
|
document.title = `[${$countDown.textContent}] ${LoadingScreen.orgWebTitle}`;
|
||||||
|
|
||||||
if (secondsLeft <= 0) {
|
if (secondsLeft <= 0) {
|
||||||
LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval);
|
LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval);
|
||||||
LoadingScreen.#waitTimeInterval = null;
|
LoadingScreen.waitTimeInterval = null;
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static hide() {
|
static hide() {
|
||||||
LoadingScreen.#orgWebTitle && (document.title = LoadingScreen.#orgWebTitle);
|
LoadingScreen.orgWebTitle && (document.title = LoadingScreen.orgWebTitle);
|
||||||
LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add('bx-gone');
|
LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add('bx-gone');
|
||||||
|
|
||||||
if (getPref(PrefKey.UI_LOADING_SCREEN_GAME_ART) && LoadingScreen.#$bgStyle) {
|
if (getPref(PrefKey.UI_LOADING_SCREEN_GAME_ART) && LoadingScreen.$bgStyle) {
|
||||||
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
const $rocketBg = document.querySelector('#game-stream rect[width="800"]');
|
||||||
$rocketBg && $rocketBg.addEventListener('transitionend', e => {
|
$rocketBg && $rocketBg.addEventListener('transitionend', e => {
|
||||||
LoadingScreen.#$bgStyle.textContent += compressCss(`
|
LoadingScreen.$bgStyle.textContent += compressCss(`
|
||||||
#game-stream {
|
#game-stream {
|
||||||
background: #000 !important;
|
background: #000 !important;
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
LoadingScreen.#$bgStyle.textContent += compressCss(`
|
LoadingScreen.$bgStyle.textContent += compressCss(`
|
||||||
#game-stream rect[width="800"] {
|
#game-stream rect[width="800"] {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
@ -166,10 +166,10 @@ export class LoadingScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static reset() {
|
static reset() {
|
||||||
LoadingScreen.#$bgStyle && (LoadingScreen.#$bgStyle.textContent = '');
|
LoadingScreen.$bgStyle && (LoadingScreen.$bgStyle.textContent = '');
|
||||||
|
|
||||||
LoadingScreen.#$waitTimeBox && LoadingScreen.#$waitTimeBox.classList.add('bx-gone');
|
LoadingScreen.$waitTimeBox && LoadingScreen.$waitTimeBox.classList.add('bx-gone');
|
||||||
LoadingScreen.#waitTimeInterval && clearInterval(LoadingScreen.#waitTimeInterval);
|
LoadingScreen.waitTimeInterval && clearInterval(LoadingScreen.waitTimeInterval);
|
||||||
LoadingScreen.#waitTimeInterval = null;
|
LoadingScreen.waitTimeInterval = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,37 +23,37 @@ export class PointerClient {
|
|||||||
return PointerClient.instance;
|
return PointerClient.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
#socket: WebSocket | undefined | null;
|
private socket: WebSocket | undefined | null;
|
||||||
#mkbHandler: MkbHandler | undefined;
|
private mkbHandler: MkbHandler | undefined;
|
||||||
|
|
||||||
start(port: number, mkbHandler: MkbHandler) {
|
start(port: number, mkbHandler: MkbHandler) {
|
||||||
if (!port) {
|
if (!port) {
|
||||||
throw new Error('PointerServer port is 0');
|
throw new Error('PointerServer port is 0');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#mkbHandler = mkbHandler;
|
this.mkbHandler = mkbHandler;
|
||||||
|
|
||||||
// Create WebSocket connection.
|
// Create WebSocket connection.
|
||||||
this.#socket = new WebSocket(`ws://localhost:${port}`);
|
this.socket = new WebSocket(`ws://localhost:${port}`);
|
||||||
this.#socket.binaryType = 'arraybuffer';
|
this.socket.binaryType = 'arraybuffer';
|
||||||
|
|
||||||
// Connection opened
|
// Connection opened
|
||||||
this.#socket.addEventListener('open', (event) => {
|
this.socket.addEventListener('open', (event) => {
|
||||||
BxLogger.info(LOG_TAG, 'connected')
|
BxLogger.info(LOG_TAG, 'connected')
|
||||||
});
|
});
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
this.#socket.addEventListener('error', (event) => {
|
this.socket.addEventListener('error', (event) => {
|
||||||
BxLogger.error(LOG_TAG, event);
|
BxLogger.error(LOG_TAG, event);
|
||||||
Toast.show('Cannot setup mouse: ' + event);
|
Toast.show('Cannot setup mouse: ' + event);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.#socket.addEventListener('close', (event) => {
|
this.socket.addEventListener('close', (event) => {
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for messages
|
// Listen for messages
|
||||||
this.#socket.addEventListener('message', (event) => {
|
this.socket.addEventListener('message', (event) => {
|
||||||
const dataView = new DataView(event.data);
|
const dataView = new DataView(event.data);
|
||||||
|
|
||||||
let messageType = dataView.getInt8(0);
|
let messageType = dataView.getInt8(0);
|
||||||
@ -84,7 +84,7 @@ export class PointerClient {
|
|||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const y = dataView.getInt16(offset);
|
const y = dataView.getInt16(offset);
|
||||||
|
|
||||||
this.#mkbHandler?.handleMouseMove({
|
this.mkbHandler?.handleMouseMove({
|
||||||
movementX: x,
|
movementX: x,
|
||||||
movementY: y,
|
movementY: y,
|
||||||
});
|
});
|
||||||
@ -94,7 +94,7 @@ export class PointerClient {
|
|||||||
onPress(messageType: PointerAction, dataView: DataView, offset: number) {
|
onPress(messageType: PointerAction, dataView: DataView, offset: number) {
|
||||||
const button = dataView.getUint8(offset);
|
const button = dataView.getUint8(offset);
|
||||||
|
|
||||||
this.#mkbHandler?.handleMouseClick({
|
this.mkbHandler?.handleMouseClick({
|
||||||
pointerButton: button,
|
pointerButton: button,
|
||||||
pressed: messageType === PointerAction.BUTTON_PRESS,
|
pressed: messageType === PointerAction.BUTTON_PRESS,
|
||||||
});
|
});
|
||||||
@ -108,7 +108,7 @@ export class PointerClient {
|
|||||||
offset += Int16Array.BYTES_PER_ELEMENT;
|
offset += Int16Array.BYTES_PER_ELEMENT;
|
||||||
const hScroll = dataView.getInt16(offset);
|
const hScroll = dataView.getInt16(offset);
|
||||||
|
|
||||||
this.#mkbHandler?.handleMouseWheel({
|
this.mkbHandler?.handleMouseWheel({
|
||||||
vertical: vScroll,
|
vertical: vScroll,
|
||||||
horizontal: hScroll,
|
horizontal: hScroll,
|
||||||
});
|
});
|
||||||
@ -118,13 +118,13 @@ export class PointerClient {
|
|||||||
|
|
||||||
onPointerCaptureChanged(dataView: DataView, offset: number) {
|
onPointerCaptureChanged(dataView: DataView, offset: number) {
|
||||||
const hasCapture = dataView.getInt8(offset) === 1;
|
const hasCapture = dataView.getInt8(offset) === 1;
|
||||||
!hasCapture && this.#mkbHandler?.stop();
|
!hasCapture && this.mkbHandler?.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
try {
|
try {
|
||||||
this.#socket?.close();
|
this.socket?.close();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
this.#socket = null;
|
this.socket = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@ type ToastOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Toast {
|
export class Toast {
|
||||||
static #$wrapper: HTMLElement;
|
private static $wrapper: HTMLElement;
|
||||||
static #$msg: HTMLElement;
|
private static $msg: HTMLElement;
|
||||||
static #$status: HTMLElement;
|
private static $status: HTMLElement;
|
||||||
static #stack: Array<[string, string, ToastOptions]> = [];
|
private static stack: Array<[string, string, ToastOptions]> = [];
|
||||||
static #isShowing = false;
|
private static isShowing = false;
|
||||||
|
|
||||||
static #timeout?: number | null;
|
private static timeout?: number | null;
|
||||||
static #DURATION = 3000;
|
private static DURATION = 3000;
|
||||||
|
|
||||||
static show(msg: string, status?: string, options: Partial<ToastOptions> = {}) {
|
static show(msg: string, status?: string, options: Partial<ToastOptions> = {}) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
@ -21,69 +21,70 @@ export class Toast {
|
|||||||
const args = Array.from(arguments) as [string, string, ToastOptions];
|
const args = Array.from(arguments) as [string, string, ToastOptions];
|
||||||
if (options.instant) {
|
if (options.instant) {
|
||||||
// Clear stack
|
// Clear stack
|
||||||
Toast.#stack = [args];
|
Toast.stack = [args];
|
||||||
Toast.#showNext();
|
Toast.showNext();
|
||||||
} else {
|
} else {
|
||||||
Toast.#stack.push(args);
|
Toast.stack.push(args);
|
||||||
!Toast.#isShowing && Toast.#showNext();
|
!Toast.isShowing && Toast.showNext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static #showNext() {
|
private static showNext() {
|
||||||
if (!Toast.#stack.length) {
|
if (!Toast.stack.length) {
|
||||||
Toast.#isShowing = false;
|
Toast.isShowing = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toast.#isShowing = true;
|
Toast.isShowing = true;
|
||||||
|
|
||||||
Toast.#timeout && clearTimeout(Toast.#timeout);
|
Toast.timeout && clearTimeout(Toast.timeout);
|
||||||
Toast.#timeout = window.setTimeout(Toast.#hide, Toast.#DURATION);
|
Toast.timeout = window.setTimeout(Toast.hide, Toast.DURATION);
|
||||||
|
|
||||||
// Get values from item
|
// Get values from item
|
||||||
const [msg, status, options] = Toast.#stack.shift()!;
|
const [msg, status, options] = Toast.stack.shift()!;
|
||||||
|
|
||||||
if (options && options.html) {
|
if (options && options.html) {
|
||||||
Toast.#$msg.innerHTML = msg;
|
Toast.$msg.innerHTML = msg;
|
||||||
} else {
|
} else {
|
||||||
Toast.#$msg.textContent = msg;
|
Toast.$msg.textContent = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
Toast.#$status.classList.remove('bx-gone');
|
Toast.$status.classList.remove('bx-gone');
|
||||||
Toast.#$status.textContent = status;
|
Toast.$status.textContent = status;
|
||||||
} else {
|
} else {
|
||||||
Toast.#$status.classList.add('bx-gone');
|
Toast.$status.classList.add('bx-gone');
|
||||||
}
|
}
|
||||||
|
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove('bx-offscreen', 'bx-hide');
|
classList.remove('bx-offscreen', 'bx-hide');
|
||||||
classList.add('bx-show');
|
classList.add('bx-show');
|
||||||
}
|
}
|
||||||
|
|
||||||
static #hide() {
|
private static hide() {
|
||||||
Toast.#timeout = null;
|
Toast.timeout = null;
|
||||||
|
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
classList.remove('bx-show');
|
classList.remove('bx-show');
|
||||||
classList.add('bx-hide');
|
classList.add('bx-hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
static setup() {
|
static setup() {
|
||||||
Toast.#$wrapper = CE('div', {'class': 'bx-toast bx-offscreen'},
|
Toast.$wrapper = CE('div', {'class': 'bx-toast bx-offscreen'},
|
||||||
Toast.#$msg = CE('span', {'class': 'bx-toast-msg'}),
|
Toast.$msg = CE('span', {'class': 'bx-toast-msg'}),
|
||||||
Toast.#$status = CE('span', {'class': 'bx-toast-status'}));
|
Toast.$status = CE('span', {'class': 'bx-toast-status'}),
|
||||||
|
);
|
||||||
|
|
||||||
Toast.#$wrapper.addEventListener('transitionend', e => {
|
Toast.$wrapper.addEventListener('transitionend', e => {
|
||||||
const classList = Toast.#$wrapper.classList;
|
const classList = Toast.$wrapper.classList;
|
||||||
if (classList.contains('bx-hide')) {
|
if (classList.contains('bx-hide')) {
|
||||||
classList.remove('bx-offscreen', 'bx-hide');
|
classList.remove('bx-offscreen', 'bx-hide');
|
||||||
classList.add('bx-offscreen');
|
classList.add('bx-offscreen');
|
||||||
|
|
||||||
Toast.#showNext();
|
Toast.showNext();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.documentElement.appendChild(Toast.#$wrapper);
|
document.documentElement.appendChild(Toast.$wrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ 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 {
|
||||||
if (!XcloudApi.instance) {
|
if (!XcloudApi.instance) {
|
||||||
XcloudApi.instance = new XcloudApi();
|
XcloudApi.instance = new XcloudApi();
|
||||||
@ -12,12 +11,12 @@ export class XcloudApi {
|
|||||||
return XcloudApi.instance;
|
return XcloudApi.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
#CACHE_TITLES: {[key: string]: XcloudTitleInfo} = {};
|
private CACHE_TITLES: {[key: string]: XcloudTitleInfo} = {};
|
||||||
#CACHE_WAIT_TIME: {[key: string]: XcloudWaitTimeInfo} = {};
|
private CACHE_WAIT_TIME: {[key: string]: XcloudWaitTimeInfo} = {};
|
||||||
|
|
||||||
async getTitleInfo(id: string): Promise<XcloudTitleInfo | null> {
|
async getTitleInfo(id: string): Promise<XcloudTitleInfo | null> {
|
||||||
if (id in this.#CACHE_TITLES) {
|
if (id in this.CACHE_TITLES) {
|
||||||
return this.#CACHE_TITLES[id];
|
return this.CACHE_TITLES[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseUri = STATES.selectedRegion.baseUri;
|
const baseUri = STATES.selectedRegion.baseUri;
|
||||||
@ -45,13 +44,13 @@ export class XcloudApi {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
json = {}
|
json = {}
|
||||||
}
|
}
|
||||||
this.#CACHE_TITLES[id] = json;
|
this.CACHE_TITLES[id] = json;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getWaitTime(id: string): Promise<XcloudWaitTimeInfo | null> {
|
async getWaitTime(id: string): Promise<XcloudWaitTimeInfo | null> {
|
||||||
if (id in this.#CACHE_WAIT_TIME) {
|
if (id in this.CACHE_WAIT_TIME) {
|
||||||
return this.#CACHE_WAIT_TIME[id];
|
return this.CACHE_WAIT_TIME[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseUri = STATES.selectedRegion.baseUri;
|
const baseUri = STATES.selectedRegion.baseUri;
|
||||||
@ -73,7 +72,7 @@ export class XcloudApi {
|
|||||||
json = {};
|
json = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#CACHE_WAIT_TIME[id] = json;
|
this.CACHE_WAIT_TIME[id] = json;
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user