Compare commits

..

12 Commits

Author SHA1 Message Date
cc9a644a5e Bump version to 1.15.1 2023-09-08 17:24:05 +07:00
a77db68afb Bump version to 1.15.1 2023-09-08 17:23:46 +07:00
cd7a7c92c7 Validate settings when getting its values 2023-09-08 17:16:38 +07:00
651402a6b4 Restore stretch to full screen feature 2023-09-08 17:15:45 +07:00
6cd2648325 Update README.md 2023-09-04 10:40:14 +07:00
fa0d761d24 Bump version to 1.15 2023-09-04 10:37:31 +07:00
f01d7a3b0b Bump version to 1.15 2023-09-04 10:37:12 +07:00
b520e8173e Update README.md 2023-09-04 10:36:43 +07:00
f15f43faf7 Remove "Bitrate" & "Decode Time" stats from default items 2023-09-04 10:31:52 +07:00
e470cb20a3 Replace "Stretch Video" setting with "Video Ratio" (#121)
* Make Game Pass' app version easier to read

* Replace numberPicker with NumberStepper

* Replace "Stretch Video" setting with "Video Ratio"

* Make number stepper's buttons a little bit bigger
2023-09-04 09:11:08 +07:00
d1882046e2 Update README.md 2023-08-29 08:42:04 +07:00
fb7bd2da0d Update README.md 2023-08-28 14:31:13 +07:00
3 changed files with 206 additions and 173 deletions

View File

@ -6,10 +6,9 @@ This script makes me spend more time with xCloud, and I hope the same thing happ
If you like this project please give it a 🌟. Thank you 🙏. If you like this project please give it a 🌟. Thank you 🙏.
[![Latest version](https://img.shields.io/github/v/release/redphx/better-xcloud?label=latest)](https://github.com/redphx/better-xcloud/releases) [![Latest version](https://img.shields.io/github/v/release/redphx/better-xcloud?label=latest)](https://github.com/redphx/better-xcloud/releases)
[![Total stars](https://img.shields.io/github/stars/redphx/better-xcloud?color=%23cca400)](https://github.com/redphx/better-xcloud/stargazers)
<!--
[![Total downloads](https://img.shields.io/github/downloads/redphx/better-xcloud/total?color=%23e15f2c)](https://github.com/redphx/better-xcloud/releases) [![Total downloads](https://img.shields.io/github/downloads/redphx/better-xcloud/total?color=%23e15f2c)](https://github.com/redphx/better-xcloud/releases)
--> [![Total stars](https://img.shields.io/github/stars/redphx/better-xcloud?color=%23cca400)](https://github.com/redphx/better-xcloud/stargazers)
## Table of Contents ## Table of Contents
- [**Features**](#features) - [**Features**](#features)
@ -29,8 +28,7 @@ If you like this project please give it a 🌟. Thank you 🙏.
<br> <br>
<img width="600" alt="Stream HUD" src="https://github.com/redphx/better-xcloud/assets/96280/e30f6514-13ca-41c6-bff2-979573cff956"> <img width="600" alt="Stream HUD" src="https://github.com/redphx/better-xcloud/assets/96280/e30f6514-13ca-41c6-bff2-979573cff956">
<br> <br>
<img width="600" alt="Video settings" src="https://github.com/redphx/better-xcloud/assets/96280/a8614693-7f56-4a49-82ad-c1fd7e2e00a5"> <img width="600" alt="Video settings" src="https://github.com/redphx/better-xcloud/assets/96280/20756157-917b-4a43-9985-df7bfdc24aa3">
&nbsp; &nbsp;
@ -93,14 +91,13 @@ If you like this project please give it a 🌟. Thank you 🙏.
> <img width="400" alt="Button styles" src="https://github.com/redphx/better-xcloud/assets/96280/2bfef2b3-6712-4924-b067-c2312f8c8062"> > <img width="400" alt="Button styles" src="https://github.com/redphx/better-xcloud/assets/96280/2bfef2b3-6712-4924-b067-c2312f8c8062">
### Loading screen ### Loading screen
- Show game art - **Show game art**
> Replace the black background with game art if it's available. > Replace the black background with game art if it's available.
- Show the estimated wait time - **Show the estimated wait time**
> The time is estimated by the server. > The time is estimated by the server.
> It's not 100% correct: you might get in the game sooner or later. > It's not 100% correct: you might get in the game sooner or later.
> Don't be mad when the estimated time is inaccurate.
> Check [#51](https://github.com/redphx/better-xcloud/issues/51) for more info. > Check [#51](https://github.com/redphx/better-xcloud/issues/51) for more info.
- Show/hide the rocket animation - **Show/hide the rocket animation**
> Always show/Hide when queuing/Always hide. > Always show/Hide when queuing/Always hide.
> Hide this animation might save some battery life while queuing. > Hide this animation might save some battery life while queuing.
@ -135,7 +132,7 @@ If you like this project please give it a 🌟. Thank you 🙏.
> ![clarity](https://github.com/redphx/better-xcloud/assets/96280/ed63bbb0-fcbf-43e2-8e51-ac2733e697b8) > ![clarity](https://github.com/redphx/better-xcloud/assets/96280/ed63bbb0-fcbf-43e2-8e51-ac2733e697b8)
> *(click to enlarge)* > *(click to enlarge)*
- **Stretch video to full sctreen** - **Change video's ratio**
> Useful when you don't have a 16:9 screen > Useful when you don't have a 16:9 screen
- **Adjust video filters** - **Adjust video filters**
> Brightness/Contrast/Saturation. > Brightness/Contrast/Saturation.
@ -159,7 +156,7 @@ If you like this project please give it a 🌟. Thank you 🙏.
1. Install [Tampermonkey extension](https://www.tampermonkey.net/) on suppported browsers. For Safari, use the [Userscripts extension](https://apps.apple.com/us/app/userscripts/id1463298887) (check [this page](https://github.com/redphx/better-xcloud/wiki/Using-with-Safari) before using). 1. Install [Tampermonkey extension](https://www.tampermonkey.net/) on suppported browsers. For Safari, use the [Userscripts extension](https://apps.apple.com/us/app/userscripts/id1463298887) (check [this page](https://github.com/redphx/better-xcloud/wiki/Using-with-Safari) before using).
2. Install **Better xCloud**: 2. Install **Better xCloud**:
- [Stable version](https://github.com/redphx/better-xcloud/releases/latest/download/better-xcloud.user.js) - [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) <!-- - [Dev version](https://github.com/redphx/better-xcloud/raw/main/better-xcloud.user.js)-->
I only distribute **Better xCloud** on GitHub, *DO NOT* download it on other websites or from unknown sources. I only distribute **Better xCloud** on GitHub, *DO NOT* download it on other websites or from unknown sources.
3. Refresh [xCloud web page](https://www.xbox.com/play/). 3. Refresh [xCloud web page](https://www.xbox.com/play/).
4. Click on the new "SERVER NAME" button next to your profile picture to adjust settings. 4. Click on the new "SERVER NAME" button next to your profile picture to adjust settings.
@ -215,7 +212,7 @@ Don't see your browser in the table? If it supports Tampermonkey/Userscript then
|------:|:-------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------| |------:|:-------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------|
| PING | Ping | The number of seconds it takes for data to be sent from your device to the server and back over (the correct term is "Round Trip Time") | | PING | Ping | The number of seconds it takes for data to be sent from your device to the server and back over (the correct term is "Round Trip Time") |
| 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) | | 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 (bugged in Kiwi Browser [#26](https://github.com/redphx/better-xcloud/issues/26)) | | DT | Decode Time | The average time it took to decode one frame in the last second (bugged on Android [#26](https://github.com/redphx/better-xcloud/issues/26)) |
| BR | Bitrate | The amount of data the server sent to your device in the last second | | 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 | | 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 | | FL | Frames Lost | The total number of frames dropped prior to decode or dropped because the frame missed its display deadline |

View File

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

View File

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Better xCloud // @name Better xCloud
// @namespace https://github.com/redphx // @namespace https://github.com/redphx
// @version 1.14.1 // @version 1.15.1
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@ -13,7 +13,7 @@
// ==/UserScript== // ==/UserScript==
'use strict'; 'use strict';
const SCRIPT_VERSION = '1.14.1'; const SCRIPT_VERSION = '1.15.1';
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud'; const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
console.log(`[Better xCloud] readyState: ${document.readyState}`); console.log(`[Better xCloud] readyState: ${document.readyState}`);
@ -1149,7 +1149,7 @@ class Preferences {
static get UI_LOADING_SCREEN_ROCKET() { return 'ui_loading_screen_rocket'; } static get UI_LOADING_SCREEN_ROCKET() { return 'ui_loading_screen_rocket'; }
static get VIDEO_CLARITY() { return 'video_clarity'; } static get VIDEO_CLARITY() { return 'video_clarity'; }
static get VIDEO_FILL_FULL_SCREEN() { return 'video_fill_full_screen'; } static get VIDEO_RATIO() { return 'video_ratio' }
static get VIDEO_BRIGHTNESS() { return 'video_brightness'; } static get VIDEO_BRIGHTNESS() { return 'video_brightness'; }
static get VIDEO_CONTRAST() { return 'video_contrast'; } static get VIDEO_CONTRAST() { return 'video_contrast'; }
static get VIDEO_SATURATION() { return 'video_saturation'; } static get VIDEO_SATURATION() { return 'video_saturation'; }
@ -1313,22 +1313,31 @@ class Preferences {
'min': 0, 'min': 0,
'max': 5, 'max': 5,
}, },
[Preferences.VIDEO_FILL_FULL_SCREEN]: { [Preferences.VIDEO_RATIO]: {
'default': false, 'default': '16:9',
'options': {
'16:9': '16:9',
'21:9': '21:9',
'16:10': '16:10',
'4:3': '4:3',
'fill': 'Stretch',
'cover': 'Cover',
},
}, },
[Preferences.VIDEO_SATURATION]: { [Preferences.VIDEO_SATURATION]: {
'default': 100, 'default': 100,
'min': 0, 'min': 50,
'max': 150, 'max': 150,
}, },
[Preferences.VIDEO_CONTRAST]: { [Preferences.VIDEO_CONTRAST]: {
'default': 100, 'default': 100,
'min': 0, 'min': 50,
'max': 150, 'max': 150,
}, },
[Preferences.VIDEO_BRIGHTNESS]: { [Preferences.VIDEO_BRIGHTNESS]: {
'default': 100, 'default': 100,
'min': 0, 'min': 50,
'max': 150, 'max': 150,
}, },
[Preferences.AUDIO_MIC_ON_PLAYING]: { [Preferences.AUDIO_MIC_ON_PLAYING]: {
@ -1336,7 +1345,7 @@ class Preferences {
}, },
[Preferences.STATS_ITEMS]: { [Preferences.STATS_ITEMS]: {
'default': [StreamStats.PING, StreamStats.FPS, StreamStats.BITRATE, StreamStats.DECODE_TIME, StreamStats.PACKETS_LOST, StreamStats.FRAMES_LOST], 'default': [StreamStats.PING, StreamStats.FPS, StreamStats.PACKETS_LOST, StreamStats.FRAMES_LOST],
'multiple_options': { 'multiple_options': {
[StreamStats.PING]: 'Ping', [StreamStats.PING]: 'Ping',
[StreamStats.FPS]: 'FPS', [StreamStats.FPS]: 'FPS',
@ -1408,7 +1417,43 @@ class Preferences {
} }
} }
get(key, defaultValue=null) { #validateValue(key, value) {
const config = Preferences.SETTINGS[key];
if (!config) {
return value;
}
if (typeof value === 'undefined' || value === null) {
value = config.default;
}
if ('min' in config) {
value = Math.max(config.min, value);
}
if ('max' in config) {
value = Math.min(config.max, value);
}
if ('options' in config && !(value in config.options)) {
value = config.default;
} else if ('multiple_options' in config) {
if (value.length) {
const validOptions = Object.keys(config.multiple_options);
value.forEach((item, idx) => {
(validOptions.indexOf(item) === -1) && value.splice(idx, 1);
});
}
if (!value.length) {
value = config.default;
}
}
return value;
}
get(key) {
if (typeof key === 'undefined') { if (typeof key === 'undefined') {
debugger; debugger;
return; return;
@ -1419,46 +1464,14 @@ class Preferences {
return 'default'; return 'default';
} }
const value = this._prefs[key]; let value = this._prefs[key];
value = this.#validateValue(key, value);
if (typeof value !== 'undefined' && value !== null && value !== '') { return value;
return value;
}
if (defaultValue !== null) {
return defaultValue;
}
// Return default value
return Preferences.SETTINGS[key].default;
} }
set(key, value) { set(key, value) {
const config = Preferences.SETTINGS[key]; value = this.#validateValue(key, value);
if (config) {
if ('min' in config) {
value = Math.max(config.min, value);
}
if ('max' in config) {
value = Math.min(config.max, value);
}
if ('options' in config && !(value in config.options)) {
value = config.default;
} else if ('multiple_options' in config) {
if (value.length) {
const validOptions = Object.keys(config.multiple_options);
value.forEach((item, idx) => {
(validOptions.indexOf(item) === -1) && value.splice(idx, 1);
});
}
if (!value.length) {
value = config.default;
}
}
}
this._prefs[key] = value; this._prefs[key] = value;
this._update_storage(); this._update_storage();
@ -1547,6 +1560,90 @@ class Preferences {
$control.id = `xcloud_setting_${key}`; $control.id = `xcloud_setting_${key}`;
return $control; return $control;
} }
toNumberStepper(key, onChange, suffix='', disabled=false) {
const setting = Preferences.SETTINGS[key]
let value = PREFS.get(key);
let $text, $decBtn, $incBtn;
const MIN = setting.min;
const MAX= setting.max;
const STEPS = Math.max(setting.steps || 1, 1);
const CE = createElement;
const $wrapper = CE('div', {},
$decBtn = CE('button', {'data-type': 'dec'}, '-'),
$text = CE('span', {}, value + suffix),
$incBtn = CE('button', {'data-type': 'inc'}, '+'),
);
if (disabled) {
$incBtn.disabled = true;
$incBtn.classList.add('better-xcloud-hidden');
$decBtn.disabled = true;
$decBtn.classList.add('better-xcloud-hidden');
return $wrapper;
}
let interval;
let isHolding = false;
const onClick = e => {
if (isHolding) {
e.preventDefault();
isHolding = false;
return;
}
const btnType = e.target.getAttribute('data-type');
if (btnType === 'dec') {
value = Math.max(MIN, value - STEPS);
} else {
value = Math.min(MAX, value + STEPS);
}
$text.textContent = value + suffix;
PREFS.set(key, value);
isHolding = false;
onChange && onChange();
}
const onMouseDown = e => {
isHolding = true;
const args = arguments;
interval = setInterval(() => {
const event = new Event('click');
event.arguments = args;
e.target.dispatchEvent(event);
}, 200);
};
const onMouseUp = e => {
clearInterval(interval);
isHolding = false;
};
$decBtn.addEventListener('click', onClick);
$decBtn.addEventListener('mousedown', onMouseDown);
$decBtn.addEventListener('mouseup', onMouseUp);
$decBtn.addEventListener('touchstart', onMouseDown);
$decBtn.addEventListener('touchend', onMouseUp);
$incBtn.addEventListener('click', onClick);
$incBtn.addEventListener('mousedown', onMouseDown);
$incBtn.addEventListener('mouseup', onMouseUp);
$incBtn.addEventListener('touchstart', onMouseDown);
$incBtn.addEventListener('touchend', onMouseUp);
return $wrapper;
}
} }
@ -1556,8 +1653,8 @@ const PREFS = new Preferences();
function checkForUpdate() { function checkForUpdate() {
const CHECK_INTERVAL_SECONDS = 4 * 3600; // check every 4 hours const CHECK_INTERVAL_SECONDS = 4 * 3600; // check every 4 hours
const currentVersion = PREFS.get(Preferences.CURRENT_VERSION, ''); const currentVersion = PREFS.get(Preferences.CURRENT_VERSION);
const lastCheck = PREFS.get(Preferences.LAST_UPDATE_CHECK, 0); const lastCheck = PREFS.get(Preferences.LAST_UPDATE_CHECK);
const now = Math.round((+new Date) / 1000); const now = Math.round((+new Date) / 1000);
if (currentVersion === SCRIPT_VERSION && now - lastCheck < CHECK_INTERVAL_SECONDS) { if (currentVersion === SCRIPT_VERSION && now - lastCheck < CHECK_INTERVAL_SECONDS) {
@ -1726,7 +1823,7 @@ function addCss() {
.better-xcloud-settings-app-version { .better-xcloud-settings-app-version {
margin-top: 10px; margin-top: 10px;
text-align: center; text-align: center;
color: #484848; color: #747474;
font-size: 12px; font-size: 12px;
} }
@ -2015,22 +2112,18 @@ div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
} }
.better-xcloud-quick-settings-bar label { .better-xcloud-quick-settings-bar label {
font-size: 16px; font-size: 18px;
font-weight: bold;
display: block; display: block;
margin-bottom: 8px; margin-bottom: 8px;
} }
.better-xcloud-quick-settings-bar input {
width: 22px;
height: 22px;
}
.better-xcloud-quick-settings-bar button { .better-xcloud-quick-settings-bar button {
border: none; border: none;
width: 22px; width: 24px;
height: 22px; height: 24px;
margin: 0 4px; margin: 0 4px;
line-height: 22px; line-height: 24px;
background-color: #515151; background-color: #515151;
color: #fff; color: #fff;
border-radius: 4px; border-radius: 4px;
@ -2053,6 +2146,7 @@ div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
width: 40px; width: 40px;
font-weight: bold; font-weight: bold;
font-family: Consolas, "Courier New", Courier, monospace; font-family: Consolas, "Courier New", Courier, monospace;
font-size: 16px;
} }
.better-xcloud-stream-menu-button-on { .better-xcloud-stream-menu-button-on {
@ -2579,7 +2673,7 @@ function injectSettingsButton($parent) {
const CE = createElement; const CE = createElement;
const PREF_PREFERRED_REGION = getPreferredServerRegion(); const PREF_PREFERRED_REGION = getPreferredServerRegion();
const PREF_LATEST_VERSION = PREFS.get(Preferences.LATEST_VERSION, null); const PREF_LATEST_VERSION = PREFS.get(Preferences.LATEST_VERSION);
// Setup Settings button // Setup Settings button
const $button = CE('button', {'class': 'better-xcloud-settings-button'}, PREF_PREFERRED_REGION); const $button = CE('button', {'class': 'better-xcloud-settings-button'}, PREF_PREFERRED_REGION);
@ -2834,17 +2928,42 @@ function updateVideoPlayerCss() {
} }
let filters = getVideoPlayerFilterStyle(); let filters = getVideoPlayerFilterStyle();
let css = ''; let videoCss = '';
if (filters) { if (filters) {
css += `filter: ${filters} !important;`; videoCss += `filter: ${filters} !important;`;
} }
if (PREFS.get(Preferences.VIDEO_FILL_FULL_SCREEN)) { const PREF_RATIO = PREFS.get(Preferences.VIDEO_RATIO);
css += 'object-fit: fill !important;'; if (PREF_RATIO && PREF_RATIO !== '16:9') {
if (PREF_RATIO.includes(':')) {
videoCss += `aspect-ratio: ${PREF_RATIO.replace(':', '/')}; object-fit: unset !important;`;
const tmp = PREF_RATIO.split(':');
const ratio = parseFloat(tmp[0]) / parseFloat(tmp[1]);
const maxRatio = window.innerWidth / window.innerHeight;
if (ratio < maxRatio) {
videoCss += 'width: fit-content !important;'
} else {
videoCss += 'height: fit-content !important;'
}
} else {
videoCss += `object-fit: ${PREF_RATIO} !important;`;
}
} }
if (css) { let css = '';
css = `#game-stream video {${css}}`; if (videoCss) {
css = `
div[data-testid="media-container"] {
display: flex;
}
#game-stream video {
margin: 0 auto;
align-self: center;
${videoCss}
}
`;
} }
$elm.textContent = css; $elm.textContent = css;
@ -3132,117 +3251,32 @@ function patchRtcCodecs() {
} }
function numberPicker(key, suffix='', disabled=false) {
const setting = Preferences.SETTINGS[key]
let value = PREFS.get(key);
let $text, $decBtn, $incBtn;
const MIN = setting.min;
const MAX= setting.max;
const CE = createElement;
const $wrapper = CE('div', {},
$decBtn = CE('button', {'data-type': 'dec'}, '-'),
$text = CE('span', {}, value + suffix),
$incBtn = CE('button', {'data-type': 'inc'}, '+'),
);
if (disabled) {
$incBtn.disabled = true;
$incBtn.classList.add('better-xcloud-hidden');
$decBtn.disabled = true;
$decBtn.classList.add('better-xcloud-hidden');
return $wrapper;
}
let interval;
let isHolding = false;
const onClick = e => {
if (isHolding) {
e.preventDefault();
isHolding = false;
return;
}
const btnType = e.target.getAttribute('data-type');
if (btnType === 'dec') {
value = (value <= MIN) ? MIN : value - 1;
} else {
value = (value >= MAX) ? MAX : value + 1;
}
$text.textContent = value + suffix;
PREFS.set(key, value);
updateVideoPlayerCss();
isHolding = false;
}
const onMouseDown = e => {
isHolding = true;
const args = arguments;
interval = setInterval(() => {
const event = new Event('click');
event.arguments = args;
e.target.dispatchEvent(event);
}, 200);
};
const onMouseUp = e => {
clearInterval(interval);
isHolding = false;
};
$decBtn.addEventListener('click', onClick);
$decBtn.addEventListener('mousedown', onMouseDown);
$decBtn.addEventListener('mouseup', onMouseUp);
$decBtn.addEventListener('touchstart', onMouseDown);
$decBtn.addEventListener('touchend', onMouseUp);
$incBtn.addEventListener('click', onClick);
$incBtn.addEventListener('mousedown', onMouseDown);
$incBtn.addEventListener('mouseup', onMouseUp);
$incBtn.addEventListener('touchstart', onMouseDown);
$incBtn.addEventListener('touchend', onMouseUp);
return $wrapper;
}
function setupVideoSettingsBar() { function setupVideoSettingsBar() {
const CE = createElement; const CE = createElement;
const isSafari = UserAgent.isSafari(); const isSafari = UserAgent.isSafari();
const onChange = e => {
updateVideoPlayerCss();
}
let $stretchInp; let $stretchInp;
const $wrapper = CE('div', {'class': 'better-xcloud-quick-settings-bar'}, const $wrapper = CE('div', {'class': 'better-xcloud-quick-settings-bar'},
CE('div', {}, CE('div', {},
CE('label', {'for': 'better-xcloud-quick-setting-stretch'}, 'Stretch Video'), CE('label', {'for': 'better-xcloud-quick-setting-stretch'}, 'Video Ratio'),
$stretchInp = CE('input', {'id': 'better-xcloud-quick-setting-stretch', 'type': 'checkbox'})), PREFS.toElement(Preferences.VIDEO_RATIO, onChange, ':9')),
CE('div', {}, CE('div', {},
CE('label', {}, 'Clarity'), CE('label', {}, 'Clarity'),
numberPicker(Preferences.VIDEO_CLARITY, '', isSafari)), // disable this feature in Safari PREFS.toNumberStepper(Preferences.VIDEO_CLARITY, onChange, '', isSafari)), // disable this feature in Safari
CE('div', {}, CE('div', {},
CE('label', {}, 'Saturation'), CE('label', {}, 'Saturation'),
numberPicker(Preferences.VIDEO_SATURATION, '%')), PREFS.toNumberStepper(Preferences.VIDEO_SATURATION, onChange, '%')),
CE('div', {}, CE('div', {},
CE('label', {}, 'Contrast'), CE('label', {}, 'Contrast'),
numberPicker(Preferences.VIDEO_CONTRAST, '%')), PREFS.toNumberStepper(Preferences.VIDEO_CONTRAST, onChange, '%')),
CE('div', {}, CE('div', {},
CE('label', {}, 'Brightness'), CE('label', {}, 'Brightness'),
numberPicker(Preferences.VIDEO_BRIGHTNESS, '%')) PREFS.toNumberStepper(Preferences.VIDEO_BRIGHTNESS, onChange, '%'))
); );
$stretchInp.checked = PREFS.get(Preferences.VIDEO_FILL_FULL_SCREEN);
$stretchInp.addEventListener('change', e => {
PREFS.set(Preferences.VIDEO_FILL_FULL_SCREEN, e.target.checked);
updateVideoPlayerCss();
});
document.documentElement.appendChild($wrapper); document.documentElement.appendChild($wrapper);
} }
@ -3514,6 +3548,8 @@ patchVideoApi();
// Setup UI // Setup UI
addCss(); addCss();
updateVideoPlayerCss(); updateVideoPlayerCss();
window.addEventListener('resize', updateVideoPlayerCss);
setupVideoSettingsBar(); setupVideoSettingsBar();
setupScreenshotButton(); setupScreenshotButton();
StreamStats.render(); StreamStats.render();