summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/ConfigurationTab.tsx6
-rw-r--r--src/components/GameConfigurationSelector.tsx29
-rw-r--r--src/components/ProfileDetails.tsx4
-rw-r--r--src/components/WorkaroundsSection.tsx21
4 files changed, 49 insertions, 11 deletions
diff --git a/src/components/ConfigurationTab.tsx b/src/components/ConfigurationTab.tsx
index 2bb0f26..c41c941 100644
--- a/src/components/ConfigurationTab.tsx
+++ b/src/components/ConfigurationTab.tsx
@@ -33,6 +33,7 @@ export function ConfigurationTab({
const [detailAppId, setDetailAppId] = useState<string | null>(null);
const [focusFpsMultiplier, setFocusFpsMultiplier] = useState(false);
const [focusDetailAction, setFocusDetailAction] = useState<"enable" | "fps" | null>(null);
+ const [focusConfiguredToggle, setFocusConfiguredToggle] = useState(false);
const enableRef = useRef<HTMLDivElement>(null);
const promptedRunningAppId = useRef<string | null>(null);
const closeDetails = useCallback(() => {
@@ -41,6 +42,7 @@ export function ConfigurationTab({
setDetailAppId(null);
}, []);
const clearFpsFocusRequest = useCallback(() => setFocusFpsMultiplier(false), []);
+ const clearConfiguredToggleFocusRequest = useCallback(() => setFocusConfiguredToggle(false), []);
useEffect(() => {
if (!focusDetailAction) return;
@@ -77,12 +79,15 @@ export function ConfigurationTab({
targets={targets}
runningGame={runningGame}
onSelect={(appid) => {
+ setFocusConfiguredToggle(false);
setFocusDetailAction(targets.find((target) => target.appid === appid)?.configured ? "fps" : "enable");
onSelect(appid);
setDetailAppId(appid);
}}
onEnableAll={onEnableAll}
onResetAll={onResetAll}
+ focusConfiguredToggle={focusConfiguredToggle}
+ onConfiguredToggleFocused={clearConfiguredToggleFocusRequest}
/>
</PanelSection>
);
@@ -96,6 +101,7 @@ export function ConfigurationTab({
if (selectedTarget?.configured) {
promptedRunningAppId.current = detailAppId;
await onReset();
+ setFocusConfiguredToggle(true);
closeDetails();
} else if (detailAppId && await onEnable(detailAppId)) {
setFocusFpsMultiplier(true);
diff --git a/src/components/GameConfigurationSelector.tsx b/src/components/GameConfigurationSelector.tsx
index 5f23b91..50b2cf8 100644
--- a/src/components/GameConfigurationSelector.tsx
+++ b/src/components/GameConfigurationSelector.tsx
@@ -1,5 +1,5 @@
import { ButtonItem, ConfirmModal, Field, PanelSectionRow, showModal } from "@decky/ui";
-import { useEffect, useState } from "react";
+import { useEffect, useRef, useState, type RefObject } from "react";
import { RiArrowDownSFill, RiArrowUpSFill } from "react-icons/ri";
import { GameTarget } from "../hooks/useGameConfiguration";
@@ -9,6 +9,8 @@ interface Props {
onSelect: (appid: string) => void;
onEnableAll: () => Promise<void>;
onResetAll: () => Promise<void>;
+ focusConfiguredToggle?: boolean;
+ onConfiguredToggleFocused?: () => void;
}
const CONFIGURED_COLLAPSED_KEY = "lsfg-configured-games-collapsed-v3";
@@ -40,12 +42,14 @@ function GameGroup({
collapsed,
onToggle,
onSelect,
+ toggleRef,
}: {
title: string;
games: GameTarget[];
collapsed: boolean;
onToggle: () => void;
onSelect: (appid: string) => void;
+ toggleRef?: RefObject<HTMLDivElement>;
}) {
if (games.length === 0) return null;
@@ -56,6 +60,7 @@ function GameGroup({
</PanelSectionRow>
<PanelSectionRow>
<div
+ ref={toggleRef}
className="LSFG_GameGroupCollapseButton_Container"
style={{ marginTop: "-2px", marginBottom: "4px" }}
>
@@ -86,7 +91,15 @@ function GameGroup({
);
}
-export function GameConfigurationSelector({ targets, runningGame, onSelect, onEnableAll, onResetAll }: Props) {
+export function GameConfigurationSelector({
+ targets,
+ runningGame,
+ onSelect,
+ onEnableAll,
+ onResetAll,
+ focusConfiguredToggle = false,
+ onConfiguredToggleFocused,
+}: Props) {
const sortGames = (games: GameTarget[]) => [...games].sort((a, b) => {
if (a.appid === runningGame?.appid) return -1;
if (b.appid === runningGame?.appid) return 1;
@@ -102,6 +115,17 @@ export function GameConfigurationSelector({ targets, runningGame, onSelect, onEn
const [configuredNonSteamCollapsed, toggleConfiguredNonSteam] = usePersistentCollapsed(`${CONFIGURED_COLLAPSED_KEY}-non-steam`);
const [availableCollapsed, toggleAvailable] = usePersistentCollapsed(AVAILABLE_COLLAPSED_KEY);
const [availableNonSteamCollapsed, toggleAvailableNonSteam] = usePersistentCollapsed(`${AVAILABLE_COLLAPSED_KEY}-non-steam`);
+ const configuredToggleRef = useRef<HTMLDivElement>(null);
+
+ useEffect(() => {
+ if (!focusConfiguredToggle) return;
+ const frame = requestAnimationFrame(() => {
+ configuredToggleRef.current?.querySelector<HTMLElement>('[role="button"], button')?.focus();
+ onConfiguredToggleFocused?.();
+ });
+ return () => cancelAnimationFrame(frame);
+ }, [configuredGames.length, focusConfiguredToggle, onConfiguredToggleFocused]);
+
const confirmResetAll = () => {
showModal(
<ConfirmModal
@@ -163,6 +187,7 @@ export function GameConfigurationSelector({ targets, runningGame, onSelect, onEn
collapsed={configuredCollapsed}
onToggle={toggleConfigured}
onSelect={onSelect}
+ toggleRef={configuredToggleRef}
/>
<GameGroup
title="LSFG-VK Enabled (Non-Steam)"
diff --git a/src/components/ProfileDetails.tsx b/src/components/ProfileDetails.tsx
index 056abbb..4dd8891 100644
--- a/src/components/ProfileDetails.tsx
+++ b/src/components/ProfileDetails.tsx
@@ -24,12 +24,12 @@ export function ProfileDetails({ description }: ProfileDetailsProps) {
bottomSeparator={expanded ? "none" : "standard"}
onClick={() => setExpanded((value) => !value)}
>
- {expanded ? <RiArrowUpSFill /> : <RiArrowDownSFill />} Details
+ {expanded ? <RiArrowUpSFill /> : <RiArrowDownSFill />} Game Details
</ButtonItem>
</PanelSectionRow>
{expanded && (
<PanelSectionRow>
- <Field label="Details" description={description} />
+ <Field label="Game Details" description={description} />
</PanelSectionRow>
)}
</Focusable>
diff --git a/src/components/WorkaroundsSection.tsx b/src/components/WorkaroundsSection.tsx
index e990784..d783620 100644
--- a/src/components/WorkaroundsSection.tsx
+++ b/src/components/WorkaroundsSection.tsx
@@ -10,7 +10,7 @@ interface WorkaroundsSectionProps {
nonSteam: boolean;
}
-const WORKAROUNDS_COLLAPSED_KEY = "lsfg-workarounds-collapsed";
+const WORKAROUNDS_COLLAPSED_KEY = "lsfg-workarounds-collapsed-v2";
type ToggleWorkaroundField = Exclude<WorkaroundField, "dxvkFrameRate">;
const TOGGLE_ROWS: readonly {
@@ -21,18 +21,25 @@ const TOGGLE_ROWS: readonly {
description: string;
}[] = [
{
+ field: "disableSteamdeckMode",
+ labelKey: "CONFIG_DISABLE_STEAMDECK_MODE",
+ label: "Disable Steam Deck Mode",
+ descriptionKey: "CONFIG_DISABLE_STEAMDECK_MODE_DESC",
+ description: "Disables a game-specific Steam Deck compatibility switch. Requires game restart to apply.",
+ },
+ {
field: "disableGamescopeWsi",
labelKey: "CONFIG_DISABLE_GAMESCOPE_WSI",
label: "Disable Gamescope WSI",
descriptionKey: "CONFIG_DISABLE_GAMESCOPE_WSI_DESC",
- description: "Adds ENABLE_GAMESCOPE_WSI=0 without changing HDR. Requires game restart to apply.",
+ description: "Adds ENABLE_GAMESCOPE_WSI=0. Requires game restart to apply.",
},
{
- field: "disableSteamdeckMode",
- labelKey: "CONFIG_DISABLE_STEAMDECK_MODE",
- label: "Disable Steam Deck Mode",
- descriptionKey: "CONFIG_DISABLE_STEAMDECK_MODE_DESC",
- description: "Disables a game-specific Steam Deck compatibility switch. Requires game restart to apply.",
+ field: "disableHdr",
+ labelKey: "CONFIG_DISABLE_HDR",
+ label: "Disable HDR",
+ descriptionKey: "CONFIG_DISABLE_HDR_DESC",
+ description: "Prevents DXVK from exposing HDR to the game. Requires game restart to apply.",
},
{
field: "disableVkbasalt",