diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Content.tsx | 2 | ||||
| -rw-r--r-- | src/components/FlatpakTab.tsx | 53 | ||||
| -rw-r--r-- | src/hooks/useFlatpakConfiguration.ts | 23 |
3 files changed, 77 insertions, 1 deletions
diff --git a/src/components/Content.tsx b/src/components/Content.tsx index 91775df..3f25320 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -200,7 +200,9 @@ export function Content() { busyAppId={flatpak.busyAppId} onRefresh={flatpak.reload} onEnable={flatpak.enableApp} + onEnableAll={flatpak.enableAll} onRemove={flatpak.removeApp} + onRemoveAll={flatpak.removeAll} onConfigChange={flatpak.updateConfig} onWorkaroundChange={flatpak.updateWorkarounds} />, diff --git a/src/components/FlatpakTab.tsx b/src/components/FlatpakTab.tsx index 0b20da0..35721f6 100644 --- a/src/components/FlatpakTab.tsx +++ b/src/components/FlatpakTab.tsx @@ -1,4 +1,4 @@ -import { ButtonItem, DialogButton, Field, Focusable, PanelSection, PanelSectionRow, gamepadDialogClasses } from "@decky/ui"; +import { ButtonItem, ConfirmModal, DialogButton, Field, Focusable, PanelSection, PanelSectionRow, gamepadDialogClasses, showModal } from "@decky/ui"; import { useCallback, useMemo, useState } from "react"; import { FaArrowLeft } from "react-icons/fa"; import type { FlatpakApp, LsfgConfig, WorkaroundState } from "../api/lsfgApi"; @@ -15,7 +15,9 @@ interface Props { busyAppId: string; onRefresh: () => Promise<void>; onEnable: (appId: string) => Promise<boolean>; + onEnableAll: () => Promise<void>; onRemove: (appId: string) => Promise<boolean>; + onRemoveAll: () => Promise<void>; onConfigChange: (appId: string, config: LsfgConfig) => Promise<boolean>; onWorkaroundChange: (appId: string, state: WorkaroundState) => Promise<boolean>; } @@ -30,7 +32,9 @@ export function FlatpakTab({ busyAppId, onRefresh, onEnable, + onEnableAll, onRemove, + onRemoveAll, onConfigChange, onWorkaroundChange, }: Props) { @@ -51,6 +55,33 @@ export function FlatpakTab({ () => apps.filter((app) => !app.enabled).sort((a, b) => a.app_name.localeCompare(b.app_name)), [apps], ); + const enableableApps = useMemo( + () => availableApps.filter((app) => !(app.prepared && !app.owned) && !app.error), + [availableApps], + ); + const confirmEnableAll = () => { + showModal( + <ConfirmModal + strTitle="Enable all available Flatpaks?" + strDescription="Create individual LSFG-VK profiles for every Flatpak app this plugin can manage. Apps prepared externally or unavailable will be skipped." + strOKButtonText="Enable all" + strCancelButtonText="Cancel" + onOK={() => void onEnableAll()} + onCancel={() => {}} + />, + ); + }; + const confirmRemoveAll = () => { + showModal( + <ConfirmModal + strTitle="Remove all Flatpak profiles?" + strOKButtonText="Remove all" + strCancelButtonText="Cancel" + onOK={() => void onRemoveAll()} + onCancel={() => {}} + />, + ); + }; const itemFor = (app: FlatpakApp) => ({ id: app.app_id, label: app.app_name, @@ -79,6 +110,26 @@ export function FlatpakTab({ onToggle={toggleAvailable} onSelect={setSelectedAppId} /> + {enableableApps.length > 0 && ( + <PanelSectionRow> + <ButtonItem + layout="below" + disabled={loading || Boolean(busyAppId)} + onClick={confirmEnableAll} + > + Enable all available Flatpaks + </ButtonItem> + </PanelSectionRow> + )} + <PanelSectionRow> + <ButtonItem + layout="below" + disabled={loading || Boolean(busyAppId) || enabledApps.length === 0} + onClick={confirmRemoveAll} + > + Remove all profiles + </ButtonItem> + </PanelSectionRow> {apps.length === 0 && !loading && ( <PanelSectionRow> <Field label="No Flatpak applications found" /> diff --git a/src/hooks/useFlatpakConfiguration.ts b/src/hooks/useFlatpakConfiguration.ts index 6ff7a79..f936271 100644 --- a/src/hooks/useFlatpakConfiguration.ts +++ b/src/hooks/useFlatpakConfiguration.ts @@ -95,6 +95,27 @@ export function useFlatpakConfiguration(enabled: boolean) { const removeApp = useCallback(async (appId: string) => ( await operate(appId, () => removeFlatpakApp(appId)) ).success, [operate]); + const enableAll = useCallback(async (): Promise<void> => { + if (busyAppId) return; + const available = apps.filter((app) => ( + !app.enabled && !(app.prepared && !app.owned) && !app.error + )); + for (const app of available) { + const result = await operate(app.app_id, () => enableFlatpakApp(app.app_id), false); + if (!result.success) break; + } + await reload(); + await pollRunning(); + }, [apps, busyAppId, operate, pollRunning, reload]); + const removeAll = useCallback(async (): Promise<void> => { + if (busyAppId) return; + for (const app of apps.filter((item) => item.enabled)) { + const result = await operate(app.app_id, () => removeFlatpakApp(app.app_id), false); + if (!result.success) break; + } + await reload(); + await pollRunning(); + }, [apps, busyAppId, operate, pollRunning, reload]); const updateConfig = useCallback( async (appId: string, config: LsfgConfig) => { const result = await operate(appId, () => updateFlatpakConfig(appId, config), false); @@ -130,7 +151,9 @@ export function useFlatpakConfiguration(enabled: boolean) { busyAppId, reload, enableApp, + enableAll, removeApp, + removeAll, updateConfig, updateWorkarounds, }; |
