@inherits LayoutComponentBase
@implements IDisposable
@inject IProjectService ProjectService
@inject ISettingsService SettingsService
@inject IThemeService ThemeService
@inject OllamaSettings OllamaSettings
@Body
@code {
private string? activeSection;
private bool showProjectList;
private List? projects;
private List? fileTree;
private int currentProjectId;
private string? currentFilePath;
private string statusText = "Bereit";
private bool isBusy;
private double operationProgress;
private bool showRenameDialog;
private string renameNewName = string.Empty;
private FileTreeItem? renameTarget;
private bool showNewFileDialog;
private string newFileName = string.Empty;
private FileTreeItem? newFileParentDir;
[Inject]
private NavigationManager Navigation { get; set; } = default!;
protected override async Task OnInitializedAsync()
{
await SettingsService.InitializeAsync();
Navigation.LocationChanged += OnLocationChanged;
await LoadProjects();
await LoadProjectContext();
await AutoLoadLastProject();
}
private async Task AutoLoadLastProject()
{
if (currentProjectId > 0) return;
var lastId = await SettingsService.GetLastProjectIdAsync();
if (lastId == null) return;
var project = projects?.FirstOrDefault(p => p.Id == lastId.Value);
if (project != null)
{
await SettingsService.InitializeAsync(lastId.Value);
await SelectProject(project);
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var theme = OllamaSettings.Theme;
if (!string.IsNullOrEmpty(theme))
await ThemeService.ApplyTheme(theme);
}
}
public void Dispose()
{
Navigation.LocationChanged -= OnLocationChanged;
}
private async void OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
{
await LoadProjects();
await LoadProjectContext();
StateHasChanged();
}
private async Task LoadProjectContext()
{
currentProjectId = SettingsService.CurrentProjectId ?? 0;
currentFilePath = SettingsService.CurrentFilePath;
if (currentProjectId > 0)
{
await LoadFileTree();
}
else
{
fileTree = null;
}
}
private async Task LoadFileTree()
{
try
{
fileTree = await ProjectService.GetProjectFileTreeAsync(currentProjectId);
}
catch
{
fileTree = new();
}
}
private async Task LoadProjects()
{
try
{
projects = await ProjectService.GetAllProjectsAsync();
}
catch
{
projects = new();
}
}
private void ToggleSection(string section)
{
activeSection = activeSection == section ? null : section;
}
private void ExitApp()
{
activeSection = null;
Navigation.NavigateTo("/");
}
private void CreateNewProject()
{
activeSection = null;
Navigation.NavigateTo("/editor/newproject");
}
private void OpenEditor()
{
activeSection = null;
Navigation.NavigateTo("/editor");
}
private void NavigateTo(string path)
{
activeSection = null;
Navigation.NavigateTo(path);
}
private async Task SelectProject(Project project)
{
activeSection = "files";
SettingsService.CurrentProjectId = project.Id;
currentProjectId = project.Id;
SettingsService.CurrentFilePath = null;
await SettingsService.SaveLastProjectIdAsync(project.Id);
await SettingsService.LoadProjectSettingsAsync();
await LoadFileTree();
Navigation.NavigateTo($"/editor/index/{project.Id}");
}
private async Task RefreshFileTree()
{
await LoadFileTree();
StateHasChanged();
}
private void BeginRename(FileTreeItem item)
{
renameTarget = item;
renameNewName = item.Name;
showRenameDialog = true;
}
private void CancelRename()
{
showRenameDialog = false;
renameTarget = null;
renameNewName = string.Empty;
}
private async Task ConfirmRename()
{
if (renameTarget == null || string.IsNullOrWhiteSpace(renameNewName)) return;
try
{
var dir = Path.GetDirectoryName(renameTarget.FullPath)!;
var newPath = Path.Combine(dir, renameNewName);
if (File.Exists(newPath))
{
statusText = "Datei existiert bereits.";
return;
}
File.Move(renameTarget.FullPath, newPath);
if (currentFilePath == renameTarget.FullPath)
SettingsService.CurrentFilePath = newPath;
statusText = $"Umbenannt zu: {renameNewName}";
}
catch (Exception ex)
{
statusText = $"Fehler: {ex.Message}";
}
finally
{
showRenameDialog = false;
renameTarget = null;
renameNewName = string.Empty;
await LoadFileTree();
StateHasChanged();
}
}
private void BeginNewFile(FileTreeItem dir)
{
newFileParentDir = dir;
newFileName = string.Empty;
showNewFileDialog = true;
}
private void CancelNewFile()
{
showNewFileDialog = false;
newFileParentDir = null;
newFileName = string.Empty;
}
private async Task ConfirmNewFile()
{
if (newFileParentDir == null || string.IsNullOrWhiteSpace(newFileName)) return;
try
{
var path = Path.Combine(newFileParentDir.FullPath, newFileName);
if (!path.EndsWith(".md", StringComparison.OrdinalIgnoreCase))
path += ".md";
if (File.Exists(path))
{
statusText = "Datei existiert bereits.";
return;
}
File.WriteAllText(path, $"# {Path.GetFileNameWithoutExtension(path)}\n\n");
statusText = $"Erstellt: {Path.GetFileName(path)}";
}
catch (Exception ex)
{
statusText = $"Fehler: {ex.Message}";
}
finally
{
showNewFileDialog = false;
newFileParentDir = null;
newFileName = string.Empty;
await LoadFileTree();
StateHasChanged();
}
}
private void OpenFile(FileTreeItem item)
{
if (item.IsDirectory) return;
activeSection = null;
SettingsService.CurrentFilePath = item.FullPath;
Navigation.NavigateTo($"/editor/file/{currentProjectId}?t={DateTime.Now.Ticks}");
}
public void SetStatus(string text, bool busy = false, double progress = 0)
{
statusText = text;
isBusy = busy;
operationProgress = progress;
StateHasChanged();
}
}