From 2a0af5d0ab4858f88ddfee7b19dcfbccfc2f38a8 Mon Sep 17 00:00:00 2001 From: redphx <96280+redphx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:59:21 +0700 Subject: [PATCH] Make Controller shortcuts settings controller-friendly --- src/assets/css/web-components.styl | 3 +- src/modules/controller-shortcut.ts | 60 +++++++++++++++++---------- src/modules/stream/stream-settings.ts | 10 +++-- src/web-components/bx-select.ts | 3 +- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/src/assets/css/web-components.styl b/src/assets/css/web-components.styl index 16a1ff6..020ceed 100644 --- a/src/assets/css/web-components.styl +++ b/src/assets/css/web-components.styl @@ -3,7 +3,7 @@ align-items: center; select { - display: none; + display: none !important; } > div, button.bx-select-value { @@ -16,6 +16,7 @@ color: #000; border-radius: 4px; padding: 2px 8px; + flex: 1; } > div { diff --git a/src/modules/controller-shortcut.ts b/src/modules/controller-shortcut.ts index bcd24a7..4c240d7 100644 --- a/src/modules/controller-shortcut.ts +++ b/src/modules/controller-shortcut.ts @@ -11,6 +11,7 @@ import { PrefKey, getPref } from "@utils/preferences"; import { SoundShortcut } from "./shortcuts/shortcut-sound"; import { BxEvent } from "@/utils/bx-event"; import { AppInterface } from "@/utils/global"; +import { BxSelectElement } from "@/web-components/bx-select"; enum ShortcutAction { STREAM_SCREENSHOT_CAPTURE = 'stream-screenshot-capture', @@ -211,6 +212,8 @@ export class ControllerShortcut { } static renderSettings() { + const PREF_CONTROLLER_FRIENDLY_UI = getPref(PrefKey.UI_CONTROLLER_FRIENDLY); + // Read actions from localStorage ControllerShortcut.#ACTIONS = JSON.parse(window.localStorage.getItem(ControllerShortcut.#STORAGE_KEY) || '{}'); @@ -287,23 +290,23 @@ export class ControllerShortcut { } let $remap: HTMLElement; - let $selectProfile: HTMLSelectElement; + const $selectProfile = CE('select', {class: 'bx-shortcut-profile', autocomplete: 'off'}); const $container = CE('div', {'data-has-gamepad': 'false'}, CE('div', {}, - CE('p', {'class': 'bx-shortcut-note'}, t('controller-shortcuts-connect-note')), + CE('p', {class: 'bx-shortcut-note'}, t('controller-shortcuts-connect-note')), ), $remap = CE('div', {}, - $selectProfile = CE('select', {'class': 'bx-shortcut-profile', autocomplete: 'off'}), - CE('p', {'class': 'bx-shortcut-note'}, - CE('span', {'class': 'bx-prompt'}, PrompFont.HOME), + PREF_CONTROLLER_FRIENDLY_UI ? CE('div', {'data-focus-container': 'true'}, BxSelectElement.wrap($selectProfile)) : $selectProfile, + CE('p', {class: 'bx-shortcut-note'}, + CE('span', {class: 'bx-prompt'}, PrompFont.HOME), ': ' + t('controller-shortcuts-xbox-note'), ), ), ); - $selectProfile.addEventListener('change', e => { + $selectProfile.addEventListener('input', e => { ControllerShortcut.#switchProfile($selectProfile.value); }); @@ -314,38 +317,51 @@ export class ControllerShortcut { const button: unknown = $target.dataset.button; const action = $target.value as ShortcutAction; - const $fakeSelect = $target.previousElementSibling! as HTMLSelectElement; - let fakeText = '---'; - if (action) { - const $selectedOption = $target.options[$target.selectedIndex]; - const $optGroup = $selectedOption.parentElement as HTMLOptGroupElement; - fakeText = $optGroup.label + ' ❯ ' + $selectedOption.text; + if (!PREF_CONTROLLER_FRIENDLY_UI) { + const $fakeSelect = $target.previousElementSibling! as HTMLSelectElement; + let fakeText = '---'; + if (action) { + const $selectedOption = $target.options[$target.selectedIndex]; + const $optGroup = $selectedOption.parentElement as HTMLOptGroupElement; + fakeText = $optGroup.label + ' ❯ ' + $selectedOption.text; + } + ($fakeSelect.firstElementChild as HTMLOptionElement).text = fakeText; } - ($fakeSelect.firstElementChild as HTMLOptionElement).text = fakeText; !(e as any).ignoreOnChange && ControllerShortcut.#updateAction(profile, button as GamepadKey, action); }; + // @ts-ignore for (const [button, prompt] of buttons) { - const $row = CE('div', {'class': 'bx-shortcut-row'}); + const $row = CE('div', { + class: 'bx-shortcut-row', + 'data-focus-container': 'true', + }); - const $label = CE('label', {'class': 'bx-prompt'}, `${PrompFont.HOME} + ${prompt}`); + const $label = CE('label', {class: 'bx-prompt'}, `${PrompFont.HOME} + ${prompt}`); - const $div = CE('div', {'class': 'bx-shortcut-actions'}); + const $div = CE('div', {class: 'bx-shortcut-actions'}); - const $fakeSelect = CE('select', {autocomplete: 'off'}, - CE('option', {}, '---'), - ); - $div.appendChild($fakeSelect); + if (!PREF_CONTROLLER_FRIENDLY_UI) { + const $fakeSelect = CE('select', {autocomplete: 'off'}, + CE('option', {}, '---'), + ); + + $div.appendChild($fakeSelect); + } const $select = $baseSelect.cloneNode(true) as HTMLSelectElement; $select.dataset.button = button.toString(); - $select.addEventListener('change', onActionChanged); + $select.addEventListener('input', onActionChanged); ControllerShortcut.#$selectActions[button] = $select; - $div.appendChild($select); + if (PREF_CONTROLLER_FRIENDLY_UI) { + $div.appendChild(BxSelectElement.wrap($select)); + } else { + $div.appendChild($select); + } $row.appendChild($label); $row.appendChild($div); diff --git a/src/modules/stream/stream-settings.ts b/src/modules/stream/stream-settings.ts index 862443e..6f52fb6 100644 --- a/src/modules/stream/stream-settings.ts +++ b/src/modules/stream/stream-settings.ts @@ -329,7 +329,7 @@ export class StreamSettings { // Current element is setting -> Find the next one // Find parent - let $parent = $focusing.closest('.bx-stream-settings-row') || $focusing.closest('h2'); + let $parent = $focusing.closest('[data-focus-container]'); if (!$parent) { return; @@ -507,7 +507,7 @@ export class StreamSettings { continue; } - $group.appendChild(CE('h2', {}, + $group.appendChild(CE('h2', {'data-focus-container': 'true'}, CE('span', {}, settingGroup.label), settingGroup.help_url && createButton({ icon: BxIcon.QUESTION, @@ -555,7 +555,11 @@ export class StreamSettings { const label = Preferences.SETTINGS[pref as PrefKey]?.label || setting.label; const note = Preferences.SETTINGS[pref as PrefKey]?.note || setting.note; - const $content = CE('div', {'class': 'bx-stream-settings-row', 'data-type': settingGroup.group}, + const $content = CE('div', { + class: 'bx-stream-settings-row', + 'data-type': settingGroup.group, + 'data-focus-container': 'true', + }, CE('label', {for: `bx_setting_${pref}`}, label, note && CE('div', {'class': 'bx-stream-settings-dialog-note'}, note), diff --git a/src/web-components/bx-select.ts b/src/web-components/bx-select.ts index 194fd1a..a70d232 100644 --- a/src/web-components/bx-select.ts +++ b/src/web-components/bx-select.ts @@ -54,7 +54,8 @@ export class BxSelectElement { } const getOptionAtIndex = (index: number): HTMLOptionElement | undefined => { - return $select.querySelector(`option:nth-of-type(${visibleIndex + 1})`) as HTMLOptionElement; + const options = Array.from($select.querySelectorAll('option')); + return options[index]; } const render = () => {