Skip to content

Commit

Permalink
[Updater] Show zipmod files with changed version in filename as a sin…
Browse files Browse the repository at this point in the history
…gle entry
  • Loading branch information
ManlyMarco committed Aug 27, 2024
1 parent e5fa511 commit e7e170d
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 10 deletions.
8 changes: 7 additions & 1 deletion src/KKManager.Core/Util/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,15 @@ public static async Task<bool> WithTimeout(this Task task, TimeSpan timeout, Can
}

public static IEnumerable<TOut> Attempt<TIn, TOut>(this IEnumerable<TIn> source, Func<TIn, TOut> action)
{
return Attempt(source, action, (@in, e) => Console.Error.WriteLine(e));
}

public static IEnumerable<TOut> Attempt<TIn, TOut>(this IEnumerable<TIn> source, Func<TIn, TOut> action, Action<TIn, Exception> onError)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (action == null) throw new ArgumentNullException(nameof(action));
if (onError == null) throw new ArgumentNullException(nameof(onError));

foreach (var item in source)
{
Expand All @@ -84,7 +90,7 @@ public static IEnumerable<TOut> Attempt<TIn, TOut>(this IEnumerable<TIn> source,
}
catch (Exception e)
{
Console.Error.WriteLine(e);
onError(item, e);
continue;
}
yield return output;
Expand Down
91 changes: 82 additions & 9 deletions src/KKManager.Updater/Windows/ModUpdateSelectDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using BrightIdeasSoftware;
using KKManager.Functions;
using KKManager.Updater.Data;
using KKManager.Updater.Properties;
using KKManager.Updater.Sources;
using KKManager.Util;

namespace KKManager.Updater.Windows
Expand All @@ -34,15 +34,15 @@ private ModUpdateSelectDialog()

objectListView2.EmptyListMsg = Resources.ModUpdateSelect_SelectTaskToView;
objectListView2.FormatRow += ObjectListView2_FormatRow;
olvColumnFileName.AspectGetter = rowObject => ((UpdateItem)rowObject).TargetPath.FullName.Substring(InstallDirectoryHelper.GameDirectory.FullName.Length);
olvColumnFileName.AspectName = "FileName";
olvColumnFileDate.AspectGetter = rowObject =>
{
var date = ((UpdateItem)rowObject).RemoteFile?.ModifiedTime;
var date = ((UpdateItemListData)rowObject).Modified;
if (date == null || date == DateTime.MinValue)
return Resources.ModUpdateSelect_WillBeRemoved;
return date.Value.ToShortDateString();
};
olvColumnFileSize.AspectGetter = rowObject => ((UpdateItem)rowObject).GetDownloadSize();
olvColumnFileSize.AspectName = "Size";
}

public static List<UpdateTask> ShowWindow(ModUpdateProgressDialog owner, List<UpdateTask> updateTasks)
Expand Down Expand Up @@ -92,11 +92,11 @@ private void buttonAccept_Click(object sender, EventArgs e)

private static void ObjectListView2_FormatRow(object sender, FormatRowEventArgs e)
{
if (e.Model is UpdateItem task)
if (e.Model is UpdateItemListData item)
{
if (task is DeleteFileUpdateItem || task.RemoteFile == null)
if (item.IsDeleted)
e.Item.ForeColor = Color.DarkRed;
else if (!task.TargetPath.Exists)
else if (item.IsNew)
e.Item.ForeColor = Color.Green;
}
}
Expand Down Expand Up @@ -133,8 +133,16 @@ private void objectListView1_ItemChecked(object sender, ItemCheckedEventArgs e)

private void objectListView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
var selection = objectListView1.SelectedObject as UpdateTask;
objectListView2.SetObjects(selection?.Items);
if (objectListView1.SelectedObject is UpdateTask selection)
{
var listItems = UpdateItemListData.ToListItems(selection.Items);
objectListView2.SetObjects(listItems);
}
else
{
objectListView2.ClearObjects();
}

if (objectListView2.GetItemCount() > 0)
objectListView2.AutoResizeColumns();
}
Expand All @@ -144,5 +152,70 @@ private void UpdateDownloadSizeLabel()
var sumFileSizes = FileSize.SumFileSizes(objectListView1.CheckedObjects.Cast<UpdateTask>().Select(x => x.TotalUpdateSize));
labelDownload.Text = sumFileSizes == FileSize.Empty ? Resources.ModUpdateSelect_SizeStatus_Nothing : string.Format(Resources.ModUpdateSelect_SizeStatus_BytesToDownload, sumFileSizes);
}

private sealed class UpdateItemListData
{
public static List<UpdateItemListData> ToListItems(List<UpdateItem> allUpdates)
{
// The goal is to correctly display if a zipmod is actually removed or just updated with a different filename
// Currently: strip the version number from the filename and group by the name, then do dirty work on the grouped UpdateItems
// TODO Do this properly by detecting these pairs in the UpdateItem factory, somehow, maybe

var allUpdatesWithVersions = allUpdates.Attempt(item =>
{
var match = Regex.Match(item.RemoteFile?.Name ?? item.TargetPath.Name, @"^(.+?)[_ -]v(\d+(\.\d+)*)\.zipmod$", RegexOptions.IgnoreCase);

var hasVersion = match.Success;

// Version extraction if it's ever needed in the future
//Version version = null;
//if (hasVersion)
//{
// var versionString = match.Groups[2].Value;
// // If version is just a single number, add .0 to the end so `new Version()` doesn't crash
// if (!match.Groups[3].Success) versionString += ".0";
// version = new Version(versionString);
//}

return new { item, name = hasVersion ? match.Groups[1].Value : null };
}, (item, exception) => Console.WriteLine($@"[Updater] WARN: Failed to parse filename of '{item}' - {exception.Message}")).ToList();

var results = new List<UpdateItemListData>(allUpdates.Count);

foreach (var group in allUpdatesWithVersions.GroupBy(x => x.name))
{
if (group.Key == null)
results.AddRange(group.Select(x => new UpdateItemListData(new[] { x.item })));
else
results.Add(new UpdateItemListData(group.Select(x => x.item).ToList()));
}

results.Sort((data1, data2) => string.Compare(data1.FileName, data2.FileName, StringComparison.CurrentCultureIgnoreCase));

return results;
}

private UpdateItemListData(ICollection<UpdateItem> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
if (items.Count == 0) throw new ArgumentException(@"Value cannot be an empty collection.", nameof(items));

Size = items.Select(x => x.GetDownloadSize()).OrderByDescending(x => x).First();
IsNew = items.All(x => x.TargetPath?.Exists != true);

var latestTargetPath = items.OrderByDescending(x => x.RemoteFile != null).Select(x => x.TargetPath).Where(x => x != null).OrderByDescending(x => x.Name, StringComparer.OrdinalIgnoreCase).First();
FileName = latestTargetPath.FullName.Substring(InstallDirectoryHelper.GameDirectory.FullName.Length);

var remote = items.Select(x => x.RemoteFile).Where(x => x != null).OrderByDescending(x => x.ModifiedTime).FirstOrDefault();
Modified = remote?.ModifiedTime;
IsDeleted = remote == null;
}

public string FileName { get; }
public DateTime? Modified { get; }
public FileSize Size { get; }
public bool IsNew { get; }
public bool IsDeleted { get; }
}
}
}

0 comments on commit e7e170d

Please sign in to comment.