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 diff --git a/src/Artemis.UI.Shared/Styles/TextBlock.axaml b/src/Artemis.UI.Shared/Styles/TextBlock.axaml index 8a5099cde..4ba8d8252 100644 --- a/src/Artemis.UI.Shared/Styles/TextBlock.axaml +++ b/src/Artemis.UI.Shared/Styles/TextBlock.axaml @@ -81,4 +81,8 @@ + + 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/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 @@