From b1fdc34d730e384a25a10a0c85210f19dddff4c2 Mon Sep 17 00:00:00 2001 From: Scott Lilly <2271154+ScottLilly@users.noreply.github.com> Date: Tue, 27 May 2025 18:00:35 -0400 Subject: [PATCH 1/2] checkpoint --- Legba.Engine/Services/FileCollector.cs | 12 +++++++----- Legba/MainWindow.xaml.cs | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Legba.Engine/Services/FileCollector.cs b/Legba.Engine/Services/FileCollector.cs index 85feab6..21c477f 100644 --- a/Legba.Engine/Services/FileCollector.cs +++ b/Legba.Engine/Services/FileCollector.cs @@ -9,12 +9,14 @@ public class FileCollector { #region Constants and Fields - private static readonly IReadOnlyList s_fileExtensionsToInclude = [".cs", ".vb", ".xaml"]; + private static readonly IReadOnlyList s_fileExtensionsToInclude = + [".cs", ".vb", ".xaml", ".vsixmanifest", ".vsct", ".resx", ".json", ".xml", ".config", ".targets", ".props", ".ruleset"]; + private static readonly IReadOnlyList s_excludedFilePatterns = - [ - new Regex(@"(AssemblyAttributes|AssemblyInfo|\.g|\.g\.i|\.Designer|\.generated)\.(cs|vb)$", - RegexOptions.IgnoreCase | RegexOptions.Compiled) - ]; + [ + new Regex(@"(AssemblyAttributes|AssemblyInfo|\.g|\.g\.i|\.Designer|\.generated)\.(cs|vb|xaml)$", + RegexOptions.IgnoreCase | RegexOptions.Compiled) + ]; #endregion diff --git a/Legba/MainWindow.xaml.cs b/Legba/MainWindow.xaml.cs index 9afa3b1..42e9f35 100644 --- a/Legba/MainWindow.xaml.cs +++ b/Legba/MainWindow.xaml.cs @@ -16,8 +16,6 @@ public partial class MainWindow : Window { private HelpView? _helpView; - private static readonly FileConsolidator s_fileConsolidator = new(); - private readonly IServiceProvider _serviceProvider; private readonly ChatSessionViewModel? _chatSessionViewModel; From 026f77331b84cd561f59be7fc7e1372590461b24 Mon Sep 17 00:00:00 2001 From: Scott Lilly <2271154+ScottLilly@users.noreply.github.com> Date: Sun, 1 Jun 2025 07:00:01 -0400 Subject: [PATCH 2/2] Initial UI conversion to FlowDocument --- Legba.Engine/Legba.Engine.csproj | 13 +++--- Legba.Engine/Models/OpenAi/Message.cs | 16 ++++---- Legba.Engine/Models/OpenAi/OpenAiResponse.cs | 8 ++-- Legba.Engine/Services/FileCollector.cs | 38 ++++++++++------- Legba.Engine/ViewModels/AboutViewModel.cs | 4 +- .../ViewModels/ChatSessionViewModel.cs | 34 +++++++++++++++ Legba/Legba.csproj | 14 +++---- Legba/MainWindow.xaml | 41 ++++--------------- Legba/MainWindow.xaml.cs | 13 +++--- README.md | 2 - RELEASE_NOTES.md | 4 ++ 11 files changed, 105 insertions(+), 82 deletions(-) diff --git a/Legba.Engine/Legba.Engine.csproj b/Legba.Engine/Legba.Engine.csproj index ff15f3c..cf38ffc 100644 --- a/Legba.Engine/Legba.Engine.csproj +++ b/Legba.Engine/Legba.Engine.csproj @@ -5,7 +5,7 @@ true enable enable - 2.0.0.0 + 2.1.0.0 @@ -14,12 +14,13 @@ - - - - + + + + - + + diff --git a/Legba.Engine/Models/OpenAi/Message.cs b/Legba.Engine/Models/OpenAi/Message.cs index 04a008a..4d64281 100644 --- a/Legba.Engine/Models/OpenAi/Message.cs +++ b/Legba.Engine/Models/OpenAi/Message.cs @@ -37,34 +37,34 @@ public string DisplayText } [JsonIgnore] - public System.Windows.HorizontalAlignment MessageAlignment + public System.Windows.Media.Brush BackgroundColor { get { if (Role == Enums.Role.System || IsInitialSourceCode) { - return System.Windows.HorizontalAlignment.Center; + return System.Windows.Media.Brushes.Gold; } return IsSentByUser - ? System.Windows.HorizontalAlignment.Right - : System.Windows.HorizontalAlignment.Left; + ? System.Windows.Media.Brushes.LightBlue + : System.Windows.Media.Brushes.LightGray; } } [JsonIgnore] - public System.Windows.Media.Brush MessageBackground + public System.Windows.TextAlignment Alignment { get { if (Role == Enums.Role.System || IsInitialSourceCode) { - return System.Windows.Media.Brushes.Gold; + return System.Windows.TextAlignment.Center; } return IsSentByUser - ? System.Windows.Media.Brushes.LightBlue - : System.Windows.Media.Brushes.LightGray; + ? System.Windows.TextAlignment.Right + : System.Windows.TextAlignment.Left; } } } \ No newline at end of file diff --git a/Legba.Engine/Models/OpenAi/OpenAiResponse.cs b/Legba.Engine/Models/OpenAi/OpenAiResponse.cs index 7e08d2a..809b7e2 100644 --- a/Legba.Engine/Models/OpenAi/OpenAiResponse.cs +++ b/Legba.Engine/Models/OpenAi/OpenAiResponse.cs @@ -5,15 +5,15 @@ namespace Legba.Engine.Models.OpenAi; public class OpenAiResponse { [JsonPropertyName("id")] - public string Id { get; set; } + public string Id { get; set; } = string.Empty; [JsonPropertyName("object")] - public string _object { get; set; } + public string _object { get; set; } = string.Empty; [JsonPropertyName("created")] public int Created { get; set; } [JsonPropertyName("model")] - public string Model { get; set; } + public string Model { get; set; } = string.Empty; [JsonPropertyName("usage")] - public Usage Usage { get; set; } + public Usage Usage { get; set; } = new Usage(); [JsonPropertyName("choices")] public List Choices { get; set; } = new List(); } \ No newline at end of file diff --git a/Legba.Engine/Services/FileCollector.cs b/Legba.Engine/Services/FileCollector.cs index 21c477f..75349a5 100644 --- a/Legba.Engine/Services/FileCollector.cs +++ b/Legba.Engine/Services/FileCollector.cs @@ -10,14 +10,20 @@ public class FileCollector #region Constants and Fields private static readonly IReadOnlyList s_fileExtensionsToInclude = - [".cs", ".vb", ".xaml", ".vsixmanifest", ".vsct", ".resx", ".json", ".xml", ".config", ".targets", ".props", ".ruleset"]; - + [ + ".cs", ".vb", ".xaml", ".xaml.cs", ".xaml.vb", ".vsixmanifest", ".vsct", ".resx", + ".targets", ".props", ".ruleset", ".settings", ".cshtml", ".vbhtml", ".aspx", ".ascx" + ]; private static readonly IReadOnlyList s_excludedFilePatterns = [ - new Regex(@"(AssemblyAttributes|AssemblyInfo|\.g|\.g\.i|\.Designer|\.generated)\.(cs|vb|xaml)$", - RegexOptions.IgnoreCase | RegexOptions.Compiled) + new Regex( + @"(AssemblyInfo|AssemblyAttributes|\.g|\.g\.i|\.Designer|\.generated|\.razor\.cs|\.g\.cshtml|\.tt|\.t4|\.Reference)\.(cs|vb|xaml|cshtml)$", + RegexOptions.IgnoreCase | RegexOptions.Compiled) ]; + private static readonly IReadOnlyList s_excludedDirectories = + [ "bin", "obj", "node_modules", ".vs", "packages" ]; + #endregion #region Public Methods @@ -93,20 +99,22 @@ public static async Task> GetFilesFromFoldersAsync(string[ { ValidateFolderPaths(folderPaths); - var filePaths = new List(); + var filePaths = new ConcurrentBag(); - foreach (var folderPath in folderPaths) + await Parallel.ForEachAsync(folderPaths, async (folderPath, ct) => { - foreach (var extension in s_fileExtensionsToInclude) + await foreach (var file in Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories) + .ToAsyncEnumerable() + .Where(file => + s_fileExtensionsToInclude.Any(ext => file.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) && + !s_excludedDirectories.Any(dir => file.Contains(Path.DirectorySeparatorChar + dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) && + !IsExcludedFile(file))) { - filePaths.AddRange( - Directory.GetFiles(folderPath, $"*{extension}", - SearchOption.AllDirectories)); + filePaths.Add(file); } - } + }); - return await Task.FromResult>( - filePaths.Where(f => !IsExcludedFile(f)).ToList().AsReadOnly()); + return filePaths.ToList().AsReadOnly(); } public static async Task> GetFilesFromFilesAsync(string[] filePaths) @@ -142,7 +150,7 @@ private static void ValidateFolderPaths(string[] folderPaths) var invalidPaths = folderPaths.Where(fp => !Directory.Exists(fp)).ToArray(); - if (invalidPaths.Any()) + if (invalidPaths.Length != 0) { throw new DirectoryNotFoundException("One or more folder paths do not exist: " + string.Join(", ", invalidPaths)); } @@ -157,7 +165,7 @@ private static void ValidateFilePaths(string[] filePaths) var invalidPaths = filePaths.Where(fp => !File.Exists(fp)).ToArray(); - if (invalidPaths.Any()) + if (invalidPaths.Length != 0) { throw new FileNotFoundException("One or more files do not exist: " + string.Join(", ", invalidPaths)); } diff --git a/Legba.Engine/ViewModels/AboutViewModel.cs b/Legba.Engine/ViewModels/AboutViewModel.cs index 387418d..dbdacc0 100644 --- a/Legba.Engine/ViewModels/AboutViewModel.cs +++ b/Legba.Engine/ViewModels/AboutViewModel.cs @@ -6,7 +6,7 @@ namespace Legba.Engine.ViewModels; public class AboutViewModel { - private int initialCopyrightYear = 2023; + private const int INITIAL_COPYRIGHT_YEAR = 2023; private static readonly Version s_version = Assembly.GetExecutingAssembly().GetName().Version; @@ -14,7 +14,7 @@ public class AboutViewModel public string VersionText => $"{s_version.Major}.{s_version.Minor}.{s_version.Revision}"; public string Copyright => - $"© {(DateTime.Now.Year == initialCopyrightYear ? $"{initialCopyrightYear}" : $"{initialCopyrightYear} - {DateTime.Now.Year}")}, Lilly Software Consulting"; + $"© {(DateTime.Now.Year == INITIAL_COPYRIGHT_YEAR ? $"{INITIAL_COPYRIGHT_YEAR}" : $"{INITIAL_COPYRIGHT_YEAR} - {DateTime.Now.Year}")}, Lilly Software Consulting"; public string License => "Licensed under the MIT License"; public string ContactInformation => diff --git a/Legba.Engine/ViewModels/ChatSessionViewModel.cs b/Legba.Engine/ViewModels/ChatSessionViewModel.cs index 5faf572..9e65a45 100644 --- a/Legba.Engine/ViewModels/ChatSessionViewModel.cs +++ b/Legba.Engine/ViewModels/ChatSessionViewModel.cs @@ -2,7 +2,10 @@ using Microsoft.Extensions.DependencyInjection; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Windows; +using System.Windows.Documents; using System.Windows.Input; +using System.Windows.Media; namespace Legba.Engine.ViewModels; @@ -44,6 +47,7 @@ public ChatSession? ChatSession OnPropertyChanged(nameof(ChatSession)); OnPropertyChanged(nameof(HasChatSession)); OnPropertyChanged(nameof(HasChatMessages)); + OnPropertyChanged(nameof(MessagesDocument)); if (_chatSession != null) { @@ -52,6 +56,35 @@ public ChatSession? ChatSession } } + public FlowDocument MessagesDocument + { + get + { + var document = new FlowDocument(); + + if (ChatSession == null) + { + return document; + } + + foreach (var message in ChatSession.Messages) + { + var paragraph = new Paragraph(new Run(message.DisplayText)) + { + Margin = new Thickness(5), + TextAlignment = message.Alignment, + Background = message.BackgroundColor, + Padding = new Thickness(8), + FontSize = 14, + FontFamily = new FontFamily("Consolas") + }; + + document.Blocks.Add(paragraph); + } + + return document; + } + } public bool HasChatSession => ChatSession != null; public bool HasChatMessages => ChatSession?.Messages.Count > 0; @@ -80,6 +113,7 @@ public ChatSessionViewModel(IServiceProvider serviceProvider) private void Messages_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(HasChatMessages)); + OnPropertyChanged(nameof(MessagesDocument)); } private void SelectModel(Settings.Model model) diff --git a/Legba/Legba.csproj b/Legba/Legba.csproj index e376f98..e10ae85 100644 --- a/Legba/Legba.csproj +++ b/Legba/Legba.csproj @@ -8,7 +8,7 @@ true True Images\LegbaIcon.ico - 2.0.0.0 + 2.1.0.0 f63a3566-54ef-4629-9a95-4254f119e9a0 @@ -24,12 +24,12 @@ - - - - - - + + + + + + diff --git a/Legba/MainWindow.xaml b/Legba/MainWindow.xaml index d04be1e..ddb2cdd 100644 --- a/Legba/MainWindow.xaml +++ b/Legba/MainWindow.xaml @@ -127,38 +127,15 @@ - - - - - - - - - - - - - - - - - - - - +