From 63d758abe6318c5877e658c7a56282a7d90ede51 Mon Sep 17 00:00:00 2001 From: xXJsonDeruloXx Date: Sat, 1 Aug 2026 13:53:52 -0400 Subject: feat: bundle v2 Flatpak runtime assets --- README.md | 3 ++- package.json | 23 +++++++++++++++---- py_modules/lsfg_vk/flatpak_service.py | 42 +++++++++++++++++++++++++++-------- py_modules/lsfg_vk/plugin.py | 6 ++--- src/components/FlatpaksModal.tsx | 8 +++---- tests/test_lsfg_v2_migration.py | 24 ++++++++++++++++++++ 6 files changed, 85 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a94d703..a1c233c 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A Decky plugin that streamlines the installation of **lsfg-vk** ([Lossless Scaling Frame Generation Vulkan layer](https://github.com/PancakeTAS/lsfg-vk)) on Steam Deck, allowing you to use the Lossless Scaling frame generation features on Linux with a controller friendly UI in SteamOS, Bazzite, or any other Linux platform compatible with Decky Loader. -> The v2 layer payload is currently pinned to the owner-fork prerelease [`v2.0.0-decky.1`](https://github.com/xXJSONDeruloXx/lsfg-vk/releases/tag/v2.0.0-decky.1). +> The v2 native layer and Flatpak runtime payloads are pinned to the owner-fork prerelease [`v2.0.0-decky.2`](https://github.com/xXJSONDeruloXx/lsfg-vk/releases/tag/v2.0.0-decky.2). ## Installation @@ -78,6 +78,7 @@ For per-game feedback and community support, please join the [decky-lsfg-vk Disc The plugin: - Downloads checksum-pinned x86_64 or Armada/aarch64 lsfg-vk v2 assets from the owner-fork release to `~/.local/lib/` +- Bundles checksum-pinned lsfg-vk v2 Flatpak extensions for runtimes 23.08, 24.08, and 25.08, and installs the selected local bundle - Configures the v2 Vulkan layer in `~/.local/share/vulkan/implicit_layer.d/` - Migrates the existing `~/.config/lsfg-vk/conf.toml` from v1 to v2 automatically on layer update, retaining a one-time `.v1.bak` backup - Automatically detects your Lossless Scaling DLL installation diff --git a/package.json b/package.json index 75bf2f7..36bf105 100644 --- a/package.json +++ b/package.json @@ -46,13 +46,28 @@ "remote_binary": [ { "name": "lsfg-vk-layer-x86_64.tar.xz", - "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.1/lsfg-vk-layer-x86_64.tar.xz", - "sha256hash": "b96c60d838cd778797406bafc31e17a3698e8145248113c2bc41151b2823a6a0" + "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.2/lsfg-vk-layer-x86_64.tar.xz", + "sha256hash": "3bf5baaf391c6240de9978161a68aa8c9a54eff4246b79f9ea5b2ad1ec1a53a4" }, { "name": "lsfg-vk-layer-aarch64.tar.xz", - "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.1/lsfg-vk-layer-aarch64.tar.xz", - "sha256hash": "b1703042f50ff9470aa0b90953077949a9f144dcbd926f80fbb7e386e8393367" + "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.2/lsfg-vk-layer-aarch64.tar.xz", + "sha256hash": "ce08a04dc78ed1b1ca4bd03b9cf6c97ee233b0f5b2c2cc514509fae7e2eec412" + }, + { + "name": "org.freedesktop.Platform.VulkanLayer.lsfg_vk_23.08.flatpak", + "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.2/org.freedesktop.Platform.VulkanLayer.lsfg_vk_23.08.flatpak", + "sha256hash": "7eff81f96b278fde6fe395c88461c55e611547bf5991d179b9145ec6f5a778b1" + }, + { + "name": "org.freedesktop.Platform.VulkanLayer.lsfg_vk_24.08.flatpak", + "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.2/org.freedesktop.Platform.VulkanLayer.lsfg_vk_24.08.flatpak", + "sha256hash": "cbd663b9021c355dddec61ec51fd4388c12705f16637cadd4b45aead0e5dc427" + }, + { + "name": "org.freedesktop.Platform.VulkanLayer.lsfg_vk_25.08.flatpak", + "url": "https://github.com/xXJSONDeruloXx/lsfg-vk/releases/download/v2.0.0-decky.2/org.freedesktop.Platform.VulkanLayer.lsfg_vk_25.08.flatpak", + "sha256hash": "615e87c03b18368ed1cca97e036f1bf54fff95fc6126aac697bb368f33281cbf" } ], "pnpm": { diff --git a/py_modules/lsfg_vk/flatpak_service.py b/py_modules/lsfg_vk/flatpak_service.py index 80dcf5d..5832cf4 100644 --- a/py_modules/lsfg_vk/flatpak_service.py +++ b/py_modules/lsfg_vk/flatpak_service.py @@ -9,6 +9,12 @@ from typing import Dict, Any, List, Optional from .base_service import BaseService from .config_schema import ConfigurationManager +from .constants import ( + BIN_DIR, + FLATPAK_23_08_FILENAME, + FLATPAK_24_08_FILENAME, + FLATPAK_25_08_FILENAME, +) from .types import BaseResponse @@ -67,6 +73,21 @@ class FlatpakService(BaseService): self.log.debug("Could not read configured DLL path for Flatpak override: %s", error) return config_path, dll_directory + def _get_bundled_extension_path(self, version: str) -> Path: + """Return the checksum-pinned Flatpak bundle shipped with this plugin.""" + filenames = { + "23.08": FLATPAK_23_08_FILENAME, + "24.08": FLATPAK_24_08_FILENAME, + "25.08": FLATPAK_25_08_FILENAME, + } + try: + filename = filenames[version] + except KeyError as error: + raise ValueError(f"Unsupported Flatpak runtime version: {version}") from error + + plugin_dir = Path(__file__).resolve().parent.parent.parent + return plugin_dir / BIN_DIR / filename + def _remove_legacy_app_overrides(self, app_id: str) -> list[str]: """Remove only the v1 overrides previously created by this plugin.""" legacy_dll_path = self.user_home / ".local/share/Steam/steamapps/common/Lossless Scaling/Lossless.dll" @@ -207,14 +228,14 @@ class FlatpakService(BaseService): if not self.check_flatpak_available(): return self._error_response(BaseResponse, "Flatpak is not available on this system") - if version == "23.08": - return self._error_response( - BaseResponse, - "Flathub supplies the lsfg-vk v2 extension for runtimes 24.08 and 25.08; install 23.08 manually.", - ) + bundle_path = self._get_bundled_extension_path(version) + if not bundle_path.is_file(): + error_msg = f"Bundled Flatpak extension not found at {bundle_path}; reinstall the plugin" + self.log.error(error_msg) + return self._error_response(BaseResponse, error_msg) result = self._run_flatpak_command( - ["install", "--user", "--noninteractive", "flathub", f"org.freedesktop.Platform.VulkanLayer.lsfgvk//{version}"], + ["install", "--user", "--noninteractive", str(bundle_path)], capture_output=True, text=True ) @@ -223,8 +244,11 @@ class FlatpakService(BaseService): self.log.error(error_msg) return self._error_response(BaseResponse, error_msg) - self.log.info(f"Successfully installed lsfg-vk Flatpak extension {version}") - return self._success_response(BaseResponse, f"lsfg-vk {version} runtime extension installed successfully") + self.log.info("Successfully installed bundled lsfg-vk Flatpak extension %s", version) + return self._success_response( + BaseResponse, + f"lsfg-vk {version} runtime extension installed successfully from the bundled asset", + ) except Exception as e: error_msg = f"Error installing Flatpak extension {version}: {str(e)}" @@ -465,4 +489,4 @@ class FlatpakService(BaseService): error_msg = f"Error removing overrides for {app_id}: {str(e)}" self.log.error(error_msg) return self._error_response(FlatpakOverrideResponse, error_msg, - app_id=app_id, operation="remove") \ No newline at end of file + app_id=app_id, operation="remove") diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py index aefec3e..c2f22e3 100644 --- a/py_modules/lsfg_vk/plugin.py +++ b/py_modules/lsfg_vk/plugin.py @@ -354,7 +354,7 @@ class Plugin: """Check status of lsfg-vk Flatpak runtime extensions Returns: - FlatpakExtensionStatus dict with installation status for both runtime versions + FlatpakExtensionStatus dict with installation status for all supported runtime versions """ return self.flatpak_service.get_extension_status() @@ -362,7 +362,7 @@ class Plugin: """Install lsfg-vk Flatpak runtime extension Args: - version: Runtime version to install ("23.08" or "24.08") + version: Runtime version to install ("23.08", "24.08", or "25.08") Returns: BaseResponse dict with success status and message/error @@ -373,7 +373,7 @@ class Plugin: """Uninstall lsfg-vk Flatpak runtime extension Args: - version: Runtime version to uninstall ("23.08" or "24.08") + version: Runtime version to uninstall ("23.08", "24.08", or "25.08") Returns: BaseResponse dict with success status and message/error diff --git a/src/components/FlatpaksModal.tsx b/src/components/FlatpaksModal.tsx index 0ab715a..a6a0e85 100644 --- a/src/components/FlatpaksModal.tsx +++ b/src/components/FlatpaksModal.tsx @@ -175,7 +175,7 @@ export const FlatpaksModal: FC = ({ closeModal }) => { : } > = ({ closeModal }) => { action(); } }} - disabled={!extensionStatus.installed_23_08 || operationInProgress === 'install-23.08' || operationInProgress === 'uninstall-23.08'} + disabled={operationInProgress === 'install-23.08' || operationInProgress === 'uninstall-23.08'} > {operationInProgress === 'install-23.08' || operationInProgress === 'uninstall-23.08' ? ( @@ -215,7 +215,7 @@ export const FlatpaksModal: FC = ({ closeModal }) => { : } > = ({ closeModal }) => { : } >