222 lines
6.2 KiB
Text
222 lines
6.2 KiB
Text
@using LANCommander.Server.Extensions;
|
|
|
|
<GridRow Class="text-editor">
|
|
<GridCol Span="6">
|
|
<Tree TItem="FileTreeNode"
|
|
DataSource="FileTree"
|
|
TitleExpression="x => x.DataItem.Name"
|
|
ChildrenExpression="x => x.DataItem.Children"
|
|
IsLeafExpression="x => !x.DataItem.HasChildren"
|
|
OnDblClick="(args) => OpenFile(args.Node.DataItem)">
|
|
</Tree>
|
|
</GridCol>
|
|
|
|
<GridCol Span="18">
|
|
<Tabs Type="@TabType.EditableCard" HideAdd @bind-ActiveKey="ActiveFile" OnClose="OnTabClose">
|
|
@foreach (var file in OpenFiles)
|
|
{
|
|
<TextEditorPane FilePath="@file" />
|
|
}
|
|
</Tabs>
|
|
</GridCol>
|
|
</GridRow>
|
|
|
|
<style>
|
|
.monaco-editor-container {
|
|
min-height: 600px;
|
|
}
|
|
|
|
.text-editor {
|
|
background: #252525;
|
|
min-height: 600px;
|
|
}
|
|
|
|
.text-editor .ant-tree {
|
|
background: none;
|
|
color: #ccc;
|
|
padding-top: 16px;
|
|
padding-left: 8px;
|
|
}
|
|
|
|
.text-editor .ant-tree-node-content-wrapper:hover {
|
|
background: none;
|
|
}
|
|
|
|
.text-editor .ant-tree-treenode:hover {
|
|
background: #37373d;
|
|
}
|
|
|
|
.text-editor .text-editor-info-bar {
|
|
padding-left: 16px;
|
|
padding-right: 16px;
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
padding-top: 8px;
|
|
padding-bottom: 8px;
|
|
background: #1e1e1e;
|
|
}
|
|
|
|
.text-editor .text-editor-info-bar .ant-breadcrumb,
|
|
.text-editor .ant-breadcrumb-separator,
|
|
.text-editor .ant-breadcrumb li:last-child {
|
|
color: #a9a9a9;
|
|
}
|
|
|
|
.text-editor .ant-tabs-card.ant-tabs-top > .ant-tabs-nav .ant-tabs-tab,
|
|
.text-editor .ant-tabs-card.ant-tabs-top > div > .ant-tabs-nav .ant-tabs-tab {
|
|
border-radius: 0;
|
|
background: #2d2d2d;
|
|
padding: 4px 10px;
|
|
color: #a9a9a9;
|
|
border: none;
|
|
}
|
|
|
|
.text-editor .ant-tabs-card > .ant-tabs-nav .ant-tabs-tab-active,
|
|
.text-editor .ant-tabs-card > div > .ant-tabs-nav .ant-tabs-tab-active {
|
|
background: #1e1e1e !important;
|
|
}
|
|
|
|
.text-editor .ant-tabs-tab .ant-tabs-tab-remove .anticon {
|
|
color: #a9a9a9;
|
|
}
|
|
|
|
.text-editor .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn,
|
|
.text-editor .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-remove .anticon {
|
|
color: #fff;
|
|
}
|
|
|
|
.text-editor .ant-tabs-top > .ant-tabs-nav::before {
|
|
border: none;
|
|
}
|
|
|
|
.text-editor .ant-tabs-nav {
|
|
margin: 0;
|
|
}
|
|
</style>
|
|
|
|
@code {
|
|
[Parameter] public string WorkingDirectory { get; set; }
|
|
|
|
StandaloneCodeEditor? Editor;
|
|
|
|
IEnumerable<string> Files;
|
|
HashSet<FileTreeNode> FileTree { get; set; } = new HashSet<FileTreeNode>();
|
|
string CurrentFile = "";
|
|
|
|
List<string> OpenFiles = new List<string>();
|
|
string ActiveFile;
|
|
|
|
private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
|
|
{
|
|
return new StandaloneEditorConstructionOptions
|
|
{
|
|
AutomaticLayout = true,
|
|
Theme = "vs-dark"
|
|
};
|
|
}
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
var root = new FileTreeNode
|
|
{
|
|
Name = "/",
|
|
FullName = WorkingDirectory,
|
|
IsExpanded = true
|
|
};
|
|
|
|
root.PopulateChildren(WorkingDirectory);
|
|
|
|
foreach (var child in root.Children)
|
|
{
|
|
FileTree.Add(child);
|
|
}
|
|
}
|
|
|
|
private void OpenFile(FileTreeNode node)
|
|
{
|
|
if (!OpenFiles.Contains(node.FullName))
|
|
OpenFiles.Add(node.FullName);
|
|
|
|
ActiveFile = node.FullName;
|
|
|
|
StateHasChanged();
|
|
}
|
|
|
|
private void OnTabClose(string key)
|
|
{
|
|
OpenFiles.Remove(key);
|
|
|
|
StateHasChanged();
|
|
}
|
|
|
|
public class FileTreeNode
|
|
{
|
|
public string Name { get; set; }
|
|
public string FullName { get; set; }
|
|
public bool IsExpanded { get; set; } = false;
|
|
public bool IsDirectory { get; set; } = false;
|
|
public bool HasChildren => Children != null && Children.Count > 0;
|
|
public HashSet<FileTreeNode> Children { get; set; } = new HashSet<FileTreeNode>();
|
|
|
|
public void PopulateChildren(string path)
|
|
{
|
|
if (Directory.Exists(path))
|
|
{
|
|
try
|
|
{
|
|
foreach (var file in Directory.GetFiles(path))
|
|
{
|
|
var fileInfo = new FileInfo(file);
|
|
|
|
Children.Add(new FileTreeNode
|
|
{
|
|
Name = fileInfo.Name,
|
|
FullName = fileInfo.FullName,
|
|
IsDirectory = false
|
|
});
|
|
}
|
|
}
|
|
catch { }
|
|
|
|
try
|
|
{
|
|
foreach (var directory in Directory.GetDirectories(path))
|
|
{
|
|
var directoryInfo = new DirectoryInfo(directory);
|
|
|
|
var child = new FileTreeNode
|
|
{
|
|
Name = directoryInfo.Name,
|
|
FullName = directoryInfo.FullName,
|
|
IsDirectory = true
|
|
};
|
|
|
|
child.PopulateChildren(directoryInfo.FullName);
|
|
|
|
Children.Add(child);
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
public void PopulateChildren(IEnumerable<string> paths)
|
|
{
|
|
var childPaths = paths.Where(p => p.StartsWith(FullName) && p.EndsWith(Path.PathSeparator));
|
|
var directChildren = childPaths.Where(p => p != FullName && p.Substring(FullName.Length + 1).TrimEnd(Path.PathSeparator).Split(Path.PathSeparator).Length == 1);
|
|
|
|
foreach (var directChild in directChildren)
|
|
{
|
|
var child = new FileTreeNode()
|
|
{
|
|
FullName = directChild,
|
|
Name = directChild.Substring(FullName.Length).TrimEnd(Path.PathSeparator)
|
|
};
|
|
|
|
child.PopulateChildren(paths);
|
|
|
|
Children.Add(child);
|
|
}
|
|
}
|
|
}
|
|
}
|