From 75d4e6f65c0f5384369a40204d47ce532bd4c6aa Mon Sep 17 00:00:00 2001
From: redphx <96280+redphx@users.noreply.github.com>
Date: Sun, 7 Jan 2024 16:59:42 +0700
Subject: [PATCH] Add a "Remote Play" button to the "Jump back in" list
---
better-xcloud.user.js | 98 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 90 insertions(+), 8 deletions(-)
diff --git a/better-xcloud.user.js b/better-xcloud.user.js
index a946f15..bd41040 100644
--- a/better-xcloud.user.js
+++ b/better-xcloud.user.js
@@ -39,6 +39,14 @@ window.NATIVE_MKB_TITLES = [
console.log(`[Better xCloud] readyState: ${document.readyState}`);
+const BxEvent = {
+ JUMP_BACK_IN_READY: 'bx-jump-back-in-ready',
+ POPSTATE: 'bx-popstate',
+
+ STREAM_STARTING: 'bx-stream-starting',
+ STREAM_STARTED: 'bx-stream-started',
+ STREAM_STOPPED: 'bx-stream-stopped',
+};
// Quickly create a tree of elements without having to use innerHTML
function createElement(elmName, props = {}) {
@@ -82,6 +90,7 @@ function createElement(elmName, props = {}) {
}
const CE = createElement;
+window.BX_CE = CE;
const CTN = document.createTextNode.bind(document);
@@ -2719,6 +2728,8 @@ const Icon = {
CURSOR_TEXT: '',
INFO: '',
+ REMOTE_PLAY: '',
+
SCREENSHOT_B64: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDMyIDMyIiBmaWxsPSIjZmZmIj48cGF0aCBkPSJNMjguMzA4IDUuMDM4aC00LjI2NWwtMi4wOTctMy4xNDVhMS4yMyAxLjIzIDAgMCAwLTEuMDIzLS41NDhoLTkuODQ2YTEuMjMgMS4yMyAwIDAgMC0xLjAyMy41NDhMNy45NTYgNS4wMzhIMy42OTJBMy43MSAzLjcxIDAgMCAwIDAgOC43MzF2MTcuMjMxYTMuNzEgMy43MSAwIDAgMCAzLjY5MiAzLjY5MmgyNC42MTVBMy43MSAzLjcxIDAgMCAwIDMyIDI1Ljk2MlY4LjczMWEzLjcxIDMuNzEgMCAwIDAtMy42OTItMy42OTJ6bS02Ljc2OSAxMS42OTJjMCAzLjAzOS0yLjUgNS41MzgtNS41MzggNS41MzhzLTUuNTM4LTIuNS01LjUzOC01LjUzOCAyLjUtNS41MzggNS41MzgtNS41MzggNS41MzggMi41IDUuNTM4IDUuNTM4eiIvPjwvc3ZnPgo=',
};
@@ -6609,6 +6620,56 @@ class Patcher {
return funcStr.replace(text, `connectMode:window.BX_REMOTE_PLAY_CONFIG?"xhome-connect":"cloud-connect",remotePlayServerId:(window.BX_REMOTE_PLAY_CONFIG&&window.BX_REMOTE_PLAY_CONFIG.serverId)||''`);
},
+ // Add a "Remote Play" button to the "Jump back in" list
+ remotePlayPatchHomeJumpBackIn: PREFS.get(Preferences.REMOTE_PLAY_ENABLED) && function(funcStr) {
+ const index = funcStr.indexOf('MruTitlesGamesRow-module__childContainer');
+ if (index === -1) {
+ return false;
+ }
+
+ const startIndex = funcStr.indexOf('return(', index);
+ const newCode = `
+setTimeout(() => { window.dispatchEvent(new Event('${BxEvent.JUMP_BACK_IN_READY}')); }, 1000);
+`;
+
+ // Add event listener
+ window.addEventListener(BxEvent.JUMP_BACK_IN_READY, e => {
+ const $list = document.querySelector('ol[class^=ItemRow-module__list]');
+ if (!$list) {
+ return;
+ }
+
+ if ($list.querySelector('.bx-jump-in-li')) {
+ return;
+ }
+
+ const $li = $list.firstElementChild.cloneNode(true);
+ $li.classList.add('bx-jump-in-li');
+
+ $li.addEventListener('click', e => { document.getElementById('bxRemotePlayBtn').click(); });
+
+ const $button = $li.querySelector('button');
+ $button.removeAttribute('id');
+ $button.removeAttribute('aria-labelledby');
+ $button.setAttribute('aria-label', __('remote-play'));
+
+ // Change card's name
+ $button.querySelector('div[class^=GameCard-module__gameTitle___]').textContent = __('remote-play');
+
+ // Rmove icons
+ $button.querySelector('div[class^=GameCard-module__children]').innerHTML = '';
+
+ const $images = $button.querySelector('div[class^=WrappedResponsiveImage]');
+ $images.innerHTML = '';
+ $images.appendChild(createSvgIcon(Icon.REMOTE_PLAY), 2);
+
+ $list.insertBefore($li, $list.firstElementChild);
+ });
+
+ funcStr = funcStr.substring(0, startIndex) + newCode + funcStr.substring(startIndex);
+ return funcStr;
+ },
+
// Disable trackEvent() function
disableTrackEvent: PREFS.get(Preferences.BLOCK_TRACKING) && function(funcStr) {
const text = 'this.trackEvent=';
@@ -6772,13 +6833,15 @@ if (window.BX_VIBRATION_INTENSITY && window.BX_VIBRATION_INTENSITY < 1) {
};
static #PATCH_ORDERS = [
- ['disableStreamGate'],
-
[
'disableAiTrack',
'disableTelemetry',
],
+ ['disableStreamGate'],
+
+ ['remotePlayPatchHomeJumpBackIn'],
+
['tvLayout'],
['enableXcloudLogger'],
@@ -7035,7 +7098,6 @@ function addCss() {
--bx-danger-button-hover-color: #e61d1d;
--bx-danger-button-disabled-color: #a26c6c;
-
--bx-toast-z-index: 9999;
--bx-dialog-z-index: 9101;
--bx-dialog-overlay-z-index: 9100;
@@ -7061,6 +7123,24 @@ div[class^=HUDButton-module__hiddenContainer] ~ div:not([class^=HUDButton-module
left: -9999px;
}
+.bx-jump-in-li {
+ display: inline-block;
+}
+
+.bx-jump-in-li button {
+ width: 140px;
+}
+
+.bx-jump-in-li div[class^=WrappedResponsiveImage-module__imageWrapper] {
+ background: linear-gradient(#005b2f, #151515);
+}
+
+.bx-jump-in-li div[class^=WrappedResponsiveImage-module__imageWrapper] svg {
+ padding: 40px;
+ height: 100%;
+ opacity: 80%;
+}
+
.bx-button {
background-color: var(--bx-default-button-color);
user-select: none;
@@ -8818,7 +8898,7 @@ function injectSettingsButton($parent) {
'href': SCRIPT_HOME,
'target': '_blank',
}, 'Better xCloud ' + SCRIPT_VERSION),
- $remotePlayBtn = CE('button', {'class': 'bx-primary-button bx-no-margin'}, __('remote-play')),
+ $remotePlayBtn = CE('button', {'id': 'bxRemotePlayBtn', 'class': 'bx-primary-button bx-no-margin'}, __('remote-play')),
)
);
$updateAvailable = CE('a', {
@@ -9806,9 +9886,10 @@ function setupScreenshotButton() {
function patchHistoryMethod(type) {
- var orig = window.history[type];
+ const orig = window.history[type];
+
return function(...args) {
- const event = new Event('xcloud_popstate');
+ const event = new Event(BxEvent.POPSTATE);
event.arguments = args;
window.dispatchEvent(event);
@@ -10025,9 +10106,10 @@ function setupBxUi() {
// Hide Settings UI when navigate to another page
-window.addEventListener('xcloud_popstate', onHistoryChanged);
+window.addEventListener(BxEvent.POPSTATE, onHistoryChanged);
window.addEventListener('popstate', onHistoryChanged);
-// Make pushState/replaceState methods dispatch "xcloud_popstate" event
+
+// Make pushState/replaceState methods dispatch BxEvent.POPSTATE event
window.history.pushState = patchHistoryMethod('pushState');
window.history.replaceState = patchHistoryMethod('replaceState');