summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py_modules/lsfg_vk/flatpak_service.py76
-rw-r--r--py_modules/lsfg_vk/plugin.py3
-rw-r--r--src/api/lsfgApi.ts17
-rw-r--r--src/components/SetupTab.tsx76
-rw-r--r--tests/test_flatpak_service.py26
5 files changed, 33 insertions, 165 deletions
diff --git a/py_modules/lsfg_vk/flatpak_service.py b/py_modules/lsfg_vk/flatpak_service.py
index c0a9c0c..11f1a82 100644
--- a/py_modules/lsfg_vk/flatpak_service.py
+++ b/py_modules/lsfg_vk/flatpak_service.py
@@ -202,11 +202,8 @@ class FlatpakService(BaseService):
extension_id=self.EXTENSION_ID,
supported_branches=list(self.SUPPORTED_RUNTIMES),
installed_branches=[],
- owned_branches=[],
- ownership_uncertain=False,
)
installed = self._installed_extension_branches()
- owned, uncertain = self._read_owned_branches()
return self._success_response(
dict,
"Flatpak runtime extension status retrieved",
@@ -214,8 +211,6 @@ class FlatpakService(BaseService):
extension_id=self.EXTENSION_ID,
supported_branches=list(self.SUPPORTED_RUNTIMES),
installed_branches=sorted(installed),
- owned_branches=sorted(owned),
- ownership_uncertain=uncertain,
)
except Exception as error:
return self._error_response(
@@ -225,8 +220,6 @@ class FlatpakService(BaseService):
extension_id=self.EXTENSION_ID,
supported_branches=list(self.SUPPORTED_RUNTIMES),
installed_branches=[],
- owned_branches=[],
- ownership_uncertain=False,
)
def get_flatpak_support_status(self) -> Dict[str, Any]:
@@ -294,18 +287,12 @@ class FlatpakService(BaseService):
)
def install_extension(self, version: str) -> Dict[str, Any]:
- """Install one missing branch and record ownership only after readback."""
+ """Install one branch, treating an already-installed branch as success."""
try:
version = self._validate_runtime(version)
if not self.check_flatpak_available():
raise FileNotFoundError("Flatpak is not available on this system")
with self._lock:
- owned, uncertain = self._read_owned_branches()
- if uncertain:
- raise RuntimeError(
- "Flatpak ownership metadata is uncertain; refusing to install "
- "until it is repaired"
- )
installed_before = self._installed_extension_branches()
if version in installed_before:
return self._success_response(
@@ -314,8 +301,6 @@ class FlatpakService(BaseService):
runtime_branch=version,
installed=True,
enabled=True,
- owned_by_plugin=version in owned,
- preserved=version not in owned,
)
bundle_path = self._bundled_extension_path(version)
if not bundle_path.is_file():
@@ -341,16 +326,16 @@ class FlatpakService(BaseService):
f"Flatpak install completed but {self._extension_ref(version)} "
"was not visible afterwards"
)
- owned.add(version)
- self._write_owned_branches(owned)
+ owned, uncertain = self._read_owned_branches()
+ if not uncertain:
+ owned.add(version)
+ self._write_owned_branches(owned)
return self._success_response(
dict,
f"lsfg-vk {version} runtime extension installed",
runtime_branch=version,
installed=True,
enabled=True,
- owned_by_plugin=True,
- preserved=False,
)
except Exception as error:
return self._error_response(
@@ -359,8 +344,6 @@ class FlatpakService(BaseService):
runtime_branch=version,
installed=False,
enabled=False,
- owned_by_plugin=False,
- preserved=False,
)
def ensure_extension(self, version: str) -> Dict[str, Any]:
@@ -384,7 +367,6 @@ class FlatpakService(BaseService):
f"lsfg-vk {version} runtime extension is ready",
runtime_branch=version,
installed=True,
- owned_by_plugin=version in status.get("owned_branches", []),
)
return self.install_extension(version)
@@ -419,41 +401,15 @@ class FlatpakService(BaseService):
)
def uninstall_extension(self, version: str) -> Dict[str, Any]:
- """Uninstall only when explicitly requested for a plugin-owned branch."""
+ """Uninstall one branch, treating an already-absent branch as success."""
try:
version = self._validate_runtime(version)
if not self.check_flatpak_available():
raise FileNotFoundError("Flatpak is not available on this system")
with self._lock:
- owned, uncertain = self._read_owned_branches()
- if uncertain:
- raise RuntimeError(
- "Flatpak ownership metadata is uncertain; refusing to uninstall"
- )
installed = self._installed_extension_branches()
- if version not in owned:
- if version in installed:
- return self._success_response(
- dict,
- f"Preserved Flatpak extension {version}; it is not plugin-owned",
- runtime_branch=version,
- removed=False,
- installed=True,
- enabled=True,
- owned_by_plugin=False,
- preserved=True,
- )
- return self._success_response(
- dict,
- f"Flatpak extension {version} is already not installed",
- runtime_branch=version,
- removed=False,
- installed=False,
- enabled=False,
- owned_by_plugin=False,
- preserved=False,
- )
- if version in installed:
+ was_installed = version in installed
+ if was_installed:
result = self._run_flatpak_command(
[
"uninstall",
@@ -471,17 +427,17 @@ class FlatpakService(BaseService):
f"Flatpak uninstall completed but {self._extension_ref(version)} "
"is still installed"
)
- owned.remove(version)
- self._write_owned_branches(owned)
+ owned, uncertain = self._read_owned_branches()
+ if not uncertain and version in owned:
+ owned.remove(version)
+ self._write_owned_branches(owned)
return self._success_response(
dict,
- f"Plugin-owned lsfg-vk {version} runtime extension removed",
+ f"lsfg-vk {version} runtime extension uninstalled",
runtime_branch=version,
- removed=True,
+ removed=was_installed,
installed=False,
enabled=False,
- owned_by_plugin=False,
- preserved=False,
)
except Exception as error:
return self._error_response(
@@ -491,8 +447,6 @@ class FlatpakService(BaseService):
removed=False,
installed=False,
enabled=False,
- owned_by_plugin=False,
- preserved=False,
)
def set_extension_enabled(self, version: str, enabled: bool) -> Dict[str, Any]:
@@ -504,8 +458,6 @@ class FlatpakService(BaseService):
runtime_branch=version,
installed=False,
enabled=False,
- owned_by_plugin=False,
- preserved=False,
)
return self.install_extension(version) if enabled else self.uninstall_extension(version)
diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py
index 76a4250..c576cc2 100644
--- a/py_modules/lsfg_vk/plugin.py
+++ b/py_modules/lsfg_vk/plugin.py
@@ -162,9 +162,6 @@ class Plugin:
async def set_flatpak_extension_enabled(self, version: str, enabled: bool) -> Dict[str, Any]:
return self.flatpak_service.set_extension_enabled(version, enabled)
-
- async def remove_plugin_owned_flatpak_extensions(self) -> Dict[str, Any]:
- return self.flatpak_service.remove_plugin_owned_extensions()
async def _main(self):
"""
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts
index 16b6eab..8179ef9 100644
--- a/src/api/lsfgApi.ts
+++ b/src/api/lsfgApi.ts
@@ -124,17 +124,6 @@ export interface FlatpakExtensionStatus {
extension_id: string;
supported_branches: string[];
installed_branches: string[];
- owned_branches: string[];
- ownership_uncertain: boolean;
-}
-
-export interface FlatpakCleanupResult {
- success: boolean;
- message: string;
- error?: string | null;
- removed_branches: string[];
- preserved_branches: string[];
- ownership_uncertain: boolean;
}
export interface FlatpakExtensionToggleResult {
@@ -144,8 +133,6 @@ export interface FlatpakExtensionToggleResult {
runtime_branch: string;
enabled: boolean;
installed: boolean;
- owned_by_plugin: boolean;
- preserved: boolean;
}
// API functions
@@ -162,10 +149,6 @@ export const setFlatpakExtensionEnabled = callable<
[string, boolean],
FlatpakExtensionToggleResult
>("set_flatpak_extension_enabled");
-export const removePluginOwnedFlatpakExtensions = callable<
- [],
- FlatpakCleanupResult
->("remove_plugin_owned_flatpak_extensions");
export const getGameConfigs = callable<[], GameConfigsResult>("get_game_configs");
export const getInstalledGames = callable<[], InstalledGamesResult>("get_installed_games");
diff --git a/src/components/SetupTab.tsx b/src/components/SetupTab.tsx
index df43c5e..aec0e93 100644
--- a/src/components/SetupTab.tsx
+++ b/src/components/SetupTab.tsx
@@ -1,8 +1,7 @@
-import { ButtonItem, ConfirmModal, Field, PanelSection, PanelSectionRow, ToggleField, showModal } from "@decky/ui";
+import { ButtonItem, Field, PanelSection, PanelSectionRow, ToggleField } from "@decky/ui";
import { useEffect, useState } from "react";
import {
getFlatpakSupportStatus,
- removePluginOwnedFlatpakExtensions,
setFlatpakExtensionEnabled,
type FlatpakExtensionStatus,
type SteamBranchStatus,
@@ -41,8 +40,6 @@ function FlatpakSupportDiagnostics({ relevant }: { relevant: boolean }) {
extension_id: "",
supported_branches: [],
installed_branches: [],
- owned_branches: [],
- ownership_uncertain: false,
});
}
};
@@ -67,61 +64,10 @@ function FlatpakSupportDiagnostics({ relevant }: { relevant: boolean }) {
}
};
- const confirmDisable = (version: string) => {
- showModal(
- <ConfirmModal
- strTitle={`Disable Flatpak runtime ${version}?`}
- strDescription="Only runtime extensions installed by this plugin can be removed. Pre-existing extensions are preserved."
- strOKButtonText="Disable"
- strCancelButtonText="Cancel"
- onOK={() => void runExtensionOperation(version, false)}
- onCancel={() => {}}
- />,
- );
- };
-
const handleExtensionToggle = (version: string, enabled: boolean) => {
- const installed = status.installed_branches.includes(version);
- const owned = status.owned_branches.includes(version);
- if (!enabled && installed && !owned) {
- showErrorToast(
- "Flatpak runtime preserved",
- `${version} was not installed by this plugin, so it will remain installed.`,
- );
- void refresh();
- return;
- }
- if (!enabled && installed && owned) {
- confirmDisable(version);
- return;
- }
void runExtensionOperation(version, enabled);
};
- const confirmCleanup = () => {
- showModal(
- <ConfirmModal
- strTitle="Remove plugin-installed Flatpak extensions?"
- strDescription="Shared runtime branches recorded as installed by this plugin will be removed. Existing unowned branches are preserved."
- strOKButtonText="Remove extensions"
- strCancelButtonText="Cancel"
- onOK={async () => {
- setOperation("cleanup");
- try {
- const result = await removePluginOwnedFlatpakExtensions();
- if (!result.success) throw new Error(result.error || result.message || "Flatpak cleanup failed");
- await refresh();
- } catch (error) {
- showErrorToast("Flatpak cleanup failed", String(error));
- } finally {
- setOperation(null);
- }
- }}
- onCancel={() => {}}
- />,
- );
- };
-
return (
<PanelSection title="Flatpak support">
<PanelSectionRow>
@@ -147,31 +93,15 @@ function FlatpakSupportDiagnostics({ relevant }: { relevant: boolean }) {
: operation === `disable-${branch}`
? "Uninstalling..."
: status.installed_branches.includes(branch)
- ? status.owned_branches.includes(branch)
- ? "Installed · plugin-owned"
- : "Installed · pre-existing (preserved)"
+ ? "Installed"
: "Not installed"
}
checked={status.installed_branches.includes(branch)}
onChange={(enabled) => handleExtensionToggle(branch, enabled)}
- disabled={operation !== null || status.ownership_uncertain}
+ disabled={operation !== null}
/>
</PanelSectionRow>
))}
- {status.ownership_uncertain && (
- <PanelSectionRow>
- <Field label="Ownership metadata is uncertain" description="Cleanup is disabled until the metadata is repaired." />
- </PanelSectionRow>
- )}
- <PanelSectionRow>
- <ButtonItem
- layout="below"
- disabled={operation !== null || status.ownership_uncertain || status.owned_branches.length === 0}
- onClick={confirmCleanup}
- >
- {operation === "cleanup" ? "Removing..." : "Remove plugin-installed extensions"}
- </ButtonItem>
- </PanelSectionRow>
</>
)}
</PanelSection>
diff --git a/tests/test_flatpak_service.py b/tests/test_flatpak_service.py
index 274c0c5..70ba228 100644
--- a/tests/test_flatpak_service.py
+++ b/tests/test_flatpak_service.py
@@ -93,7 +93,8 @@ class FlatpakServiceTests(unittest.TestCase):
response = self.service.install_extension("24.08")
self.assertTrue(response["success"])
- self.assertTrue(response["owned_by_plugin"])
+ self.assertTrue(response["enabled"])
+ self.assertTrue(response["installed"])
install_args = self.service._run_flatpak_command.call_args_list[1].args[0]
self.assertEqual(install_args[:4], ["install", "--user", "--noninteractive", "--or-update"])
self.assertEqual(
@@ -110,28 +111,33 @@ class FlatpakServiceTests(unittest.TestCase):
cleanup_response = self.service.remove_plugin_owned_extensions()
self.assertTrue(install_response["success"])
- self.assertFalse(install_response["owned_by_plugin"])
+ self.assertTrue(install_response["enabled"])
+ self.assertTrue(install_response["installed"])
self.assertFalse(self.service.ownership_path.exists())
self.assertTrue(cleanup_response["success"])
self.assertEqual(self.service._run_flatpak_command.call_count, 1)
- def test_extension_toggle_is_idempotent_and_preserves_preexisting_branch(self):
- self.service._run_flatpak_command.return_value = self._result(
- self._extension_line("24.08")
- )
+ def test_extension_toggle_installs_and_uninstalls_preexisting_branch(self):
+ self.service._run_flatpak_command.side_effect = [
+ self._result(self._extension_line("24.08")),
+ self._result(self._extension_line("24.08")),
+ self._result(""),
+ self._result(""),
+ ]
enable_response = self.service.set_extension_enabled("24.08", True)
disable_response = self.service.set_extension_enabled("24.08", False)
self.assertTrue(enable_response["success"])
self.assertTrue(enable_response["enabled"])
+ self.assertTrue(enable_response["installed"])
self.assertTrue(disable_response["success"])
- self.assertTrue(disable_response["enabled"])
- self.assertTrue(disable_response["preserved"])
- self.assertFalse(disable_response["owned_by_plugin"])
+ self.assertFalse(disable_response["enabled"])
+ self.assertFalse(disable_response["installed"])
+ self.assertTrue(disable_response["removed"])
self.assertEqual(
[call.args[0][0] for call in self.service._run_flatpak_command.call_args_list],
- ["list", "list"],
+ ["list", "list", "uninstall", "list"],
)
def test_extension_toggle_removes_owned_branch_and_can_repeat_disable(self):