From 704d649fba52d2eebeab379e3c60c3745d636927 Mon Sep 17 00:00:00 2001 From: Robert Date: Sun, 30 Jul 2023 10:42:31 +0200 Subject: [PATCH 1/9] Core - Limit log file size to 5 MB and only retain max 14 log files --- src/Artemis.Core/DryIoc/Factories/LoggerFactory.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Artemis.Core/DryIoc/Factories/LoggerFactory.cs b/src/Artemis.Core/DryIoc/Factories/LoggerFactory.cs index ba5e90db7..3aaa23f08 100644 --- a/src/Artemis.Core/DryIoc/Factories/LoggerFactory.cs +++ b/src/Artemis.Core/DryIoc/Factories/LoggerFactory.cs @@ -13,7 +13,10 @@ internal class LoggerFactory : ILoggerFactory internal static readonly ILogger Logger = new LoggerConfiguration() .Enrich.FromLogContext() .WriteTo.File(Path.Combine(Constants.LogsFolder, "Artemis log-.log"), + fileSizeLimitBytes: 5 * 1024 * 1024, + rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 14, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}") .WriteTo.Console() #if DEBUG From 2621542479f2d9a7646d677b5a185558e7c517fb Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 31 Jul 2023 22:30:52 +0200 Subject: [PATCH 2/9] Editor - Fixed crash when moving folders due to a race condition --- .../Panels/Properties/PropertiesViewModel.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertiesViewModel.cs index 46228ff84..9ed832d8c 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/Properties/PropertiesViewModel.cs @@ -111,7 +111,6 @@ public class PropertiesViewModel : ActivatableViewModelBase } public RenderProfileElement? ProfileElement => _profileElement?.Value; - public Layer? Layer => _profileElement?.Value as Layer; public ILayerProperty? LayerProperty => _layerProperty?.Value; public bool SuspendedEditing => _suspendedEditing?.Value ?? false; @@ -133,26 +132,27 @@ public class PropertiesViewModel : ActivatableViewModelBase private void UpdatePropertyGroups() { - if (ProfileElement == null) + RenderProfileElement? profileElement = ProfileElement; + if (profileElement == null) { PropertyGroupViewModels.Clear(); return; } ObservableCollection viewModels = new(); - if (Layer != null) + if (profileElement is Layer layer) { // Add base VMs - viewModels.Add(GetOrCreatePropertyViewModel(Layer.General, null, null)); - viewModels.Add(GetOrCreatePropertyViewModel(Layer.Transform, null, null)); + viewModels.Add(GetOrCreatePropertyViewModel(layer.General, null, null)); + viewModels.Add(GetOrCreatePropertyViewModel(layer.Transform, null, null)); // Add brush VM if the brush has properties - if (Layer.LayerBrush?.BaseProperties != null) - viewModels.Add(GetOrCreatePropertyViewModel(Layer.LayerBrush.BaseProperties, Layer.LayerBrush, null)); + if (layer.LayerBrush?.BaseProperties != null) + viewModels.Add(GetOrCreatePropertyViewModel(layer.LayerBrush.BaseProperties, layer.LayerBrush, null)); } // Add effect VMs - foreach (BaseLayerEffect layerEffect in ProfileElement.LayerEffects.OrderBy(e => e.Order)) + foreach (BaseLayerEffect layerEffect in profileElement.LayerEffects.OrderBy(e => e.Order)) { if (layerEffect.BaseProperties != null) viewModels.Add(GetOrCreatePropertyViewModel(layerEffect.BaseProperties, null, layerEffect)); From e0869e4f28654afa926fdc4d8bb5e30610d93369 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 9 Aug 2023 11:58:28 +0200 Subject: [PATCH 3/9] UI - Update Avalonia to 11.0.2 UI - Update FluentAvalonia to 2.0.1 --- src/Artemis.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Artemis.props b/src/Artemis.props index 6292d8cfa..a03be36cb 100644 --- a/src/Artemis.props +++ b/src/Artemis.props @@ -1,7 +1,7 @@ - 11.0.1 - 2.0.0 + 11.0.2 + 2.0.1 2.0.0-prerelease.94 2.88.3 From 4a152f4e95d9a24e48682da4b7ab0939467e0a59 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 14 Aug 2023 20:42:51 +0200 Subject: [PATCH 4/9] UI - Fixed possible crash when loading profiles with broken icons Debugger - Added routing debugger --- .../Screens/Debugger/DebugViewModel.cs | 5 +- .../Tabs/Routing/RoutingDebugView.axaml | 28 +++++ .../Tabs/Routing/RoutingDebugView.axaml.cs | 26 +++++ .../Tabs/Routing/RoutingDebugViewModel.cs | 108 ++++++++++++++++++ .../SidebarProfileConfigurationViewModel.cs | 10 +- 5 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml create mode 100644 src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml.cs create mode 100644 src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugViewModel.cs diff --git a/src/Artemis.UI/Screens/Debugger/DebugViewModel.cs b/src/Artemis.UI/Screens/Debugger/DebugViewModel.cs index 44f80c8d7..87cc92d7d 100644 --- a/src/Artemis.UI/Screens/Debugger/DebugViewModel.cs +++ b/src/Artemis.UI/Screens/Debugger/DebugViewModel.cs @@ -5,6 +5,7 @@ using Artemis.UI.Screens.Debugger.DataModel; using Artemis.UI.Screens.Debugger.Logs; using Artemis.UI.Screens.Debugger.Performance; using Artemis.UI.Screens.Debugger.Render; +using Artemis.UI.Screens.Debugger.Routing; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared; using ReactiveUI; @@ -15,9 +16,9 @@ public class DebugViewModel : ActivatableViewModelBase, IScreen { private ViewModelBase _selectedItem; - public DebugViewModel(IDebugService debugService, RenderDebugViewModel render, DataModelDebugViewModel dataModel, PerformanceDebugViewModel performance, LogsDebugViewModel logs) + public DebugViewModel(IDebugService debugService, RenderDebugViewModel render, DataModelDebugViewModel dataModel, PerformanceDebugViewModel performance, RoutingDebugViewModel routing, LogsDebugViewModel logs) { - Items = new ObservableCollection {render, dataModel, performance, logs}; + Items = new ObservableCollection {render, dataModel, performance, routing, logs}; _selectedItem = render; this.WhenActivated(d => Disposable.Create(debugService.ClearDebugger).DisposeWith(d)); diff --git a/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml new file mode 100644 index 000000000..e89fddd28 --- /dev/null +++ b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml @@ -0,0 +1,28 @@ + + + + + + + + + + + Navigation logs + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml.cs b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml.cs new file mode 100644 index 000000000..05c2474ea --- /dev/null +++ b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugView.axaml.cs @@ -0,0 +1,26 @@ +using Avalonia.Controls; +using Avalonia.ReactiveUI; +using Avalonia.Threading; + +namespace Artemis.UI.Screens.Debugger.Routing; + +public partial class RoutingDebugView : ReactiveUserControl +{ + public RoutingDebugView() + { + InitializeComponent(); + } + + protected override void OnInitialized() + { + base.OnInitialized(); + Dispatcher.UIThread.Post(() => LogsScrollViewer.ScrollToEnd(), DispatcherPriority.ApplicationIdle); + } + + private void Control_OnSizeChanged(object? sender, SizeChangedEventArgs e) + { + if (!(LogsScrollViewer.Extent.Height - LogsScrollViewer.Offset.Y - LogsScrollViewer.Bounds.Bottom <= 60)) + return; + Dispatcher.UIThread.Post(() => LogsScrollViewer.ScrollToEnd(), DispatcherPriority.Normal); + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugViewModel.cs b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugViewModel.cs new file mode 100644 index 000000000..63fc7cf10 --- /dev/null +++ b/src/Artemis.UI/Screens/Debugger/Tabs/Routing/RoutingDebugViewModel.cs @@ -0,0 +1,108 @@ +using System; +using System.IO; +using System.Reactive; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using Artemis.Core; +using Artemis.UI.Shared; +using Artemis.UI.Shared.Routing; +using Avalonia.Controls.Documents; +using Avalonia.Media; +using Avalonia.Threading; +using ReactiveUI; +using Serilog.Events; +using Serilog.Formatting.Display; + +namespace Artemis.UI.Screens.Debugger.Routing; + +public class RoutingDebugViewModel : ActivatableViewModelBase +{ + private readonly IRouter _router; + private const int MAX_ENTRIES = 1000; + private readonly MessageTemplateTextFormatter _formatter; + private string? _route; + + public RoutingDebugViewModel(IRouter router) + { + _router = router; + DisplayName = "Routing"; + Navigate = ReactiveCommand.CreateFromTask(ExecuteNavigate, this.WhenAnyValue(vm => vm.Route).Select(r => !string.IsNullOrWhiteSpace(r))); + + _formatter = new MessageTemplateTextFormatter( + "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff}] [{Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}" + ); + + foreach (LogEvent logEvent in LogStore.Events) + AddLogEvent(logEvent); + + this.WhenActivated(disp => + { + LogStore.EventAdded += OnLogEventAdded; + Disposable.Create(() => LogStore.EventAdded -= OnLogEventAdded).DisposeWith(disp); + + _router.CurrentPath.Subscribe(p => Route = p).DisposeWith(disp); + }); + } + + public InlineCollection Lines { get; } = new(); + public ReactiveCommand Navigate { get; } + + public string? Route + { + get => _route; + set => RaiseAndSetIfChanged(ref _route, value); + } + + private void OnLogEventAdded(object? sender, LogEventEventArgs e) + { + Dispatcher.UIThread.Post(() => AddLogEvent(e.LogEvent)); + } + + private void AddLogEvent(LogEvent? logEvent) + { + if (logEvent is null) + return; + if (!logEvent.Properties.TryGetValue("SourceContext", out LogEventPropertyValue? sourceContext) || sourceContext.ToString() != "\"Artemis.UI.Shared.Routing.Navigation\"") + return; + + using StringWriter writer = new(); + _formatter.Format(logEvent, writer); + string line = writer.ToString(); + + Lines.Add(new Run(line.TrimEnd('\r', '\n') + '\n') + { + Foreground = logEvent.Level switch + { + LogEventLevel.Verbose => new SolidColorBrush(Colors.White), + LogEventLevel.Debug => new SolidColorBrush(Color.FromRgb(216, 216, 216)), + LogEventLevel.Information => new SolidColorBrush(Color.FromRgb(93, 201, 255)), + LogEventLevel.Warning => new SolidColorBrush(Color.FromRgb(255, 177, 53)), + LogEventLevel.Error => new SolidColorBrush(Color.FromRgb(255, 63, 63)), + LogEventLevel.Fatal => new SolidColorBrush(Colors.Red), + _ => throw new ArgumentOutOfRangeException() + } + }); + LimitLines(); + } + + private void LimitLines() + { + if (Lines.Count > MAX_ENTRIES) + Lines.RemoveRange(0, Lines.Count - MAX_ENTRIES); + } + + private async Task ExecuteNavigate(CancellationToken arg) + { + try + { + if (Route != null) + await _router.Navigate(Route.Trim()); + } + catch (Exception) + { + // ignored + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs index 98749cb51..4fa5728a5 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs @@ -42,7 +42,15 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase .Select(p => p == null) .ToProperty(this, vm => vm.IsDisabled) .DisposeWith(d)); - _profileService.LoadProfileConfigurationIcon(ProfileConfiguration); + + try + { + _profileService.LoadProfileConfigurationIcon(ProfileConfiguration); + } + catch (Exception) + { + // ignored, too bad but don't crash over corrupt icons + } } public ProfileConfiguration ProfileConfiguration { get; } From 65c071e0bdb97234127477061204bc3f762eaa32 Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 14 Aug 2023 20:55:45 +0200 Subject: [PATCH 5/9] UI - Fixed navigating to deep links --- src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs index 039cc2404..b8ad5aede 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs @@ -30,6 +30,7 @@ public class SidebarViewModel : ActivatableViewModelBase private readonly IWindowService _windowService; private ReadOnlyObservableCollection _sidebarCategories = new(new ObservableCollection()); private SidebarScreenViewModel? _selectedScreen; + private bool _updating; public SidebarViewModel(IRouter router, IProfileService profileService, IWindowService windowService, ISidebarVmFactory sidebarVmFactory) { @@ -57,7 +58,12 @@ public class SidebarViewModel : ActivatableViewModelBase SourceList profileCategories = new(); this.WhenActivated(d => { - _router.CurrentPath.WhereNotNull().Subscribe(r => SelectedScreen = SidebarScreen.GetMatch(r)).DisposeWith(d); + _router.CurrentPath.WhereNotNull().Subscribe(r => + { + _updating = true; + SelectedScreen = SidebarScreen.GetMatch(r); + _updating = false; + }).DisposeWith(d); Observable.FromEventPattern(x => profileService.ProfileCategoryAdded += x, x => profileService.ProfileCategoryAdded -= x) .Subscribe(e => profileCategories.Add(e.EventArgs.ProfileCategory)) @@ -115,6 +121,9 @@ public class SidebarViewModel : ActivatableViewModelBase private void NavigateToScreen(SidebarScreenViewModel sidebarScreenViewModel) { + if (_updating) + return; + Dispatcher.UIThread.Invoke(async () => { try From 4223879e726dfcadaed4188c7dd7d1ee7fde7acc Mon Sep 17 00:00:00 2001 From: Diogo Trindade Date: Wed, 16 Aug 2023 17:27:51 +0100 Subject: [PATCH 6/9] UI - Fix layout loading --- .../Device/Tabs/DeviceGeneralTabViewModel.cs | 8 ----- .../Device/Tabs/DeviceLayoutTabView.axaml | 8 +++-- .../Device/Tabs/DeviceLayoutTabView.axaml.cs | 4 +-- .../Device/Tabs/DeviceLayoutTabViewModel.cs | 36 +++++++++++++------ 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabViewModel.cs b/src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabViewModel.cs index 40945c443..f8f21599b 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabViewModel.cs +++ b/src/Artemis.UI/Screens/Device/Tabs/DeviceGeneralTabViewModel.cs @@ -66,13 +66,11 @@ public class DeviceGeneralTabViewModel : ActivatableViewModelBase this.WhenActivated(d => { - Device.PropertyChanged += DeviceOnPropertyChanged; _coreService.FrameRendering += OnFrameRendering; Disposable.Create(() => { _coreService.FrameRendering -= OnFrameRendering; - Device.PropertyChanged -= DeviceOnPropertyChanged; Apply(); }).DisposeWith(d); }); @@ -244,10 +242,4 @@ public class DeviceGeneralTabViewModel : ActivatableViewModelBase using SKPaint overlayPaint = new() { Color = CurrentColor }; e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint); } - - private void DeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout)) - Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device)); - } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml b/src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml index 414f63d93..d253e231f 100644 --- a/src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml +++ b/src/Artemis.UI/Screens/Device/Tabs/DeviceLayoutTabView.axaml @@ -21,6 +21,7 @@