summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py_modules/lsfg_vk/flatpak_service.py29
-rw-r--r--py_modules/lsfg_vk/installation.py24
-rw-r--r--py_modules/lsfg_vk/plugin.py10
-rw-r--r--src/components/ConfigurationTab.tsx11
-rw-r--r--src/i18n/i18n.ts25
-rw-r--r--tests/test_plugin_migration.py50
-rw-r--r--tsconfig.json1
7 files changed, 74 insertions, 76 deletions
diff --git a/py_modules/lsfg_vk/flatpak_service.py b/py_modules/lsfg_vk/flatpak_service.py
index 6f8a596..6aebf11 100644
--- a/py_modules/lsfg_vk/flatpak_service.py
+++ b/py_modules/lsfg_vk/flatpak_service.py
@@ -323,32 +323,3 @@ class FlatpakService(BaseService):
app_id=app_id,
operation="remove",
)
-
- def migrate_v2(self) -> None:
- if not self.check_flatpak_available():
- return
-
- apps_result = self._run_flatpak_command(
- ["list", "--user", "--app", "--columns=application"],
- capture_output=True,
- text=True,
- )
- if apps_result.returncode != 0:
- return
-
- for app_id in apps_result.stdout.splitlines():
- app_id = app_id.strip()
- if not app_id:
- continue
- output = self._override_output(app_id)
- paths = self._override_paths()
- legacy_markers = (
- "LSFG_CONFIG=",
- paths["legacy_home"],
- paths["legacy_dll"],
- paths["legacy_script"],
- )
- if any(marker in output for marker in legacy_markers):
- result = self.set_app_override(app_id)
- if not result.get("success"):
- self.log.warning(result.get("error"))
diff --git a/py_modules/lsfg_vk/installation.py b/py_modules/lsfg_vk/installation.py
index 09bd3a3..b583cc7 100644
--- a/py_modules/lsfg_vk/installation.py
+++ b/py_modules/lsfg_vk/installation.py
@@ -171,30 +171,6 @@ class InstallationService(BaseService):
for path in (self.legacy_lib_file, self.legacy_json_file):
self._remove_if_exists(path)
- def needs_v2_migration(self) -> bool:
- legacy_layer = self.legacy_lib_file.exists() or self.legacy_json_file.exists()
- legacy_config = False
- if self.config_file_path.exists():
- try:
- legacy_config = ConfigurationManager.is_legacy_v1(
- self.config_file_path.read_text(encoding="utf-8")
- )
- except OSError:
- legacy_config = False
- if legacy_layer or legacy_config:
- return True
- try:
- if self.config_file_path.exists():
- data = ConfigurationManager.parse_toml_content_multi_profile(
- self.config_file_path.read_text(encoding="utf-8")
- )
- configured = str(data["global_config"].get("dll") or "")
- if (not configured or not Path(configured).is_file()) and self.steam_service.find_lsfg_vk_dll():
- return True
- return not self.runtime_service.is_healthy()
- except Exception:
- return True
-
def check_installation(self) -> InstallationCheckResponse:
try:
installation_error = None
diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py
index 6977b9c..0472e42 100644
--- a/py_modules/lsfg_vk/plugin.py
+++ b/py_modules/lsfg_vk/plugin.py
@@ -236,14 +236,4 @@ class Plugin:
os.path.join(decky.DECKY_HOME, "lossless-scaling-vk"),
os.path.join(decky.DECKY_USER_HOME, ".local", "share", "decky-lossless-scaling-vk"))
- if self.installation_service.needs_v2_migration():
- result = self.installation_service.install()
- if not result.get("success"):
- decky.logger.warning(f"Native v2 migration failed: {result.get('error')}")
-
- try:
- self.flatpak_service.migrate_v2()
- except Exception as error:
- decky.logger.warning(f"Flatpak v2 migration skipped: {error}")
-
decky.logger.info("decky-lsfg-vk plugin migrations completed")
diff --git a/src/components/ConfigurationTab.tsx b/src/components/ConfigurationTab.tsx
index 2175eb9..b3c0281 100644
--- a/src/components/ConfigurationTab.tsx
+++ b/src/components/ConfigurationTab.tsx
@@ -1,5 +1,6 @@
-import { ButtonItem, Field, Focusable, PanelSection, PanelSectionRow } from "@decky/ui";
+import { ButtonItem, DialogButton, Field, Focusable, PanelSection, PanelSectionRow } from "@decky/ui";
import { useCallback, useEffect, useRef, useState } from "react";
+import { FaArrowLeft } from "react-icons/fa";
import { RiArrowDownSFill, RiArrowUpSFill } from "react-icons/ri";
import { ConfigurationData } from "../config/configSchema";
import { GameTarget } from "../hooks/useGameConfiguration";
@@ -116,7 +117,13 @@ export function ConfigurationTab({
)}
<PanelSectionRow>
<Focusable ref={backToGamesRef} noFocusRing>
- <ButtonItem layout="below" onClick={closeDetails}>Back to games</ButtonItem>
+ <DialogButton
+ aria-label="Back to games"
+ onClick={closeDetails}
+ style={{ width: "48px", minWidth: "48px", height: "48px", padding: "10px" }}
+ >
+ <FaArrowLeft />
+ </DialogButton>
</Focusable>
</PanelSectionRow>
</PanelSection>
diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts
index dc8de8b..31a55cb 100644
--- a/src/i18n/i18n.ts
+++ b/src/i18n/i18n.ts
@@ -2,8 +2,16 @@
// to generate for localhost/dev, run `build_i18n_json.sh` script
import * as languages from "./languages.json";
-const steamLanguageMap: Record<string, string> =
- languages.steam_language_map as Record<string, string>;
+type LanguageStrings = Record<string, string>;
+type Language = { name: string; strings?: LanguageStrings };
+type LanguageData = {
+ language_metadata: Record<string, Language>;
+ steam_language_map: Record<string, string>;
+ [language: string]: LanguageStrings | Record<string, Language> | Record<string, string>;
+};
+
+const languageData = languages as unknown as LanguageData;
+const steamLanguageMap = languageData.steam_language_map;
const normalizeLanguage = (language: string): string => {
const normalized = language.trim().toLowerCase();
@@ -11,13 +19,13 @@ const normalizeLanguage = (language: string): string => {
};
function getLangs() {
- const langs = languages.language_metadata;
+ const langs = languageData.language_metadata;
- Object.keys(languages).map((lang) => {
+ Object.keys(languageData).forEach((lang) => {
if (lang === "language_metadata" || lang == "steam_language_map") {
return;
}
- const strs = languages[lang];
+ const strs = languageData[lang] as LanguageStrings;
if (lang && strs && langs[lang]?.name) {
langs[lang].strings = strs;
}
@@ -27,12 +35,7 @@ function getLangs() {
}
export const LANGS: {
- [key: string]: {
- name: string;
- strings: {
- [key: string]: string;
- };
- };
+ [key: string]: Language;
} = getLangs();
let cachedLang: string | undefined;
diff --git a/tests/test_plugin_migration.py b/tests/test_plugin_migration.py
new file mode 100644
index 0000000..a392f85
--- /dev/null
+++ b/tests/test_plugin_migration.py
@@ -0,0 +1,50 @@
+import asyncio
+import sys
+import types
+import unittest
+from unittest.mock import Mock
+
+
+class PluginMigrationTests(unittest.TestCase):
+ def test_migration_only_runs_decky_path_migrations(self):
+ decky = types.SimpleNamespace(
+ DECKY_HOME="/decky",
+ DECKY_USER_HOME="/home/deck",
+ migrate_logs=Mock(),
+ migrate_settings=Mock(),
+ migrate_runtime=Mock(),
+ logger=Mock(),
+ )
+ previous_decky = sys.modules.get("decky")
+ previous_tomllib = sys.modules.get("tomllib")
+ sys.modules["decky"] = decky
+ sys.modules["tomllib"] = types.SimpleNamespace(loads=Mock())
+ try:
+ sys.path.insert(0, "py_modules")
+ from lsfg_vk.plugin import Plugin
+
+ plugin = Plugin.__new__(Plugin)
+ plugin.installation_service = Mock()
+ plugin.flatpak_service = Mock()
+
+ asyncio.run(plugin._migration())
+
+ decky.migrate_logs.assert_called_once()
+ decky.migrate_settings.assert_called_once()
+ decky.migrate_runtime.assert_called_once()
+ plugin.installation_service.install.assert_not_called()
+ plugin.flatpak_service.migrate_v2.assert_not_called()
+ finally:
+ sys.path.remove("py_modules")
+ if previous_decky is None:
+ sys.modules.pop("decky", None)
+ else:
+ sys.modules["decky"] = previous_decky
+ if previous_tomllib is None:
+ sys.modules.pop("tomllib", None)
+ else:
+ sys.modules["tomllib"] = previous_tomllib
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tsconfig.json b/tsconfig.json
index 626c60f..f4b795f 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,6 +8,7 @@
"jsxFragmentFactory": "window.SP_REACT.Fragment",
"declaration": false,
"moduleResolution": "node",
+ "resolveJsonModule": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"esModuleInterop": true,