Compare commits

..

12 Commits

Author SHA1 Message Date
redphx
adf689d61d Bump version to 3.2.3 2024-03-10 20:47:21 +07:00
redphx
086385fbfb Update translations 2024-03-10 20:45:18 +07:00
redphx
705446ffb9 Fix language names 2024-03-10 20:21:45 +07:00
redphx
e366cb73e4 Stop exposing Toast class 2024-03-10 18:02:03 +07:00
redphx
d148fc708e Minor bug fixes 2024-03-10 18:01:36 +07:00
redphx
f75e22b5f6 Move Touch control settings to Controller tab 2024-03-10 17:57:16 +07:00
redphx
0f7ac4c372 Don't call MkbHandler.destroy() if the MKB feature is not enabled 2024-03-10 17:45:19 +07:00
redphx
a4874c76db Stop redrawing the "👀" emoji every seconds in the stats bar 2024-03-10 17:39:08 +07:00
redphx
397b3baa9b Avoid rendering the Settings multiple times 2024-03-10 16:20:53 +07:00
redphx
0330d0d811 Shorten name of the MKB controller 2024-03-10 07:54:08 +07:00
redphx
f8e035d98f Show a toast when a controller is connected/disconnected 2024-03-09 22:51:42 +07:00
redphx
1e7bc366ca Change STREAM_TARGET_RESOLUTION's default value back to "auto" 2024-03-09 21:29:19 +07:00
2 changed files with 141 additions and 54 deletions

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 3.2.2 // @version 3.2.3
// ==/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 3.2.2 // @version 3.2.3
// @description Improve Xbox Cloud Gaming (xCloud) experience // @description Improve Xbox Cloud Gaming (xCloud) experience
// @author redphx // @author redphx
// @license MIT // @license MIT
@@ -14,7 +14,7 @@
// ==/UserScript== // ==/UserScript==
'use strict'; 'use strict';
const SCRIPT_VERSION = '3.2.2'; const SCRIPT_VERSION = '3.2.3';
const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud'; const SCRIPT_HOME = 'https://github.com/redphx/better-xcloud';
const ENABLE_XCLOUD_LOGGER = false; const ENABLE_XCLOUD_LOGGER = false;
@@ -675,6 +675,22 @@ const Translations = {
"Bạn có muốn kết nối lại stream không?", "Bạn có muốn kết nối lại stream không?",
"您想要刷新吗?", "您想要刷新吗?",
], ],
"connected": [
,
"Connected",
"Conectado",
,
,
"接続済み",
,
"Połączony",
,
"Подключен",
"Bağlı",
"Під’єднано",
"Đã kết nối",
"已连接",
],
"console-connect": [ "console-connect": [
"Verbinden", "Verbinden",
"Connect", "Connect",
@@ -963,6 +979,22 @@ const Translations = {
"Đã tắt", "Đã tắt",
"禁用", "禁用",
], ],
"disconnected": [
,
"Disconnected",
"Desconectado",
,
,
"切断",
,
"Rozłączony",
,
"Отключен",
"Bağlı değil",
"Роз’єднано",
"Đã ngắt kết nối",
"已断开连接",
],
"edit": [ "edit": [
"Bearbeiten", "Bearbeiten",
"Edit", "Edit",
@@ -1045,18 +1077,18 @@ const Translations = {
], ],
"enable-mkb": [ "enable-mkb": [
"Maus- und Tastaturunterstützung aktivieren", "Maus- und Tastaturunterstützung aktivieren",
"Enable Mouse & Keyboard support", "Emulate controller with Mouse & Keyboard",
"Habilitar soporte para ratón y teclado", "Emular mandos con teclado y ratón",
, ,
"Abilitare il supporto di mouse e tastiera", "Abilitare il supporto di mouse e tastiera",
"マウス&キーボードのサポートを有効化", "マウス&キーボード操作をコントローラー化",
"마우스 & 키보드 활성화", "마우스 & 키보드 활성화",
"Włącz obsługę myszy i klawiatury", "Włącz obsługę myszy i klawiatury",
"Habilitar suporte ao Mouse & Teclado", "Habilitar suporte ao Mouse & Teclado",
"Включить поддержку мыши и клавиатуры", "Эмулировать контроллер с помощью мыши и клавиатуры",
"Klavye ve fare desteğini aktive et", "Klavye ve fare desteğini aktive et",
"Увімкнути підтримку миші та клавіатури", "Емуляція контролера за допомогою миші та клавіатури",
"Kích hoạt hỗ trợ Chuột & Bàn phím", "Giả lập tay cầm bằng Chuột Bàn phím",
"启用鼠标和键盘支持", "启用鼠标和键盘支持",
], ],
"enable-quick-glance-mode": [ "enable-quick-glance-mode": [
@@ -2636,8 +2668,8 @@ const Translations = {
"コントローラー接続時に無効化", "コントローラー接続時に無効化",
, ,
"Wyłącz, gdy kontroler zostanie znaleziony", "Wyłącz, gdy kontroler zostanie znaleziony",
, "Desligar toque quando o controle estiver conectado",
, "Выключить, когда контроллер найден",
"Başka bir kumanda bağlandığında kapat", "Başka bir kumanda bağlandığında kapat",
"Вимкнено, коли контролер знайдено", "Вимкнено, коли контролер знайдено",
"Tắt khi sử dụng tay cầm", "Tắt khi sử dụng tay cầm",
@@ -4063,14 +4095,39 @@ class Toast {
static #$wrapper; static #$wrapper;
static #$msg; static #$msg;
static #$status; static #$status;
static #stack = [];
static #isShowing = false;
static #timeout; static #timeout;
static #DURATION = 3000; static #DURATION = 3000;
static show(msg, status) { static show(msg, status, options) {
options = options || {};
if (options.instant) {
// Clear stack
Toast.#stack = [arguments];
Toast.#showNext();
} else {
Toast.#stack.push(arguments);
!Toast.#isShowing && Toast.#showNext();
}
}
static #showNext() {
if (!Toast.#stack.length) {
Toast.#isShowing = false;
return;
}
Toast.#isShowing = true;
Toast.#timeout && clearTimeout(Toast.#timeout); Toast.#timeout && clearTimeout(Toast.#timeout);
Toast.#timeout = setTimeout(Toast.#hide, Toast.#DURATION); Toast.#timeout = setTimeout(Toast.#hide, Toast.#DURATION);
// Get values from item
const [msg, status, options] = Toast.#stack.shift();
Toast.#$msg.textContent = msg; Toast.#$msg.textContent = msg;
if (status) { if (status) {
@@ -4103,6 +4160,8 @@ class Toast {
if (classList.contains('bx-hide')) { if (classList.contains('bx-hide')) {
classList.remove('bx-offscreen', 'bx-hide'); classList.remove('bx-offscreen', 'bx-hide');
classList.add('bx-offscreen'); classList.add('bx-offscreen');
Toast.#showNext();
} }
}); });
@@ -4847,7 +4906,7 @@ class MkbHandler {
static get MAXIMUM_STICK_RANGE() { return 1.1; } static get MAXIMUM_STICK_RANGE() { return 1.1; }
#VIRTUAL_GAMEPAD = { #VIRTUAL_GAMEPAD = {
id: 'Xbox 360 Controller (XInput STANDARD GAMEPAD)', id: 'Xbox 360 Controller',
index: 3, index: 3,
connected: false, connected: false,
hapticActuators: null, hapticActuators: null,
@@ -6802,18 +6861,18 @@ class Preferences {
'options': { 'options': {
'de-DE': 'Deutsch', 'de-DE': 'Deutsch',
'en-US': 'English (United States)', 'en-US': 'English (United States)',
'es-ES': 'espa\xf1ol (Espa\xf1a)', 'es-ES': 'español (España)',
'fr-FR': 'fran\xe7ais', 'fr-FR': 'français',
'it-IT': 'italiano', 'it-IT': 'italiano',
'ja-JP': '\u65e5\u672c\u8a9e', 'ja-JP': '日本語',
'ko-KR': '\ud55c\uad6d\uc5b4', 'ko-KR': '한국어',
'pl-PL': 'polski', 'pl-PL': 'polski',
'pt-BR': 'portugu\xeas (Brasil)', 'pt-BR': 'português (Brasil)',
'ru-RU': '\u0440\u0443\u0441\u0441\u043a\u0438\u0439', 'ru-RU': 'русский',
'tr-TR': 'T\xfcrk\xe7e', 'tr-TR': 'Türkçe',
'uk-UA': 'українська', 'uk-UA': 'українська',
'vi-VN': 'Tiếng Việt', 'vi-VN': 'Tiếng Việt',
'zh-CN': '\u4e2d\u6587(\u7b80\u4f53)', 'zh-CN': '中文(简体)',
}, },
}, },
[Preferences.SERVER_REGION]: { [Preferences.SERVER_REGION]: {
@@ -6823,37 +6882,37 @@ class Preferences {
'default': 'default', 'default': 'default',
'options': { 'options': {
'default': t('default'), 'default': t('default'),
'ar-SA': '\u0627\u0644\u0639\u0631\u0628\u064a\u0629', 'ar-SA': 'العربية',
'cs-CZ': '\u010de\u0161tina', 'cs-CZ': 'čeština',
'da-DK': 'dansk', 'da-DK': 'dansk',
'de-DE': 'Deutsch', 'de-DE': 'Deutsch',
'el-GR': '\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac', 'el-GR': 'Ελληνικά',
'en-GB': 'English (United Kingdom)', 'en-GB': 'English (United Kingdom)',
'en-US': 'English (United States)', 'en-US': 'English (United States)',
'es-ES': 'espa\xf1ol (Espa\xf1a)', 'es-ES': 'español (España)',
'es-MX': 'espa\xf1ol (Latinoam\xe9rica)', 'es-MX': 'español (Latinoamérica)',
'fi-FI': 'suomi', 'fi-FI': 'suomi',
'fr-FR': 'fran\xe7ais', 'fr-FR': 'français',
'he-IL': '\u05e2\u05d1\u05e8\u05d9\u05ea', 'he-IL': 'עברית',
'hu-HU': 'magyar', 'hu-HU': 'magyar',
'it-IT': 'italiano', 'it-IT': 'italiano',
'ja-JP': '\u65e5\u672c\u8a9e', 'ja-JP': '日本語',
'ko-KR': '\ud55c\uad6d\uc5b4', 'ko-KR': '한국어',
'nb-NO': 'norsk bokm\xe5l', 'nb-NO': 'norsk bokmål',
'nl-NL': 'Nederlands', 'nl-NL': 'Nederlands',
'pl-PL': 'polski', 'pl-PL': 'polski',
'pt-BR': 'portugu\xeas (Brasil)', 'pt-BR': 'português (Brasil)',
'pt-PT': 'portugu\xeas (Portugal)', 'pt-PT': 'português (Portugal)',
'ru-RU': '\u0440\u0443\u0441\u0441\u043a\u0438\u0439', 'ru-RU': 'русский',
'sk-SK': 'sloven\u010dina', 'sk-SK': 'slovenčina',
'sv-SE': 'svenska', 'sv-SE': 'svenska',
'tr-TR': 'T\xfcrk\xe7e', 'tr-TR': 'Türkçe',
'zh-CN': '\u4e2d\u6587(\u7b80\u4f53)', 'zh-CN': '中文(简体)',
'zh-TW': '\u4e2d\u6587 (\u7e41\u9ad4)', 'zh-TW': '中文 (繁體)',
}, },
}, },
[Preferences.STREAM_TARGET_RESOLUTION]: { [Preferences.STREAM_TARGET_RESOLUTION]: {
'default': '1080p', 'default': 'auto',
'options': { 'options': {
'auto': t('default'), 'auto': t('default'),
'1080p': '1080p', '1080p': '1080p',
@@ -8207,7 +8266,7 @@ a.bx-button {
margin: 0 !important; margin: 0 !important;
} }
.better_xcloud_settings { .bx-settings-container {
background-color: #151515; background-color: #151515;
user-select: none; user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
@@ -8511,9 +8570,15 @@ div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
border-right: none; border-right: none;
} }
.bx-stats-bar[data-display=glancing]::before { .bx-stats-bar::before {
content: '👀 '; display: none;
content: '👀';
vertical-align: middle; vertical-align: middle;
margin-right: 8px;
}
.bx-stats-bar[data-display=glancing]::before {
display: inline-block;
} }
.bx-stats-bar[data-position=top-left] { .bx-stats-bar[data-position=top-left] {
@@ -8922,6 +8987,7 @@ div[class*=StreamMenu-module__menuContainer] > div[class*=Menu-module] {
-webkit-appearance: none; -webkit-appearance: none;
background: transparent; background: transparent;
text-align-last: right; text-align-last: right;
border: none;
} }
.bx-mkb-pointer-lock-msg { .bx-mkb-pointer-lock-msg {
@@ -9912,7 +9978,7 @@ function injectSettingsButton($parent) {
label: PREF_PREFERRED_REGION, label: PREF_PREFERRED_REGION,
style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE | ButtonStyle.FULL_HEIGHT, style: ButtonStyle.GHOST | ButtonStyle.FOCUSABLE | ButtonStyle.FULL_HEIGHT,
onClick: e => { onClick: e => {
const $settings = document.querySelector('.better_xcloud_settings'); const $settings = document.querySelector('.bx-settings-container');
$settings.classList.toggle('bx-gone'); $settings.classList.toggle('bx-gone');
$settings.scrollIntoView(); $settings.scrollIntoView();
document.activeElement && document.activeElement.blur(); document.activeElement && document.activeElement.blur();
@@ -9926,12 +9992,16 @@ function injectSettingsButton($parent) {
// Add the Settings button to the web page // Add the Settings button to the web page
$headerFragment.appendChild($settingsBtn); $headerFragment.appendChild($settingsBtn);
$parent.appendChild($headerFragment); $parent.appendChild($headerFragment);
// Avoid rendering the Settings multiple times
if (document.querySelector('.bx-settings-container')) {
return;
}
// Setup Settings UI // Setup Settings UI
const $container = CE('div', { const $container = CE('div', {
'class': 'better_xcloud_settings bx-gone', 'class': 'bx-settings-container bx-gone',
}); });
let $updateAvailable; let $updateAvailable;
@@ -10773,14 +10843,8 @@ function setupQuickSettingsBar() {
}, },
], ],
}, },
],
},
HAS_TOUCH_SUPPORT && { HAS_TOUCH_SUPPORT && {
icon: Icon.HAND_TAP,
group: 'touch-controller',
items: [
{
group: 'touch-controller', group: 'touch-controller',
label: t('touch-controller'), label: t('touch-controller'),
items: [ items: [
@@ -10939,6 +11003,10 @@ function setupQuickSettingsBar() {
const $group = CE('div', {'data-group': settingTab.group, 'class': 'bx-gone'}); const $group = CE('div', {'data-group': settingTab.group, 'class': 'bx-gone'});
for (const settingGroup of settingTab.items) { for (const settingGroup of settingTab.items) {
if (!settingGroup) {
continue;
}
$group.appendChild(CE('h2', {}, $group.appendChild(CE('h2', {},
CE('span', {}, settingGroup.label), CE('span', {}, settingGroup.label),
settingGroup.help_url && createButton({ settingGroup.help_url && createButton({
@@ -11096,7 +11164,7 @@ function onHistoryChanged(e) {
setTimeout(RemotePlay.detect, 10); setTimeout(RemotePlay.detect, 10);
const $settings = document.querySelector('.better_xcloud_settings'); const $settings = document.querySelector('.bx-settings-container');
if ($settings) { if ($settings) {
$settings.classList.add('bx-gone'); $settings.classList.add('bx-gone');
} }
@@ -11211,7 +11279,7 @@ window.addEventListener(BxEvent.STREAM_STOPPED, e => {
IS_PLAYING = false; IS_PLAYING = false;
// Stop MKB listeners // Stop MKB listeners
MkbHandler.INSTANCE.destroy(); getPref(Preferences.MKB_ENABLED) && MkbHandler.INSTANCE.destroy();
const $quickBar = document.querySelector('.bx-quick-settings-bar'); const $quickBar = document.querySelector('.bx-quick-settings-bar');
if ($quickBar) { if ($quickBar) {
@@ -11337,3 +11405,22 @@ RemotePlay.detect();
StreamBadges.setupEvents(); StreamBadges.setupEvents();
StreamStats.setupEvents(); StreamStats.setupEvents();
MkbHandler.setupEvents(); MkbHandler.setupEvents();
// Show a toast when connecting/disconecting controller
function showGamepadToast(gamepad) {
let text = '🎮';
if (getPref(Preferences.LOCAL_CO_OP_ENABLED)) {
text += ` #${gamepad.index + 1}`;
}
// Remove "(STANDARD GAMEPAD Vendor: xxx Product: xxx)" from ID
const gamepadId = gamepad.id.replace(/ \(.* Vendor: \w+ Product: \w+\)$/, '');
text += ` - ${gamepadId}`;
const status = gamepad.connected ? t('connected') : t('disconnected');
Toast.show(text, status, {instant: false});
}
window.addEventListener('gamepadconnected', e => showGamepadToast(e.gamepad));
window.addEventListener('gamepaddisconnected', e => showGamepadToast(e.gamepad));