diff --git a/Knossos.NET/Classes/KnUtils.cs b/Knossos.NET/Classes/KnUtils.cs
index a21d798d..a97a435a 100644
--- a/Knossos.NET/Classes/KnUtils.cs
+++ b/Knossos.NET/Classes/KnUtils.cs
@@ -411,50 +411,62 @@ public static void OpenFolder(string path)
///
///
///
- public static async Task CopyDirectoryAsync(string sourceDir, string destinationDir, bool recursive, CancellationTokenSource cancelSource, Action? progressCallback = null)
+ public static async Task CopyDirectoryAsync(string sourceDir, string destinationDir, bool recursive, CancellationTokenSource cancelSource,
+ Action? 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;
});
}
diff --git a/Knossos.NET/ViewModels/FsoBuildsViewModel.cs b/Knossos.NET/ViewModels/FsoBuildsViewModel.cs
index da660005..6ea34934 100644
--- a/Knossos.NET/ViewModels/FsoBuildsViewModel.cs
+++ b/Knossos.NET/ViewModels/FsoBuildsViewModel.cs
@@ -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(MainWindow.instance);
}
diff --git a/Knossos.NET/ViewModels/Windows/AddUserBuildViewModel.cs b/Knossos.NET/ViewModels/Windows/AddUserBuildViewModel.cs
index 1bbf5d74..6a3cb814 100644
--- a/Knossos.NET/ViewModels/Windows/AddUserBuildViewModel.cs
+++ b/Knossos.NET/ViewModels/Windows/AddUserBuildViewModel.cs
@@ -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;
@@ -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
@@ -55,8 +57,6 @@ 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;
@@ -64,14 +64,26 @@ public partial class AddUserBuildViewModel : ViewModelBase
[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
@@ -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)
@@ -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);
@@ -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);
@@ -125,7 +137,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("qtfred"))
{
- QtFredDebug = file.Name;
+ QtFredDebug = Path.GetRelativePath(folderPath, exe);
}
}
}
@@ -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);
@@ -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);
@@ -156,7 +168,7 @@ internal async void OpenFolderCommand()
{
if (file.Name.ToLower().Contains("qtfred"))
{
- QtFred = file.Name;
+ QtFred = Path.GetRelativePath(folderPath, exe);
}
}
}
@@ -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
@@ -304,22 +319,20 @@ internal async void ChangeQtFredDebugCommand()
public async Task 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;
@@ -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;
@@ -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);
}
}
}
@@ -531,37 +555,10 @@ private bool Verify()
return true;
}
- private async Task CopyFilesRecursively(string sourcePath, string targetPath)
+ private async void copyCallback(string filename)
{
- return await Task.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++;
});
}
}
diff --git a/Knossos.NET/Views/Windows/AddUserBuildView.axaml b/Knossos.NET/Views/Windows/AddUserBuildView.axaml
index c3a3d367..8bd14451 100644
--- a/Knossos.NET/Views/Windows/AddUserBuildView.axaml
+++ b/Knossos.NET/Views/Windows/AddUserBuildView.axaml
@@ -2,15 +2,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ mc:Ignorable="d" d:DesignWidth="550" d:DesignHeight="600"
x:Class="Knossos.NET.Views.Windows.AddUserBuildView"
xmlns:v="using:Knossos.NET.Views"
xmlns:vm="using:Knossos.NET.ViewModels"
x:DataType="vm:AddUserBuildViewModel"
Icon="/Assets/knossos-icon.ico"
WindowStartupLocation="CenterScreen"
- Title="Add Custom FSO Build"
- SizeToContent="Width"
+ Title="Add Custom FSO Build"
+ Width="550"
Height="600"
CanResize="True">
@@ -19,49 +19,71 @@
-
+
-
- X86
- X64
- AVX
- AVX2
- ARM32
- ARM64
- RISCV32
- RISCV64
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Build Data
+
+
+
+
+
+
+
+
+
+
+
+
+ Build CPU Arch
+
+
+
+ X86
+ X64
+ AVX
+ AVX2
+ ARM64
+ RISCV64
+ RISCV32
+ ARM32
+
+
+
+
+
+
+ Build Executables
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -69,7 +91,6 @@
-