-
Notifications
You must be signed in to change notification settings - Fork 1
Develop #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop #7
Changes from all commits
8ddfa5e
51ae44a
db589ad
1d03b93
b134353
94b78e0
a607760
ed67149
c1b87e4
5041a8b
76d826c
d350740
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # Auto detect text files and perform LF normalization | ||
| * text=auto | ||
|
|
||
| # Force Windows line endings (CRLF) for C# and related files | ||
| *.cs text eol=crlf | ||
| *.csproj text eol=crlf | ||
| *.sln text eol=crlf | ||
| *.props text eol=crlf | ||
| *.targets text eol=crlf | ||
| *.config text eol=crlf | ||
| *.json text eol=crlf | ||
| *.xml text eol=crlf | ||
| *.xaml text eol=crlf | ||
| *.axaml text eol=crlf | ||
| *.resx text eol=crlf | ||
|
|
||
| # EditorConfig files | ||
| .editorconfig text eol=crlf | ||
|
|
||
| # Shell scripts should use LF | ||
| *.sh text eol=lf | ||
|
|
||
| # Batch/PowerShell scripts use CRLF | ||
| *.bat text eol=crlf | ||
| *.cmd text eol=crlf | ||
| *.ps1 text eol=crlf | ||
|
|
||
| # Markdown files | ||
| *.md text eol=crlf | ||
|
|
||
| # YAML files for GitHub Actions | ||
| *.yml text eol=lf | ||
| *.yaml text eol=lf | ||
|
|
||
| # Binary files | ||
| *.dll binary | ||
| *.exe binary | ||
| *.png binary | ||
| *.jpg binary | ||
| *.jpeg binary | ||
| *.gif binary | ||
| *.ico binary | ||
| *.pdf binary | ||
| *.zip binary | ||
| *.7z binary | ||
| *.gz binary | ||
| *.nupkg binary |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -96,22 +96,27 @@ private static void ConfigureServices(IServiceCollection services) | |||
| services.AddDbContextFactory<LogAnalyzerDbContext>(options => | ||||
| { | ||||
| options.UseSqlite(DbContextConfig.ConnectionString); | ||||
| options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); | ||||
| }); | ||||
|
|
||||
| services.AddSingleton<ISettingsService, SettingsService>(); | ||||
| services.AddSingleton<IDialogService, DialogService>(); | ||||
|
|
||||
| services.AddSingleton<ILogRepository, LogRepository>(); | ||||
| services.AddSingleton<IEmailService, EmailService>(); | ||||
| services.AddSingleton<IFileSystemService, FileSystemService>(); | ||||
| services.AddSingleton<ILogStatisticsService, LogStatisticsService>(); | ||||
| services.AddSingleton<ILogMonitor, LogMonitor>(); | ||||
| services.AddSingleton<ITrayIconService, TrayIconService>(); | ||||
| services.AddSingleton<ILogExportService, LogExportService>(); | ||||
|
|
||||
| services.AddTransient<IDialogService, DialogService>(); | ||||
| services.AddTransient<IEmailService, EmailService>(); | ||||
| services.AddTransient<IFileSystemService, FileSystemService>(); | ||||
|
|
||||
| services.AddTransient<MainWindowViewModel>(); | ||||
| services.AddTransient<SettingsViewModel>(); | ||||
| services.AddTransient<Func<ILogRepository, PaginationViewModel>>(sp => | ||||
| repository => new PaginationViewModel(repository)); | ||||
| services.AddTransient<DashboardViewModel>(); | ||||
| services.AddTransient<PaginationViewModel>(); | ||||
|
||||
| services.AddTransient<PaginationViewModel>(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| using System.Windows.Input; | ||
| using Avalonia.Threading; | ||
|
|
||
| namespace LogAnalyzerForWindows.Commands; | ||
|
|
||
| internal sealed class AsyncRelayCommand : ICommand | ||
| { | ||
| private readonly Func<Task> _execute; | ||
| private readonly Func<bool>? _canExecute; | ||
| private bool _isExecuting; | ||
|
|
||
| public AsyncRelayCommand(Func<Task> execute, Func<bool>? canExecute = null) | ||
| { | ||
| _execute = execute ?? throw new ArgumentNullException(nameof(execute)); | ||
| _canExecute = canExecute; | ||
| } | ||
|
|
||
| public event EventHandler? CanExecuteChanged; | ||
|
|
||
| public bool CanExecute(object? parameter) => !_isExecuting && (_canExecute?.Invoke() ?? true); | ||
|
|
||
| public async void Execute(object? parameter) | ||
| { | ||
| if (!CanExecute(parameter)) return; | ||
|
|
||
| _isExecuting = true; | ||
| OnCanExecuteChanged(); | ||
|
|
||
| try | ||
| { | ||
| await _execute().ConfigureAwait(false); | ||
| } | ||
| finally | ||
| { | ||
| _isExecuting = false; | ||
| await Dispatcher.UIThread.InvokeAsync(OnCanExecuteChanged); | ||
| } | ||
| } | ||
|
Comment on lines
+22
to
+38
|
||
|
|
||
| public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); | ||
| } | ||
|
|
||
| internal sealed class AsyncRelayCommand<T> : ICommand | ||
| { | ||
| private readonly Func<T?, Task> _execute; | ||
| private readonly Func<T?, bool>? _canExecute; | ||
| private bool _isExecuting; | ||
|
|
||
| public AsyncRelayCommand(Func<T?, Task> execute, Func<T?, bool>? canExecute = null) | ||
| { | ||
| _execute = execute ?? throw new ArgumentNullException(nameof(execute)); | ||
| _canExecute = canExecute; | ||
| } | ||
|
|
||
| public event EventHandler? CanExecuteChanged; | ||
|
|
||
| public bool CanExecute(object? parameter) | ||
| { | ||
| if (_isExecuting) return false; | ||
| if (_canExecute == null) return true; | ||
| return _canExecute(parameter is T t ? t : default); | ||
| } | ||
|
|
||
| public async void Execute(object? parameter) | ||
| { | ||
| if (!CanExecute(parameter)) return; | ||
|
|
||
| _isExecuting = true; | ||
| OnCanExecuteChanged(); | ||
|
|
||
| try | ||
| { | ||
| await _execute(parameter is T t ? t : default).ConfigureAwait(false); | ||
| } | ||
| finally | ||
| { | ||
| _isExecuting = false; | ||
| await Dispatcher.UIThread.InvokeAsync(OnCanExecuteChanged); | ||
| } | ||
| } | ||
|
|
||
| public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the default query tracking behavior to
NoTrackingat the DbContext level (line 99) is good for read-heavy operations, but it means write operations will need to explicitly attach entities or use tracking. Ensure that all write operations (e.g.,SaveLogsAsync) are tested to verify they work correctly with this global setting.This is generally a good optimization for this read-heavy application, but it's worth documenting this design decision.