Add Sortium - #231
Conversation
There was a problem hiding this comment.
Pull request overview
Adds the Sortium plugin to the Millennium Plugin Database as a Git submodule under plugins/, enabling advanced Steam library sorting using external completion/achievement metrics.
Changes:
- Register
plugins/sortiumas a new submodule pointing tohttps://github.com/SalvadorCorreia/Sortium. - Configure the submodule to track the
prodbranch (via.gitmodules).
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Nice plugin, and an unusual one to review: a Lua backend that reaches out to third party APIs deserves a closer look than a display-only plugin, so I read all of it rather than skimming. Short version: I found nothing concerning on the security side, one blocker, and one bug I think you will want to fix before anyone runs a full sync. 1. Blocker: the build fails from a clean checkoutReproduced exactly as the store CI runs it ( Cause. TypeScript 7 no longer exposes Fix, verified. Declaring TypeScript explicitly is enough. With only this change, "devDependencies": {
"typescript": "5.9.3"
},
"pnpm": {
"overrides": {
"typescript": "5.9.3"
}
}I hit precisely this on my own plugin, and a reviewer caught it the same way, so this is me passing the favour along rather than anything clever. Related. Minor. 2. Serious: one failed request parks the whole queue
if (isHigh) this.highPriority.push(target);
else this.lowPriority.push(target);
await new Promise((r) => setTimeout(r, 1000000));
It runs on any failure not classified as a rate limit, so anything outside The queue is a single sequential loop, so this does not delay one item, it stops everything behind it for nearly 17 minutes. The failing target is also pushed back before the sleep, and the high priority queue is LIFO ( For what it is worth, I could not trigger it through unknown app ids: both Suggested shape: a short backoff, a retry cap per app, and moving a repeatedly failing app out of the queue instead of back onto the top of it. 3. No cleanup on unload
4. Hardening notes on the Lua backendNone of these are remotely exploitable. They matter because the backend is not sandboxed the way the frontend is. Path built from unvalidated IPC input. local function get_cache_path(stream_id)
return millennium.get_install_path() .. "/cache_" .. stream_id .. ".json"
end
App id interpolated into the URL. Correct already: no 5. Transparency: the HLTB data comes from a third partyThe feature is presented as HowLongToBeat and the metric ids are To state the thing a reviewer should actually answer: only the app id leaves the machine, over HTTPS, to two hardcoded hosts. No SteamID, no account identifier, no library listing, no telemetry, no analytics. I grepped for the usual suspects and found none: no 6. Smaller points
Happy to re-test once the build is sorted, and to take screenshots of the sort views for the PR if that helps. |
|
@Norphirion, thank you very much for your thorough analysis of my codebase and for your detailed feedback |
|
Over the last couple of days I have been working on addressing all issues raised by @Norphirion's comment. Today I was able to finish all the needed work. 1. Build Configuration 2. Queue Architecture (The 16-Minute Block)
3. Plugin Unload / Dismount 4. Lua Backend Hardening
5. Transparency 6. Minor Fixes
The build successfully passes from a clean checkout on my end. |
Re-checked on Build. The queue. This is a real rewrite, not a patch. The The detail I want to call out, because it is the one that actually kills the infinite loop: a failing app is now pushed onto Unload. Lua. Transparency. The README now names Minor. Two small things, neither blocking:
Installed and used this time rather than just read. The six fixes all hold in practice, and the plugin does what it says. Three problems showed up in use, and two of them share a cause. 1. The Sortium grid paints over the collection filter editorWith the filter editor open, turning Sortium on visually swallows it: the editor's controls still show but its background is gone, and reopening the editor makes the controls flicker away and back without restoring it. It is not a rendering glitch, it is an overflow. Measured on a live client with both open:
It is worse than cosmetic: The reason it looks fine normally is that the toggle also hides Steam's own grid, so there is nothing left underneath for the overflow to cover. It works by accident rather than by construction. Adding 2 and 3. The order churns for tens of seconds after sorting, and again when switching streamThese are the same bug seen twice. The grid subscribes with: const unsubscribe = queueService.subscribe(() => {
setRenderTrigger((prev) => prev + 1);
});and What makes it visible rather than subtle is where unknown values land: if (value === null || value === undefined) {
return direction === 'asc' ? Infinity : -Infinity;
}Every app without data yet is parked at one end of the list, then jumps to its real position the moment its value arrives. One jump per fetched app, twice a second. Switching metric from HLTB to Steam Hunters starts the same process over, because that stream's cache is cold, which is your third symptom rather than a separate one. Worth saying: the underlying behaviour is correct, the data does converge and the final order is right. It is purely that sorting live while the data streams in makes the list unusable during the fill. A few directions, cheapest first: debounce the subscription so re-sorts happen at most every second or two; hold the previous position of apps that have no value yet instead of sending them to the end; or only re-sort once the active stream's queue has drained, with the incremental progress shown by the counter rather than by the list moving. Also worth checking whether the grid needs to re-sort at all when the fetch that triggered the notify belongs to a stream other than the one currently displayed. For completeness, since I have a plugin that injects into that same filter editor: I checked, and the element covering the editor is Sortium's, not mine. |
|
Thank you for verifying the initial fixes and for the continued testing. I am also grateful that we were able to discuss some of the fixes through discord. This comment will serve more as documentation. Here is how I addressed the new findings: 1. The Sortium Grid & Collection Filter Overlap 2 & 3. Sorting Churn & Visual Feedback |
Adds Sortium https://github.com/SalvadorCorreia/Sortium as a submodule under
plugins/.Sortium introduces advanced collection sorting to the Steam client using external data metrics.
Key Features
MIT licensed.