Replaces the single-select tag QComboBox with a TagsButton + TagsPopup
mirroring the friends pattern: a combo-styled button labelled "Tags (N) ▾"
opens a borderless popup containing a search input and a checkable list of
tags. Selecting multiple tags AND-filters games — a game must carry every
selected tag to survive — which makes it easy to narrow large libraries to
specific intersections (e.g. Roguelike + Co-op).
The search input is auto-focused on popup open and filters the list as the
user types, with a status line showing "N of M tag(s)". Selection state
survives search filtering and popup close/reopen.
The popup style and button style are renamed from FRIENDS_*_STYLE to
MULTISELECT_*_STYLE and reused by both FriendsPopup and TagsPopup; the
popup objectName moves from "FriendsPopup" to "MultiSelectPopup". The
TagsPopup adds a QLineEdit selector to the shared style.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a fourth filter control next to install/genre/tag: a "Friends ▾" button
that opens a checkable popup of the user's Steam friends. Selected friends'
libraries are intersected with the user's so only games everyone owns survive,
making it easy to combine with genre/tag to find a category of game everyone
in the room can play.
Friend list (with display names) is fetched via GetFriendList +
GetPlayerSummaries and cached at ~/.cache/steam-dice/friends.json. Each
friend's owned-games set is fetched lazily the first time they're checked
and cached at ~/.cache/steam-dice/friend_games/<steamid>.json. The main
refresh button re-fetches selected friends alongside the user's library;
the popup's own refresh button re-pulls just the friend list.
While a selected friend's library is still loading, the dice button stays
disabled and the status line shows which friend(s) are pending. Settings
changes that switch the steam_id clear in-memory friends state so the
previous user's friends don't pollute the new account.
Window width grows 40px (500 -> 540) and combo width shrinks 115 -> 100 so
all four controls fit on a single row.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The genre column hid its progress sub-label by default, so its effective
height was 28px while the filter and tag columns were 46px (combo +
sub-label). Qt's default vertical centering then dropped the genre combo
~9px below the others.
Use a single _combo_column() helper for all three filters, with fixed
115px width, fixed 28px combo height, and an always-present 14px sub-row
(progress label for genres, empty spacer for filter/tag). The progress
label now toggles its text instead of its visibility, preserving the
column's reserved space.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Steam's official genres list is coarse (~12 entries) and doesn't include
community-relevant categories like Roguelike, Soulslike, or Metroidvania —
those live in Steam's store tags. This adds a second combo box that filters
by store tag, AND'd with the genre filter.
Tag IDs in appinfo.vdf are translated via Steam's IStoreService/GetTagList
endpoint (~450 entries, fetched once on first use, cached at
~/.cache/steam-dice/tags.json). The genre cache file is replaced by
~/.cache/steam-dice/taxonomy.json, which stores both genres and tags per
appid as {"genres": [...], "tags": [...]}; the old genres.json is left in
place as harmless orphan data. Cache merge logic preserves non-empty
fields per appid so the API-fallback genre fetcher doesn't clobber tags
populated from appinfo.vdf.
Tags are appinfo.vdf-only — Steam's appdetails endpoint doesn't return
store_tags, so there's no API fallback. Without python-steam, the tag
combo stays empty and a tooltip-style dialog explains why.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds genre/category filter dropdown. Reads from Steam's local
appinfo.vdf for instant population, with rate-limited appdetails API
as fallback when local data is unavailable.
_save_genre_cache now reads the on-disk state and merges before writing,
so a concurrent writer can't shrink the cache. Likewise the API thread's
progress/done handlers now `update()` the in-memory cache instead of
replacing it wholesale.
Reachable only in the rare path where both the appinfo loader and the
API fetch thread run in the same session.
Adds a second dropdown next to the install filter that lets the user
narrow rolls to a single Steam genre (RPG, Strategy, etc.).
Genre data is loaded from Steam's local appinfo.vdf cache via
python-steam (instant, no network). If that's unavailable or a game
isn't in the cache, falls back to a rate-limited background fetch of
appdetails?filters=genres, prompted via confirm dialog. Cached at
~/.cache/steam-dice/genres.json across runs.
python-steam declared as optdepends — app degrades gracefully to the
API path if missing.
2026-05-08 15:26:53 -04:00
2 changed files with 1132 additions and 10 deletions
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.