1
0
Fork 0
mirror of https://github.com/oMaN-Rod/nxDumpFuse.git synced 2024-11-22 10:16:40 +00:00

Clean up code

This commit is contained in:
Omar 2021-10-22 18:45:35 -04:00
parent 846ac96c72
commit e48947c499
15 changed files with 194 additions and 189 deletions

View file

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Avalonia/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -1,6 +1,5 @@
using nxDumpFuse.Extensions;
using nxDumpFuse.Interfaces;
using nxDumpFuse.Model;
using nxDumpFuse.Services;
using Splat;

View file

@ -1,6 +1,5 @@
using System.Threading.Tasks;
using Avalonia.Controls;
using nxDumpFuse.ViewModels;
namespace nxDumpFuse.Interfaces
{

View file

@ -0,0 +1,8 @@
namespace nxDumpFuse.Model.Enums
{
public enum FuseSimpleLogType
{
Error,
Information
}
}

View file

@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using nxDumpFuse.Events;
using nxDumpFuse.Model.Enums;
namespace nxDumpFuse.Model
{
@ -26,7 +26,6 @@ namespace nxDumpFuse.Model
}
public event EventHandlers.FuseUpdateEventHandler? FuseUpdateEvent;
public event EventHandlers.FuseSimpleLogEventHandler? FuseSimpleLogEvent;
protected virtual void OnFuseUpdate(FuseUpdateInfo fuseUpdateInfo)
@ -34,6 +33,17 @@ namespace nxDumpFuse.Model
FuseUpdateEvent?.Invoke(fuseUpdateInfo);
}
private void Update(int part, int parts, double progress, double progressPart)
{
OnFuseUpdate(new FuseUpdateInfo
{
Part = part,
Parts = parts,
Progress = progress,
ProgressPart = progressPart
});
}
protected virtual void OnFuseSimpleLogEvent(FuseSimpleLog log)
{
FuseSimpleLogEvent?.Invoke(log);
@ -51,92 +61,98 @@ namespace nxDumpFuse.Model
Log(FuseSimpleLogType.Error, "Input File cannot be empty");
return;
}
if (string.IsNullOrEmpty(_outputDir))
{
Log(FuseSimpleLogType.Error, "Output Directory cannot be empty");
return;
}
Log(FuseSimpleLogType.Information, "Fuse Started");
GetOutputFilePath(_inputFilePath, _outputDir);
GetOutputFilePath();
if (string.IsNullOrEmpty(_outputFilePath))
{
Log(FuseSimpleLogType.Error, "Output path was null");
return;
}
var inputFiles = GetInputFiles();
if (inputFiles.Length == 0)
{
Log(FuseSimpleLogType.Error, "No input files found");
return;
}
FuseFiles(inputFiles, _outputFilePath);
}
private void GetOutputFilePath(string inputFilePath, string outputDir)
private void GetOutputFilePath()
{
string? fileName = Path.GetFileName(inputFilePath);
var fileName = Path.GetFileName(_inputFilePath);
if (Path.HasExtension(fileName))
{
string ext = Path.GetExtension(fileName).Replace(".", string.Empty);
List<string> split = fileName.Split(".").ToList();
var ext = Path.GetExtension(fileName).Replace(".", string.Empty);
var split = fileName.Split(".").ToList();
if (int.TryParse(ext, out _) && split.Count >= 3 && split[^2] == XciExt) // .xci.00
{
_outputFilePath = Path.Join(outputDir, $"{string.Join("", split.Take(split.Count - 2))}.{XciExt}");
_outputFilePath = Path.Join(_outputDir, $"{string.Join("", split.Take(split.Count - 2))}.{XciExt}");
}
else if (int.TryParse(ext, out _) && split.Count >= 3 && split[^2] == NspExt) // .nsp.00
_outputFilePath = Path.Join(outputDir, $"{string.Join("", split.Take(split.Count - 2))}.{NspExt}");
else switch (ext.Substring(0, 2))
_outputFilePath = Path.Join(_outputDir, $"{string.Join("", split.Take(split.Count - 2))}.{NspExt}");
else switch (ext[..2])
{
// .xc0
case "xc" when int.TryParse(ext.Substring(ext.Length - 1, 1), out _):
_outputFilePath = Path.Join(outputDir, $"{Path.GetFileNameWithoutExtension(fileName)}.{XciExt}");
_outputFilePath = Path.Join(_outputDir, $"{Path.GetFileNameWithoutExtension(fileName)}.{XciExt}");
break;
// .ns0
case "ns" when int.TryParse(ext.Substring(ext.Length - 1, 1), out _):
_outputFilePath = Path.Join(outputDir, $"{Path.GetFileNameWithoutExtension(fileName)}.{NspExt}");
_outputFilePath = Path.Join(_outputDir, $"{Path.GetFileNameWithoutExtension(fileName)}.{NspExt}");
break;
}
}
else // dir/00
{
var inputDir = new FileInfo(inputFilePath).Directory?.Name;
var inputDir = new FileInfo(_inputFilePath).Directory?.Name;
if (string.IsNullOrEmpty(inputDir))
{
inputDir = Path.GetPathRoot(_inputFilePath);
_outputFilePath = $"{inputDir}.{NspExt}";
return;
}
var inputDirSplit = inputDir.Split(".");
_outputFilePath = Path.Join(outputDir, inputDirSplit.Length == 1
_outputFilePath = Path.Join(_outputDir, inputDirSplit.Length == 1
? $"{inputDir}.{NspExt}"
: $"{string.Join("", (inputDirSplit).Take(inputDirSplit.Length - 1))}.{NspExt}");
}
}
private async void FuseFiles(string[] inputFiles, string outputFilePath)
private async void FuseFiles(IReadOnlyCollection<string> inputFiles, string outputFilePath)
{
var buffer = new byte[1024 * 1024];
var count = 0;
long totalBytes = 0;
var totalFileLength = GetTotalFileSize(inputFiles);
Log(FuseSimpleLogType.Information, $"Fusing {inputFiles.Length} parts to {outputFilePath}:{totalFileLength / 1000}kB");
Log(FuseSimpleLogType.Information, $"Fusing {inputFiles.Count} parts to {outputFilePath} ({ToMb(totalFileLength)}MB)");
await using var outputStream = File.Create(outputFilePath);
foreach (var inputFilePath in inputFiles)
{
if (_cts.Token.IsCancellationRequested) return;
++count;
await using var inputStream = File.OpenRead(inputFilePath);
Log(FuseSimpleLogType.Information, $"Fusing file part {count} --> {inputFilePath}/{inputStream.Length / 1000}kB");
var fileLength = inputStream.Length;
long currentBytes = 0;
int currentBlockSize;
await using var inputStream = File.OpenRead(inputFilePath);
var fileLength = inputStream.Length;
Log(FuseSimpleLogType.Information, $"Fusing file part {++count}-> {inputFilePath} ({ToMb(fileLength)}MB)");
while ((currentBlockSize = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
if (_cts.Token.IsCancellationRequested) return;
currentBytes += currentBlockSize;
totalBytes += currentBlockSize;
@ -149,20 +165,21 @@ namespace nxDumpFuse.Model
Log(FuseSimpleLogType.Error, e.Message);
}
OnFuseUpdate(new FuseUpdateInfo
{
Part = count,
Parts = inputFiles.Length,
ProgressPart = currentBytes * 100.0 / fileLength,
Progress = totalBytes * 100.0 / totalFileLength
});
var progress = totalBytes * 100.0 / totalFileLength;
var progressPart = currentBytes * 100.0 / fileLength;
Update(count, inputFiles.Count, progress, progressPart);
}
}
Log(FuseSimpleLogType.Information, "Fuse Complete");
}
private static long GetTotalFileSize(string[] inputFiles)
private static long ToMb(long bytes)
{
return bytes / 1000000;
}
private static long GetTotalFileSize(IEnumerable<string> inputFiles)
{
long totalFileSize = 0;
inputFiles.Select(f => f).ToList().ForEach(f => totalFileSize += new FileInfo(f).Length);
@ -179,14 +196,9 @@ namespace nxDumpFuse.Model
public void StopFuse()
{
_cts.Cancel();
Log(FuseSimpleLogType.Information, "Fuse Stopped");
OnFuseUpdate(new FuseUpdateInfo
{
Part = 0,
Parts = 0,
ProgressPart = 0,
Progress = 0
});
if (File.Exists(_outputFilePath))
{
Task.Run((() =>
@ -198,6 +210,7 @@ namespace nxDumpFuse.Model
{
File.Delete(_outputFilePath);
Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => Log(FuseSimpleLogType.Information, $"Deleted {_outputFilePath}"));
Update(0, 0, 0, 0);
break;
}
catch (IOException)

View file

@ -1,15 +1,9 @@
using System;
using System.Diagnostics;
using Avalonia.Media;
using nxDumpFuse.Model.Enums;
namespace nxDumpFuse.Model
{
public enum FuseSimpleLogType
{
Error,
Information
}
public class FuseSimpleLog
{
public FuseSimpleLog(FuseSimpleLogType type, DateTime time, string message)
@ -17,8 +11,9 @@ namespace nxDumpFuse.Model
Type = type;
Time = time;
Message = message;
// This is not working, seems to be an issue https://github.com/AvaloniaUI/Avalonia/issues/2482
// needs to be reviewed. Setting Foreground property directly works fine, however binding fails
Color = Type == FuseSimpleLogType.Information ? Brushes.White : Brushes.Red;
Debug.WriteLine($"Color is {Color}");
}
public FuseSimpleLogType Type { get; }

View file

@ -1,18 +1,18 @@
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using nxDumpFuse.Interfaces;
using nxDumpFuse.ViewModels;
namespace nxDumpFuse.Services
{
public class DialogService : IDialogService
{
private readonly IMainWindowProvider _mainWindowProvider;
public DialogService(IMainWindowProvider mainWindowProvider)
{
_mainWindowProvider = mainWindowProvider;
}
public async Task<string> ShowOpenFileDialogAsync(string title, FileDialogFilter filter)
{
var openFileDialog = new OpenFileDialog()

View file

@ -9,8 +9,7 @@ namespace nxDumpFuse.ViewModels
{
public class AboutViewModel : ViewModelBase, IAboutViewModel
{
private string _gitHubUrl = "https://github.com/oMaN-Rod/nxDumpFuse";
private string _explorer = "explorer.exe";
private const string GitHubUrl = "https://github.com/oMaN-Rod/nxDumpFuse";
public AboutViewModel()
{
@ -20,28 +19,29 @@ namespace nxDumpFuse.ViewModels
public ReactiveCommand<Unit, Unit> OpenGithubCommand { get; }
public string UsageText => BuildUsageText();
public string AuthorInfo => "Made for fun by oMaN-Rod, check me out on -->";
private void OpenGithub()
private static void OpenGithub()
{
try
{
Process.Start(_explorer, _gitHubUrl);
Process.Start("explorer.exe", GitHubUrl);
}
catch
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("xdg-open", _gitHubUrl);
Process.Start("xdg-open", GitHubUrl);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Process.Start("open", _gitHubUrl);
Process.Start("open", GitHubUrl);
}
}
}
private string BuildUsageText()
private static string BuildUsageText()
{
var sb = new StringBuilder();
sb.AppendLine("To fuse files make sure all file parts are alone in a directory with no other files, i.e");

View file

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reactive;
using Avalonia.Controls;
using nxDumpFuse.Interfaces;
using nxDumpFuse.Model;
using nxDumpFuse.Services;
using nxDumpFuse.Model.Enums;
using ReactiveUI;
namespace nxDumpFuse.ViewModels

View file

@ -2,22 +2,16 @@
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"
xmlns:imaging="clr-namespace:Avalonia.Media.Imaging;assembly=Avalonia.Visuals"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="nxDumpFuse.Views.AboutView"
xmlns:vm="clr-namespace:nxDumpFuse.ViewModels"
x:DataType="vm:AboutViewModel">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Margin="20"
RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Text="{Binding UsageText}" />
<TextBlock Grid.Row="1" Margin="5" VerticalAlignment="Center" Text="{Binding AuthorInfo}" HorizontalAlignment="Right"/>
<TextBlock Grid.Row="1" Grid.Column="0" Margin="5" VerticalAlignment="Center" Text="{Binding AuthorInfo}"
HorizontalAlignment="Right" />
<Button Grid.Row="1" Grid.Column="1" Padding="-10" Command="{Binding OpenGithubCommand}">
<Panel>
<Image Width="75" Height="75" Source="resm:nxDumpFuse.Assets.github_icon.png" />

View file

@ -5,37 +5,33 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="nxDumpFuse.Views.FuseView"
xmlns:vm="clr-namespace:nxDumpFuse.ViewModels"
x:DataType="vm:FuseViewModel"
Name="FuseViewControl">
x:DataType="vm:FuseViewModel">
<DockPanel LastChildFill="True">
<Grid Margin="20" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Margin="20" DockPanel.Dock="Top"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto"
ColumnDefinitions="Auto,*">
<Button Grid.Row="0" Grid.Column="0" Command="{Binding SelectInputFileCommand}" Content="Input" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" VerticalAlignment="Center" Text="{Binding InputFilePath}" Name="InputFileTextBox"/>
<Button Grid.Row="0" Grid.Column="0" Command="{Binding SelectInputFileCommand}" Content="Input"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="5" VerticalAlignment="Center" Text="{Binding InputFilePath}"
Name="InputFileTextBox" />
<Button Grid.Row="1" Grid.Column="0" Command="{Binding SelectOutputFolderCommand}" Content="Output" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
<Button Grid.Row="1" Grid.Column="0" Command="{Binding SelectOutputFolderCommand}" Content="Output"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" />
<TextBox Grid.Row="1" Grid.Column="1" Margin="5" VerticalAlignment="Center" Text="{Binding OutputDir}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding ProgressPartText}" HorizontalAlignment="Right" Margin="2"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding ProgressPartText}" HorizontalAlignment="Right"
Margin="2" />
<ProgressBar Grid.Row="2" Grid.Column="1" Margin="2" Height="10" Value="{Binding ProgressPart}" />
<TextBlock Grid.Row="3" Grid.Column="0" Text="Total" HorizontalAlignment="Right" Margin="2" />
<ProgressBar Grid.Row="3" Grid.Column="1" Margin="2" Height="10" Value="{Binding Progress}" />
<StackPanel Grid.Row="4" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Command="{Binding FuseCommand}" Content="Fuse" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Margin="2"/>
<Button Command="{Binding StopCommand}" Content="Stop" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Margin="2"/>
<Button Command="{Binding FuseCommand}" Content="Fuse" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" Margin="2" />
<Button Command="{Binding StopCommand}" Content="Stop" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center" Margin="2" />
</StackPanel>
<DataGrid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2"
@ -46,14 +42,13 @@
CanUserReorderColumns="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
Width="{Binding #InputFileTextBox.Width}"
VerticalAlignment="Top"
Margin="4"
Height="350">
Height="300">
<DataGrid.Columns>
<DataGridTextColumn Header="Type" Binding="{Binding Type}" Width="Auto" Foreground="{Binding Color}"/>
<DataGridTextColumn Header="Time" Binding="{Binding Time}" Width="Auto"/>
<DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="Auto"/>
<DataGridTextColumn Header="Type" Binding="{Binding Type}" Width="Auto"
Foreground="{Binding Color}" FontSize="12" />
<DataGridTextColumn Header="Time" Binding="{Binding Time}" Width="Auto" FontSize="12" />
<DataGridTextColumn Header="Message" Binding="{Binding Message}" Width="Auto" FontSize="12" />
</DataGrid.Columns>
</DataGrid>
</Grid>

View file

@ -1,6 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:nxDumpFuse.ViewModels;assembly=nxDumpFuse"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="1350" d:DesignHeight="700"
@ -19,7 +18,8 @@
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="#222222" MaterialOpacity="0.85" TintOpacity="1" />
</ExperimentalAcrylicBorder.Material>
<TextBlock Text="{Binding #TabControl.SelectedItem.Header}" Margin="40 20" FontSize="32" FontWeight="Light" />
<TextBlock Text="{Binding #TabControl.SelectedItem.Header}" Margin="40 20" FontSize="32"
FontWeight="Light" />
</ExperimentalAcrylicBorder>
</DockPanel>

View file

@ -5,8 +5,9 @@
<Nullable>enable</Nullable>
<SelfContained>true</SelfContained>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<!--<RuntimeIdentifier>win10-x64</RuntimeIdentifier>-->
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
<!--<RuntimeIdentifier>linux-x64</RuntimeIdentifier>-->
<!--<RuntimeIdentifier>osx-x64</RuntimeIdentifier>-->
<PublishSingleFile>true</PublishSingleFile>
<ApplicationIcon>nxDumpFuse.ico</ApplicationIcon>
</PropertyGroup>