Both modals now use SystemDecorations=None with a draggable title bar, sectioned layout matching the rest of the island shell, Escape-to-cancel, and themed brushes instead of hard-coded colours. ListSettings adds a Browse... button that reads agent frontmatter from arbitrary .md files.
91 lines
3.0 KiB
C#
91 lines
3.0 KiB
C#
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Interactivity;
|
|
using Avalonia.Platform.Storage;
|
|
using ClaudeDo.Data.Models;
|
|
using ClaudeDo.Ui.ViewModels.Modals;
|
|
|
|
namespace ClaudeDo.Ui.Views.Modals;
|
|
|
|
public partial class ListSettingsModalView : Window
|
|
{
|
|
public ListSettingsModalView()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private void TitleBar_PointerPressed(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
|
BeginMoveDrag(e);
|
|
}
|
|
|
|
private async void BrowseAgentClicked(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not ListSettingsModalViewModel vm) return;
|
|
var top = TopLevel.GetTopLevel(this);
|
|
if (top is null) return;
|
|
|
|
var files = await top.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
|
{
|
|
Title = "Choose agent file",
|
|
AllowMultiple = false,
|
|
FileTypeFilter = new[]
|
|
{
|
|
new FilePickerFileType("Agent files (*.md)") { Patterns = new[] { "*.md" } },
|
|
new FilePickerFileType("All files") { Patterns = new[] { "*" } },
|
|
},
|
|
});
|
|
if (files.Count == 0) return;
|
|
|
|
var path = files[0].Path.LocalPath;
|
|
var existing = vm.Agents.FirstOrDefault(a => string.Equals(a.Path, path, StringComparison.OrdinalIgnoreCase));
|
|
if (existing is not null)
|
|
{
|
|
vm.SelectedAgent = existing;
|
|
return;
|
|
}
|
|
|
|
var (name, description) = ReadFrontmatter(path);
|
|
var agent = new AgentInfo(name, description, path);
|
|
vm.Agents.Add(agent);
|
|
vm.SelectedAgent = agent;
|
|
}
|
|
|
|
private static (string name, string description) ReadFrontmatter(string filePath)
|
|
{
|
|
var fallback = System.IO.Path.GetFileNameWithoutExtension(filePath);
|
|
try
|
|
{
|
|
using var reader = new System.IO.StreamReader(filePath);
|
|
if (reader.ReadLine()?.Trim() != "---") return (fallback, "");
|
|
string name = fallback, description = "";
|
|
while (reader.ReadLine() is { } line)
|
|
{
|
|
if (line.Trim() == "---") break;
|
|
if (line.StartsWith("name:")) name = line["name:".Length..].Trim();
|
|
else if (line.StartsWith("description:")) description = line["description:".Length..].Trim();
|
|
}
|
|
return (name, description);
|
|
}
|
|
catch { return (fallback, ""); }
|
|
}
|
|
|
|
private async void BrowseClicked(object? sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is not ListSettingsModalViewModel vm) return;
|
|
var top = TopLevel.GetTopLevel(this);
|
|
if (top is null) return;
|
|
|
|
var folders = await top.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
|
|
{
|
|
Title = "Choose working directory",
|
|
AllowMultiple = false,
|
|
});
|
|
if (folders.Count > 0)
|
|
{
|
|
vm.WorkingDir = folders[0].Path.LocalPath;
|
|
}
|
|
}
|
|
}
|