move interfaces to separate folder

This commit is contained in:
2025-12-10 22:32:48 +05:00
parent 30256a86c2
commit b1d4f3693b
16 changed files with 244 additions and 183 deletions

View File

@@ -1,4 +1,5 @@
using System.Windows; using System.Windows;
using CodeContextGenerator.Interfaces;
using CodeContextGenerator.Services; using CodeContextGenerator.Services;
using CodeContextGenerator.ViewModels; using CodeContextGenerator.ViewModels;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;

View File

@@ -0,0 +1,6 @@
namespace CodeContextGenerator.Interfaces;
public interface IContextFileGenerator
{
Task GenerateContextFileAsync(List<string> selectedFiles, string outputPath, string projectRootPath, IProgress<int> progress, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,6 @@
namespace CodeContextGenerator.Interfaces;
public interface IFileProcessorService
{
string ProcessFileContent(string content, string fileName);
}

View File

@@ -0,0 +1,9 @@
using CodeContextGenerator.Models;
namespace CodeContextGenerator.Interfaces;
public interface IFileScannerService
{
Task BuildDirectoryTreeAsync(string path, FileItem parentItem, IProgress<int> progress = null, CancellationToken cancellationToken = default);
List<string> GetSelectedFiles(FileItem rootItem);
}

View File

@@ -0,0 +1,9 @@
using CodeContextGenerator.Models;
namespace CodeContextGenerator.Interfaces;
public interface IProjectLoaderService
{
Task<FileItem> LoadProjectFromPathAsync(string projectPath, IProgress<int> progress, CancellationToken cancellationToken);
string GetDefaultOutputFileName(string projectPath);
}

View File

@@ -0,0 +1,7 @@
namespace CodeContextGenerator.Interfaces;
public interface ISettingsService
{
string GetLastProjectPath();
void SaveLastProjectPath(string path);
}

View File

@@ -0,0 +1,11 @@
using System.Windows;
namespace CodeContextGenerator.Interfaces;
public interface IUIService
{
string ShowFolderBrowserDialog(string initialDirectory = null);
bool ShowOpenProjectFileDialog(out string selectedPath);
bool ShowSaveFileDialog(string defaultFileName, string initialDirectory, out string savePath);
void ShowMessage(string message, string title, MessageBoxImage icon = MessageBoxImage.Information);
}

View File

@@ -1,13 +1,9 @@
using System.IO; using CodeContextGenerator.Interfaces;
using System.IO;
using System.Text; using System.Text;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface IContextFileGenerator
{
Task GenerateContextFileAsync(List<string> selectedFiles, string outputPath, string projectRootPath, IProgress<int> progress, CancellationToken cancellationToken);
}
public class ContextFileGenerator : IContextFileGenerator public class ContextFileGenerator : IContextFileGenerator
{ {
private readonly IFileProcessorService _fileProcessorService; private readonly IFileProcessorService _fileProcessorService;

View File

@@ -1,13 +1,9 @@
using System.Text; using CodeContextGenerator.Interfaces;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface IFileProcessorService
{
string ProcessFileContent(string content, string fileName);
}
public class FileProcessorService : IFileProcessorService public class FileProcessorService : IFileProcessorService
{ {
public string ProcessFileContent(string content, string fileName) public string ProcessFileContent(string content, string fileName)

View File

@@ -1,14 +1,9 @@
using CodeContextGenerator.Models; using CodeContextGenerator.Interfaces;
using CodeContextGenerator.Models;
using System.IO; using System.IO;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface IFileScannerService
{
Task BuildDirectoryTreeAsync(string path, FileItem parentItem, IProgress<int> progress = null, CancellationToken cancellationToken = default);
List<string> GetSelectedFiles(FileItem rootItem);
}
public class FileScannerService : IFileScannerService public class FileScannerService : IFileScannerService
{ {
private static readonly string[] ExcludedDirectories = { private static readonly string[] ExcludedDirectories = {

View File

@@ -1,15 +1,10 @@
using CodeContextGenerator.Models; using CodeContextGenerator.Interfaces;
using CodeContextGenerator.Models;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface IProjectLoaderService
{
Task<FileItem> LoadProjectFromPathAsync(string projectPath, IProgress<int> progress, CancellationToken cancellationToken);
string GetDefaultOutputFileName(string projectPath);
}
public class ProjectLoaderService : IProjectLoaderService public class ProjectLoaderService : IProjectLoaderService
{ {
private readonly IFileScannerService _fileScannerService; private readonly IFileScannerService _fileScannerService;

View File

@@ -1,96 +1,91 @@
using System.IO; using CodeContextGenerator.Models;
using CodeContextGenerator.Models; using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
namespace CodeContextGenerator.Services namespace CodeContextGenerator.Services;
public static class ProjectScannerService
{ {
public static class ProjectScannerService private static readonly string[] ExcludedDirectories = {
"bin", "obj", ".git", "packages", ".vs", "Properties",
"node_modules", ".vscode", ".idea", ".vs", "Debug", "Release"
};
private static readonly string[] IncludedExtensions = { ".cs", ".xaml" };
public static async Task BuildDirectoryTreeAsync(string path, FileItem parentItem, IProgress<int> progress = null, CancellationToken cancellationToken = default)
{ {
private static readonly string[] ExcludedDirectories = { cancellationToken.ThrowIfCancellationRequested();
"bin", "obj", ".git", "packages", ".vs", "Properties",
"node_modules", ".vscode", ".idea", ".vs", "Debug", "Release"
};
private static readonly string[] IncludedExtensions = { ".cs", ".xaml" }; try
public static async Task BuildDirectoryTreeAsync(string path, FileItem parentItem, IProgress<int> progress = null, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); if (!Directory.Exists(path))
return;
try var directories = Directory.GetDirectories(path)
.Where(d => !ExcludedDirectories.Any(ex => d.EndsWith(ex, System.StringComparison.OrdinalIgnoreCase) ||
Path.GetFileName(d).Equals(ex, System.StringComparison.OrdinalIgnoreCase)))
.ToList();
var files = Directory.GetFiles(path)
.Where(f => IncludedExtensions.Any(ext => f.EndsWith(ext, System.StringComparison.OrdinalIgnoreCase)))
.ToList();
int totalItems = directories.Count + files.Count;
int processedItems = 0;
// Обрабатываем поддиректории
foreach (var dir in directories)
{ {
if (!Directory.Exists(path)) cancellationToken.ThrowIfCancellationRequested();
return;
var directories = Directory.GetDirectories(path) var dirName = Path.GetFileName(dir);
.Where(d => !ExcludedDirectories.Any(ex => d.EndsWith(ex, System.StringComparison.OrdinalIgnoreCase) || var dirItem = new FileItem
Path.GetFileName(d).Equals(ex, System.StringComparison.OrdinalIgnoreCase)))
.ToList();
var files = Directory.GetFiles(path)
.Where(f => IncludedExtensions.Any(ext => f.EndsWith(ext, System.StringComparison.OrdinalIgnoreCase)))
.ToList();
int totalItems = directories.Count + files.Count;
int processedItems = 0;
// Обрабатываем поддиректории
foreach (var dir in directories)
{ {
cancellationToken.ThrowIfCancellationRequested(); Name = dirName,
FullName = dir,
IsDirectory = true,
Parent = parentItem,
IsSelected = false
};
var dirName = Path.GetFileName(dir); await BuildDirectoryTreeAsync(dir, dirItem, progress, cancellationToken);
var dirItem = new FileItem
{
Name = dirName,
FullName = dir,
IsDirectory = true,
Parent = parentItem,
IsSelected = false
};
await BuildDirectoryTreeAsync(dir, dirItem, progress, cancellationToken); // Добавляем директорию только если в ней есть файлы или поддиректории с файлами
if (dirItem.Children.Any())
// Добавляем директорию только если в ней есть файлы или поддиректории с файлами {
if (dirItem.Children.Any()) parentItem.Children.Add(dirItem);
{
parentItem.Children.Add(dirItem);
}
processedItems++;
progress?.Report((int)((processedItems * 100.0) / totalItems));
} }
// Обрабатываем файлы processedItems++;
foreach (var file in files) progress?.Report((int)((processedItems * 100.0) / totalItems));
}
// Обрабатываем файлы
foreach (var file in files)
{
cancellationToken.ThrowIfCancellationRequested();
var fileItem = new FileItem
{ {
cancellationToken.ThrowIfCancellationRequested(); Name = Path.GetFileName(file),
FullName = file,
IsDirectory = false,
Parent = parentItem,
IsSelected = false
};
var fileItem = new FileItem parentItem.Children.Add(fileItem);
{ processedItems++;
Name = Path.GetFileName(file), progress?.Report((int)((processedItems * 100.0) / totalItems));
FullName = file,
IsDirectory = false,
Parent = parentItem,
IsSelected = false
};
parentItem.Children.Add(fileItem);
processedItems++;
progress?.Report((int)((processedItems * 100.0) / totalItems));
}
}
catch (IOException)
{
// Игнорируем ошибки доступа к директориям
}
catch (UnauthorizedAccessException)
{
// Игнорируем ошибки доступа
} }
} }
catch (IOException)
{
// Игнорируем ошибки доступа к директориям
}
catch (UnauthorizedAccessException)
{
// Игнорируем ошибки доступа
}
} }
} }

View File

@@ -1,14 +1,9 @@
using System.IO; using CodeContextGenerator.Interfaces;
using System.IO;
using System.Text.Json; using System.Text.Json;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface ISettingsService
{
string GetLastProjectPath();
void SaveLastProjectPath(string path);
}
public class SettingsService : ISettingsService public class SettingsService : ISettingsService
{ {
private const string SettingsFileName = "app_settings.json"; private const string SettingsFileName = "app_settings.json";

View File

@@ -1,17 +1,10 @@
using Microsoft.Win32; using CodeContextGenerator.Interfaces;
using Microsoft.Win32;
using System.IO; using System.IO;
using System.Windows; using System.Windows;
namespace CodeContextGenerator.Services; namespace CodeContextGenerator.Services;
public interface IUIService
{
string ShowFolderBrowserDialog(string initialDirectory = null);
bool ShowOpenProjectFileDialog(out string selectedPath);
bool ShowSaveFileDialog(string defaultFileName, string initialDirectory, out string savePath);
void ShowMessage(string message, string title, MessageBoxImage icon = MessageBoxImage.Information);
}
public class UIService : IUIService public class UIService : IUIService
{ {
public string ShowFolderBrowserDialog(string initialDirectory = null) public string ShowFolderBrowserDialog(string initialDirectory = null)

View File

@@ -1,5 +1,5 @@
using CodeContextGenerator.Models; using CodeContextGenerator.Interfaces;
using CodeContextGenerator.Services; using CodeContextGenerator.Models;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using System.IO; using System.IO;

View File

@@ -1,68 +1,93 @@
<Window x:Class="CodeContextGenerator.Views.MainWindow" <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x:Class="CodeContextGenerator.Views.MainWindow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CodeContextGenerator.Views" xmlns:local="clr-namespace:CodeContextGenerator.Views"
mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Code Context Generator" Height="600" Width="800" Title="Code Context Generator"
WindowStartupLocation="CenterScreen"> Width="800"
Height="600"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<Window.Resources> <Window.Resources>
<Style TargetType="TreeViewItem"> <Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True"/> <Setter Property="IsExpanded" Value="True" />
<Setter Property="Focusable" Value="False"/> <Setter Property="Focusable" Value="False" />
</Style> </Style>
<Style TargetType="Button"> <Style TargetType="Button">
<Setter Property="Padding" Value="10,5"/> <Setter Property="Padding" Value="10,5" />
<Setter Property="Margin" Value="5,0"/> <Setter Property="Margin" Value="5,0" />
</Style> </Style>
<Style TargetType="TextBlock"> <Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center" />
</Style> </Style>
</Window.Resources> </Window.Resources>
<Grid Margin="10"> <Grid Margin="10">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto" />
<RowDefinition Height="*"/> <RowDefinition Height="*" />
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Выберите файл решения, проекта или папку:" FontWeight="Bold" Margin="0,0,0,5"/> <TextBlock
Grid.Row="0"
Margin="0,0,0,5"
FontWeight="Bold"
Text="Выберите файл решения, проекта или папку:" />
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,10"> <StackPanel
<Button Content="Выбрать..." Grid.Row="1"
Command="{Binding SelectProjectCommand}" Margin="0,0,0,10"
IsEnabled="{Binding CanSelectProject}" Orientation="Horizontal">
Width="100"/> <Button
<TextBlock Text="{Binding SelectedProjectPath}" Width="100"
VerticalAlignment="Center" Command="{Binding SelectProjectCommand}"
TextWrapping="Wrap" Content="Выбрать..."
MaxWidth="600" IsEnabled="{Binding CanSelectProject}" />
Margin="10,0,0,0"/> <TextBlock
MaxWidth="600"
Margin="10,0,0,0"
VerticalAlignment="Center"
Text="{Binding SelectedProjectPath}"
TextWrapping="Wrap" />
</StackPanel> </StackPanel>
<Border Grid.Row="2" BorderBrush="Gray" BorderThickness="1" CornerRadius="4" Padding="5" <Border
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}"> Grid.Row="2"
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Padding="5"
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"> BorderBrush="Gray"
<TreeView x:Name="ProjectTree" ItemsSource="{Binding RootDirectory.Children}" BorderThickness="1"
VirtualizingPanel.IsVirtualizing="True" CornerRadius="4"
VirtualizingPanel.VirtualizationMode="Recycling"> Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}">
<ScrollViewer
HorizontalScrollBarVisibility="Auto"
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"
VerticalScrollBarVisibility="Auto">
<TreeView
x:Name="ProjectTree"
ItemsSource="{Binding RootDirectory.Children}"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling">
<TreeView.ItemTemplate> <TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}"> <HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" MinHeight="24"> <StackPanel MinHeight="24" Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}" <CheckBox
IsThreeState="True" Margin="2,0,5,0"
VerticalAlignment="Center" Margin="2,0,5,0" VerticalAlignment="Center"
Click="CheckBox_Click"/> Click="CheckBox_Click"
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"
ToolTip="{Binding FullName}"/> IsThreeState="True" />
<TextBlock
VerticalAlignment="Center"
Text="{Binding Name}"
ToolTip="{Binding FullName}" />
</StackPanel> </StackPanel>
</HierarchicalDataTemplate> </HierarchicalDataTemplate>
</TreeView.ItemTemplate> </TreeView.ItemTemplate>
@@ -70,27 +95,49 @@
</ScrollViewer> </ScrollViewer>
</Border> </Border>
<TextBlock Grid.Row="2" Text="Проект еще не загружен. Выберите файл решения или проекта." <TextBlock
HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="2"
Foreground="Gray" FontSize="14" HorizontalAlignment="Center"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Collapsed}"/> VerticalAlignment="Center"
FontSize="14"
Foreground="Gray"
Text="Проект еще не загружен. Выберите файл решения или проекта."
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter=Collapsed}" />
<ProgressBar Grid.Row="3" Value="{Binding ProgressValue}" Height="20" Margin="0,10,0,10" <ProgressBar
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"/> Grid.Row="3"
Height="20"
Margin="0,10,0,10"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"
Value="{Binding ProgressValue}" />
<TextBlock Grid.Row="3" Text="{Binding ProgressText}" HorizontalAlignment="Center" <TextBlock
VerticalAlignment="Center" FontWeight="Bold" Grid.Row="3"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}"/> HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding ProgressText}"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0"> <StackPanel
<Button Content="Отмена" Command="{Binding CancelProcessingCommand}" Grid.Row="4"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}" Margin="0,10,0,0"
Background="#FFDC3545" Foreground="White"/> HorizontalAlignment="Right"
<Button Content="Закрыть" Command="{Binding ExitApplicationCommand}"/> Orientation="Horizontal">
<Button Content="Сформировать" Command="{Binding GenerateContextFileCommand}" <Button
IsEnabled="{Binding CanGenerate}" Background="#FFDC3545"
Background="#FF28A745" Foreground="White" Command="{Binding CancelProcessingCommand}"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}"/> Content="Отмена"
Foreground="White"
Visibility="{Binding IsProcessing, Converter={StaticResource BooleanToVisibilityConverter}}" />
<Button Command="{Binding ExitApplicationCommand}" Content="Закрыть" />
<Button
Background="#FF28A745"
Command="{Binding GenerateContextFileCommand}"
Content="Сформировать"
Foreground="White"
IsEnabled="{Binding CanGenerate}"
Visibility="{Binding IsProjectLoaded, Converter={StaticResource BooleanToVisibilityConverter}}" />
</StackPanel> </StackPanel>
</Grid> </Grid>
</Window> </Window>