diff --git a/Needlework.Net.Desktop/Needlework.Net.Desktop.csproj b/Needlework.Net.Desktop/Needlework.Net.Desktop.csproj index 07b15b0..81a673b 100644 --- a/Needlework.Net.Desktop/Needlework.Net.Desktop.csproj +++ b/Needlework.Net.Desktop/Needlework.Net.Desktop.csproj @@ -11,7 +11,7 @@ False app.ico NeedleworkDotNet - 0.5.0.0 + 0.5.1.0 $(AssemblyVersion) False diff --git a/Needlework.Net.Desktop/ViewModels/OperationViewModel.cs b/Needlework.Net.Desktop/ViewModels/OperationViewModel.cs index 0d298a6..f755392 100644 --- a/Needlework.Net.Desktop/ViewModels/OperationViewModel.cs +++ b/Needlework.Net.Desktop/ViewModels/OperationViewModel.cs @@ -73,11 +73,20 @@ private List CreateTemplate(AvaloniaList request { var type = template[i]; if (!type.Contains("#")) continue; - if (requestClasses.Where(c => c.Id == type.Replace("#", string.Empty)).Any()) + + var foundClass = requestClasses.Where(c => c.Id == type.Replace("#", string.Empty)); + if (foundClass.Any()) { - AvaloniaList classes = [.. requestClasses]; - classes.Remove(rootClass); - template[i] = string.Join(string.Empty, CreateTemplate(classes)); + if (foundClass.First().PropertyEnums.Any()) + { + template[i] = string.Join(string.Empty, CreateTemplate([.. foundClass])); + } + else + { + AvaloniaList classes = [.. requestClasses]; + classes.Remove(rootClass); + template[i] = string.Join(string.Empty, CreateTemplate(classes)); + } } else { diff --git a/Needlework.Net.Desktop/ViewModels/WebsocketViewModel.cs b/Needlework.Net.Desktop/ViewModels/WebsocketViewModel.cs index 71d5548..69a162b 100644 --- a/Needlework.Net.Desktop/ViewModels/WebsocketViewModel.cs +++ b/Needlework.Net.Desktop/ViewModels/WebsocketViewModel.cs @@ -18,6 +18,8 @@ namespace Needlework.Net.Desktop.ViewModels public partial class WebsocketViewModel : PageBase { public ObservableCollection EventLog { get; } = []; + public SemaphoreSlim EventLogLock { get; } = new(1, 1); + [NotifyPropertyChangedFor(nameof(FilteredEventLog))] [ObservableProperty] private string _search = string.Empty; [ObservableProperty] private bool _isAttach = true; @@ -94,25 +96,34 @@ private void OnDisconnection(DisconnectionInfo info) private void OnMessage(EventMessage message) { - Avalonia.Threading.Dispatcher.UIThread.Invoke(() => + Avalonia.Threading.Dispatcher.UIThread.Invoke(async () => { if (!IsAttach) return; var line = $"{DateTime.Now:HH:mm:ss.fff} {message.Data?.EventType.ToUpper()} {message.Data?.Uri}"; Trace.WriteLine($"Message: {line}"); - if (EventLog.Count < 1000) + + await EventLogLock.WaitAsync(); + try { - EventLog.Add(line); - _events[line] = message; + if (EventLog.Count < 1000) + { + EventLog.Add(line); + _events[line] = message; + } + else + { + var key = EventLog[0]; + EventLog.RemoveAt(0); + _events.Remove(key); + + EventLog.Add(line); + _events[line] = message; + } } - else + finally { - var key = EventLog[0]; - EventLog.RemoveAt(0); - _events.Remove(key); - - EventLog.Add(line); - _events[line] = message; + EventLogLock.Release(); } }); } diff --git a/Needlework.Net.Desktop/Views/WebsocketView.axaml.cs b/Needlework.Net.Desktop/Views/WebsocketView.axaml.cs index c751251..af1ec95 100644 --- a/Needlework.Net.Desktop/Views/WebsocketView.axaml.cs +++ b/Needlework.Net.Desktop/Views/WebsocketView.axaml.cs @@ -7,6 +7,7 @@ using Needlework.Net.Desktop.Extensions; using Needlework.Net.Desktop.Messages; using Needlework.Net.Desktop.ViewModels; +using System; using TextMateSharp.Grammars; namespace Needlework.Net.Desktop.Views; @@ -14,6 +15,8 @@ namespace Needlework.Net.Desktop.Views; public partial class WebsocketView : UserControl, IRecipient { private TextEditor? _responseEditor; + public WebsocketViewModel? _viewModel; + private ListBox? _viewer; public WebsocketView() { @@ -29,9 +32,9 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); - var vm = (WebsocketViewModel)DataContext!; - var viewer = this.FindControl("EventViewer"); - vm.EventLog.CollectionChanged += (s, e) => { if (vm.IsTail) viewer!.ScrollIntoView(vm.EventLog.Count - 1); }; + _viewModel = (WebsocketViewModel)DataContext!; + _viewer = this.FindControl("EventViewer"); + _viewModel.EventLog.CollectionChanged += EventLog_CollectionChanged; ; _responseEditor = this.FindControl("ResponseEditor"); _responseEditor?.ApplyJsonEditorSettings(); @@ -41,6 +44,26 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) OnBaseThemeChanged(Application.Current!.ActualThemeVariant); } + private void EventLog_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) + { + Avalonia.Threading.Dispatcher.UIThread.Post(async () => + { + if (_viewModel!.IsTail) + { + await _viewModel.EventLogLock.WaitAsync(); + try + { + _viewer!.ScrollIntoView(_viewModel.EventLog.Count - 1); + } + catch (InvalidOperationException) { } + finally + { + _viewModel.EventLogLock.Release(); + } + } + }); + } + private void OnBaseThemeChanged(ThemeVariant currentTheme) {