diff --git a/py_modules/adapters/romm/http.py b/py_modules/adapters/romm/http.py index c1a0c77..d2ce98a 100644 --- a/py_modules/adapters/romm/http.py +++ b/py_modules/adapters/romm/http.py @@ -5,6 +5,7 @@ """ import base64 +import gzip import json import logging import os @@ -198,9 +199,13 @@ def request(self, path: str): def _do_request(): req = urllib.request.Request(url, method="GET") req.add_header("Authorization", self.auth_header()) + req.add_header("Accept-Encoding", "gzip") try: with urllib.request.urlopen(req, context=self.ssl_context(), timeout=30) as resp: - return json.loads(resp.read().decode()) + data = resp.read() + if resp.headers.get("Content-Encoding") == "gzip": + data = gzip.decompress(data) + return json.loads(data.decode()) except RommApiError: raise except Exception as exc: diff --git a/py_modules/services/library.py b/py_modules/services/library.py index 7a6222f..9f9ae6f 100644 --- a/py_modules/services/library.py +++ b/py_modules/services/library.py @@ -630,7 +630,7 @@ async def _try_incremental_skip( async def _full_fetch_platform_roms(self, platform_id, platform_name, platform_slug, all_roms, pi, total_platforms): """Full paginated fetch of ROMs for a single platform.""" offset = 0 - limit = 50 + limit = 250 await self._emit_progress( "roms", current=len(all_roms), @@ -689,7 +689,7 @@ async def _fetch_single_collection_roms( coll_rom_ids: list[int] = [] offset = 0 - limit = 50 + limit = 250 while True: self._check_cancelling() if is_virtual: diff --git a/src/index.tsx b/src/index.tsx index dcfff43..0e0e659 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -14,7 +14,7 @@ import { DownloadQueue } from "./components/DownloadQueue"; import { initSyncManager } from "./utils/syncManager"; import { setSyncProgress } from "./utils/syncProgress"; import { updateDownload, getDownloadState } from "./utils/downloadStore"; -import { registerGameDetailPatch, unregisterGameDetailPatch, registerRomMAppId } from "./patches/gameDetailPatch"; +import { unregisterGameDetailPatch, registerRomMAppId } from "./patches/gameDetailPatch"; import { registerMetadataPatches, unregisterMetadataPatches, applyAllPlaytime } from "./patches/metadataPatches"; import { registerLaunchInterceptor, unregisterLaunchInterceptor } from "./utils/launchInterceptor"; import { getAllMetadataCache, getAppIdRomIdMap, ensureDeviceRegistered, getSaveSyncSettings, getAllPlaytime, getMigrationStatus, getSaveSortMigrationStatus, logError, logInfo } from "./api/backend"; @@ -48,7 +48,9 @@ const QAMPanel: FC = () => { }; export default definePlugin(() => { - registerGameDetailPatch(); + // registerGameDetailPatch() intentionally removed — it calls + // routerHook.addPatch() which triggers Decky route re-renders that crash + // Steam's Library page (GetAppCountWithToolsFilter TypeError). registerLaunchInterceptor(); // Load metadata cache, register store patches, and populate RomM app ID set. diff --git a/tests/adapters/romm/test_http.py b/tests/adapters/romm/test_http.py index f8de212..86ef447 100644 --- a/tests/adapters/romm/test_http.py +++ b/tests/adapters/romm/test_http.py @@ -157,6 +157,7 @@ def test_uses_auth_header(self, plugin): fake_resp = MagicMock() fake_resp.read.return_value = _json.dumps({"ok": True}).encode() + fake_resp.headers = {"Content-Type": "application/json"} fake_resp.__enter__ = MagicMock(return_value=fake_resp) fake_resp.__exit__ = MagicMock(return_value=False) @@ -166,6 +167,31 @@ def test_uses_auth_header(self, plugin): assert result == {"ok": True} req = mock_open.call_args[0][0] assert "Basic " in req.get_header("Authorization") + assert req.get_header("Accept-encoding") == "gzip" + + def test_decompresses_gzip_response(self, plugin): + import gzip as _gzip + import json as _json + from unittest.mock import MagicMock, patch + + plugin.settings["romm_url"] = "http://romm.local" + plugin.settings["romm_user"] = "user" + plugin.settings["romm_pass"] = "pass" + plugin.settings["romm_allow_insecure_ssl"] = False + + payload = _json.dumps({"items": [1, 2, 3]}).encode() + compressed = _gzip.compress(payload) + + fake_resp = MagicMock() + fake_resp.read.return_value = compressed + fake_resp.headers = {"Content-Encoding": "gzip", "Content-Type": "application/json"} + fake_resp.__enter__ = MagicMock(return_value=fake_resp) + fake_resp.__exit__ = MagicMock(return_value=False) + + with patch("urllib.request.urlopen", return_value=fake_resp): + result = plugin._http_adapter.request("/api/roms") + + assert result == {"items": [1, 2, 3]} class TestRommJsonRequest: