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
This commit is contained in:
MaxsTechReview authored and GitHub committed 2026-11-08 19:37:20 -05:00
1 parent 6b110581ac
commit 5e438e9248
3 files changed
+27 -4

No files matched your search

@@ -64,6 +64,8 @@ object GogBackend : StoreBackend {
}, "gog-sync").start()
}
override fun search(context: Context, query: String): List<CatalogItem> = GogStoreCatalog.search(query)
override fun loadShelves(context: Context, force: Boolean) {
val app = context.applicationContext
GogStoreCatalog.cachedFeatured(app)?.let { StoresState.post { StoresState.shelves[store] = it } }
@@ -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<GogGame> = 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<String, Boolean>())
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<String>, account: List<String>?, cached: Set<String> = emptySet()): Set<String> =
if (account == null) listed + cached else listed + account
private fun ownedIds(token: String): List<String>? {
val json = StoreNet.get(OWNED_URL, bearer = token, userAgent = GogAuth.GALAXY_UA) ?: return null
val owned = runCatching { JSONObject(json).optJSONArray("owned") }.getOrNull() ?: return null
@@ -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 })