Copy status, fixes

This commit is contained in:
2022-02-13 16:49:59 +01:00
parent afb72ae491
commit 7019918496
17 changed files with 207 additions and 32 deletions

View File

@@ -6,10 +6,11 @@ namespace FileTime.Core.Command
{ {
public class CopyCommand : ITransportationCommand public class CopyCommand : ITransportationCommand
{ {
private Func<AbsolutePath, AbsolutePath, Task>? _copyOperation; private Func<AbsolutePath, AbsolutePath, OperationProgress?, CopyCommandContext, Task>? _copyOperation;
private Dictionary<AbsolutePath, OperationProgress> _operationStatuses = new(); private Dictionary<AbsolutePath, List<OperationProgress>> _operationStatuses = new();
private Func<IContainer, string, Task<IContainer>>? _createContainer; private Func<IContainer, string, Task<IContainer>>? _createContainer;
private Func<AbsolutePath, Task>? _containerCopyDone; private Func<AbsolutePath, Task>? _containerCopyDone;
private OperationProgress? _currentOperationProgress;
public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>(); public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>();
@@ -18,6 +19,7 @@ namespace FileTime.Core.Command
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;
public int Progress { get; private set; } public int Progress { get; private set; }
public int CurrentProgress { get; private set; }
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
@@ -26,16 +28,27 @@ namespace FileTime.Core.Command
private async Task UpdateProgress() private async Task UpdateProgress()
{ {
var total = 0; var total = 0L;
var current = 0; var current = 0L;
foreach (var item in _operationStatuses.Values) foreach (var folder in _operationStatuses.Values)
{ {
current += item.Progress; foreach (var item in folder)
total += item.TotalCount; {
current += item.Progress;
total += item.TotalCount;
}
} }
Progress = current * 100 / total; Progress = (int)(current * 100 / total);
if (_currentOperationProgress == null)
{
CurrentProgress = 0;
}
else
{
CurrentProgress = (int)(_currentOperationProgress.Progress * 100 / _currentOperationProgress.TotalCount);
}
await ProgressChanged.InvokeAsync(this, AsyncEventArgs.Empty); await ProgressChanged.InvokeAsync(this, AsyncEventArgs.Empty);
} }
@@ -47,7 +60,7 @@ namespace FileTime.Core.Command
var newDiffs = new List<Difference>(); var newDiffs = new List<Difference>();
_copyOperation = (_, to) => _copyOperation = (_, to, _, _) =>
{ {
var target = to.GetParentAsAbsolutePath().Resolve(); var target = to.GetParentAsAbsolutePath().Resolve();
newDiffs.Add(new Difference( newDiffs.Add(new Difference(
@@ -79,7 +92,7 @@ namespace FileTime.Core.Command
return startPoint.WithDifferences(newDiffs); return startPoint.WithDifferences(newDiffs);
} }
public async Task Execute(Action<AbsolutePath, AbsolutePath> copy, TimeRunner timeRunner) public async Task Execute(Func<AbsolutePath, AbsolutePath, OperationProgress?, CopyCommandContext, Task> copy, TimeRunner timeRunner)
{ {
if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null"); if (Sources == null) throw new ArgumentException(nameof(Sources) + " can not be null");
if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null"); if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null");
@@ -87,13 +100,12 @@ namespace FileTime.Core.Command
await CalculateProgress(); await CalculateProgress();
_copyOperation = async (from, to) => _copyOperation = async (from, to, operation, context) =>
{ {
copy(from, to); await copy(from, to, operation, context);
var parentPath = to.GetParentAsAbsolutePath(); if (operation != null)
if (_operationStatuses.ContainsKey(parentPath))
{ {
_operationStatuses[parentPath].Progress++; operation.Progress = operation.TotalCount;
} }
await UpdateProgress(); await UpdateProgress();
}; };
@@ -101,7 +113,11 @@ namespace FileTime.Core.Command
_createContainer = async (IContainer target, string name) => await target.CreateContainer(name); _createContainer = async (IContainer target, string name) => await target.CreateContainer(name);
_containerCopyDone = async (path) => _containerCopyDone = async (path) =>
{ {
_operationStatuses[path].Progress = _operationStatuses[path].TotalCount; foreach (var item in _operationStatuses[path])
{
item.Progress = item.TotalCount;
}
if (timeRunner != null) if (timeRunner != null)
{ {
await timeRunner.RefreshContainer.InvokeAsync(this, path); await timeRunner.RefreshContainer.InvokeAsync(this, path);
@@ -117,24 +133,23 @@ namespace FileTime.Core.Command
if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null"); if (Target == null) throw new ArgumentException(nameof(Target) + " can not be null");
if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null"); if (TransportMode == null) throw new ArgumentException(nameof(TransportMode) + " can not be null");
var operationStatuses = new Dictionary<AbsolutePath, OperationProgress>(); var operationStatuses = new Dictionary<AbsolutePath, List<OperationProgress>>();
_copyOperation = (_, to) => _copyOperation = async (from, to, _, _) =>
{ {
var parentPath = to.GetParentAsAbsolutePath(); var parentPath = to.GetParentAsAbsolutePath();
OperationProgress operation; List<OperationProgress> operationsByFolder;
if (operationStatuses.ContainsKey(parentPath)) if (operationStatuses.ContainsKey(parentPath))
{ {
operation = operationStatuses[parentPath]; operationsByFolder = operationStatuses[parentPath];
} }
else else
{ {
operation = new OperationProgress(); var resolvedFrom = await from.Resolve();
operationStatuses.Add(parentPath, operation); operationsByFolder = new List<OperationProgress>();
operationStatuses.Add(parentPath, operationsByFolder);
operationsByFolder.Add(new OperationProgress(from.Path, resolvedFrom is IElement element ? await element.GetElementSize() : 0L));
} }
operation.TotalCount++;
return Task.CompletedTask;
}; };
await TraverseTree(Sources, Target, TransportMode.Value); await TraverseTree(Sources, Target, TransportMode.Value);
@@ -180,7 +195,25 @@ namespace FileTime.Core.Command
continue; continue;
} }
_copyOperation?.Invoke(new AbsolutePath(element), AbsolutePath.FromParentAndChildName(target, targetName)); OperationProgress? operation = null;
var targetFolderPath = new AbsolutePath(target);
var targetElementPath = AbsolutePath.FromParentAndChildName(target, targetName);
foreach(var asd in _operationStatuses.Keys)
{
var hash1 = asd.GetHashCode();
var hash2 = targetFolderPath.GetHashCode();
var eq = asd == targetFolderPath;
}
if (_operationStatuses.TryGetValue(targetFolderPath, out var targetPathOperations))
{
var path = new AbsolutePath(element).Path;
operation = targetPathOperations.Find(o => o.Key == path);
}
_currentOperationProgress = operation;
if (_copyOperation != null) await _copyOperation.Invoke(new AbsolutePath(element), targetElementPath, operation, new CopyCommandContext(UpdateProgress));
} }
} }
} }

View File

@@ -0,0 +1,14 @@
namespace FileTime.Core.Command
{
public class CopyCommandContext
{
private readonly Func<Task> _updateProgress;
public CopyCommandContext(Func<Task> updateProgress)
{
_updateProgress = updateProgress;
}
public async Task UpdateProgress() => await _updateProgress.Invoke();
}
}

View File

@@ -10,11 +10,13 @@ namespace FileTime.Core.Command
public string NewContainerName { get; } public string NewContainerName { get; }
public int Progress => 100; public int Progress => 100;
public int CurrentProgress => 100;
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
public string DisplayLabel { get; } public string DisplayLabel { get; }
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly(); public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
public CreateContainerCommand(AbsolutePath container, string newContainerName) public CreateContainerCommand(AbsolutePath container, string newContainerName)
{ {
Container = container; Container = container;

View File

@@ -10,6 +10,7 @@ namespace FileTime.Core.Command
public string NewElementName { get; } public string NewElementName { get; }
public int Progress => 100; public int Progress => 100;
public int CurrentProgress => 100;
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
public string DisplayLabel { get; } public string DisplayLabel { get; }
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly(); public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();

View File

@@ -1,5 +1,4 @@
using AsyncEvent; using AsyncEvent;
using FileTime.Core.Extensions;
using FileTime.Core.Models; using FileTime.Core.Models;
using FileTime.Core.Timeline; using FileTime.Core.Timeline;
@@ -11,6 +10,7 @@ namespace FileTime.Core.Command
private Func<IElement, Task>? _deleteElement; private Func<IElement, Task>? _deleteElement;
public int Progress => 100; public int Progress => 100;
public int CurrentProgress => 100;
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
@@ -85,7 +85,6 @@ namespace FileTime.Core.Command
if (_deleteContainer != null) await _deleteContainer.Invoke(container); if (_deleteContainer != null) await _deleteContainer.Invoke(container);
} }
} }
else if (item is IElement element) else if (item is IElement element)
{ {

View File

@@ -10,6 +10,7 @@ namespace FileTime.Core.Command
Task<CanCommandRun> CanRun(PointInTime startPoint); Task<CanCommandRun> CanRun(PointInTime startPoint);
Task<PointInTime> SimulateCommand(PointInTime startPoint); Task<PointInTime> SimulateCommand(PointInTime startPoint);
int Progress { get; } int Progress { get; }
int CurrentProgress { get; }
AsyncEventHandler ProgressChanged { get; } AsyncEventHandler ProgressChanged { get; }
} }
} }

View File

@@ -12,6 +12,7 @@ namespace FileTime.Core.Command
public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge; public TransportMode? TransportMode { get; set; } = Command.TransportMode.Merge;
public int Progress => 100; public int Progress => 100;
public int CurrentProgress => 100;
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
public string DisplayLabel { get; } = "MoveCommand"; public string DisplayLabel { get; } = "MoveCommand";
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly(); public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();

View File

@@ -2,7 +2,15 @@ namespace FileTime.Core.Command
{ {
public class OperationProgress public class OperationProgress
{ {
public int Progress { get; set; } public string Key { get; }
public int TotalCount { get; set; } public long Progress { get; set; }
public long TotalCount { get; }
public bool IsDone => Progress == TotalCount;
public OperationProgress(string key, long totalCount)
{
Key = key;
TotalCount = totalCount;
}
} }
} }

View File

@@ -11,6 +11,7 @@ namespace FileTime.Core.Command
public string Target { get; } public string Target { get; }
public int Progress => 100; public int Progress => 100;
public int CurrentProgress => 100;
public AsyncEventHandler ProgressChanged { get; } = new(); public AsyncEventHandler ProgressChanged { get; } = new();
public string DisplayLabel { get; } = "RenameCommand"; public string DisplayLabel { get; } = "RenameCommand";
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly(); public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();

View File

@@ -35,6 +35,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AsyncEvent", "Core\AsyncEve
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileTime.Avalonia", "GuiApp\FileTime.Avalonia\FileTime.Avalonia.csproj", "{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileTime.Avalonia", "GuiApp\FileTime.Avalonia\FileTime.Avalonia.csproj", "{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{0D2B4BAA-0399-459C-B022-41DB7F408225}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileTime.Tools.Compression", "Tools\FileTime.Tools.Compression\FileTime.Tools.Compression.csproj", "{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -269,6 +273,26 @@ Global
{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x64.Build.0 = Release|Any CPU {22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x64.Build.0 = Release|Any CPU
{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x86.ActiveCfg = Release|Any CPU {22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x86.ActiveCfg = Release|Any CPU
{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x86.Build.0 = Release|Any CPU {22B33BC6-3987-4BE6-8C54-BFC75C78CCE7}.Release|x86.Build.0 = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|ARM.ActiveCfg = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|ARM.Build.0 = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|ARM64.Build.0 = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|x64.ActiveCfg = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|x64.Build.0 = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|x86.ActiveCfg = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Debug|x86.Build.0 = Debug|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|Any CPU.Build.0 = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|ARM.ActiveCfg = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|ARM.Build.0 = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|ARM64.ActiveCfg = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|ARM64.Build.0 = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|x64.ActiveCfg = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|x64.Build.0 = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|x86.ActiveCfg = Release|Any CPU
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -285,6 +309,7 @@ Global
{35963404-39F6-4CDA-A0FE-A91036FA8DAC} = {517D96CE-A956-4638-A93D-465D34DE22B1} {35963404-39F6-4CDA-A0FE-A91036FA8DAC} = {517D96CE-A956-4638-A93D-465D34DE22B1}
{9BDAC126-200F-4056-8D35-36EC059B40F3} = {38B1B927-4201-4B7A-87EE-737B8C6D4090} {9BDAC126-200F-4056-8D35-36EC059B40F3} = {38B1B927-4201-4B7A-87EE-737B8C6D4090}
{22B33BC6-3987-4BE6-8C54-BFC75C78CCE7} = {890275FF-943A-4D07-83BA-14E5C52D7846} {22B33BC6-3987-4BE6-8C54-BFC75C78CCE7} = {890275FF-943A-4D07-83BA-14E5C52D7846}
{B6F6A8F9-9B7B-4E3E-AE99-A90ECFDDC966} = {0D2B4BAA-0399-459C-B022-41DB7F408225}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8D679DCE-AC84-4A91-BFED-8F8D8E1D8183} SolutionGuid = {8D679DCE-AC84-4A91-BFED-8F8D8E1D8183}

View File

@@ -41,7 +41,7 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="MvvmGen" Version="1.1.2" /> <PackageReference Include="MvvmGen" Version="1.1.3" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" /> <PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.3.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

View File

@@ -56,6 +56,7 @@ namespace FileTime.Avalonia.Services
|| keyMapping.Command == Commands.Open || keyMapping.Command == Commands.Open
|| keyMapping.Command == Commands.OpenOrRun || keyMapping.Command == Commands.OpenOrRun
|| keyMapping.Command == Commands.MoveCursorUp || keyMapping.Command == Commands.MoveCursorUp
|| keyMapping.Command == Commands.MoveCursorDown
|| keyMapping.Command == Commands.MoveCursorUpPage || keyMapping.Command == Commands.MoveCursorUpPage
|| keyMapping.Command == Commands.MoveCursorDownPage; || keyMapping.Command == Commands.MoveCursorDownPage;
} }

View File

@@ -245,6 +245,7 @@
<ListBox <ListBox
x:Name="CurrentItems" x:Name="CurrentItems"
x:CompileBindings="False" x:CompileBindings="False"
AutoScrollToSelectedItem="True"
IsTabStop="True" IsTabStop="True"
Items="{Binding AppState.SelectedTab.CurrentLocation.Items^}" Items="{Binding AppState.SelectedTab.CurrentLocation.Items^}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled"

View File

@@ -24,7 +24,7 @@ namespace FileTime.Providers.Local.CommandHandlers
await copyCommand.Execute(CopyElement, timeRunner); await copyCommand.Execute(CopyElement, timeRunner);
} }
public static void CopyElement(AbsolutePath sourcePath, AbsolutePath targetPath) public static async Task CopyElement(AbsolutePath sourcePath, AbsolutePath targetPath, OperationProgress? operationProgress, CopyCommandContext copyCommandContext)
{ {
using var sourceStream = File.OpenRead(sourcePath.Path); using var sourceStream = File.OpenRead(sourcePath.Path);
using var sourceReader = new BinaryReader(sourceStream); using var sourceReader = new BinaryReader(sourceStream);
@@ -40,6 +40,8 @@ namespace FileTime.Providers.Local.CommandHandlers
dataRead = sourceReader.ReadBytes(bufferSize); dataRead = sourceReader.ReadBytes(bufferSize);
targetWriter.Write(dataRead); targetWriter.Write(dataRead);
targetWriter.Flush(); targetWriter.Flush();
if (operationProgress != null) operationProgress.Progress += dataRead.LongLength;
await copyCommandContext.UpdateProgress();
} }
while (dataRead.Length > 0); while (dataRead.Length > 0);
} }

View File

@@ -0,0 +1,35 @@
using AsyncEvent;
using FileTime.Core.Command;
using FileTime.Core.Models;
using FileTime.Core.Timeline;
namespace FileTime.Tools.Compression.Command
{
public class CompressCommand : IExecutableCommand
{
public IList<AbsolutePath> Sources { get; } = new List<AbsolutePath>();
public string DisplayLabel { get; } = "Compress";
public IReadOnlyList<string> CanRunMessages { get; } = new List<string>().AsReadOnly();
public int Progress { get; }
public AsyncEventHandler ProgressChanged { get; } = new AsyncEventHandler();
public Task<CanCommandRun> CanRun(PointInTime startPoint)
{
//TODO: implement
return Task.FromResult(CanCommandRun.True);
}
public Task<PointInTime> SimulateCommand(PointInTime startPoint)
{
return Task.FromResult(startPoint.WithDifferences(new List<Difference>()));
}
public Task Execute(TimeRunner timeRunner)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,34 @@
using AsyncEvent;
using FileTime.Core.Command;
using FileTime.Core.Timeline;
namespace FileTime.Tools.Compression.Command
{
public class DecompressCommand : IExecutableCommand
{
public string DisplayLabel => throw new NotImplementedException();
public IReadOnlyList<string> CanRunMessages => throw new NotImplementedException();
public int Progress => throw new NotImplementedException();
public AsyncEventHandler ProgressChanged => throw new NotImplementedException();
public int CurrentProgress => throw new NotImplementedException();
public Task<CanCommandRun> CanRun(PointInTime startPoint)
{
throw new NotImplementedException();
}
public Task Execute(TimeRunner timeRunner)
{
throw new NotImplementedException();
}
public Task<PointInTime> SimulateCommand(PointInTime startPoint)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.30.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\AppCommon\FileTime.App.Core\FileTime.App.Core.csproj" />
</ItemGroup>
</Project>