summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2025-09-22 09:38:20 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2025-09-22 09:38:20 -0400
commit0da3682755e551a7d3c23fa979686d8dbcdd4f7b (patch)
treef07d360ebaeefba28fe5b5be730c807ce337bddc /src
parent84de5901cd1fb7d89031e4e7b3b47ed805e324c8 (diff)
downloaddecky-lsfg-vk-0da3682755e551a7d3c23fa979686d8dbcdd4f7b.tar.gz
decky-lsfg-vk-0da3682755e551a7d3c23fa979686d8dbcdd4f7b.zip
bring forward old flatpak modal attempt
Diffstat (limited to 'src')
-rw-r--r--src/api/lsfgApi.ts40
-rw-r--r--src/components/Content.tsx15
-rw-r--r--src/components/FlatpaksModal.tsx291
-rw-r--r--src/components/index.ts1
4 files changed, 347 insertions, 0 deletions
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts
index 8db0c82..d08cd42 100644
--- a/src/api/lsfgApi.ts
+++ b/src/api/lsfgApi.ts
@@ -96,6 +96,38 @@ export interface FgmodCheckResult {
error?: string;
}
+// Flatpak management interfaces
+export interface FlatpakExtensionStatus {
+ success: boolean;
+ message: string;
+ error?: string;
+ installed_23_08: boolean;
+ installed_24_08: boolean;
+}
+
+export interface FlatpakApp {
+ app_id: string;
+ app_name: string;
+ has_filesystem_override: boolean;
+ has_env_override: boolean;
+}
+
+export interface FlatpakAppInfo {
+ success: boolean;
+ message: string;
+ error?: string;
+ apps: FlatpakApp[];
+ total_apps: number;
+}
+
+export interface FlatpakOperationResult {
+ success: boolean;
+ message: string;
+ error?: string;
+ app_id?: string;
+ operation?: string;
+}
+
// Profile management interfaces
export interface ProfilesResult {
success: boolean;
@@ -125,6 +157,14 @@ export const getConfigFileContent = callable<[], FileContentResult>("get_config_
export const getLaunchScriptContent = callable<[], FileContentResult>("get_launch_script_content");
export const checkFgmodDirectory = callable<[], FgmodCheckResult>("check_fgmod_directory");
+// Flatpak management API functions
+export const checkFlatpakExtensionStatus = callable<[], FlatpakExtensionStatus>("check_flatpak_extension_status");
+export const installFlatpakExtension = callable<[string], FlatpakOperationResult>("install_flatpak_extension");
+export const uninstallFlatpakExtension = callable<[string], FlatpakOperationResult>("uninstall_flatpak_extension");
+export const getFlatpakApps = callable<[], FlatpakAppInfo>("get_flatpak_apps");
+export const setFlatpakAppOverride = callable<[string], FlatpakOperationResult>("set_flatpak_app_override");
+export const removeFlatpakAppOverride = callable<[string], FlatpakOperationResult>("remove_flatpak_app_override");
+
// Updated config function using object-based configuration (single source of truth)
export const updateLsfgConfig = callable<
[ConfigurationData],
diff --git a/src/components/Content.tsx b/src/components/Content.tsx
index a00a595..b76ff59 100644
--- a/src/components/Content.tsx
+++ b/src/components/Content.tsx
@@ -15,6 +15,7 @@ import { FgmodClipboardButton } from "./FgmodClipboardButton";
// import { ClipboardDisplay } from "./ClipboardDisplay";
import { PluginUpdateChecker } from "./PluginUpdateChecker";
import { NerdStuffModal } from "./NerdStuffModal";
+import { FlatpaksModal } from "./index";
import { ConfigurationData } from "../config/configSchema";
export function Content() {
@@ -76,6 +77,10 @@ export function Content() {
showModal(<NerdStuffModal />);
};
+ const handleShowFlatpaks = () => {
+ showModal(<FlatpaksModal />);
+ };
+
return (
<PanelSection>
{/* Show installation components at top when not fully installed */}
@@ -165,6 +170,16 @@ export function Content() {
Nerd Stuff
</ButtonItem>
</PanelSectionRow>
+
+ {/* Flatpaks Button */}
+ <PanelSectionRow>
+ <ButtonItem
+ layout="below"
+ onClick={handleShowFlatpaks}
+ >
+ Flatpaks
+ </ButtonItem>
+ </PanelSectionRow>
</PanelSection>
);
}
diff --git a/src/components/FlatpaksModal.tsx b/src/components/FlatpaksModal.tsx
index e69de29..a57c683 100644
--- a/src/components/FlatpaksModal.tsx
+++ b/src/components/FlatpaksModal.tsx
@@ -0,0 +1,291 @@
+import { FC, useState, useEffect } from 'react';
+import {
+ ModalRoot,
+ DialogBody,
+ DialogHeader,
+ DialogControlsSection,
+ DialogControlsSectionHeader,
+ ButtonItem,
+ PanelSectionRow,
+ Field,
+ Toggle,
+ Spinner,
+ Focusable,
+ showModal,
+ ConfirmModal
+} from '@decky/ui';
+import { FaCheck, FaTimes, FaDownload, FaTrash, FaCog } from 'react-icons/fa';
+import {
+ checkFlatpakExtensionStatus,
+ installFlatpakExtension,
+ uninstallFlatpakExtension,
+ getFlatpakApps,
+ setFlatpakAppOverride,
+ removeFlatpakAppOverride,
+ FlatpakExtensionStatus,
+ FlatpakApp,
+ FlatpakAppInfo
+} from '../api/lsfgApi';
+
+interface FlatpaksModalProps {
+ closeModal?: () => void;
+}
+
+const FlatpaksModal: FC<FlatpaksModalProps> = ({ closeModal }) => {
+ const [extensionStatus, setExtensionStatus] = useState<FlatpakExtensionStatus | null>(null);
+ const [flatpakApps, setFlatpakApps] = useState<FlatpakAppInfo | null>(null);
+ const [loading, setLoading] = useState(true);
+ const [operationInProgress, setOperationInProgress] = useState<string | null>(null);
+
+ const loadData = async () => {
+ setLoading(true);
+ try {
+ const [statusResult, appsResult] = await Promise.all([
+ checkFlatpakExtensionStatus(),
+ getFlatpakApps()
+ ]);
+
+ setExtensionStatus(statusResult);
+ setFlatpakApps(appsResult);
+ } catch (error) {
+ console.error('Error loading Flatpak data:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ loadData();
+ }, []);
+
+ const handleExtensionOperation = async (operation: 'install' | 'uninstall', version: string) => {
+ const operationId = `${operation}-${version}`;
+ setOperationInProgress(operationId);
+
+ try {
+ const result = operation === 'install'
+ ? await installFlatpakExtension(version)
+ : await uninstallFlatpakExtension(version);
+
+ if (result.success) {
+ // Reload status after operation
+ const newStatus = await checkFlatpakExtensionStatus();
+ setExtensionStatus(newStatus);
+ }
+ } catch (error) {
+ console.error(`Error ${operation}ing extension:`, error);
+ } finally {
+ setOperationInProgress(null);
+ }
+ };
+
+ const handleAppOverrideToggle = async (app: FlatpakApp) => {
+ const hasOverrides = app.has_filesystem_override && app.has_env_override;
+ const operationId = `app-${app.app_id}`;
+ setOperationInProgress(operationId);
+
+ try {
+ const result = hasOverrides
+ ? await removeFlatpakAppOverride(app.app_id)
+ : await setFlatpakAppOverride(app.app_id);
+
+ if (result.success) {
+ // Reload apps data after operation
+ const newApps = await getFlatpakApps();
+ setFlatpakApps(newApps);
+ }
+ } catch (error) {
+ console.error('Error toggling app override:', error);
+ } finally {
+ setOperationInProgress(null);
+ }
+ };
+
+ const confirmOperation = (operation: () => void, title: string, description: string) => {
+ showModal(
+ <ConfirmModal
+ strTitle={title}
+ strDescription={description}
+ onOK={operation}
+ onCancel={() => {}}
+ />
+ );
+ };
+
+ if (loading) {
+ return (
+ <ModalRoot closeModal={closeModal}>
+ <DialogHeader>Flatpak Extensions</DialogHeader>
+ <DialogBody>
+ <div style={{ display: 'flex', justifyContent: 'center', padding: '20px' }}>
+ <Spinner />
+ </div>
+ </DialogBody>
+ </ModalRoot>
+ );
+ }
+
+ return (
+ <ModalRoot closeModal={closeModal}>
+ <DialogHeader>Flatpak Extensions</DialogHeader>
+ <DialogBody>
+ <Focusable>
+ {/* Extension Status Section */}
+ <DialogControlsSection>
+ <DialogControlsSectionHeader>Runtime Extensions</DialogControlsSectionHeader>
+
+ {extensionStatus && extensionStatus.success ? (
+ <>
+ {/* 23.08 Runtime */}
+ <PanelSectionRow>
+ <Field
+ label="Runtime 23.08"
+ description={extensionStatus.installed_23_08 ? "Installed" : "Not installed"}
+ icon={extensionStatus.installed_23_08 ? <FaCheck style={{color: 'green'}} /> : <FaTimes style={{color: 'red'}} />}
+ >
+ <ButtonItem
+ layout="below"
+ onClick={() => {
+ const operation = extensionStatus.installed_23_08 ? 'uninstall' : 'install';
+ const action = () => handleExtensionOperation(operation, '23.08');
+
+ if (operation === 'uninstall') {
+ confirmOperation(
+ action,
+ 'Uninstall Runtime Extension',
+ 'Are you sure you want to uninstall the 23.08 runtime extension?'
+ );
+ } else {
+ action();
+ }
+ }}
+ disabled={operationInProgress === 'install-23.08' || operationInProgress === 'uninstall-23.08'}
+ >
+ {operationInProgress === 'install-23.08' || operationInProgress === 'uninstall-23.08' ? (
+ <Spinner />
+ ) : extensionStatus.installed_23_08 ? (
+ <>
+ <FaTrash /> Uninstall
+ </>
+ ) : (
+ <>
+ <FaDownload /> Install
+ </>
+ )}
+ </ButtonItem>
+ </Field>
+ </PanelSectionRow>
+
+ {/* 24.08 Runtime */}
+ <PanelSectionRow>
+ <Field
+ label="Runtime 24.08"
+ description={extensionStatus.installed_24_08 ? "Installed" : "Not installed"}
+ icon={extensionStatus.installed_24_08 ? <FaCheck style={{color: 'green'}} /> : <FaTimes style={{color: 'red'}} />}
+ >
+ <ButtonItem
+ layout="below"
+ onClick={() => {
+ const operation = extensionStatus.installed_24_08 ? 'uninstall' : 'install';
+ const action = () => handleExtensionOperation(operation, '24.08');
+
+ if (operation === 'uninstall') {
+ confirmOperation(
+ action,
+ 'Uninstall Runtime Extension',
+ 'Are you sure you want to uninstall the 24.08 runtime extension?'
+ );
+ } else {
+ action();
+ }
+ }}
+ disabled={operationInProgress === 'install-24.08' || operationInProgress === 'uninstall-24.08'}
+ >
+ {operationInProgress === 'install-24.08' || operationInProgress === 'uninstall-24.08' ? (
+ <Spinner />
+ ) : extensionStatus.installed_24_08 ? (
+ <>
+ <FaTrash /> Uninstall
+ </>
+ ) : (
+ <>
+ <FaDownload /> Install
+ </>
+ )}
+ </ButtonItem>
+ </Field>
+ </PanelSectionRow>
+ </>
+ ) : (
+ <PanelSectionRow>
+ <Field
+ label="Error"
+ description={extensionStatus?.error || 'Failed to check extension status'}
+ icon={<FaTimes style={{color: 'red'}} />}
+ />
+ </PanelSectionRow>
+ )}
+ </DialogControlsSection>
+
+ {/* Flatpak Apps Section */}
+ <DialogControlsSection>
+ <DialogControlsSectionHeader>Flatpak Applications</DialogControlsSectionHeader>
+
+ {flatpakApps && flatpakApps.success ? (
+ flatpakApps.apps.length > 0 ? (
+ flatpakApps.apps.map((app) => {
+ const hasOverrides = app.has_filesystem_override && app.has_env_override;
+ const partialOverrides = app.has_filesystem_override || app.has_env_override;
+
+ let statusColor = 'red';
+ let statusText = 'No overrides';
+
+ if (hasOverrides) {
+ statusColor = 'green';
+ statusText = 'Configured';
+ } else if (partialOverrides) {
+ statusColor = 'orange';
+ statusText = 'Partial';
+ }
+
+ return (
+ <PanelSectionRow key={app.app_id}>
+ <Field
+ label={app.app_name || app.app_id}
+ description={`${app.app_id} - ${statusText}`}
+ icon={<FaCog style={{color: statusColor}} />}
+ >
+ <Toggle
+ value={hasOverrides}
+ onChange={() => handleAppOverrideToggle(app)}
+ disabled={operationInProgress === `app-${app.app_id}`}
+ />
+ </Field>
+ </PanelSectionRow>
+ );
+ })
+ ) : (
+ <PanelSectionRow>
+ <Field
+ label="No Flatpak Apps Found"
+ description="No Flatpak applications are currently installed"
+ />
+ </PanelSectionRow>
+ )
+ ) : (
+ <PanelSectionRow>
+ <Field
+ label="Error"
+ description={flatpakApps?.error || 'Failed to load Flatpak applications'}
+ icon={<FaTimes style={{color: 'red'}} />}
+ />
+ </PanelSectionRow>
+ )}
+ </DialogControlsSection>
+ </Focusable>
+ </DialogBody>
+ </ModalRoot>
+ );
+};
+
+export default FlatpaksModal;
diff --git a/src/components/index.ts b/src/components/index.ts
index 802cd3c..50480be 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -10,4 +10,5 @@ export { FgmodClipboardButton } from "./FgmodClipboardButton";
// export { ClipboardDisplay } from "./ClipboardDisplay";
export { PluginUpdateChecker } from "./PluginUpdateChecker";
export { NerdStuffModal } from "./NerdStuffModal";
+export { default as FlatpaksModal } from "./FlatpaksModal";
export { ProfileManagement } from "./ProfileManagement";