You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

140 lines
3.7 KiB

using AuroraDesk.Presentation.ViewModels.Pages;
using System;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using Avalonia.VisualTree;
using ReactiveUI;
using ReactiveUI.Avalonia;
namespace AuroraDesk.Presentation.Views.Pages;
public partial class TcpClientPageView : ReactiveUserControl<TcpClientPageViewModel>
{
private ContentControl? _sessionDetailContent;
private ListBox? _receivedMessagesListBox;
private TcpClientSessionViewModel? _currentSession;
private IDisposable? _messagesSubscription;
private IDisposable? _autoScrollSubscription;
public TcpClientPageView()
{
InitializeComponent();
this.WhenActivated(disposables =>
{
_sessionDetailContent ??= this.FindControl<ContentControl>("SessionDetailContent");
var sessionSubscription = this.WhenAnyValue(x => x.ViewModel)
.WhereNotNull()
.Select(vm => vm.WhenAnyValue(v => v.SelectedSession))
.Switch()
.Subscribe(OnSessionChanged);
disposables.Add(sessionSubscription);
disposables.Add(Disposable.Create(ClearSessionState));
});
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void OnSessionChanged(TcpClientSessionViewModel? session)
{
if (ReferenceEquals(_currentSession, session))
{
UpdateReceivedMessagesListBox();
return;
}
ClearSessionState();
_currentSession = session;
UpdateReceivedMessagesListBox();
if (session is null)
{
return;
}
_messagesSubscription = Observable.FromEventPattern<NotifyCollectionChangedEventHandler, NotifyCollectionChangedEventArgs>(
h => session.ReceivedMessages.CollectionChanged += h,
h => session.ReceivedMessages.CollectionChanged -= h)
.Subscribe(_ => CheckAutoScroll());
_autoScrollSubscription = session.WhenAnyValue(x => x.IsAutoScrollToBottom)
.Subscribe(_ => CheckAutoScroll());
CheckAutoScroll();
}
private void CheckAutoScroll()
{
if (_currentSession?.IsAutoScrollToBottom == true)
{
ScrollToBottom();
}
}
private void ClearSessionState()
{
_messagesSubscription?.Dispose();
_messagesSubscription = null;
_autoScrollSubscription?.Dispose();
_autoScrollSubscription = null;
_currentSession = null;
}
private void UpdateReceivedMessagesListBox()
{
if (_sessionDetailContent is null)
{
return;
}
Dispatcher.UIThread.Post(() =>
{
_receivedMessagesListBox = _sessionDetailContent
.GetVisualDescendants()
.OfType<ListBox>()
.FirstOrDefault(x => x.Name == "SessionReceivedMessagesListBox");
CheckAutoScroll();
}, DispatcherPriority.Background);
}
private void ScrollToBottom()
{
if (_receivedMessagesListBox is null || _currentSession is null)
{
return;
}
if (_currentSession.ReceivedMessages.Count == 0)
{
return;
}
var lastItem = _currentSession.ReceivedMessages[^1];
Dispatcher.UIThread.Post(() =>
{
if (_receivedMessagesListBox is null)
{
return;
}
_receivedMessagesListBox.ScrollIntoView(lastItem);
_receivedMessagesListBox.SelectedIndex = -1;
}, DispatcherPriority.Background);
}
}