diff options
| author | saturneric <[email protected]> | 2026-09-24 23:25:25 +0200 |
|---|---|---|
| committer | saturneric <[email protected]> | 2026-09-24 23:25:25 +0200 |
| commit | 1c95ebf2cbb4d4c841141f568eb394f4091b6ba7 (patch) | |
| tree | edc4ae7cddc999d9500cc10dd6c83821c14fd9e0 /src/m_ver_check/UpdateChecker.cpp | |
| parent | feat(update): add robust GitHub update checking (diff) | |
| download | modules-1c95ebf2cbb4d4c841141f568eb394f4091b6ba7.tar.gz modules-1c95ebf2cbb4d4c841141f568eb394f4091b6ba7.zip | |
feat(update): track unseen releases without prompting
- replace startup dialogs with quiet background update checks
- track and persist the latest update seen by the user
- expose update attention state for badges and UI indicators
- acknowledge updates when the update page is opened
- retain acknowledgements across failures, restarts, and rebuilds
- expand tests for attention, persistence, and rediscovered releases
Diffstat (limited to 'src/m_ver_check/UpdateChecker.cpp')
| -rw-r--r-- | src/m_ver_check/UpdateChecker.cpp | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/src/m_ver_check/UpdateChecker.cpp b/src/m_ver_check/UpdateChecker.cpp index 82f62b3..d65ca03 100644 --- a/src/m_ver_check/UpdateChecker.cpp +++ b/src/m_ver_check/UpdateChecker.cpp @@ -28,6 +28,8 @@ #include "UpdateChecker.h" +#include <GFSDKApp.h> + #include <QJsonDocument> #include <QJsonObject> #include <QPointer> @@ -60,6 +62,13 @@ auto UpdateChecker::IsFresh() const -> bool { good->checked_at.secsTo(clock_()) < kFreshSeconds; } +void UpdateChecker::Acknowledge() { + if (AttentionFor(state_) == UpdateAttention::kNone) return; + state_.last_seen_update_version = state_.last_good->list.latest.version; + if (store_.save) store_.save(ToStorage(state_)); + emit Changed(); +} + void UpdateChecker::Start(CheckMode mode) { if (state_.checking) return; if (mode == CheckMode::kIfStale && IsFresh()) return; @@ -130,6 +139,9 @@ auto UpdateChecker::ToStorage(const UpdateSnapshot& s) -> QByteArray { obj["last_attempt"] = s.last_attempt.toSecsSinceEpoch(); } obj["last_attempt_failed"] = s.last_attempt_failed; + if (!s.last_seen_update_version.isEmpty()) { + obj["last_seen_update_version"] = s.last_seen_update_version; + } return QJsonDocument(obj).toJson(QJsonDocument::Compact); } @@ -142,6 +154,10 @@ auto UpdateChecker::FromStorage(const QByteArray& data, const Build& build) const auto obj = doc.object(); if (obj.value("schema").toInt() != kStorageSchema) return s; + // Which update the user has seen is not a fact about this build: an + // upgrade, or a rebuild, must not advertise it again. + s.last_seen_update_version = obj.value("last_seen_update_version").toString(); + auto good = SoftwareVersion::FromJson(obj.value("last_good").toObject()); // What was learned about another build says nothing about this one, and // neither does how asking about it went. @@ -156,7 +172,16 @@ auto UpdateChecker::FromStorage(const QByteArray& data, const Build& build) return s; } -auto ShouldPromptOnStartup(const UpdateSnapshot& s) -> bool { - return !s.checking && s.last_good && - ShouldPromptAtStartup(Decide(*s.last_good)); +auto AttentionFor(const UpdateSnapshot& s) -> UpdateAttention { + if (!s.last_good || Decide(*s.last_good) != Verdict::kUpdateAvailable) { + return UpdateAttention::kNone; + } + const auto& latest = s.last_good->list.latest.version; + const auto& seen = s.last_seen_update_version; + if (!seen.isEmpty() && + GFCompareSoftwareVersion(latest.toUtf8().constData(), + seen.toUtf8().constData()) <= 0) { + return UpdateAttention::kNone; + } + return UpdateAttention::kUpdateAvailable; } |
