152 lines
5.9 KiB
C#
152 lines
5.9 KiB
C#
using Explorer.Contracts;
|
|
using Explorer.Domain;
|
|
using Explorer.Domain.Abstractions;
|
|
|
|
namespace Explorer.FileOperations;
|
|
|
|
public sealed class FileOperationService
|
|
{
|
|
private readonly ITransferHost _queue;
|
|
private readonly IShellFileOperations _shell;
|
|
private readonly IFileSystemEnumerator _enumerator;
|
|
|
|
public FileOperationService(ITransferHost queue, IShellFileOperations shell, IFileSystemEnumerator enumerator)
|
|
{
|
|
_queue = queue;
|
|
_shell = shell;
|
|
_enumerator = enumerator;
|
|
}
|
|
|
|
public void Open(IReadOnlyList<string> paths)
|
|
{
|
|
foreach (var path in paths)
|
|
{
|
|
_shell.Open(path);
|
|
}
|
|
}
|
|
|
|
public Task CopyAsync(IReadOnlyList<string> sources, string destinationDirectory, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueCopyAsync(sources, destinationDirectory, cancellationToken);
|
|
|
|
public Task MoveAsync(IReadOnlyList<string> sources, string destinationDirectory, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueMoveAsync(sources, destinationDirectory, cancellationToken);
|
|
|
|
public Task DeleteAsync(IReadOnlyList<string> paths, bool permanent = false, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueDeleteAsync(paths, permanent, cancellationToken);
|
|
|
|
public Task CreateShortcutsAsync(IReadOnlyList<string> sources, string destinationDirectory, CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
foreach (var source in sources)
|
|
{
|
|
var dest = UniqueShortcutPath(destinationDirectory, PathRules.GetFileName(source));
|
|
if (!_shell.CreateShortcut(source, dest, out var error) && error is not null)
|
|
{
|
|
throw new IOException(error);
|
|
}
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private static string UniqueShortcutPath(string directory, string sourceName)
|
|
{
|
|
var stem = sourceName + " - Shortcut";
|
|
var dest = Path.Combine(directory, stem + ".lnk");
|
|
var i = 2;
|
|
while (File.Exists(PathRules.ToExtended(dest)) || Directory.Exists(PathRules.ToExtended(dest)))
|
|
{
|
|
dest = Path.Combine(directory, $"{stem} ({i++}).lnk");
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
public Task EnqueueRenameAsync(string path, string newName, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueRenameAsync(path, newName, cancellationToken);
|
|
|
|
public async Task EnqueueRenameAsync(IReadOnlyList<(string Path, string NewName)> items, CancellationToken cancellationToken = default)
|
|
{
|
|
foreach (var (path, newName) in items)
|
|
{
|
|
await _queue.EnqueueRenameAsync(path, newName, cancellationToken).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
public Task EmptyRecycleBinAsync(CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueEmptyRecycleBinAsync(cancellationToken);
|
|
|
|
public Task ExtractAsync(string archivePath, string destinationDirectory, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueExtractAsync(archivePath, destinationDirectory, cancellationToken);
|
|
|
|
public Task CompressAsync(IReadOnlyList<string> sources, string archivePath, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueCompressAsync(sources, archivePath, cancellationToken);
|
|
|
|
public Task AddToArchiveAsync(string archivePath, IReadOnlyList<string> sources, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueAddToArchiveAsync(archivePath, sources, cancellationToken);
|
|
|
|
public Task VerifyArchiveAsync(string archivePath, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueVerifyArchiveAsync(archivePath, cancellationToken);
|
|
|
|
public Task ConvertAsync(string sourcePath, string destinationPath, ConversionKind kind, CancellationToken cancellationToken = default)
|
|
=> _queue.EnqueueConvertAsync(sourcePath, destinationPath, kind, cancellationToken);
|
|
|
|
public async Task ConvertAsync(IReadOnlyList<PlannedOperation> operations, CancellationToken cancellationToken = default)
|
|
{
|
|
foreach (var op in operations.Where(o => o.Op == TransferOp.Convert && o.DestinationPath is not null))
|
|
{
|
|
var kind = Enum.TryParse<ConversionKind>(op.NewName, true, out var parsed)
|
|
? parsed
|
|
: ConversionFormats.Infer(op.SourcePath, op.DestinationPath!);
|
|
await _queue.EnqueueConvertAsync(op.SourcePath, op.DestinationPath!, kind, cancellationToken).ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
public static string UniqueArchivePath(string directory, string stem, string extension)
|
|
{
|
|
extension = extension.Trim().TrimStart('.');
|
|
var dest = Path.Combine(directory, stem + "." + extension);
|
|
var i = 2;
|
|
while (File.Exists(PathRules.ToExtended(dest)) || Directory.Exists(PathRules.ToExtended(dest)))
|
|
{
|
|
dest = Path.Combine(directory, $"{stem} ({i++}).{extension}");
|
|
}
|
|
|
|
return dest;
|
|
}
|
|
|
|
public void Rename(string path, string newName)
|
|
{
|
|
var parent = PathRules.Parent(path);
|
|
var dest = Path.Combine(parent, newName);
|
|
var src = PathRules.ToExtended(path);
|
|
var dst = PathRules.ToExtended(dest);
|
|
if (Directory.Exists(src))
|
|
{
|
|
Directory.Move(src, dst);
|
|
}
|
|
else
|
|
{
|
|
File.Move(src, dst);
|
|
}
|
|
}
|
|
|
|
public string NewFolder(string parent)
|
|
{
|
|
var baseName = "New folder";
|
|
var name = baseName;
|
|
var i = 2;
|
|
var dest = Path.Combine(parent, name);
|
|
while (Directory.Exists(PathRules.ToExtended(dest)) || File.Exists(PathRules.ToExtended(dest)))
|
|
{
|
|
name = $"{baseName} ({i++})";
|
|
dest = Path.Combine(parent, name);
|
|
}
|
|
|
|
Directory.CreateDirectory(PathRules.ToExtended(dest));
|
|
return dest;
|
|
}
|
|
|
|
public FileSystemItem? GetItem(string path) => _enumerator.GetItem(path);
|
|
}
|