Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,26 @@ public class ModUpdateDialogViewModel : ObservableObject
/// </summary>
public bool CanDownload { get; set; }

/// <summary/>
public ModUpdateDialogViewModel(Updater updater, ModUpdateSummary summary)
/// <summary>
/// Creates the ViewModel using precomputed update info.
/// </summary>
public ModUpdateDialogViewModel(Updater updater, ModUpdateSummary summary, ModUpdate[] updateInfo)
{
Updater = updater;
Summary = summary;
UpdateInfo = Summary.GetUpdateInfo();
UpdateInfo = updateInfo;
TotalSize = UpdateInfo.Sum(x => x.UpdateSize);
SelectedUpdate = UpdateInfo[0];
CanDownload = true;

if (UpdateInfo.Length > 0)
{
SelectedUpdate = UpdateInfo[0];
CanDownload = true;
}
else
{
SelectedUpdate = null;
CanDownload = false;
}
}

/// <summary>
Expand Down
7 changes: 6 additions & 1 deletion source/Reloaded.Mod.Launcher.Lib/Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,14 @@ public static async Task<bool> CheckForModUpdatesAsync()

if (updateDetails.HasUpdates())
{
// Fetch update metadata (download sizes, changelogs) on a background thread.
// Doing this inside the ViewModel constructor blocked the UI thread on
// unbounded network I/O, freezing the launcher on startup. See issue #910.
var updateInfo = await updateDetails.GetUpdateInfoAsync();

Actions.SynchronizationContext.Send(_ =>
{
Actions.ShowModUpdateDialog.Invoke(new ModUpdateDialogViewModel(updater, updateDetails));
Actions.ShowModUpdateDialog.Invoke(new ModUpdateDialogViewModel(updater, updateDetails, updateInfo));
}, null);

return true;
Expand Down
71 changes: 41 additions & 30 deletions source/Reloaded.Mod.Loader.Update/Structures/ModUpdateSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,61 +39,72 @@ public bool HasUpdates()

/// <summary>
/// Retrieves info about the individual updates.
/// Synchronous wrapper; do not call from the UI thread. Prefer <see cref="GetUpdateInfoAsync"/>.
/// </summary>
/// <returns></returns>
public ModUpdate[] GetUpdateInfo()
public ModUpdate[] GetUpdateInfo() => Task.Run(GetUpdateInfoAsync).GetAwaiter().GetResult();

/// <summary>
/// Retrieves info about the individual updates without blocking the calling thread.
/// </summary>
/// <returns></returns>
public async Task<ModUpdate[]> GetUpdateInfoAsync()
{
if (_updates != null)
return _updates;

_updates = new ModUpdate[ManagerModResultPairs.Count];
Task.Run(async () =>
var updates = new ModUpdate[ManagerModResultPairs.Count];
for (var x = 0; x < ManagerModResultPairs.Count; x++)
{
for (var x = 0; x < ManagerModResultPairs.Count; x++)
var resultPairs = ManagerModResultPairs[x];
var modName = resultPairs.ModTuple.Config.ModName;
var modId = resultPairs.ModTuple.Config.ModId;
var oldVersion = resultPairs.ModTuple.Config.ModVersion;
var newVersion = resultPairs.Result.LastVersion;
var resolver = resultPairs.Manager.Resolver;
var updateSize = (long)0;
string? changelog = null;

if (resolver is IPackageResolverDownloadSize hasDownloadSize)
{
var resultPairs = ManagerModResultPairs[x];
var modName = resultPairs.ModTuple.Config.ModName;
var modId = resultPairs.ModTuple.Config.ModId;
var oldVersion = resultPairs.ModTuple.Config.ModVersion;
var newVersion = resultPairs.Result.LastVersion;
var resolver = ((IPackageResolverDownloadSize)resultPairs.Manager.Resolver);
var updateSize = (long)0;
string? changelog = null;

try
{
updateSize = await resolver.GetDownloadFileSizeAsync(newVersion!, resultPairs.ModTuple.GetVerificationInfo());
updateSize = await hasDownloadSize.GetDownloadFileSizeAsync(newVersion!, resultPairs.ModTuple.GetVerificationInfo()).ConfigureAwait(false);
Comment thread
Sewer56 marked this conversation as resolved.
}
catch (Exception) { /* Ignored */ }
}

// Get changelog from supported resolver.
if (resolver is IPackageResolverGetLatestReleaseMetadata getMetadata)
// Get changelog from supported resolver.
if (resolver is IPackageResolverGetLatestReleaseMetadata getMetadata)
{
try
{
try
{
var releaseMetadata = await getMetadata.GetReleaseMetadataAsync(default);
var extraData = releaseMetadata?.GetExtraData<ReleaseMetadataExtraData>();
if (extraData != null)
changelog = extraData.Changelog;
}
catch (Exception) { /* Ignored */ }
var releaseMetadata = await getMetadata.GetReleaseMetadataAsync(default).ConfigureAwait(false);
var extraData = releaseMetadata?.GetExtraData<ReleaseMetadataExtraData>();
if (extraData != null)
changelog = extraData.Changelog;
}
catch (Exception) { /* Ignored */ }
}

// NuGet has special case, since it doesn't support release metadata but supports changelogs in nuspec.
if (string.IsNullOrEmpty(changelog) && resolver is NuGetUpdateResolver nugetResolver)
// NuGet has special case, since it doesn't support release metadata but supports changelogs in nuspec.
if (string.IsNullOrEmpty(changelog) && resolver is NuGetUpdateResolver nugetResolver)
{
try
{
var copiedSettings = nugetResolver.GetResolverSettings();
var repository = NugetRepository.FromSourceUrl(copiedSettings.NugetRepository!.SourceUrl);
var reader = await repository.DownloadNuspecReaderAsync(new PackageIdentity(copiedSettings.PackageId, newVersion!));
var reader = await repository.DownloadNuspecReaderAsync(new PackageIdentity(copiedSettings.PackageId, newVersion!)).ConfigureAwait(false);
if (reader != null)
changelog = reader?.GetReleaseNotes();
}

_updates[x] = new ModUpdate(modId, NuGetVersion.Parse(oldVersion), newVersion!, updateSize, changelog, modName);
catch (Exception) { /* Ignored */ }
}

}).Wait();
updates[x] = new ModUpdate(modId, NuGetVersion.Parse(oldVersion), newVersion!, updateSize, changelog, modName);
}

_updates = updates;
return _updates;
}

Expand Down