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');