Conversation
Titles can be blacklisted from the right-click menu or the new Blacklist button next to Add to Wishlist on the detail page. They are stored in a new blacklist_entries table, so they stay hidden across restarts, and Settings > Blacklist lists them with a Remove button. The exclusion lives in the shared catalog WHERE clause on both the index and the union query paths (electron/db/blacklistSql.js), so the Browse total and scrollbar stay correct. Installed titles are never hidden, and blacklisting a wishlisted title removes it from the wishlist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Adds a Browse blacklist. A title can be blacklisted from its right-click menu or with a new Blacklist button next to Add to Wishlist on its detail page. It is then hidden from Browse and stays hidden across restarts. Settings > Blacklist lists every blacklisted title and has a Remove button that brings it back.
Why
Browse has no way to get rid of a title you never want to see again; it keeps coming back in every scroll and search.
Design points:
buildIndexWhereincatalogIndex.js, andgetCatalogGamesFromUnioninversions.js, which serves index-not-ready,updateAvailableand fast-path failures. Both use one builder,electron/db/blacklistSql.js, so they cannot drift. Filtering a fetched page instead would size the scrollbar for rows that never render and leave holes in the sparse grid.NOT EXISTSper column, in the same style aswishlistOnly.resolveMissingIdsfills in sibling ids first, so blacklisting the F95 tile also hides the same game's Atlas and LewdCorner tiles.blacklist-updated, and the main window refetches Browse from the first page. Patching the sparse array in place would shift every loaded page. The Settings list refreshes from the same event, so each window reflects changes made in the other.How it was tested
tests/browse-blacklist.test.jsruns against a real sqlite DB:totaldrops on both the union path and the index path;tests/context-menu.test.js:tests/context-action-result.test.js:blacklistGamewrites and broadcasts; a failure is returned and not broadcast.tests/blacklist-action-bar.test.jsx: the button renders when allowed, routes the click, and is disabled while busy.tests/blacklist-settings.test.jsx: the tab is visible; the section lists entries; Remove sends the row back and re-reads; empty state; refresh on a change from another window.Added tests that cover this change
For a fix: the regression test fails against the unfixed code (not a fix; the exclusion tests were still confirmed red without the clause)
npm run checkpasses locallyNew functions and IPC handlers have comments explaining why
CHANGELOG.mdupdatedThis PR targets
nightly, notmainAI assistance
Tool and model: Claude Opus 5 (
claude-opus-5) via Claude CodeWhat it wrote: All of it:
electron/db/blacklist.jselectron/db/blacklistSql.jssrc/components/settings/BlacklistSettings.jsxelectron/db/index.js(table and indexes)electron/db/catalogIndex.jsandelectron/db/versions.js(exclusion)electron/db/wishlist.js(one added export)electron/ipc/games.jsandelectron/ipc/windows.jselectron/preload.jssrc/App.jsxGameDetailPage.jsxandActionBar.jsxgameContextMenu.jsSettings.jsxandsettingsIcons.jsCHANGELOG.mdWhat you verified yourself: The assistant ran
npm run check(lint clean with no new warnings, 124 files / 1389 tests passing, renderer build OK) and confirmed that the two exclusion tests fail with their clause removed. I tested a Linux AppImage built from this branch by hand and confirmed:IPC changes
Added, both sides in this PR:
blacklist-add,blacklist-removeandblacklist-list:ipcMain.handleinelectron/ipc/games.js↔ipcRenderer.invokeinelectron/preload.js.blacklist-updated: sent fromelectron/ipc/games.js(add/remove handlers) andelectron/ipc/windows.js(blacklistGamecontext action) ↔ipcRenderer.oninpreload.js, consumed byApp.jsxandBlacklistSettings.jsx.run-context-actioncase:blacklistGame.electron/preload.jsgains fourelectronAPIentries:addBlacklistEntry,removeBlacklistEntry,getBlacklistEntriesandonBlacklistUpdated. The last returns its own unsubscribe.removeAllListenersallowlist is not widened.Anything the reviewer should know
isWishlistEntryflag was removed on nightly, and blacklisting from there has a visible effect because it removes the wishlist entry.--color-dangertoken rather than a new--color-detail-*variable, so existing custom themes don't render it transparent.🤖 Generated with Claude Code