From 0da3682755e551a7d3c23fa979686d8dbcdd4f7b Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Mon, 22 Sep 2025 09:38:20 -0400 Subject: bring forward old flatpak modal attempt --- src/api/lsfgApi.ts | 40 ++++++ src/components/Content.tsx | 15 ++ src/components/FlatpaksModal.tsx | 291 +++++++++++++++++++++++++++++++++++++++ src/components/index.ts | 1 + 4 files changed, 347 insertions(+) (limited to 'src') 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(); }; + const handleShowFlatpaks = () => { + showModal(); + }; + return ( {/* Show installation components at top when not fully installed */} @@ -165,6 +170,16 @@ export function Content() { Nerd Stuff + + {/* Flatpaks Button */} + + + Flatpaks + + ); } 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 = ({ closeModal }) => { + const [extensionStatus, setExtensionStatus] = useState(null); + const [flatpakApps, setFlatpakApps] = useState(null); + const [loading, setLoading] = useState(true); + const [operationInProgress, setOperationInProgress] = useState(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( + {}} + /> + ); + }; + + if (loading) { + return ( + + Flatpak Extensions + +
+ +
+
+
+ ); + } + + return ( + + Flatpak Extensions + + + {/* Extension Status Section */} + + Runtime Extensions + + {extensionStatus && extensionStatus.success ? ( + <> + {/* 23.08 Runtime */} + + : } + > + { + 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' ? ( + + ) : extensionStatus.installed_23_08 ? ( + <> + Uninstall + + ) : ( + <> + Install + + )} + + + + + {/* 24.08 Runtime */} + + : } + > + { + 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' ? ( + + ) : extensionStatus.installed_24_08 ? ( + <> + Uninstall + + ) : ( + <> + Install + + )} + + + + + ) : ( + + } + /> + + )} + + + {/* Flatpak Apps Section */} + + Flatpak Applications + + {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 ( + + } + > + handleAppOverrideToggle(app)} + disabled={operationInProgress === `app-${app.app_id}`} + /> + + + ); + }) + ) : ( + + + + ) + ) : ( + + } + /> + + )} + + + + + ); +}; + +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"; -- cgit v1.2.3