1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
import {
useState,
// useEffect
} from "react";
import {
PanelSection,
PanelSectionRow,
ButtonItem,
// Dropdown,
// DropdownOption
} from "@decky/ui";
import { definePlugin, callable } from "@decky/api";
import { FaShip } from "react-icons/fa";
// "run_install_fgmod" corresponds to the Python method run_install_fgmod()
const runInstallFGMod = callable<
[],
{ status: string; message?: string; output?: string }
>("run_install_fgmod");
// "get_installed_games" corresponds to the Python method get_installed_games()
// const fetchInstalledGames = callable<[], string>("get_installed_games");
function FGModInstallerSection() {
const [installing, setInstalling] = useState(false);
const [installResult, setInstallResult] = useState<{
status: string;
output?: string;
message?: string;
} | null>(null);
const handleInstallClick = async () => {
setInstalling(true);
const result = await runInstallFGMod();
setInstalling(false);
setInstallResult(result);
};
return (
<PanelSection title="FG Mod Installer">
<PanelSectionRow>
<ButtonItem layout="below" onClick={handleInstallClick} disabled={installing}>
{installing ? "Installing..." : "Install FG Mod"}
</ButtonItem>
</PanelSectionRow>
{installResult && (
<PanelSectionRow>
<div>
<strong>Status:</strong>{" "}
{installResult.status === "success" ? "Success" : "Error"}
<br />
{installResult.output && (
<>
<strong>Output:</strong>
<pre style={{ whiteSpace: "pre-wrap" }}>{installResult.output}</pre>
</>
)}
{installResult.message && (
<>
<strong>Error:</strong> {installResult.message}
</>
)}
</div>
</PanelSectionRow>
)}
</PanelSection>
);
}
// function GameSelectorSection() {
// const [games, setGames] = useState<DropdownOption[]>([]);
// const [selectedGame, setSelectedGame] = useState<DropdownOption | null>(null);
// useEffect(() => {
// const loadGames = async () => {
// const result = await fetchInstalledGames();
// const gameList = JSON.parse(result) as { appid: string; name: string }[];
// setGames(gameList.map((g) => ({ data: g.appid, label: g.name })));
// };
// loadGames();
// }, []);
// return (
// <PanelSection title="Installed Games">
// <PanelSectionRow>
// <Dropdown
// rgOptions={games}
// selectedOption={selectedGame?.data || null}
// onChange={(option) => setSelectedGame(option)}
// strDefaultLabel="Select a game"
// />
// </PanelSectionRow>
// {selectedGame && (
// <PanelSectionRow>
// <div>You selected: {selectedGame.label}</div>
// </PanelSectionRow>
// )}
// </PanelSection>
// );
// }
function MainContent() {
return (
<>
<FGModInstallerSection />
{/* <GameSelectorSection /> */}
</>
);
}
// One default export, one plugin
export default definePlugin(() => ({
name: "Framegen Plugin",
titleView: <div>Framegen Plugin</div>,
content: <MainContent />,
icon: <FaShip />,
onDismount() {
console.log("Framegen Plugin unmounted");
},
}));
|