WIP file manager
parent
329c147419
commit
235d50a73a
|
@ -0,0 +1,224 @@
|
|||
@using AntDesign.TableModels;
|
||||
<GridRow>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<Button Type="@ButtonType.Text" Icon="@IconType.Outline.ArrowLeft" OnClick="NavigateBack" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Button Type="@ButtonType.Text" Icon="@IconType.Outline.ArrowRight" OnClick="NavigateForward" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Button Type="@ButtonType.Text" Icon="@IconType.Outline.ArrowUp" OnClick="NavigateUp" Disabled="@(Path.Parent == null)" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Button Type="@ButtonType.Text" Icon="@IconType.Outline.Reload" OnClick="() => ChangeDirectory(Path, false)" />
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<Breadcrumb>
|
||||
@foreach (var breadcrumb in Breadcrumbs)
|
||||
{
|
||||
<BreadcrumbItem OnClick="() => ChangeDirectory(breadcrumb, false)">@breadcrumb.Name</BreadcrumbItem>
|
||||
}
|
||||
</Breadcrumb>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</GridRow>
|
||||
|
||||
<GridRow>
|
||||
<GridCol Span="6" Class="file-manager-tree">
|
||||
<Tree TItem="FileManagerDirectory"
|
||||
DataSource="Directories"
|
||||
TitleExpression="x => x.DataItem.Name"
|
||||
ChildrenExpression="x => x.DataItem.Children"
|
||||
IsLeafExpression="x => !x.DataItem.HasChildren"
|
||||
OnClick="(args) => ChangeDirectory(args.Node.DataItem, false)"
|
||||
OnNodeLoadDelayAsync="ExpandTree" />
|
||||
</GridCol>
|
||||
|
||||
<GridCol Span="18" Class="file-manager-list">
|
||||
<Table
|
||||
TItem="IFileManagerEntry"
|
||||
DataSource="Entries"
|
||||
HidePagination="true"
|
||||
Loading="Entries == null"
|
||||
OnRow="OnRow">
|
||||
<Column TData="string" Width="32">
|
||||
<Text></Text>
|
||||
</Column>
|
||||
<PropertyColumn Property="e => e.Path" Sortable Title="Name">
|
||||
@GetEntryName(context)
|
||||
</PropertyColumn>
|
||||
<PropertyColumn Property="e => e.Length" Sortable Title="Size">
|
||||
@ByteSizeLib.ByteSize.FromBytes(context.Length)
|
||||
</PropertyColumn>
|
||||
<PropertyColumn Property="e => e.ModifiedOn" Format="MM/dd/yyyy hh:mm tt" Sortable Title="Modified" />
|
||||
</Table>
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid ArchiveId { get; set; }
|
||||
[Parameter] public string WorkingDirectory { get; set; }
|
||||
|
||||
FileManagerDirectory Path { get; set; }
|
||||
|
||||
List<FileManagerDirectory> Past { get; set; } = new List<FileManagerDirectory>();
|
||||
List<FileManagerDirectory> Future { get; set; } = new List<FileManagerDirectory>();
|
||||
List<FileManagerDirectory> Breadcrumbs = new List<FileManagerDirectory>();
|
||||
|
||||
List<IFileManagerEntry> Entries { get; set; } = new List<IFileManagerEntry>();
|
||||
HashSet<FileManagerDirectory> Directories { get; set; } = new HashSet<FileManagerDirectory>();
|
||||
|
||||
Dictionary<string, object> OnRow(RowData<IFileManagerEntry> row) => new()
|
||||
{
|
||||
["data-path"] = row.Data.Path,
|
||||
["ondblclick"] = ((System.Action)delegate
|
||||
{
|
||||
if (row.Data is FileManagerDirectory)
|
||||
ChangeDirectory((FileManagerDirectory)row.Data, true);
|
||||
})
|
||||
};
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (!String.IsNullOrWhiteSpace(WorkingDirectory))
|
||||
{
|
||||
Directories = GetDirectories(WorkingDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
HashSet<FileManagerDirectory> GetDirectories(string path)
|
||||
{
|
||||
var paths = Directory.EnumerateDirectories(path, "*", new EnumerationOptions
|
||||
{
|
||||
IgnoreInaccessible = true,
|
||||
RecurseSubdirectories = true,
|
||||
MaxRecursionDepth = 1
|
||||
});
|
||||
|
||||
var root = new FileManagerDirectory()
|
||||
{
|
||||
Name = path,
|
||||
Path = path,
|
||||
IsExpanded = true
|
||||
};
|
||||
|
||||
root.PopulateChildren(paths);
|
||||
|
||||
ChangeDirectory(root, true);
|
||||
|
||||
return new HashSet<FileManagerDirectory>
|
||||
{
|
||||
root
|
||||
};
|
||||
}
|
||||
|
||||
string GetEntryName(IFileManagerEntry entry)
|
||||
{
|
||||
if (String.IsNullOrWhiteSpace(entry.Name) && entry.Length == 0)
|
||||
{
|
||||
return entry.Path.TrimEnd('/').Split('/').Last();
|
||||
}
|
||||
else
|
||||
return entry.Name;
|
||||
}
|
||||
|
||||
void ChangeDirectory(FileManagerDirectory directory, bool clearFuture)
|
||||
{
|
||||
Past.Add(Path);
|
||||
|
||||
Path = directory;
|
||||
|
||||
UpdateEntries();
|
||||
UpdateBreadcrumbs();
|
||||
|
||||
if (clearFuture)
|
||||
Future.Clear();
|
||||
}
|
||||
|
||||
async Task ExpandTree(TreeEventArgs<FileManagerDirectory> args)
|
||||
{
|
||||
var directory = (FileManagerDirectory)args.Node.DataItem;
|
||||
|
||||
foreach (var child in directory.Children)
|
||||
{
|
||||
var paths = Directory.EnumerateDirectories(child.Path, "*", new EnumerationOptions
|
||||
{
|
||||
IgnoreInaccessible = true,
|
||||
RecurseSubdirectories = true,
|
||||
MaxRecursionDepth = 1
|
||||
});
|
||||
|
||||
child.PopulateChildren(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateEntries()
|
||||
{
|
||||
Entries.Clear();
|
||||
var entries = Directory.EnumerateFileSystemEntries(Path.Path);
|
||||
var separator = System.IO.Path.DirectorySeparatorChar;
|
||||
|
||||
foreach (var entry in Directory.EnumerateFileSystemEntries(Path.Path))
|
||||
{
|
||||
if (Directory.Exists(entry))
|
||||
{
|
||||
Entries.Add(new FileManagerDirectory
|
||||
{
|
||||
Path = entry,
|
||||
Name = entry.Substring(Path.Path.Length).TrimStart(separator),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Entries.Add(new FileManagerFile
|
||||
{
|
||||
Path = entry,
|
||||
Name = System.IO.Path.GetFileNameWithoutExtension(entry)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateBreadcrumbs()
|
||||
{
|
||||
Breadcrumbs.Clear();
|
||||
|
||||
var currentPath = Path;
|
||||
|
||||
while (currentPath != null)
|
||||
{
|
||||
Breadcrumbs.Add(currentPath);
|
||||
|
||||
currentPath = currentPath.Parent;
|
||||
}
|
||||
|
||||
Breadcrumbs.Reverse();
|
||||
}
|
||||
|
||||
void NavigateBack()
|
||||
{
|
||||
if (Past.Count > 0)
|
||||
{
|
||||
Future.Add(Path);
|
||||
Path = Past.Last();
|
||||
Past = Past.Take(Past.Count - 1).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigateForward()
|
||||
{
|
||||
if (Future.Count > 0)
|
||||
{
|
||||
Past.Add(Path);
|
||||
Path = Future.First();
|
||||
Future = Future.Skip(1).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
void NavigateUp()
|
||||
{
|
||||
if (Path.Parent != null)
|
||||
ChangeDirectory(Path.Parent, true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using System.IO.Compression;
|
||||
|
||||
namespace LANCommander.Components.FileManagerComponents
|
||||
{
|
||||
public class FileManagerDirectory : FileManagerEntry
|
||||
{
|
||||
public bool IsExpanded { get; set; } = false;
|
||||
public bool HasChildren => Children != null && Children.Count > 0;
|
||||
public HashSet<FileManagerDirectory> Children { get; set; } = new HashSet<FileManagerDirectory>();
|
||||
|
||||
public void PopulateChildren(IEnumerable<ZipArchiveEntry> entries)
|
||||
{
|
||||
var childPaths = entries.Where(e => e.FullName.StartsWith("/") && e.FullName.EndsWith('/'));
|
||||
var directChildren = childPaths.Where(p => p.FullName != Path && p.FullName.Substring(Path.Length + 1).TrimEnd('/').Split('/').Length == 1);
|
||||
|
||||
foreach (var directChild in directChildren)
|
||||
{
|
||||
var child = new FileManagerDirectory()
|
||||
{
|
||||
Path = directChild.FullName,
|
||||
Name = directChild.FullName.Substring(Path.Length).TrimEnd('/')
|
||||
};
|
||||
|
||||
child.PopulateChildren(entries);
|
||||
|
||||
Children.Add(child);
|
||||
}
|
||||
}
|
||||
|
||||
public void PopulateChildren(IEnumerable<string> entries)
|
||||
{
|
||||
var separator = System.IO.Path.DirectorySeparatorChar;
|
||||
var childPaths = entries.Where(e => e.StartsWith(Path));
|
||||
var directChildren = childPaths.Where(p => p != Path && p.Substring(Path.Length + 1).Split(separator).Length == 1);
|
||||
|
||||
foreach (var directChild in directChildren)
|
||||
{
|
||||
if (!Children.Any(c => c.Path == directChild))
|
||||
{
|
||||
var child = new FileManagerDirectory()
|
||||
{
|
||||
Path = directChild,
|
||||
Name = directChild.Substring(Path.Length).TrimStart(separator),
|
||||
Parent = this
|
||||
};
|
||||
|
||||
child.PopulateChildren(entries);
|
||||
|
||||
Children.Add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace LANCommander.Components.FileManagerComponents
|
||||
{
|
||||
public abstract class FileManagerEntry : IFileManagerEntry
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long Length { get; set; }
|
||||
public FileManagerDirectory Parent { get; set; }
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
public DateTime CreatedOn { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace LANCommander.Components.FileManagerComponents
|
||||
{
|
||||
public class FileManagerFile : FileManagerEntry
|
||||
{
|
||||
public string Extension => Name.Contains('.') ? Name.Split('.').Last() : Name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
namespace LANCommander.Components.FileManagerComponents
|
||||
{
|
||||
public interface IFileManagerEntry
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long Length { get; set; }
|
||||
public FileManagerDirectory Parent { get; set; }
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
public DateTime CreatedOn { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
@page "/Files"
|
||||
@using LANCommander.Components.FileManagerComponents
|
||||
|
||||
<FileManager WorkingDirectory="C:\Games" />
|
||||
|
||||
@code {
|
||||
|
||||
}
|
Loading…
Reference in New Issue