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
This commit is contained in:
redphx 2023-09-04 09:11:08 +07:00 committed by GitHub
parent d1882046e2
commit e470cb20a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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,8 +1313,11 @@ class Preferences {
'min': 0, 'min': 0,
'max': 5, 'max': 5,
}, },
[Preferences.VIDEO_FILL_FULL_SCREEN]: { [Preferences.VIDEO_RATIO]: {
'default': false, 'default': 16,
'min': 16,
'max': 21,
'steps': 1,
}, },
[Preferences.VIDEO_SATURATION]: { [Preferences.VIDEO_SATURATION]: {
'default': 100, 'default': 100,
@ -1547,6 +1550,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;
}
} }
@ -1726,7 +1813,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 +2102,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 +2136,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 {
@ -2834,17 +2918,33 @@ 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) {
const minRatio = 16 / 9;
let maxRatio = window.innerWidth / window.innerHeight;
const ratio = Math.min(maxRatio, PREF_RATIO / 9);
if (ratio > minRatio) {
videoCss += `aspect-ratio: ${ratio}; width: auto !important; object-fit: unset !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;
${videoCss}
}
`;
} }
$elm.textContent = css; $elm.textContent = css;
@ -3132,117 +3232,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.toNumberStepper(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 +3529,8 @@ patchVideoApi();
// Setup UI // Setup UI
addCss(); addCss();
updateVideoPlayerCss(); updateVideoPlayerCss();
window.addEventListener('resize', updateVideoPlayerCss);
setupVideoSettingsBar(); setupVideoSettingsBar();
setupScreenshotButton(); setupScreenshotButton();
StreamStats.render(); StreamStats.render();