Skip to content

Commit

Permalink
Merge pull request #384 from CollapseLauncher/main
Browse files Browse the repository at this point in the history
Preview 1.73.2 Release
  • Loading branch information
Cryotechnic authored Feb 1, 2024
2 parents 68c06f7 + 4deb8cc commit 84a7c8a
Show file tree
Hide file tree
Showing 78 changed files with 4,361 additions and 377 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
8 changes: 7 additions & 1 deletion CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ internal class ThemeProperty
}
#endregion
#region ErrorSenderRegion
public enum ErrorType { Unhandled, GameError, Connection }
public enum ErrorType { Unhandled, GameError, Connection, Warning }

internal static class ErrorSender
{
Expand All @@ -160,6 +160,8 @@ internal static class ErrorSender
public static string ExceptionTitle;
public static string ExceptionSubtitle;
public static void SendException(Exception e, ErrorType eT = ErrorType.Unhandled) => invoker.SendException(e, eT);
public static void SendWarning(Exception e, ErrorType eT = ErrorType.Warning) =>
invoker.SendException(e, eT);
public static void SendExceptionWithoutPage(Exception e, ErrorType eT = ErrorType.Unhandled)
{
ExceptionContent = e.ToString();
Expand All @@ -183,6 +185,10 @@ public static void SetPageTitle(ErrorType errorType)
ExceptionTitle = Lang._UnhandledExceptionPage.UnhandledTitle3;
ExceptionSubtitle = Lang._UnhandledExceptionPage.UnhandledSubtitle3;
break;
case ErrorType.Warning:
ExceptionTitle = Lang._UnhandledExceptionPage.UnhandledTitle4;
ExceptionSubtitle = Lang._UnhandledExceptionPage.UnhandledSubtitle4;
break;
}
}
}
Expand Down
67 changes: 67 additions & 0 deletions CollapseLauncher/Classes/FileMigrationProcess/Events.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Hi3Helper;
using Hi3Helper.Data;
using System;
using System.Threading.Tasks;

namespace CollapseLauncher
{
internal partial class FileMigrationProcess
{
private void UpdateCountProcessed(FileMigrationProcessUIRef uiRef, string currentPathProcessed)
{
lock (this) { this.CurrentFileCountMoved++; }

string fileCountProcessedString = string.Format(Locale.Lang._Misc.PerFromTo,
this.CurrentFileCountMoved,
this.TotalFileCount);

lock (uiRef.fileCountIndicatorSubtitle)
{
this.parentUI.DispatcherQueue.TryEnqueue(() =>
{
uiRef.fileCountIndicatorSubtitle.Text = fileCountProcessedString;
uiRef.pathActivitySubtitle.Text = currentPathProcessed;
});
}
}

private async void UpdateSizeProcessed(FileMigrationProcessUIRef uiRef, long currentRead)
{
lock (this) { this.CurrentSizeMoved += currentRead; }

if (await CheckIfNeedRefreshStopwatch())
{
double percentage = Math.Round((double)this.CurrentSizeMoved / this.TotalFileSize * 100d, 2);
double speed = this.CurrentSizeMoved / this.ProcessStopwatch.Elapsed.TotalSeconds;

lock (uiRef.progressBarIndicator)
{
this.parentUI.DispatcherQueue.TryEnqueue(() =>
{
string speedString = string.Format(Locale.Lang._Misc.SpeedPerSec, ConverterTool.SummarizeSizeSimple(speed));
string sizeProgressString = string.Format(Locale.Lang._Misc.PerFromTo,
ConverterTool.SummarizeSizeSimple(this.CurrentSizeMoved),
ConverterTool.SummarizeSizeSimple(this.TotalFileSize));

uiRef.speedIndicatorSubtitle.Text = speedString;
uiRef.fileSizeIndicatorSubtitle.Text = sizeProgressString;
uiRef.progressBarIndicator.Value = percentage;
uiRef.progressBarIndicator.IsIndeterminate = false;
});
}
}
}

private async ValueTask<bool> CheckIfNeedRefreshStopwatch()
{
if (this.EventsStopwatch.ElapsedMilliseconds > _refreshInterval)
{
this.EventsStopwatch.Restart();
return true;
}

await Task.Delay(_refreshInterval);
return false;
}
}
}
160 changes: 160 additions & 0 deletions CollapseLauncher/Classes/FileMigrationProcess/FileMigrationProcess.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
using Microsoft.UI.Xaml;
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace CollapseLauncher
{
internal partial class FileMigrationProcess
{
private const int _refreshInterval = 100; // 100ms UI refresh interval

private string dialogTitle { get; set; }
private string inputPath { get; set; }
private string outputPath { get; set; }
private bool isFileTransfer { get; set; }
private UIElement parentUI { get; set; }
private CancellationTokenSource tokenSource { get; set; }

private long CurrentSizeMoved;
private long CurrentFileCountMoved;
private long TotalFileSize;
private long TotalFileCount;
private bool IsSameOutputDrive;
private Stopwatch ProcessStopwatch;
private Stopwatch EventsStopwatch;

private FileMigrationProcess(UIElement parentUI, string dialogTitle, string inputPath, string outputPath, bool isFileTransfer, CancellationTokenSource tokenSource)
{
this.dialogTitle = dialogTitle;
this.inputPath = inputPath;
this.outputPath = outputPath;
this.isFileTransfer = isFileTransfer;
this.parentUI = parentUI;
this.tokenSource = tokenSource;
}

internal async Task<string> StartRoutine()
{
bool isSuccess = false;
this.CurrentSizeMoved = 0;
this.CurrentFileCountMoved = 0;
this.TotalFileSize = 0;
this.TotalFileCount = 0;
FileMigrationProcessUIRef? uiRef = null;

try
{
if (!await IsOutputPathSpaceSufficient(this.inputPath, this.outputPath))
throw new OperationCanceledException($"Disk space is not sufficient. Cancelling!");

uiRef = BuildMainMigrationUI();
string outputPath = await StartRoutineInner(uiRef.Value);
uiRef.Value.mainDialogWindow.Hide();
isSuccess = true;

return outputPath;
}
catch when (!isSuccess) // Throw if the isSuccess is not set to true
{
if (uiRef.HasValue && uiRef.Value.mainDialogWindow != null)
{
uiRef.Value.mainDialogWindow.Hide();
await Task.Delay(500); // Give artificial delay to give main dialog window thread to close first
}
throw;
}
finally
{
if (ProcessStopwatch != null) ProcessStopwatch.Stop();
if (EventsStopwatch != null) EventsStopwatch.Stop();
}
}

private async Task<string> StartRoutineInner(FileMigrationProcessUIRef uiRef)
{
this.ProcessStopwatch = Stopwatch.StartNew();
this.EventsStopwatch = Stopwatch.StartNew();
return this.isFileTransfer ? await MoveFile(uiRef) : await MoveDirectory(uiRef);
}

private async Task<string> MoveFile(FileMigrationProcessUIRef uiRef)
{
FileInfo inputPathInfo = new FileInfo(this.inputPath);
FileInfo outputPathInfo = new FileInfo(this.outputPath);

string inputPathDir = Path.GetDirectoryName(inputPathInfo.FullName);
string outputPathDir = Path.GetDirectoryName(outputPathInfo.FullName);

if (!Directory.Exists(outputPathDir))
Directory.CreateDirectory(outputPathDir);

// Update path display
string inputFileBasePath = inputPathInfo.FullName.Substring(inputPathDir.Length + 1);
UpdateCountProcessed(uiRef, inputFileBasePath);

if (this.IsSameOutputDrive)
{
// Logger.LogWriteLine($"[FileMigrationProcess::MoveFile()] Moving file in the same drive from: {inputPathInfo.FullName} to {outputPathInfo.FullName}", LogType.Default, true);
inputPathInfo.MoveTo(outputPathInfo.FullName);
UpdateSizeProcessed(uiRef, inputPathInfo.Length);
}
else
{
// Logger.LogWriteLine($"[FileMigrationProcess::MoveFile()] Moving file across different drives from: {inputPathInfo.FullName} to {outputPathInfo.FullName}", LogType.Default, true);
await MoveWriteFile(uiRef, inputPathInfo, outputPathInfo, this.tokenSource == null ? default : this.tokenSource.Token);
}

return outputPathInfo.FullName;
}

private async Task<string> MoveDirectory(FileMigrationProcessUIRef uiRef)
{
DirectoryInfo inputPathInfo = new DirectoryInfo(this.inputPath);
if (!Directory.Exists(this.outputPath))
Directory.CreateDirectory(this.outputPath);

DirectoryInfo outputPathInfo = new DirectoryInfo(this.outputPath);

int parentInputPathLength = inputPathInfo.Parent.FullName.Length + 1;
string outputDirBaseNamePath = inputPathInfo.FullName.Substring(parentInputPathLength);
string outputDirPath = Path.Combine(this.outputPath, outputDirBaseNamePath);

await Parallel.ForEachAsync(
inputPathInfo.EnumerateFiles("*", SearchOption.AllDirectories),
this.tokenSource?.Token ?? default,
async (inputFileInfo, cancellationToken) =>
{
int parentInputPathLength = inputPathInfo.Parent.FullName.Length + 1;
string inputFileBasePath = inputFileInfo.FullName.Substring(parentInputPathLength);

// Update path display
UpdateCountProcessed(uiRef, inputFileBasePath);

string outputTargetPath = Path.Combine(outputPathInfo.FullName, inputFileBasePath);
string outputTargetDirPath = Path.GetDirectoryName(outputTargetPath);

if (!Directory.Exists(outputTargetDirPath))
Directory.CreateDirectory(outputTargetDirPath);

if (this.IsSameOutputDrive)
{
// Logger.LogWriteLine($"[FileMigrationProcess::MoveDirectory()] Moving directory content in the same drive from: {inputFileInfo.FullName} to {outputTargetPath}", LogType.Default, true);
inputFileInfo.MoveTo(outputTargetPath);
UpdateSizeProcessed(uiRef, inputFileInfo.Length);
}
else
{
// Logger.LogWriteLine($"[FileMigrationProcess::MoveDirectory()] Moving directory content across different drives from: {inputFileInfo.FullName} to {outputTargetPath}", LogType.Default, true);
FileInfo outputFileInfo = new FileInfo(outputTargetPath);
await MoveWriteFile(uiRef, inputFileInfo, outputFileInfo, cancellationToken);
}
});

inputPathInfo.Delete(true);
return outputDirPath;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using CollapseLauncher.CustomControls;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Documents;

namespace CollapseLauncher
{
internal struct FileMigrationProcessUIRef
{
internal ContentDialogCollapse mainDialogWindow;
internal TextBlock pathActivitySubtitle;
internal Run speedIndicatorSubtitle;
internal Run fileCountIndicatorSubtitle;
internal Run fileSizeIndicatorSubtitle;
internal ProgressBar progressBarIndicator;
}
}
Loading

0 comments on commit 84a7c8a

Please sign in to comment.