From 1dfb2db3cc65f83e07ea891f1da6096ed92d9d0b Mon Sep 17 00:00:00 2001 From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Date: Thu, 10 Sep 2026 15:45:58 -0400 Subject: feat: add explicit flatpak setup --- src/components/FlatpakSetupSection.tsx | 110 +++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/components/FlatpakSetupSection.tsx (limited to 'src') diff --git a/src/components/FlatpakSetupSection.tsx b/src/components/FlatpakSetupSection.tsx new file mode 100644 index 0000000..0119250 --- /dev/null +++ b/src/components/FlatpakSetupSection.tsx @@ -0,0 +1,110 @@ +import { ButtonItem, Field, PanelSection, PanelSectionRow } from "@decky/ui"; +import { useCallback, useEffect, useState } from "react"; +import { + getFlatpakApps, + prepareFlatpakApp, + removeFlatpakApp, + type FlatpakApp, +} from "../api/lsfgApi"; +import { showErrorToast } from "../utils/toastUtils"; + +interface Props { + enabled: boolean; +} + +export function FlatpakSetupSection({ enabled }: Props) { + const [apps, setApps] = useState([]); + const [loading, setLoading] = useState(false); + const [busyApp, setBusyApp] = useState(""); + const [error, setError] = useState(null); + + const load = useCallback(async () => { + if (!enabled) { + setApps([]); + setError(null); + return; + } + setLoading(true); + try { + const result = await getFlatpakApps(); + if (!result.success) throw new Error(result.error || "Could not list Flatpak applications"); + setApps(result.apps || []); + setError(null); + } catch (loadError) { + const message = loadError instanceof Error ? loadError.message : String(loadError); + setError(message); + } finally { + setLoading(false); + } + }, [enabled]); + + useEffect(() => { + void load(); + }, [load]); + + const toggle = async (app: FlatpakApp) => { + if (busyApp || (app.prepared && !app.owned)) return; + setBusyApp(app.app_id); + try { + const result = app.prepared + ? await removeFlatpakApp(app.app_id) + : await prepareFlatpakApp(app.app_id); + if (!result.success) throw new Error(result.error || "Flatpak setup failed"); + await load(); + } catch (operationError) { + const message = operationError instanceof Error ? operationError.message : String(operationError); + showErrorToast("Flatpak setup failed", message); + } finally { + setBusyApp(""); + } + }; + + if (!enabled) return null; + + return ( + + + + + {error && ( + + + + )} + {apps.map((app) => { + const busy = busyApp === app.app_id; + const description = [ + app.app_id, + app.runtime_branch ? `runtime ${app.runtime_branch}` : null, + app.error, + ].filter(Boolean).join(" ยท "); + const label = busy + ? "Working..." + : app.prepared + ? app.owned ? "Remove" : "Prepared externally" + : app.error ? "Unavailable" : "Prepare"; + return ( + + + void toggle(app)} + > + {label} + + + + ); + })} + + void load()}> + {loading ? "Refreshing..." : "Refresh Flatpaks"} + + + + ); +} -- cgit v1.2.3