diff --git a/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs b/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs index f0e90a0f..8b3467bd 100644 --- a/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs +++ b/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs @@ -10,10 +10,9 @@ namespace ServiceLib.ViewModels; public class MsgViewModel : MyReactiveObject { private readonly ConcurrentQueue _queueMsg = new(); - private readonly StringBuilder _msgBuilder = new(); - private readonly int _numMaxMsg = 500; - private bool _lastMsgFilterNotAvailable; - private bool _blLockShow = false; + private volatile bool _lastMsgFilterNotAvailable; + private int _showLock = 0; // 0 = unlocked, 1 = locked + public int NumMaxMsg { get; } = 50; [Reactive] public string MsgFilter { get; set; } @@ -35,50 +34,52 @@ public class MsgViewModel : MyReactiveObject this.WhenAnyValue( x => x.AutoRefresh, y => y == true) - .Subscribe(c => { _config.MsgUIItem.AutoRefresh = AutoRefresh; }); + .Subscribe(c => _config.MsgUIItem.AutoRefresh = AutoRefresh); AppEvents.SendMsgViewRequested .AsObservable() //.ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(async content => await AppendQueueMsg(content)); + .Subscribe(content => _ = AppendQueueMsg(content)); } private async Task AppendQueueMsg(string msg) - { + { if (AutoRefresh == false) { return; } - _ = EnqueueQueueMsg(msg); - if (_blLockShow) - { - return; - } + EnqueueQueueMsg(msg); + if (!_config.UiItem.ShowInTaskbar) { return; } - _blLockShow = true; - - _msgBuilder.Clear(); - //foreach (var it in _queueMsg) - //{ - // _msgBuilder.Append(it); - //} - while (_queueMsg.TryDequeue(out var line)) + if (Interlocked.CompareExchange(ref _showLock, 1, 0) != 0) { - _msgBuilder.Append(line); + return; } + try + { + await Task.Delay(500).ConfigureAwait(false); - await _updateView?.Invoke(EViewAction.DispatcherShowMsg, _msgBuilder.ToString()); + var sb = new StringBuilder(); + while (_queueMsg.TryDequeue(out var line)) + { + sb.Append(line); + } - _blLockShow = false; + await _updateView?.Invoke(EViewAction.DispatcherShowMsg, sb.ToString()); + } + finally + { + Interlocked.Exchange(ref _showLock, 0); + } } - private async Task EnqueueQueueMsg(string msg) + private void EnqueueQueueMsg(string msg) { //filter msg if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable) @@ -97,26 +98,17 @@ public class MsgViewModel : MyReactiveObject } } - //Enqueue - if (_queueMsg.Count > _numMaxMsg) - { - for (int k = 0; k < _queueMsg.Count - _numMaxMsg; k++) - { - _queueMsg.TryDequeue(out _); - } - } _queueMsg.Enqueue(msg); if (!msg.EndsWith(Environment.NewLine)) { _queueMsg.Enqueue(Environment.NewLine); } - await Task.CompletedTask; } - public void ClearMsg() - { - _queueMsg.Clear(); - } + //public void ClearMsg() + //{ + // _queueMsg.Clear(); + //} private void DoMsgFilter() { diff --git a/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs index 3473cf23..ae12fa07 100644 --- a/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs @@ -5,6 +5,7 @@ using Avalonia.Controls.Notifications; using Avalonia.Controls.Primitives; using Avalonia.Media; using Avalonia.Styling; +using AvaloniaEdit; using ReactiveUI; using ReactiveUI.Fody.Helpers; using Semi.Avalonia; @@ -112,7 +113,8 @@ public class ThemeSettingViewModel : MyReactiveObject x.OfType(), x.OfType(), x.OfType(), - x.OfType() + x.OfType(), + x.OfType() )); style.Add(new Setter() { @@ -153,7 +155,8 @@ public class ThemeSettingViewModel : MyReactiveObject x.OfType(), x.OfType(), x.OfType(), - x.OfType() + x.OfType(), + x.OfType() )); style.Add(new Setter() { diff --git a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml index 54cd078e..cb8b2cbe 100644 --- a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml @@ -75,7 +75,8 @@ Name="txtMsg" Margin="{StaticResource Margin8}" IsReadOnly="True" - VerticalScrollBarVisibility="Auto"> + VerticalScrollBarVisibility="Auto" + WordWrap="True"> { - private readonly ScrollViewer _scrollViewer; - public MsgView() { InitializeComponent(); - _scrollViewer = this.FindControl("msgScrollViewer"); ViewModel = new MsgViewModel(UpdateViewHandler); @@ -44,19 +40,23 @@ public partial class MsgView : ReactiveUserControl private void ShowMsg(object msg) { - // txtMsg.Text = msg.ToString(); - txtMsg.AppendText(msg.ToString()); + if (txtMsg.Document.LineCount > ViewModel?.NumMaxMsg) + { + ClearMsg(); + } + if (togScrollToEnd.IsChecked ?? true) { + //txtMsg.ScrollToLine(txtMsg.Document.LineCount); txtMsg.ScrollToEnd(); - _scrollViewer?.ScrollToEnd(); } + txtMsg.AppendText(msg.ToString()); } public void ClearMsg() { - ViewModel?.ClearMsg(); - txtMsg.Text = ""; + txtMsg.Clear(); + txtMsg.AppendText("----- Message cleared -----\n"); } private void menuMsgViewSelectAll_Click(object? sender, RoutedEventArgs e) diff --git a/v2rayN/v2rayN/Views/MsgView.xaml.cs b/v2rayN/v2rayN/Views/MsgView.xaml.cs index 3cc1fdfa..af8eb5f4 100644 --- a/v2rayN/v2rayN/Views/MsgView.xaml.cs +++ b/v2rayN/v2rayN/Views/MsgView.xaml.cs @@ -48,18 +48,25 @@ public partial class MsgView private void ShowMsg(object msg) { txtMsg.BeginChange(); - txtMsg.Text = msg.ToString(); + + if (txtMsg.LineCount > ViewModel?.NumMaxMsg) + { + ClearMsg(); + } + + txtMsg.AppendText(msg.ToString()); if (togScrollToEnd.IsChecked ?? true) { txtMsg.ScrollToEnd(); } + txtMsg.EndChange(); } public void ClearMsg() { - ViewModel?.ClearMsg(); txtMsg.Clear(); + txtMsg.AppendText("----- Message cleared -----\n"); } private void menuMsgViewSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)