Working validate files dialog
Very basic, but it will compare local files against what's available on the server and allow you to selectively replace them. Save paths are ignored to avoid accidental replacement. Implements #142
This commit is contained in:
parent
a734ef9793
commit
65be58fbf2
6 changed files with 77 additions and 14 deletions
|
|
@ -192,12 +192,11 @@ else
|
|||
{
|
||||
Title = $"File Conflicts",
|
||||
Maximizable = false,
|
||||
DefaultMaximized = false,
|
||||
DefaultMaximized = true,
|
||||
Closable = true,
|
||||
Draggable = true,
|
||||
Centered = true,
|
||||
OkText = "Replace",
|
||||
Footer = null,
|
||||
OkText = "Replace Selected",
|
||||
};
|
||||
|
||||
var modalRef = ModalService.CreateModal<ValidateFilesDialog, Game>(modalOptions, Model.DataItem as Game);
|
||||
|
|
|
|||
|
|
@ -5,13 +5,34 @@
|
|||
@inject SDK.Client Client
|
||||
@inject IMessageService MessageService
|
||||
|
||||
<Table DataSource="Conflicts" Size="TableSize.Small" RowKey="c => c.FullName" @bind-SelectedRows="Selected">
|
||||
<Table DataSource="Conflicts" Resizable Size="TableSize.Small" RowKey="c => c.FullName" @bind-SelectedRows="Selected" Loading="Loading">
|
||||
<Selection Type="checkbox" />
|
||||
<PropertyColumn Property="c => c.FullName" Title="Name" />
|
||||
<Column TData="string" Title="Created">
|
||||
@context.LocalFileInfo?.CreationTime
|
||||
</Column>
|
||||
<Column TData="string" Title="Modified">
|
||||
@context.LocalFileInfo?.LastWriteTime
|
||||
</Column>
|
||||
<Column TData="string" Title="Local Size">
|
||||
@if (context.LocalFileInfo?.Length > 0)
|
||||
{
|
||||
@ByteSizeLib.ByteSize.FromBytes(context.LocalFileInfo.Length)
|
||||
}
|
||||
</Column>
|
||||
<PropertyColumn Property="c => c.Length" Title="Original Size">
|
||||
@if (context.Length > 0)
|
||||
{
|
||||
@ByteSizeLib.ByteSize.FromBytes(context.Length)
|
||||
}
|
||||
</PropertyColumn>
|
||||
</Table>
|
||||
|
||||
@code {
|
||||
IEnumerable<ArchiveEntry> Conflicts = new List<ArchiveEntry>();
|
||||
IEnumerable<ArchiveEntry> Selected = new List<ArchiveEntry>();
|
||||
IEnumerable<ArchiveValidationConflict> Conflicts = new List<ArchiveValidationConflict>();
|
||||
IEnumerable<ArchiveValidationConflict> Selected = new List<ArchiveValidationConflict>();
|
||||
|
||||
bool Loading = true;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
|
@ -26,12 +47,22 @@
|
|||
async Task LoadData()
|
||||
{
|
||||
Conflicts = await Client.Games.ValidateFilesAsync(Options.InstallDirectory, Options.Id);
|
||||
|
||||
Loading = false;
|
||||
}
|
||||
|
||||
public override async Task OnFeedbackOkAsync(ModalClosingEventArgs args)
|
||||
{
|
||||
Loading = true;
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
|
||||
await Client.Games.DownloadFilesAsync(Options.InstallDirectory, Options.Id, Selected.Select(e => e.FullName));
|
||||
|
||||
Loading = false;
|
||||
StateHasChanged();
|
||||
await Task.Yield();
|
||||
|
||||
await base.CloseFeedbackAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ public class ArchiveEntry
|
|||
public string FullName { get; set; }
|
||||
public string Name { get; set; }
|
||||
public uint Crc32 { get; set; }
|
||||
public long Length { get; set; }
|
||||
}
|
||||
13
LANCommander.SDK/Models/ArchiveValidationConflict.cs
Normal file
13
LANCommander.SDK/Models/ArchiveValidationConflict.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System.IO;
|
||||
|
||||
namespace LANCommander.SDK.Models
|
||||
{
|
||||
public class ArchiveValidationConflict
|
||||
{
|
||||
public string FullName { get; set; }
|
||||
public string Name { get; set; }
|
||||
public uint Crc32 { get; set; }
|
||||
public long Length { get; set; }
|
||||
public FileInfo LocalFileInfo { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1025,20 +1025,33 @@ namespace LANCommander.SDK.Services
|
|||
/// <param name="installDirectory">The game's install directory</param>
|
||||
/// <param name="gameId">The game's ID</param>
|
||||
/// <returns>List of file conflicts</returns>
|
||||
public async Task<IEnumerable<ArchiveEntry>> ValidateFilesAsync(string installDirectory, Guid gameId)
|
||||
public async Task<IEnumerable<ArchiveValidationConflict>> ValidateFilesAsync(string installDirectory, Guid gameId)
|
||||
{
|
||||
var manifest = await ManifestHelper.ReadAsync(installDirectory, gameId);
|
||||
var archive = await Client.GetRequestAsync<Archive>($"/api/Archives/Contents/{gameId}/{manifest.Version}");
|
||||
var entries = await Client.GetRequestAsync<IEnumerable<ArchiveEntry>>($"/api/Archives/{archive.Id}");
|
||||
var entries = await Client.GetRequestAsync<IEnumerable<ArchiveEntry>>($"/api/Archives/Contents/{gameId}/{manifest.Version}");
|
||||
|
||||
var conflictedEntries = new List<ArchiveEntry>();
|
||||
var conflictedEntries = new List<ArchiveValidationConflict>();
|
||||
|
||||
var savePathEntries = manifest.SavePaths?.SelectMany(p => Client.Saves.GetFileSavePathEntries(p, installDirectory)) ?? new List<SavePathEntry>();
|
||||
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
if (savePathEntries.Any(e => e.ArchivePath.Equals(entry.FullName, StringComparison.OrdinalIgnoreCase)))
|
||||
continue;
|
||||
|
||||
if (entry.FullName.EndsWith('/'))
|
||||
continue;
|
||||
|
||||
var localFile = Path.Combine(installDirectory, entry.FullName.Replace('/', Path.DirectorySeparatorChar));
|
||||
|
||||
if (!Path.Exists(localFile))
|
||||
conflictedEntries.Add(entry);
|
||||
conflictedEntries.Add(new ArchiveValidationConflict
|
||||
{
|
||||
Name = entry.Name,
|
||||
FullName = entry.FullName,
|
||||
Crc32 = entry.Crc32,
|
||||
Length = entry.Length,
|
||||
});
|
||||
else
|
||||
{
|
||||
uint crc = 0;
|
||||
|
|
@ -1062,7 +1075,13 @@ namespace LANCommander.SDK.Services
|
|||
}
|
||||
|
||||
if (crc == 0 || crc != entry.Crc32)
|
||||
conflictedEntries.Add(entry);
|
||||
conflictedEntries.Add(new ArchiveValidationConflict
|
||||
{
|
||||
Name = entry.Name,
|
||||
FullName = entry.FullName,
|
||||
Crc32 = entry.Crc32,
|
||||
LocalFileInfo = new FileInfo(localFile)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1096,7 +1115,6 @@ namespace LANCommander.SDK.Services
|
|||
{
|
||||
Overwrite = true,
|
||||
PreserveFileTime = true,
|
||||
PreserveAttributes = true,
|
||||
});
|
||||
}
|
||||
else // Skip to next entry
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ namespace LANCommander.Server.Controllers.Api
|
|||
{
|
||||
FullName = entry.FullName,
|
||||
Name = entry.Name,
|
||||
Crc32 = entry.Crc32
|
||||
Crc32 = entry.Crc32,
|
||||
Length = entry.Length,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue