import { useState, useEffect } from "react";
import {
PanelSection,
PanelSectionRow,
Dropdown,
DropdownOption,
showModal,
ConfirmModal,
Field,
DialogButton,
Focusable,
ModalRoot,
TextField
} from "@decky/ui";
import {
getProfiles,
createProfile,
deleteProfile,
renameProfile,
setCurrentProfile,
ProfilesResult,
ProfileResult
} from "../api/lsfgApi";
import { showSuccessToast, showErrorToast } from "../utils/toastUtils";
interface ProfileManagementProps {
currentProfile?: string;
onProfileChange?: (profileName: string) => void;
}
interface TextInputModalProps {
title: string;
description: string;
defaultValue?: string;
okText?: string;
cancelText?: string;
onOK: (value: string) => void;
closeModal?: () => void;
}
function TextInputModal({
title,
description,
defaultValue = "",
okText = "OK",
cancelText = "Cancel",
onOK,
closeModal
}: TextInputModalProps) {
const [value, setValue] = useState(defaultValue);
const handleOK = () => {
onOK(value);
closeModal?.();
};
return (
{title}
{description}
setValue(e?.target?.value || "")}
/>
{okText}
{cancelText}
);
}
interface ProfileManagementProps {
currentProfile?: string;
onProfileChange?: (profileName: string) => void;
}
export function ProfileManagement({ currentProfile, onProfileChange }: ProfileManagementProps) {
const [profiles, setProfiles] = useState([]);
const [selectedProfile, setSelectedProfile] = useState(currentProfile || "decky-lsfg-vk");
const [isLoading, setIsLoading] = useState(false);
// Load profiles on component mount
useEffect(() => {
loadProfiles();
}, []);
// Update selected profile when prop changes
useEffect(() => {
if (currentProfile) {
setSelectedProfile(currentProfile);
}
}, [currentProfile]);
const loadProfiles = async () => {
try {
const result: ProfilesResult = await getProfiles();
if (result.success && result.profiles) {
setProfiles(result.profiles);
if (result.current_profile) {
setSelectedProfile(result.current_profile);
}
} else {
console.error("Failed to load profiles:", result.error);
showErrorToast("Failed to load profiles", result.error || "Unknown error");
}
} catch (error) {
console.error("Error loading profiles:", error);
showErrorToast("Error loading profiles", String(error));
}
};
const handleProfileChange = async (profileName: string) => {
setIsLoading(true);
try {
const result: ProfileResult = await setCurrentProfile(profileName);
if (result.success) {
setSelectedProfile(profileName);
showSuccessToast("Profile switched", `Switched to profile: ${profileName}`);
onProfileChange?.(profileName);
} else {
console.error("Failed to switch profile:", result.error);
showErrorToast("Failed to switch profile", result.error || "Unknown error");
}
} catch (error) {
console.error("Error switching profile:", error);
showErrorToast("Error switching profile", String(error));
} finally {
setIsLoading(false);
}
};
const handleCreateProfile = () => {
showModal(
{
if (name.trim()) {
createNewProfile(name.trim());
}
}}
/>
);
};
const createNewProfile = async (profileName: string) => {
setIsLoading(true);
try {
const result: ProfileResult = await createProfile(profileName, selectedProfile);
if (result.success) {
showSuccessToast("Profile created", `Created profile: ${profileName}`);
await loadProfiles();
} else {
console.error("Failed to create profile:", result.error);
showErrorToast("Failed to create profile", result.error || "Unknown error");
}
} catch (error) {
console.error("Error creating profile:", error);
showErrorToast("Error creating profile", String(error));
} finally {
setIsLoading(false);
}
};
const handleDeleteProfile = () => {
if (selectedProfile === "decky-lsfg-vk") {
showErrorToast("Cannot delete default profile", "The default profile cannot be deleted");
return;
}
showModal(
deleteSelectedProfile()}
/>
);
};
const deleteSelectedProfile = async () => {
setIsLoading(true);
try {
const result: ProfileResult = await deleteProfile(selectedProfile);
if (result.success) {
showSuccessToast("Profile deleted", `Deleted profile: ${selectedProfile}`);
await loadProfiles();
// If we deleted the current profile, it should have switched to default
setSelectedProfile("decky-lsfg-vk");
onProfileChange?.("decky-lsfg-vk");
} else {
console.error("Failed to delete profile:", result.error);
showErrorToast("Failed to delete profile", result.error || "Unknown error");
}
} catch (error) {
console.error("Error deleting profile:", error);
showErrorToast("Error deleting profile", String(error));
} finally {
setIsLoading(false);
}
};
const handleRenameProfile = () => {
if (selectedProfile === "decky-lsfg-vk") {
showErrorToast("Cannot rename default profile", "The default profile cannot be renamed");
return;
}
showModal(
{
if (newName.trim() && newName.trim() !== selectedProfile) {
renameSelectedProfile(newName.trim());
}
}}
/>
);
};
const renameSelectedProfile = async (newName: string) => {
setIsLoading(true);
try {
const result: ProfileResult = await renameProfile(selectedProfile, newName);
if (result.success) {
showSuccessToast("Profile renamed", `Renamed profile to: ${newName}`);
await loadProfiles();
setSelectedProfile(newName);
onProfileChange?.(newName);
} else {
console.error("Failed to rename profile:", result.error);
showErrorToast("Failed to rename profile", result.error || "Unknown error");
}
} catch (error) {
console.error("Error renaming profile:", error);
showErrorToast("Error renaming profile", String(error));
} finally {
setIsLoading(false);
}
};
const profileOptions: DropdownOption[] = profiles.map(profile => ({
data: profile,
label: profile === "decky-lsfg-vk" ? `${profile} (default)` : profile
}));
return (
handleProfileChange(option.data)}
disabled={isLoading}
/>
New Profile
Rename
Delete
);
}