feat(magos-modificus): Phase 4 Stage 5 mod-list update badges + per-mod update - #43
Merged
Merged
Conversation
Two convention refinements for agent output discipline: 1. Don't surface implementation-detail questions to the operator without grounding the actual problem in plain terms. Decide internal plumbing yourself; reserve surfaced questions for genuine forks (irreversible, UI design shape, external deps, real user-facing trade-offs). Includes the one-sentence-non-plumbing-WHY test. 2. AGENTS.md tweaks ride in the current PR; convention fine-tuning does not need its own docs PR.
…od update Wires the update-check service into the mod-list UI: per-row update markers, a premium-only one-click Update button, a configurable periodic check + a manual thorough check, and the supporting fixes discovered during testing. UI (ModListView + ModItemViewModel + ModListViewModel): - Source badge is now a HyperlinkButton linking to the mod's Nexus page (or GitHub repo). The update-available marker shows 'Update available' text alongside a drawn accent Ellipse, linked to the mod's files tab. - Per-mod Update button (premium-only, hidden for non-premium): a drawn download-arrow that calls AcquireLatestNexusAsync, shows an indeterminate spinner during, reloads on success (marker clears via a fresh check), alerts on failure. One update at a time. - Header: a refresh button for manual 'check now' (with spinner), a rate-limit notice, and a 'showing recent updates' notice after Month-only checks. The mod count was removed (stale-INPC bug; operator's call). Update check (UpdateCheckService + UpdateCheckRunner): - Periodic check (configurable interval, default 10 min, toggle in the Integrations dialog) fires Month-only (1 API call). The manual 'check now' fires CheckThoroughAsync (per-mod ListModFilesAsync for mods outside the Month window, catching mods whose latest release is > 1 month old). - UpdateCheckResult gains a Thorough flag so the UI can show 'recent-only' vs 'complete' coverage. Comparison-basis fix (ModVersion.RemoteUploadedAt): - The check now compares the imported file's Nexus publish date (RemoteUploadedAt, captured at acquisition) against the latest file's publish date, not against ImportAt (when Magos imported it). Fixes the bug where reinstalling an older file masked available updates. - RemoteUploadedAt flows: acquisition captures ModFile.UploadedTimestamp -> Import -> AddVersion -> ModVersion.RemoteUploadedAt. The check falls back to ImportedAt for versions imported before this change. Backend (Integrations): - AcquireLatestNexusAsync: resolves the newest non-archived MAIN file + forwards to the existing AcquireFromNexusAsync (the premium/auth-only path). Shared LatestMain helper used by both the acquisition + the thorough check. Concurrency: the CheckCompleted handler marshals to the UI thread via an injectable Action<Action> seam (the established NxmModDownloadHandler pattern). Tests: 818 passing (+65 new). Operator UAT-verified: marker text, source-badge link, Integrations dialog interval controls, manual thorough check catches the Numeric UI case, marker clears after update.
This was referenced Jul 8, 2026
ModifAmorphic
added a commit
that referenced
this pull request
Jul 8, 2026
🤖 I have created a release *beep* *boop* --- ## 0.1.0 (2026-07-08) ### Features * **component-a:** Hybrid Rust+C discovery + shell + launcher ([#1](#1)) ([491e5d1](491e5d1)) * **magos-modificus:** implement Phase 1 Enginseer-client launch façade ([#20](#20)) ([7950ed1](7950ed1)) * **magos-modificus:** implement Phase 1 Integrations (GitHub Releases client) ([#19](#19)) ([781d65c](781d65c)) * **magos-modificus:** implement Phase 1 Profiles library ([#17](#17)) ([f355ceb](f355ceb)) * **magos-modificus:** implement Phase 1 Steam discovery library ([#18](#18)) ([8f6ec00](8f6ec00)) * **magos-modificus:** implement Phase 2 shared-first mod storage ([#22](#22)) ([cf2af80](cf2af80)) * **magos-modificus:** Phase 3 Track B mod-list, import, source model ([#29](#29)) ([5075cee](5075cee)) * **magos-modificus:** Phase 3 Track C launch + Settings + escape-hatch + base-folder mod loading ([#32](#32)) ([c595700](c595700)) * **magos-modificus:** Phase 4 Stage 1 nxm scheme handler + IPC ([#34](#34)) ([0017529](0017529)) * **magos-modificus:** Phase 4 Stage 2 Nexus auth + Integrations dialog ([#35](#35)) ([0790a8e](0790a8e)) * **magos-modificus:** Phase 4 Stage 3 Nexus mod acquisition ([#36](#36)) ([d01105f](d01105f)) * **magos-modificus:** Phase 4 Stage 4 Nexus update-check service ([#39](#39)) ([1749e76](1749e76)) * **magos-modificus:** Phase 4 Stage 5 mod-list update badges + per-mod update ([#43](#43)) ([423e146](423e146)) * **magos-modificus:** Phase 4 Stage 6 DMF new-profile/auth prompt ([#44](#44)) ([994b4f8](994b4f8)) * **magos-modificus:** scaffold .NET 10 + Avalonia 12 app + libraries ([#16](#16)) ([d1fac91](d1fac91)) * **mod-loader:** own the load-order contract (mods.lst), drop DMF prepend ([#14](#14)) ([1ccb891](1ccb891)) * **release:** add Curator release pipeline ([#49](#49)) ([01517e4](01517e4)) * **runtime:** engine-context proven — trampoline, Enginseer v1, launcher fail-fast ([#4](#4)) ([4565ba8](4565ba8)) * **runtime:** Enginseer v2 — mod loader + launcher config + logging ([#5](#5)) ([1e65b3f](1e65b3f)) * **runtime:** package Enginseer with the runtime; relocate build files to runtime/ ([#6](#6)) ([7221bdb](7221bdb)) * **ui:** Phase 3 Track A — app shell + profile management ([#27](#27)) ([f7f8250](f7f8250)) * **ui:** Phase 3 Track D — Preferences + i18n + custom title bars + icon ([#28](#28)) ([c921650](c921650)) ### Bug Fixes * **enginseer:** DMF integration fixes — IO re-root, load timing, destroy ([#7](#7)) ([401759c](401759c)) * **magos-modificus:** multi-format archive import (zip + 7z + rar) ([#41](#41)) ([ee4f5c6](ee4f5c6)) * **magos-modificus:** search all Steam libraries for the compatdata prefix ([#21](#21)) ([895fa2b](895fa2b)) * **steam:** detect running Darktide via /proc argv[0] under Proton ([#23](#23)) ([c5f38c4](c5f38c4)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: ModifAmorphic <86930443+ModifAmorphic@users.noreply.github.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
Wires the update-check service into the mod-list UI: per-row update markers, a premium-only one-click Update button, a configurable periodic check + manual thorough check, and the comparison-basis fix for the update check.
UI (ModListView + ModItemViewModel + ModListViewModel)
Update check (UpdateCheckService + UpdateCheckRunner)
Comparison-basis fix (ModVersion.RemoteUploadedAt)
The update check now compares the imported file Nexus publish date (RemoteUploadedAt, captured at acquisition) against the latest file publish date, not against ImportedAt (when Magos imported it). This fixes the bug where reinstalling an older file today masked available updates (the import time was newer than any past file upload).
RemoteUploadedAt flows: acquisition captures ModFile.UploadedTimestamp, passes it through Import to AddVersion to ModVersion.RemoteUploadedAt. The check falls back to ImportedAt for versions imported before this change (backward-compatible).
Backend (Integrations)
AcquireLatestNexusAsync: resolves the newest non-archived MAIN file and forwards to the existing AcquireFromNexusAsync (the premium/auth-only path). A shared LatestMain helper is used by both the acquisition and the thorough check.
Concurrency
The CheckCompleted handler marshals to the UI thread via an injectable Action seam (the established NxmModDownloadHandler pattern), preventing off-thread Mods iteration racing with UI-thread Reload.
Tests + verification
818 tests passing (+65 new). Operator UAT-verified: marker text, source-badge link, Integrations dialog interval controls, manual thorough check catches mods outside the Month window (Numeric UI scenario), marker clears after update. Build: 0 warnings.