Compare commits

...

21 Commits
v1.7 ... v1.8.1

Author SHA1 Message Date
b770a4c9d3 Bump version to 1.8.1 2023-08-01 08:32:29 +07:00
a27c0ed8f6 Bump version to 1.8.1 2023-08-01 08:31:56 +07:00
8ac37754e6 Combine "Resolution" and "Video" badges into one 2023-08-01 08:31:01 +07:00
d9288a322b Update battery stat 2023-08-01 08:23:48 +07:00
5facfd2348 Fix inaccurate percentages of PL & FL stats 2023-08-01 08:18:03 +07:00
889717be7d Show confirm dialog to refresh the stream after holding for 1s 2023-08-01 08:07:57 +07:00
4b0f0784ae Fix stats bar not showing sometimes 2023-08-01 08:05:18 +07:00
31217d01bb Update bug_report.md 2023-08-01 07:40:50 +07:00
2f6176e906 Update README.md 2023-07-31 14:49:03 +07:00
fe011fd0f2 Update README.md 2023-07-31 08:28:37 +07:00
c23f55ee6b Bump version to 1.8 2023-07-31 07:49:11 +07:00
0c85770ed1 Bump version to 1.8 2023-07-31 07:48:52 +07:00
8233192b8d Update README.md 2023-07-31 07:47:45 +07:00
6c5fa3c061 Simplify playtime text 2023-07-31 07:31:03 +07:00
e47c6d9103 Use colors from PICO-8 palette for stream badges 2023-07-31 07:25:52 +07:00
563ad65580 Fix battery calculation 2023-07-31 07:16:32 +07:00
7933d8d22c Update README.md 2023-07-31 06:43:47 +07:00
b0e23ca335 Hold the "Quit game" button for 1s to refresh the stream (#43)
* Hold "Quit game" button to refresh the stream

* Fix problem with touch screen

* Another fix
2023-07-30 22:03:25 +07:00
c9f3990173 Show playtime & battery level badges (#42) 2023-07-30 21:07:25 +07:00
5d301b6588 Add setting to hide/disable touch controller (#38) 2023-07-30 15:47:56 +07:00
32123a7891 Update README.md 2023-07-29 18:02:20 +07:00
4 changed files with 153 additions and 53 deletions

View File

@ -24,10 +24,11 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Platform (please complete the following information):**
- OS: [e.g. Android]
- Browser: [e.g. chrome, firefox]
- Browser Version: [e.g. 100]
- Better xCloud Version: [e.g. 1.4]
- Device: [e.g. Phone/Laptop/Desktop/TV]
- OS: [e.g. Android]
- Browser: [e.g. Chrome, Kiwi]
- Browser Version: [e.g. 100]
- Better xCloud Version: [e.g. 1.4]
**Additional context**
Add any other context about the problem here.

View File

@ -14,9 +14,9 @@ Give this project a 🌟 if you like it. Thank you 🙏.
## Features
<img width="475" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/ef689e3b-0235-4635-8623-ebcc332774b2">
<img width="475" alt="Settings UI" src="https://github.com/redphx/better-xcloud/assets/96280/f4187ef8-fa10-4eab-b085-ef3c3aed3201">
<img width="475" alt="Stream HUD UI" src="https://github.com/redphx/better-xcloud/assets/96280/905750b2-5d02-41e0-af36-2e8b590d81a0">
<img width="475" alt="Stream HUD UI" src="https://github.com/redphx/better-xcloud/assets/96280/68f91041-10b2-4fd9-adc1-e2a21db7e36f">
&nbsp;
@ -25,6 +25,11 @@ Give this project a 🌟 if you like it. Thank you 🙏.
- **🔥 Show stream stats**
> Check [Stream stats section](#stream-stats) for more info.
- **🔥 Capture screenshot**
> Exclusive to **Better xCloud**. Check the [**Capture screenshot** section](#capture-screenshot) for more info.
- **🔥 Hold the "Quit game" button for one second to refresh the stream**
> Sometimes you can fix the bad connection to the stream simply by refreshing the page.
> Useful on mobile where the pull-to-refresh feature doesn't work while playing.
- **Switch region of streaming server**
> Connect to another server instead of the default one. Check the [**FAQ** section](#faq) for some notes.
- **Preferred game's language**
@ -43,22 +48,23 @@ Give this project a 🌟 if you like it. Thank you 🙏.
> Might reduce latency.
- **Disable bandwidth checking**
> xCloud won't warn about slow connection speed.
- **🔥 Capture screenshot**
> Exclusive to **Better xCloud**. Check the [**Capture screenshot** section](#capture-screenshot) for more info.
- **Skip Xbox splash video**
> Save 3 seconds.
- **Hide Dots icon while playing**
> You can still click on it, but it doesn't block the screen anymore.
- **Disable touch controller**
> Stop the touch controller from showing when touching the screen.
> Useful when you play on a device with a built-in controller like Logitech G Cloud, Steam Deck, Retroid, etc.
- **Hide mouse cursor while playing**
> Hide the mouse cursor after 3 seconds of not moving.
- **Reduce UI animations**
> Disable `transition` CSS property in some elements. The smooth scrolling cannot be disabled.
> Hide the mouse cursor after 3 seconds of not moving.
- **Stretch video to full sctreen**
> Useful when you don't have a 16:9 screen
- **Adjust video filters**
> Brightness/Contrast/Saturation.
- **Display stream's statuses**
> Region/Server/Quality/Resolution...
> Region/Server/Codecs/Resolution...
> Current playtime of the session.
> Current battery level. Only visible on battery-powered devices.
- **Disable social features**
> Features like friends, chat... Disable these will make the page load faster.
- **Disable xCloud analytics**
@ -67,12 +73,15 @@ Give this project a 🌟 if you like it. Thank you 🙏.
> Useful when you're using unsupported browsers.
> If you're on Safari, changing User-Agent to "Edge on Windows" will allow you to use Mic feature.
> This setting only affects xCloud, and it doesn't change browser's global User-Agent.
> 📝 If you get 404 error after using this feature, try refreshing the page a few times. See [#34](https://github.com/redphx/better-xcloud/issues/34).
- **Reduce UI animations**
> Disable `transition` CSS property in some elements. The smooth scrolling cannot be disabled.
- **Hide footer and other UI elements**
<sup>(\*)</sup> By default (for compatibility reasons) xCloud only uses high quality codec profile when you use Tizen TV or Chrome/Edge/Chromium browser on Chrome/MacOS. Enable this setting will give you the best experience no matter what platform & browser you're on.
## How to use
1. Install [Tampermonkey extension](https://www.tampermonkey.net/) on suppported browsers.
1. Install [Tampermonkey extension](https://www.tampermonkey.net/) on suppported browsers. For Safari, use [Userscripts app](https://apps.apple.com/us/app/userscripts/id1463298887).
2. Install **Better xCloud**:
- [Stable version](https://github.com/redphx/better-xcloud/releases/latest/download/better-xcloud.user.js)
- [Dev version](https://github.com/redphx/better-xcloud/raw/main/better-xcloud.user.js)
@ -120,14 +129,14 @@ Don't see your browser in the table? If it supports Tampermonkey/Userscript then
- This bar is updated every second.
- ⚠️ Using **Better xCloud** or showing the stats bar also affects the performance of the stream.
| Abbr. | Full name | Explain |
|------:|:-------------------|:-----------------------------------------------------------------------------------------------------------------------------------|
| FPS | Frames per Seconds | The number of decoded frames in the last second of the stream (equal to or lower than the FPS of the game) |
| DT | Decode Time | The average time it took to decode one frame in the last second (might be bugged [#26](https://github.com/redphx/better-xcloud/issues/26)) |
| RTT | Round Trip Time | The number of seconds it takes for data to be sent from your device to the server and back over (similar to ping, lower is better) |
| BR | Bitrate | The amount of data the server sent to your device in the last second |
| PL | Packets Lost | The total number of packets lost |
| FL | Frames Lost | The total number of frames dropped prior to decode or dropped because the frame missed its display deadline |
| Abbr. | Full name | Explain |
|------:|:-------------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
| FPS | Frames per Seconds | The number of decoded frames in the last second of the stream (may not be the same as the FPS of the game) |
| DT | Decode Time | The average time it took to decode one frame in the last second (might be bugged [#26](https://github.com/redphx/better-xcloud/issues/26)) |
| RTT | Round Trip Time | The number of seconds it takes for data to be sent from your device to the server and back over (similar to ping, lower is better) |
| BR | Bitrate | The amount of data the server sent to your device in the last second |
| PL | Packets Lost | The total number of packets lost |
| FL | Frames Lost | The total number of frames dropped prior to decode or dropped because the frame missed its display deadline |
This info is provided by WebRTC API. You can use browser's built-in tool to see more info:
- Chrome/Edge/Chromium variants: `chrome://webrtc-internals`
@ -139,8 +148,7 @@ Colors:
- Green = Good
- White = Great
📝 Having this info on all the time might reduce your enjoyment, so I'd recommend only using it when having network problems.
⚠️ Having this info on all the time will drain the battery faster, so I'd recommend only using it when having network problems.
## Capture screenshot
- This feature is only available in **Better xCloud**.

View File

@ -1,5 +1,5 @@
// ==UserScript==
// @name Better xCloud
// @namespace https://github.com/redphx
// @version 1.7
// @version 1.8.1
// ==/UserScript==

View File

@ -1,7 +1,7 @@
// ==UserScript==
// @name Better xCloud
// @namespace https://github.com/redphx
// @version 1.7
// @version 1.8.1
// @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx
// @license MIT
@ -13,7 +13,7 @@
// ==/UserScript==
'use strict';
const SCRIPT_VERSION = '1.7';
const SCRIPT_VERSION = '1.8.1';
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
const SERVER_REGIONS = {};
@ -22,6 +22,10 @@ var $STREAM_VIDEO;
var $SCREENSHOT_CANVAS;
var GAME_TITLE_ID;
// Credit: https://www.iconfinder.com/iconsets/user-interface-outline-27
const ICON_VIDEO_SETTINGS = '<path d="M8 2c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h2.186C5.602 7.158 6.706 8 8 8s2.395-.843 2.813-2h10.188a1 1 0 1 0 0-2H10.813C10.395 2.843 9.293 2 8 2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1zm7 5c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h9.186c.417 1.158 1.521 2 2.814 2s2.395-.843 2.813-2H21a1 1 0 1 0 0-2h-3.187c-.418-1.157-1.52-2-2.813-2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1zm-7 5c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h2.188c.417 1.157 1.519 2 2.813 2s2.398-.842 2.814-2H21a1 1 0 1 0 0-2H10.812c-.417-1.157-1.519-2-2.812-2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1z"/>';
const ICON_STREAM_STATS = '<path d="M12.005 5C9.184 5 6.749 6.416 5.009 7.903c-.87.743-1.571 1.51-2.074 2.18-.251.335-.452.644-.605.934-.434.733-.389 1.314-.004 1.98a6.98 6.98 0 0 0 .609.949 13.62 13.62 0 0 0 2.076 2.182C6.753 17.606 9.188 19 12.005 19s5.252-1.394 6.994-2.873a13.62 13.62 0 0 0 2.076-2.182 6.98 6.98 0 0 0 .609-.949c.425-.737.364-1.343-.004-1.98-.154-.29-.354-.599-.605-.934-.503-.669-1.204-1.436-2.074-2.18C17.261 6.416 14.826 5 12.005 5zm0 2c2.135 0 4.189 1.135 5.697 2.424.754.644 1.368 1.32 1.773 1.859.203.27.354.509.351.733s-.151.462-.353.732c-.404.541-1.016 1.214-1.77 1.854C16.198 15.881 14.145 17 12.005 17s-4.193-1.12-5.699-2.398a11.8 11.8 0 0 1-1.77-1.854c-.202-.27-.351-.508-.353-.732s.149-.463.351-.733c.406-.54 1.019-1.215 1.773-1.859C7.816 8.135 9.87 7 12.005 7zm.025 1.975c-1.645 0-3 1.355-3 3s1.355 3 3 3 3-1.355 3-3-1.355-3-3-3zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1z"/>';
class MouseCursorHider {
static #timeout;
@ -67,6 +71,9 @@ class StreamBadges {
static fps = 0;
static region = '';
static startBatteryLevel = 100;
static startTimestamp = 0;
static #renderBadge(name, value, color) {
const CE = createElement;
const $badge = CE('div', {'class': 'better-xcloud-badge'},
@ -76,10 +83,24 @@ class StreamBadges {
return $badge;
}
static render() {
let video;
static #secondsToHm(seconds) {
const h = Math.floor(seconds / 3600);
const m = Math.floor(seconds % 3600 / 60) + 1;
const hDisplay = h > 0 ? `${h}h`: '';
const mDisplay = m > 0 ? `${m}m`: '';
return hDisplay + mDisplay;
}
static async render() {
let video = '';
if (StreamBadges.resolution) {
video = `${StreamBadges.resolution.width}x${StreamBadges.resolution.height}`;
}
if (StreamBadges.video) {
video = StreamBadges.video.codec;
video && (video += '/');
video += StreamBadges.video.codec;
if (StreamBadges.video.profile) {
let profile = StreamBadges.video.profile;
profile = profile.startsWith('4d') ? 'High' : (profile.startsWith('42') ? 'Normal' : profile);
@ -94,12 +115,31 @@ class StreamBadges {
audio += ` (${bitrate} kHz)`;
}
let batteryLevel = '';
if (navigator.getBattery && StreamBadges.startBatteryLevel < 100) {
try {
const currentLevel = (await navigator.getBattery()).level * 100;
batteryLevel = `${currentLevel}%`;
if (currentLevel != StreamBadges.startBatteryLevel) {
const diffLevel = currentLevel - StreamBadges.startBatteryLevel;
const sign = diffLevel > 0 ? '+' : '';
batteryLevel += ` (${sign}${diffLevel}%)`;
}
} catch(e) {}
}
let now = +new Date;
const diffSeconds = Math.ceil((now - StreamBadges.startTimestamp) / 1000);
const playtime = StreamBadges.#secondsToHm(diffSeconds);
const BADGES = [
['region', StreamBadges.region, '#d7450b'],
['server', StreamBadges.ipv6 ? 'IPv6' : 'IPv4', '#008746'],
video ? ['video', video, '#007c8f'] : null,
audio ? ['audio', audio, '#007c8f'] : null,
StreamBadges.resolution && ['resolution', `${StreamBadges.resolution.width}x${StreamBadges.resolution.height}`, '#ff3977'],
playtime ? ['playtime', playtime, '#ff004d'] : null,
batteryLevel ? ['battery', batteryLevel, '#008751'] : null,
['region', StreamBadges.region, '#ff6c24'],
['server', StreamBadges.ipv6 ? 'IPv6' : 'IPv4', '#065ab5'],
video ? ['video', video, '#065AB5'] : null,
audio ? ['audio', audio, '#5f574f'] : null,
];
const $wrapper = createElement('div', {'class': 'better-xcloud-badges'});
@ -127,14 +167,14 @@ class StreamStats {
static #lastStat;
static start() {
StreamStats.#$container.style.display = 'block';
StreamStats.#$container.classList.remove('better-xcloud-gone');
StreamStats.#interval = setInterval(StreamStats.update, StreamStats.#updateInterval);
}
static stop() {
clearInterval(StreamStats.#interval);
StreamStats.#$container.style.display = 'none';
StreamStats.#$container.classList.add('better-xcloud-gone');
StreamStats.#interval = null;
StreamStats.#lastStat = null;
}
@ -143,7 +183,7 @@ class StreamStats {
StreamStats.#isHidden() ? StreamStats.start() : StreamStats.stop();
}
static #isHidden = () => StreamStats.#$container.style.display === 'none';
static #isHidden = () => StreamStats.#$container.classList.contains('better-xcloud-gone');
static update() {
if (StreamStats.#isHidden() || !STREAM_WEBRTC) {
@ -161,13 +201,15 @@ class StreamStats {
// Packets Lost
const packetsLost = stat.packetsLost;
const packetsReceived = stat.packetsReceived || 1;
StreamStats.#$pl.textContent = `${packetsLost} (${(packetsLost * 100 / packetsReceived).toFixed(2)}%)`;
const packetsReceived = stat.packetsReceived;
const packetsLostPercentage = (packetsLost * 100 / ((packetsLost + packetsReceived) || 1)).toFixed(2);
StreamStats.#$pl.textContent = `${packetsLost} (${packetsLostPercentage}%)`;
// Frames Dropped
const framesDropped = stat.framesDropped;
const framesReceived = stat.framesReceived || 1;
StreamStats.#$fl.textContent = `${framesDropped} (${(framesDropped * 100 / framesReceived).toFixed(2)}%)`;
const framesReceived = stat.framesReceived;
const framesDroppedPercentage = (framesDropped * 100 / ((framesDropped + framesReceived) || 1)).toFixed(2);
StreamStats.#$fl.textContent = `${framesDropped} (${framesDroppedPercentage}%)`;
if (StreamStats.#lastStat) {
const lastStat = StreamStats.#lastStat;
@ -230,7 +272,7 @@ class StreamStats {
}
const CE = createElement;
StreamStats.#$container = CE('div', {'class': 'better-xcloud-stats-bar'},
StreamStats.#$container = CE('div', {'class': 'better-xcloud-stats-bar better-xcloud-gone'},
CE('label', {}, 'FPS'),
StreamStats.#$fps = CE('span', {}, 0),
CE('label', {}, 'RTT'),
@ -370,6 +412,7 @@ class Preferences {
static get USE_DESKTOP_CODEC() { return 'use_desktop_codec'; }
static get USER_AGENT_PROFILE() { return 'user_agent_profile'; }
static get USER_AGENT_CUSTOM() { return 'user_agent_custom'; }
static get STREAM_HIDE_TOUCH_CONTROLLER() { return 'stream_hide_touch_controller'; }
static get SCREENSHOT_BUTTON_POSITION() { return 'screenshot_button_position'; }
static get BLOCK_TRACKING() { return 'block_tracking'; }
@ -477,6 +520,10 @@ class Preferences {
'label': 'Hide Dots icon while playing',
'default': false,
},
[Preferences.STREAM_HIDE_TOUCH_CONTROLLER]: {
'label': 'Disable touch controller',
'default': false,
},
[Preferences.HIDE_IDLE_CURSOR]: {
'label': 'Hide mouse cursor while playing',
'default': false,
@ -728,8 +775,8 @@ function addCss() {
font-family: "Segoe UI", Arial, Helvetica, sans-serif
}
.better-xcloud-settings-gone {
display: none;
.better-xcloud-gone {
display: none !important;
}
.better-xcloud-settings-wrapper {
@ -911,7 +958,7 @@ div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
}
.better-xcloud-stats-bar {
display: none;
display: block;
user-select: none;
position: fixed;
top: 0;
@ -1184,6 +1231,15 @@ div[class*=StreamHUD-module__buttonsContainer] {
`;
}
// Hide touch controller
if (PREFS.get(Preferences.STREAM_HIDE_TOUCH_CONTROLLER)) {
css += `
#MultiTouchSurface, #BabylonCanvasContainer-main {
display: none !important;
}
`;
}
const $style = createElement('style', {}, css);
document.documentElement.appendChild($style);
}
@ -1454,7 +1510,7 @@ function injectSettingsButton($parent) {
const $button = CE('button', {'class': 'better-xcloud-settings-button'}, PREF_PREFERRED_REGION);
$button.addEventListener('click', e => {
const $settings = document.querySelector('.better_xcloud_settings');
$settings.classList.toggle('better-xcloud-settings-gone');
$settings.classList.toggle('better-xcloud-gone');
$settings.scrollIntoView();
});
@ -1465,7 +1521,7 @@ function injectSettingsButton($parent) {
$parent.appendChild($button);
const $container = CE('div', {
'class': 'better_xcloud_settings better-xcloud-settings-gone',
'class': 'better_xcloud_settings better-xcloud-gone',
});
let $updateAvailable;
@ -1727,7 +1783,7 @@ function injectVideoSettingsButton() {
return;
}
item.addedNodes.forEach(node => {
item.addedNodes.forEach(async node => {
if (!node.className || !node.className.startsWith('StreamMenu')) {
return;
}
@ -1737,8 +1793,6 @@ function injectVideoSettingsButton() {
return;
}
// Credit: https://www.iconfinder.com/iconsets/user-interface-outline-27
const ICON_VIDEO_SETTINGS = '<path d="M8 2c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h2.186C5.602 7.158 6.706 8 8 8s2.395-.843 2.813-2h10.188a1 1 0 1 0 0-2H10.813C10.395 2.843 9.293 2 8 2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1zm7 5c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h9.186c.417 1.158 1.521 2 2.814 2s2.395-.843 2.813-2H21a1 1 0 1 0 0-2h-3.187c-.418-1.157-1.52-2-2.813-2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1zm-7 5c-1.293 0-2.395.843-2.812 2H3a1 1 0 1 0 0 2h2.188c.417 1.157 1.519 2 2.813 2s2.398-.842 2.814-2H21a1 1 0 1 0 0-2H10.812c-.417-1.157-1.519-2-2.812-2zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1z"/>';
// Create Video Settings button
const $btnVideoSettings = cloneStreamMenuButton($orgButton, 'Video settings', ICON_VIDEO_SETTINGS);
$btnVideoSettings.addEventListener('click', e => {
@ -1764,7 +1818,6 @@ function injectVideoSettingsButton() {
$quickBar.style.display = 'none';
});
const ICON_STREAM_STATS = '<path d="M12.005 5C9.184 5 6.749 6.416 5.009 7.903c-.87.743-1.571 1.51-2.074 2.18-.251.335-.452.644-.605.934-.434.733-.389 1.314-.004 1.98a6.98 6.98 0 0 0 .609.949 13.62 13.62 0 0 0 2.076 2.182C6.753 17.606 9.188 19 12.005 19s5.252-1.394 6.994-2.873a13.62 13.62 0 0 0 2.076-2.182 6.98 6.98 0 0 0 .609-.949c.425-.737.364-1.343-.004-1.98-.154-.29-.354-.599-.605-.934-.503-.669-1.204-1.436-2.074-2.18C17.261 6.416 14.826 5 12.005 5zm0 2c2.135 0 4.189 1.135 5.697 2.424.754.644 1.368 1.32 1.773 1.859.203.27.354.509.351.733s-.151.462-.353.732c-.404.541-1.016 1.214-1.77 1.854C16.198 15.881 14.145 17 12.005 17s-4.193-1.12-5.699-2.398a11.8 11.8 0 0 1-1.77-1.854c-.202-.27-.351-.508-.353-.732s.149-.463.351-.733c.406-.54 1.019-1.215 1.773-1.859C7.816 8.135 9.87 7 12.005 7zm.025 1.975c-1.645 0-3 1.355-3 3s1.355 3 3 3 3-1.355 3-3-1.355-3-3-3zm0 2c.564 0 1 .436 1 1s-.436 1-1 1-1-.436-1-1 .436-1 1-1z"/>';
// Create Stream Stats button
const $btnStreamStats = cloneStreamMenuButton($orgButton, 'Stream stats', ICON_STREAM_STATS);
$btnStreamStats.addEventListener('click', e => {
@ -1780,9 +1833,37 @@ function injectVideoSettingsButton() {
// Insert after Video Settings button
$orgButton.parentElement.insertBefore($btnStreamStats, $btnVideoSettings);
// Get "Quit game" button
const $btnQuit = $orgButton.parentElement.querySelector('button:last-of-type');
let isHolding = false;
let holdTimeout;
const onMouseDown = e => {
isHolding = false;
holdTimeout = setTimeout(() => {
isHolding = true;
confirm('Do you want to refresh the stream?') && window.location.reload();
}, 1000);
};
const onMouseUp = e => {
holdTimeout && clearTimeout(holdTimeout);
if (isHolding) {
e.preventDefault();
e.stopPropagation();
}
isHolding = false;
};
$btnQuit.addEventListener('mousedown', onMouseDown);
$btnQuit.addEventListener('click', onMouseUp);
$btnQuit.addEventListener('touchstart', onMouseDown);
$btnQuit.addEventListener('touchend', onMouseUp);
// Render stream badges
const $menu = document.querySelector('div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module]');
$menu.appendChild(StreamBadges.render());
$menu.appendChild(await StreamBadges.render());
});
});
});
@ -1807,7 +1888,17 @@ function patchVideoApi() {
$STREAM_VIDEO = this;
$SCREENSHOT_CANVAS.width = this.videoWidth;
$SCREENSHOT_CANVAS.height = this.videoHeight;
StreamBadges.resolution = {width: this.videoWidth, height: this.videoHeight};
StreamBadges.startTimestamp = +new Date;
// Get battery level
if (navigator.getBattery) {
try {
navigator.getBattery().then(bm => {
StreamBadges.startBatteryLevel = bm.level * 100;
});
} catch(e) {}
}
STREAM_WEBRTC.getStats().then(stats => {
stats.forEach(stat => {
@ -2097,7 +2188,7 @@ function patchHistoryMethod(type) {
function onHistoryChange() {
const $settings = document.querySelector('.better_xcloud_settings');
if ($settings) {
$settings.classList.add('better-xcloud-settings-gone');
$settings.classList.add('better-xcloud-gone');
}
const $quickBar = document.querySelector('.better-xcloud-quick-settings-bar');