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
72 changes: 42 additions & 30 deletions Knossos.NET/Classes/KnUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,50 +411,62 @@ public static void OpenFolder(string path)
/// <returns></returns>
/// <exception cref="DirectoryNotFoundException"></exception>
/// <exception cref="TaskCanceledException"></exception>
public static async Task CopyDirectoryAsync(string sourceDir, string destinationDir, bool recursive, CancellationTokenSource cancelSource, Action<string>? progressCallback = null)
public static async Task<bool> CopyDirectoryAsync(string sourceDir, string destinationDir, bool recursive, CancellationTokenSource cancelSource,
Action<string>? progressCallback = null, string[]? ignoreExtensions = null)
{
await Task.Run(async () =>
return await Task.Run(async () =>
{
var dir = new DirectoryInfo(sourceDir);
try
{
var dir = new DirectoryInfo(sourceDir);

if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");

var dirs = dir.GetDirectories();
var dirs = dir.GetDirectories();

Directory.CreateDirectory(destinationDir);
Directory.CreateDirectory(destinationDir);

foreach (var file in dir.GetFiles())
{
if (cancelSource.IsCancellationRequested)
{
throw new TaskCanceledException();
}
var targetFilePath = Path.Combine(destinationDir, file.Name);
if (progressCallback != null)
{
progressCallback(file.Name);
}
file.CopyTo(targetFilePath);
}

if (recursive)
{
foreach (var subDir in dirs)
foreach (var file in dir.GetFiles())
{
if (cancelSource.IsCancellationRequested)
{
throw new TaskCanceledException();
}
if (ignoreExtensions == null || !ignoreExtensions.Contains(file.Extension.ToLower()))
{
var targetFilePath = Path.Combine(destinationDir, file.Name);
if (progressCallback != null)
{
progressCallback(file.Name);
}
file.CopyTo(targetFilePath);
}
}

var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
await CopyDirectoryAsync(subDir.FullName, newDestinationDir, true, cancelSource, progressCallback);
if (recursive)
{
foreach (var subDir in dirs)
{
if (cancelSource.IsCancellationRequested)
{
throw new TaskCanceledException();
}

var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
await CopyDirectoryAsync(subDir.FullName, newDestinationDir, true, cancelSource, progressCallback);
}
}
}

Directory.SetCreationTime(destinationDir, Directory.GetCreationTime(sourceDir));
Directory.SetLastAccessTime(destinationDir, Directory.GetLastAccessTime(sourceDir));
Directory.SetLastWriteTime(destinationDir, Directory.GetLastWriteTime(sourceDir));
Directory.SetCreationTime(destinationDir, Directory.GetCreationTime(sourceDir));
Directory.SetLastAccessTime(destinationDir, Directory.GetLastAccessTime(sourceDir));
Directory.SetLastWriteTime(destinationDir, Directory.GetLastWriteTime(sourceDir));
}catch(Exception ex)
{
Log.Add(Log.LogSeverity.Error, "KnUtils.CopyDirectoryAsync()", ex);
return false;
}
return true;
});
}

Expand Down
2 changes: 1 addition & 1 deletion Knossos.NET/ViewModels/FsoBuildsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ internal async void CommandAddUserBuild()
if (MainWindow.instance != null)
{
var dialog = new AddUserBuildView();
dialog.DataContext = new AddUserBuildViewModel();
dialog.DataContext = new AddUserBuildViewModel(dialog);

await dialog.ShowDialog<AddUserBuildView?>(MainWindow.instance);
}
Expand Down
107 changes: 52 additions & 55 deletions Knossos.NET/ViewModels/Windows/AddUserBuildViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Avalonia.Platform.Storage;
using Avalonia.Controls;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Knossos.NET.Classes;
Expand All @@ -8,6 +9,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Knossos.NET.ViewModels
Expand Down Expand Up @@ -55,23 +57,33 @@ public partial class AddUserBuildViewModel : ViewModelBase
[ObservableProperty]
internal bool riscv64 = false;
[ObservableProperty]
internal bool modCreated = false;
[ObservableProperty]
internal int copyProgress = 0;
[ObservableProperty]
internal int maxFiles = 100;

[ObservableProperty]
internal string buildNewPath = string.Empty;

[ObservableProperty]
internal bool collapseData = false;
[ObservableProperty]
internal bool collapseArch = false;
[ObservableProperty]
internal bool collapseExecs = false;

private string buildId = string.Empty;
private string? folderPath = null;

private Window? window = null;

public AddUserBuildViewModel()
{
}

public AddUserBuildViewModel(Window window)
{
this.window = window;
}

internal async void OpenFolderCommand()
{
try
Expand All @@ -83,15 +95,15 @@ internal async void OpenFolderCommand()
string[] execs;
if (KnUtils.IsWindows)
{
execs=Directory.GetFiles(folderPath, "*.exe");
execs=Directory.GetFiles(folderPath, "*.exe", SearchOption.AllDirectories);
}
else if (KnUtils.IsMacOS)
{
execs=Directory.GetDirectories(folderPath, "*.app");
execs=Directory.GetDirectories(folderPath, "*.app", SearchOption.AllDirectories);
}
else
{
execs=Directory.GetFiles(folderPath, "*.AppImage");
execs=Directory.GetFiles(folderPath, "*.AppImage", SearchOption.AllDirectories);
}
ScanResults += "\nDetected Executables: " + execs.Count();
foreach (string exe in execs)
Expand All @@ -103,7 +115,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("fs2_open"))
{
DebugFile = file.Name;
DebugFile = Path.GetRelativePath(folderPath, exe);
if (BuildVersion == string.Empty)
{
ParseVersion(file.Name);
Expand All @@ -114,7 +126,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("fred2_open"))
{
Fred2Debug = file.Name;
Fred2Debug = Path.GetRelativePath(folderPath, exe);
if (BuildVersion == string.Empty)
{
ParseVersion(file.Name);
Expand All @@ -125,7 +137,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("qtfred"))
{
QtFredDebug = file.Name;
QtFredDebug = Path.GetRelativePath(folderPath, exe);
}
}
}
Expand All @@ -134,7 +146,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("fs2_open"))
{
Release = file.Name;
Release = Path.GetRelativePath(folderPath, exe);
if (BuildVersion == string.Empty)
{
ParseVersion(file.Name);
Expand All @@ -145,7 +157,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("fred2_open"))
{
Fred2 = file.Name;
Fred2 = Path.GetRelativePath(folderPath, exe);
if (BuildVersion == string.Empty)
{
ParseVersion(file.Name);
Expand All @@ -156,7 +168,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("qtfred"))
{
QtFred = file.Name;
QtFred = Path.GetRelativePath(folderPath, exe);
}
}
}
Expand Down Expand Up @@ -224,7 +236,10 @@ private void ParseVersion(string filename)
FolderPickerOpenOptions options = new FolderPickerOpenOptions();
options.AllowMultiple = false;
options.Title = "Select the folder containing the FSO execs files";
var result = await MainWindow.instance.StorageProvider.OpenFolderPickerAsync(options);

var topmostWindow = window == null ? MainWindow.instance : window;

var result = await topmostWindow.StorageProvider.OpenFolderPickerAsync(options);
if (result != null && result.Count > 0)
return result[0].Path.LocalPath.ToString();
else
Expand Down Expand Up @@ -304,22 +319,20 @@ internal async void ChangeQtFredDebugCommand()

public async Task<string?> GetPath(string? folderRoot)
{
if(MainWindow.instance != null && folderPath != null)
if(MainWindow.instance != null && folderRoot != null)
{
FilePickerOpenOptions options = new FilePickerOpenOptions();
options.AllowMultiple = false;
options.Title = "Select the executable file";
if (folderRoot != null)
{
options.SuggestedStartLocation = await MainWindow.instance.StorageProvider.TryGetFolderFromPathAsync(folderRoot);
}
options.SuggestedStartLocation = await MainWindow.instance.StorageProvider.TryGetFolderFromPathAsync(folderRoot);

var topmostWindow = window == null ? MainWindow.instance : window;

var result = await MainWindow.instance.StorageProvider.OpenFilePickerAsync(options);
var result = await topmostWindow.StorageProvider.OpenFilePickerAsync(options);

if (result != null && result.Count > 0)
{
var file = new FileInfo(result[0].Path.LocalPath.ToString());
return file.Name;
return Path.GetRelativePath(folderRoot, result[0].Path.LocalPath.ToString());
}
}
return null;
Expand All @@ -331,10 +344,14 @@ internal async void AddCommand()
{
return;
}

if (folderPath != null)
{
if(await CopyFilesRecursively(folderPath, BuildNewPath))
CollapseData = true;
CollapseExecs = true;
CollapseArch = true;
string[] ignoreList = { ".pdb", ".lib", ".exp", ".a", ".map" };
if(await KnUtils.CopyDirectoryAsync(folderPath, BuildNewPath, true, new CancellationTokenSource(), copyCallback, ignoreList))
{
Mod mod = new Mod();
mod.fullPath = BuildNewPath + Path.DirectorySeparatorChar;
Expand Down Expand Up @@ -485,7 +502,14 @@ internal async void AddCommand()
Knossos.AddBuild(userBuild);
FsoBuildsViewModel.Instance?.AddBuildToUi(userBuild);

ModCreated = true;
Dispatcher.UIThread.Invoke(() => { window?.Close(); });
}
else
{
CollapseData = false;
CollapseExecs = false;
CollapseArch = false;
await MessageBox.Show(window, "An error has ocurred while copying files", "Filecopy error", MessageBox.MessageBoxButtons.OK);
}
}
}
Expand Down Expand Up @@ -531,37 +555,10 @@ private bool Verify()
return true;
}

private async Task<bool> CopyFilesRecursively(string sourcePath, string targetPath)
private async void copyCallback(string filename)
{
return await Task<bool>.Factory.StartNew(() => {
try
{
Directory.CreateDirectory(targetPath);
foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
{
Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
}
var allFiles = Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories);
Dispatcher.UIThread.Invoke(()=> MaxFiles = allFiles.Length );
foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
{
if (!newPath.ToLower().Contains(".pdb") && !newPath.ToLower().Contains(".lib") && !newPath.ToLower().Contains(".exp") && !newPath.ToLower().EndsWith(".a"))
{
System.IO.File.Copy(newPath, newPath.Replace(sourcePath, targetPath), true);
}
Dispatcher.UIThread.Invoke(() => CopyProgress++);
}
return true;
}
catch (Exception ex)
{
Log.Add(Log.LogSeverity.Error, "AddUserBuildViewModel.CopyFilesRecursively()", ex);
if (MainWindow.instance != null)
{
MessageBox.Show(MainWindow.instance, "Error while copying files:\n"+ex.Message.ToString(), "Filecopy error", MessageBox.MessageBoxButtons.OK);
}
return false;
}
await Dispatcher.UIThread.InvokeAsync(() => {
CopyProgress++;
});
}
}
Expand Down
Loading