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
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);
|
|
}
|
|
}
|
|
|
|
|