-
Notifications
You must be signed in to change notification settings - Fork 1
DashboardViewModel #6
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
Changes from all commits
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 |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| using System.Runtime.Versioning; | ||
| using System.Diagnostics; | ||
| using System.Runtime.Versioning; | ||
| using System.Security.Principal; | ||
| using Avalonia; | ||
| using Avalonia.ReactiveUI; | ||
| using LogAnalyzerForWindows.Services; | ||
|
|
@@ -10,13 +12,21 @@ | |
| internal sealed class Program | ||
| { | ||
| public static SingleInstanceService? SingleInstance { get; private set; } | ||
| private static bool IsElevated { get; set; } | ||
|
|
||
| // Initialization code. Don't use any Avalonia, third-party APIs or any | ||
| // SynchronizationContext-reliant code before AppMain is called: things aren't initialized | ||
| // yet and stuff might break. | ||
| [STAThread] | ||
| public static void Main(string[] args) | ||
| { | ||
| IsElevated = IsRunningAsAdmin(); | ||
|
|
||
| if (!IsElevated && !args.Contains("--no-elevate")) | ||
| { | ||
| if (TryRestartAsAdmin()) | ||
| { | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| SingleInstance = new SingleInstanceService(); | ||
|
|
||
| if (!SingleInstance.TryStart()) | ||
|
|
@@ -35,7 +45,51 @@ | |
| } | ||
| } | ||
|
|
||
| // Avalonia configuration, don't remove; also used by visual designer. | ||
| private static bool IsRunningAsAdmin() | ||
| { | ||
| try | ||
| { | ||
| using var identity = WindowsIdentity.GetCurrent(); | ||
| var principal = new WindowsPrincipal(identity); | ||
| return principal.IsInRole(WindowsBuiltInRole.Administrator); | ||
| } | ||
| catch | ||
|
Check warning on line 56 in LogAnalyzerForWindows/Program.cs
|
||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| private static bool TryRestartAsAdmin() | ||
| { | ||
| try | ||
| { | ||
| var exePath = Environment.ProcessPath; | ||
| if (string.IsNullOrEmpty(exePath)) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| var startInfo = new ProcessStartInfo | ||
| { | ||
| FileName = exePath, | ||
| UseShellExecute = true, | ||
| Verb = "runas", | ||
| Arguments = string.Join(" ", Environment.GetCommandLineArgs().Skip(1)) | ||
|
||
| }; | ||
|
|
||
| Process.Start(startInfo); | ||
| return true; | ||
| } | ||
| catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 1223) | ||
| { | ||
| return false; | ||
| } | ||
| catch | ||
|
Check warning on line 87 in LogAnalyzerForWindows/Program.cs
|
||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public static AppBuilder BuildAvaloniaApp() | ||
| => AppBuilder.Configure<App>() | ||
| .UsePlatformDetect() | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -34,6 +34,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| private Axis[] _sourcesXAxes = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private Axis[] _sourcesYAxes = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| private Axis[] _eventIdsXAxes = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private Axis[] _eventIdsYAxes = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public DashboardViewModel(ILogRepository repository) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| _repository = repository ?? throw new ArgumentNullException(nameof(repository)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -114,6 +117,18 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| private set => SetProperty(ref _timelineYAxes, value); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public Axis[] EventIdsXAxes | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| get => _eventIdsXAxes; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private set => SetProperty(ref _eventIdsXAxes, value); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public Axis[] EventIdsYAxes | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| get => _eventIdsYAxes; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| private set => SetProperty(ref _eventIdsYAxes, value); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| public ISeries[] TopSourcesSeries | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| get => _topSourcesSeries; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -186,6 +201,27 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| MinLimit = 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| EventIdsYAxes = | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| new Axis | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Labels = [], | ||||||||||||||||||||||||||||||||||||||||||||||||||
| LabelsPaint = new SolidColorPaint(SKColors.LightGray), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| TextSize = 12 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| EventIdsXAxes = | ||||||||||||||||||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||||||||||||||||||
| new Axis | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
| Name = "Count", | ||||||||||||||||||||||||||||||||||||||||||||||||||
| NamePaint = new SolidColorPaint(SKColors.White), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| LabelsPaint = new SolidColorPaint(SKColors.LightGray), | ||||||||||||||||||||||||||||||||||||||||||||||||||
| MinLimit = 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+209
to
+223
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| Labels = [], | |
| LabelsPaint = new SolidColorPaint(SKColors.LightGray), | |
| TextSize = 12 | |
| } | |
| ]; | |
| EventIdsXAxes = | |
| [ | |
| new Axis | |
| { | |
| Name = "Count", | |
| NamePaint = new SolidColorPaint(SKColors.White), | |
| LabelsPaint = new SolidColorPaint(SKColors.LightGray), | |
| MinLimit = 0 | |
| } | |
| // Initialize with empty labels; full styling will be applied when data is loaded. | |
| Labels = [] | |
| } | |
| ]; | |
| EventIdsXAxes = | |
| [ | |
| // Minimal initialization; full styling will be applied when data is loaded. | |
| new Axis() |
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Code Quality & Linting
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Debug)
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Release)
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Publish Self-Contained (win-x64)
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Debug)
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Release)
Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Code Quality & Linting
Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Publish Self-Contained (win-x64)
Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Debug)
Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
GitHub Actions / Build & Test (Release)
Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
Copilot
AI
Dec 18, 2025
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.
Inconsistent axis reset behavior in empty data handling. When topEventIds.Count == 0, only EventIdsYAxes is reset but EventIdsXAxes is not. This is inconsistent with the UpdateTopSourcesChart method which doesn't reset any axes when data is empty, and also inconsistent within the same method. For consistency and to prevent displaying stale axis labels, both EventIdsXAxes and EventIdsYAxes should be reset when there's no data, similar to how both axes are updated together when data is present.
| EventIdsYAxes = [new Axis { Labels = [] }]; | |
| EventIdsYAxes = []; | |
| EventIdsXAxes = []; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,44 +1,25 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||
| <!-- This manifest is used on Windows only. | ||
| Don't remove it as it might cause problems with window transparency and embeded controls. | ||
| For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> | ||
| <assemblyIdentity version="1.0.0.0" name="LogAnalyzerForWindows.Desktop"/> | ||
|
|
||
| <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> | ||
| <security> | ||
| <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
| <!-- UAC Manifest Options | ||
|
|
||
|
|
||
| <requestedExecutionLevel level="asInvoker" uiAccess="false" /> | ||
| <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> | ||
| <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> | ||
| --> | ||
| <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> | ||
| <requestedExecutionLevel level="asInvoker" uiAccess="false" /> | ||
| </requestedPrivileges> | ||
| </security> | ||
| </trustInfo> | ||
|
|
||
| <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | ||
| <application> | ||
| <!-- A list of the Windows versions that this application has been tested on | ||
| and is designed to work with. --> | ||
|
|
||
| <!-- Windows 10 and Windows 11 --> | ||
| <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> | ||
| </application> | ||
| </compatibility> | ||
|
|
||
| <!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher | ||
| DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need | ||
| to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should | ||
| also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. --> | ||
| <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
| <windowsSettings> | ||
| <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> | ||
| <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware> | ||
| </windowsSettings> | ||
| </application> | ||
|
|
||
| </assembly> |
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.
Potential infinite restart loop if elevation is required. When TryRestartAsAdmin successfully launches the elevated process and returns true, the current process exits. However, if the elevated process also fails the admin check (which shouldn't happen but could in edge cases), it would attempt to elevate again. Additionally, the --no-elevate flag is not automatically added when restarting, so if the user cancels the UAC prompt (error 1223), the application continues running without admin privileges but will attempt elevation again on next start.
Consider adding the --no-elevate flag when restarting to prevent repeated UAC prompts if the user cancels, or documenting this behavior clearly.