From 5e438e9248e46be8ab2e5de2af7cbb3b0ecc5a0a Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Sun, 8 Nov 2026 19:37:20 -0500 Subject: [PATCH] fix(gog): owned games the listing leaves out stay owned, and search reaches GOG's catalog (#2296) * fix(gog): owned games the library listing leaves out stay owned Since the GOG library is read from account/getFilteredProducts, a game that listing does not return (one hidden in GOG Galaxy, for example) dropped out of the library, and with it out of the GOG tab, which shows owned games and the shelves. 0.5.0 read every owned id from user/data/games and showed them. The sync now takes the union of the listing and user/data/games. The listing still names most games at once, and an owned id it lacks is fetched like any other. * fix(gog): the GOG tab's search reaches GOG's catalog GogStoreCatalog.search was never wired to the backend, so searching the GOG tab only filtered the owned library and the featured shelves; a game that is neither could not be found. GogBackend now answers search from GOG's catalog, like the other stores. * fix(gog): keep cached owned games when the account list is unavailable --- .../droiddeck/launcher/stores/gog/GogBackend.kt | 2 ++ .../droiddeck/launcher/stores/gog/GogLibrary.kt | 12 ++++++++---- .../launcher/stores/gog/GogListingTest.kt | 17 +++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/stores/gog/GogBackend.kt b/app/src/main/java/com/droiddeck/launcher/stores/gog/GogBackend.kt index fb6b0c890..e36f0fc16 100644 --- a/app/src/main/java/com/droiddeck/launcher/stores/gog/GogBackend.kt +++ b/app/src/main/java/com/droiddeck/launcher/stores/gog/GogBackend.kt @@ -64,6 +64,8 @@ object GogBackend : StoreBackend { }, "gog-sync").start() } + override fun search(context: Context, query: String): List = GogStoreCatalog.search(query) + override fun loadShelves(context: Context, force: Boolean) { val app = context.applicationContext GogStoreCatalog.cachedFeatured(app)?.let { StoresState.post { StoresState.shelves[store] = it } } diff --git a/app/src/main/java/com/droiddeck/launcher/stores/gog/GogLibrary.kt b/app/src/main/java/com/droiddeck/launcher/stores/gog/GogLibrary.kt index 8f48740ee..5b8be2230 100644 --- a/app/src/main/java/com/droiddeck/launcher/stores/gog/GogLibrary.kt +++ b/app/src/main/java/com/droiddeck/launcher/stores/gog/GogLibrary.kt @@ -58,16 +58,17 @@ object GogLibrary { val token = GogAuth.validToken(app) ?: return SyncResult.NotLoggedIn onStatus(app.getString(R.string.stores_sync_game_list)) val listing = ownedListing(token) + val account = ownedIds(token) val listed: List = listing?.games - ?: ownedIds(token)?.map { GogGame(it, "", "", "", "", "", 1, null, "", "") } + ?: account?.map { GogGame(it, "", "", "", "", "", 1, null, "", "") } ?: return SyncResult.Failed(app.getString(R.string.stores_sync_gog_unreachable)) val named = listing != null - StoresState.logLine(if (named) "GOG: listing ${listed.size} games" else "GOG: listing unreadable, ${listed.size} owned ids") - val ownedSet = listing?.owned ?: listed.mapTo(HashSet()) { it.gameId } val cachedList = cached(app) + val cachedIds = cachedList.mapTo(HashSet()) { it.gameId } + val ownedSet = ownedSet(listing?.owned ?: listed.mapTo(HashSet()) { it.gameId }, account, cachedIds) + StoresState.logLine(if (named) "GOG: listing ${listed.size} games, ${ownedSet.size} owned ids" else "GOG: listing unreadable, ${listed.size} owned ids") val stale = System.currentTimeMillis() - p.getLong(LAST_SYNC_KEY, 0L) >= THROTTLE_MS val heavy = force || cachedList.isEmpty() || stale - val cachedIds = cachedList.mapTo(HashSet()) { it.gameId } val skipped = java.util.Collections.newSetFromMap(java.util.concurrent.ConcurrentHashMap()) skipped.addAll(p.getStringSet(SKIPPED_KEY, emptySet()).orEmpty()) val idsToFetch = if (heavy) ownedSet.toList() else ownedSet.filter { it !in cachedIds && it !in skipped } @@ -133,6 +134,9 @@ object GogLibrary { return all.ifEmpty { null }?.let { Listing(it, owned) } } + fun ownedSet(listed: Set, account: List?, cached: Set = emptySet()): Set = + if (account == null) listed + cached else listed + account + private fun ownedIds(token: String): List? { val json = StoreNet.get(OWNED_URL, bearer = token, userAgent = GogAuth.GALAXY_UA) ?: return null val owned = runCatching { JSONObject(json).optJSONArray("owned") }.getOrNull() ?: return null diff --git a/app/src/test/java/com/droiddeck/launcher/stores/gog/GogListingTest.kt b/app/src/test/java/com/droiddeck/launcher/stores/gog/GogListingTest.kt index 5aace971f..86e54aad0 100644 --- a/app/src/test/java/com/droiddeck/launcher/stores/gog/GogListingTest.kt +++ b/app/src/test/java/com/droiddeck/launcher/stores/gog/GogListingTest.kt @@ -24,6 +24,23 @@ class GogListingTest { assertEquals("", shadowrun.description) } + @Test + fun ownedGamesTheListingLeavesOutStayOwned() { + assertEquals(setOf("1", "2", "1086370078"), GogLibrary.ownedSet(setOf("1", "2"), listOf("2", "1086370078"))) + } + + @Test + fun withoutTheAccountListTheListingStillCounts() { + assertEquals(setOf("1", "2"), GogLibrary.ownedSet(setOf("1", "2"), null)) + assertEquals(setOf("3"), GogLibrary.ownedSet(emptySet(), listOf("3"))) + } + + @Test + fun cachedGamesStayWhenTheAccountListIsUnavailable() { + assertEquals(setOf("1", "2", "1086370078"), GogLibrary.ownedSet(setOf("1", "2"), null, setOf("1086370078"))) + assertEquals(setOf("1", "2", "3"), GogLibrary.ownedSet(setOf("1"), listOf("2", "3"), setOf("1086370078"))) + } + @Test fun moviesOtherPlatformsAndGalaxysOwnEntryAreLeftOut() { assertEquals(listOf("1207660413", "1207664663"), GogLibrary.parseListing(PAGE)!!.games.map { it.gameId })