diff options
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | src/components/ConfigurationSection.tsx | 16 | ||||
| -rw-r--r-- | src/components/Content.tsx | 57 | ||||
| -rw-r--r-- | src/components/ProfileManagement.tsx | 175 |
4 files changed, 181 insertions, 69 deletions
diff --git a/package.json b/package.json index 9751add..bcc9af4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "decky-lossless-scaling-vk", - "version": "0.10.1", + "version": "0.10.3", "description": "Use Lossless Scaling on the Steam Deck using the lsfg-vk vulkan layer", "type": "module", "scripts": { diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx index 92d1867..c14a2fd 100644 --- a/src/components/ConfigurationSection.tsx +++ b/src/components/ConfigurationSection.tsx @@ -52,22 +52,6 @@ export function ConfigurationSection({ `} </style> - <PanelSectionRow> - <div - style={{ - fontSize: "14px", - fontWeight: "bold", - marginTop: "16px", - marginBottom: "16px", - borderBottom: "1px solid rgba(255, 255, 255, 0.2)", - paddingBottom: "4px", - color: "white" - }} - > - LSFG Configuration - </div> - </PanelSectionRow> - {/* FPS Multiplier */} <FpsMultiplierControl config={config} onConfigChange={onConfigChange} /> diff --git a/src/components/Content.tsx b/src/components/Content.tsx index 7815951..e0adf3f 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -76,20 +76,25 @@ export function Content() { return ( <PanelSection> - <InstallationButton - isInstalled={isInstalled} - isInstalling={isInstalling} - isUninstalling={isUninstalling} - onInstall={onInstall} - onUninstall={onUninstall} - /> - - <StatusDisplay - dllDetected={dllDetected} - dllDetectionStatus={dllDetectionStatus} - isInstalled={isInstalled} - installationStatus={installationStatus} - /> + {/* Show installation components at top when not fully installed */} + {!isInstalled && ( + <> + <InstallationButton + isInstalled={isInstalled} + isInstalling={isInstalling} + isUninstalling={isUninstalling} + onInstall={onInstall} + onUninstall={onUninstall} + /> + + <StatusDisplay + dllDetected={dllDetected} + dllDetectionStatus={dllDetectionStatus} + isInstalled={isInstalled} + installationStatus={installationStatus} + /> + </> + )} <SmartClipboardButton /> @@ -118,7 +123,29 @@ export function Content() { <ClipboardButton /> {/* Plugin Update Checker */} - <PluginUpdateChecker /> {/* Nerd Stuff Button */} + <PluginUpdateChecker /> + + {/* Show installation components at bottom when fully installed */} + {isInstalled && ( + <> + <InstallationButton + isInstalled={isInstalled} + isInstalling={isInstalling} + isUninstalling={isUninstalling} + onInstall={onInstall} + onUninstall={onUninstall} + /> + + <StatusDisplay + dllDetected={dllDetected} + dllDetectionStatus={dllDetectionStatus} + isInstalled={isInstalled} + installationStatus={installationStatus} + /> + </> + )} + + {/* Nerd Stuff Button */} <PanelSectionRow> <ButtonItem layout="below" diff --git a/src/components/ProfileManagement.tsx b/src/components/ProfileManagement.tsx index 67f0645..6e2a8f8 100644 --- a/src/components/ProfileManagement.tsx +++ b/src/components/ProfileManagement.tsx @@ -1,6 +1,5 @@ import { useState, useEffect } from "react"; import { - PanelSection, PanelSectionRow, Dropdown, DropdownOption, @@ -11,8 +10,11 @@ import { ButtonItem, ModalRoot, TextField, - Focusable + Focusable, + AppOverview, + Router } from "@decky/ui"; +import { RiArrowDownSFill, RiArrowUpSFill } from "react-icons/ri"; import { getProfiles, createProfile, @@ -24,10 +26,7 @@ import { } from "../api/lsfgApi"; import { showSuccessToast, showErrorToast } from "../utils/toastUtils"; -interface ProfileManagementProps { - currentProfile?: string; - onProfileChange?: (profileName: string) => void; -} +const PROFILES_COLLAPSED_KEY = 'lsfg-profiles-collapsed'; interface TextInputModalProps { title: string; @@ -110,6 +109,26 @@ export function ProfileManagement({ currentProfile, onProfileChange }: ProfileMa const [profiles, setProfiles] = useState<string[]>([]); const [selectedProfile, setSelectedProfile] = useState<string>(currentProfile || "decky-lsfg-vk"); const [isLoading, setIsLoading] = useState(false); + const [mainRunningApp, setMainRunningApp] = useState<AppOverview | undefined>(undefined); + + // Initialize with localStorage value, fallback to false (expanded) if not found + const [profilesCollapsed, setProfilesCollapsed] = useState(() => { + try { + const saved = localStorage.getItem(PROFILES_COLLAPSED_KEY); + return saved !== null ? JSON.parse(saved) : false; + } catch { + return false; + } + }); + + // Persist profiles collapse state to localStorage + useEffect(() => { + try { + localStorage.setItem(PROFILES_COLLAPSED_KEY, JSON.stringify(profilesCollapsed)); + } catch (error) { + console.warn('Failed to save profiles collapse state:', error); + } + }, [profilesCollapsed]); // Load profiles on component mount useEffect(() => { @@ -123,6 +142,22 @@ export function ProfileManagement({ currentProfile, onProfileChange }: ProfileMa } }, [currentProfile]); + // Poll for running app every 2 seconds + useEffect(() => { + const checkRunningApp = () => { + setMainRunningApp(Router.MainRunningApp); + }; + + // Check immediately + checkRunningApp(); + + // Set up polling interval + const interval = setInterval(checkRunningApp, 2000); + + // Cleanup interval on unmount + return () => clearInterval(interval); + }, []); + const loadProfiles = async () => { try { const result: ProfilesResult = await getProfiles(); @@ -300,41 +335,107 @@ export function ProfileManagement({ currentProfile, onProfileChange }: ProfileMa ]; return ( - <PanelSection title="Select Profile"> - <PanelSectionRow> - <Field - label="" - childrenLayout="below" - childrenContainerWidth="max" - > - <Dropdown - rgOptions={profileOptions} - selectedOption={selectedProfile} - onChange={handleDropdownChange} - disabled={isLoading} - /> - </Field> - </PanelSectionRow> - + <> + <style> + {` + .LSFG_ProfilesCollapseButton_Container > div > div > div > button { + height: 10px !important; + } + .LSFG_ProfilesCollapseButton_Container > div > div > div > div > button { + height: 10px !important; + } + `} + </style> + + {/* Display currently running game info - always visible */} + {mainRunningApp && ( + <PanelSectionRow> + <div style={{ + padding: "8px 12px", + backgroundColor: "rgba(0, 255, 0, 0.1)", + borderRadius: "4px", + border: "1px solid rgba(0, 255, 0, 0.3)", + fontSize: "13px" + }}> + <strong>{mainRunningApp.display_name}</strong> running. Close game to change profile. + </div> + </PanelSectionRow> + )} + <PanelSectionRow> - <ButtonItem - layout="below" - onClick={handleRenameProfile} - disabled={isLoading || selectedProfile === "decky-lsfg-vk"} + <div + style={{ + fontSize: "14px", + fontWeight: "bold", + marginTop: "16px", + marginBottom: "8px", + borderBottom: "1px solid rgba(255, 255, 255, 0.2)", + paddingBottom: "4px", + color: "white" + }} > - Rename - </ButtonItem> + Profile: {selectedProfile === "decky-lsfg-vk" ? "Default" : selectedProfile} + </div> </PanelSectionRow> - + <PanelSectionRow> - <ButtonItem - layout="below" - onClick={handleDeleteProfile} - disabled={isLoading || selectedProfile === "decky-lsfg-vk"} - > - Delete - </ButtonItem> + <div className="LSFG_ProfilesCollapseButton_Container"> + <ButtonItem + layout="below" + bottomSeparator={profilesCollapsed ? "standard" : "none"} + onClick={() => setProfilesCollapsed(!profilesCollapsed)} + > + {profilesCollapsed ? ( + <RiArrowDownSFill + style={{ transform: "translate(0, -13px)", fontSize: "1.5em" }} + /> + ) : ( + <RiArrowUpSFill + style={{ transform: "translate(0, -12px)", fontSize: "1.5em" }} + /> + )} + </ButtonItem> + </div> </PanelSectionRow> - </PanelSection> + + {!profilesCollapsed && ( + <> + <PanelSectionRow> + <Field + label="" + childrenLayout="below" + childrenContainerWidth="max" + > + <Dropdown + rgOptions={profileOptions} + selectedOption={selectedProfile} + onChange={handleDropdownChange} + disabled={isLoading || !!mainRunningApp} + /> + </Field> + </PanelSectionRow> + + <PanelSectionRow> + <ButtonItem + layout="below" + onClick={handleRenameProfile} + disabled={isLoading || selectedProfile === "decky-lsfg-vk" || !!mainRunningApp} + > + Rename + </ButtonItem> + </PanelSectionRow> + + <PanelSectionRow> + <ButtonItem + layout="below" + onClick={handleDeleteProfile} + disabled={isLoading || selectedProfile === "decky-lsfg-vk" || !!mainRunningApp} + > + Delete + </ButtonItem> + </PanelSectionRow> + </> + )} + </> ); } |
