//
// LogTabViewModel.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using Avalonia;
using DynamicData;
using DynamicData.Binding;
using PacketLogger.Models.Filters;
using PacketLogger.Models.Packets;
using ReactiveUI;
namespace PacketLogger.ViewModels;
///
public class LogTabViewModel : ViewModelBase, IDisposable
{
private readonly ReadOnlyObservableCollection _packets;
private IDisposable _packetsSubscription;
///
/// Initializes a new instance of the class.
///
public LogTabViewModel()
{
var dynamicFilter = this.WhenValueChanged(@this => @this.CurrentFilter)
.Select
(
filter =>
{
return (Func)((pi) =>
{
if (filter is null)
{
return true;
}
return filter.Match(pi);
});
}
);
_packetsSubscription = Provider.Packets.Connect()
.Filter(dynamicFilter)
.Sort(SortExpressionComparer.Ascending(x => x.PacketIndex))
.Bind(out _packets)
.ObserveOn(RxApp.MainThreadScheduler)
.DisposeMany()
.Subscribe();
CopyPackets = ReactiveCommand.CreateFromObservable
(
(l) => Observable.StartAsync
(
async () =>
{
var clipboardString = string.Join
('\n', l.OfType().Select(x => x.PacketString));
await Application.Current!.Clipboard!.SetTextAsync(clipboardString);
}
)
);
TogglePane = ReactiveCommand.Create
(
_ => PaneOpen = !PaneOpen
);
Clear = ReactiveCommand.Create
(
() => Provider.Clear()
);
SendFilter = new();
RecvFilter = new();
SendFilter.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "Whitelist")
{
CreateSendRecv();
}
};
RecvFilter.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "Whitelist")
{
CreateSendRecv();
}
};
SendFilter.Filters.CollectionChanged += (s, e) => { CreateSendRecv(); };
RecvFilter.Filters.CollectionChanged += (s, e) => { CreateSendRecv(); };
}
///
/// Gets the send filter model.
///
public LogFilterTabViewModel SendFilter { get; }
///
/// Gets the receive filter model.
///
public LogFilterTabViewModel RecvFilter { get; }
///
/// Gets the currently applied filter.
///
public IFilter? CurrentFilter { get; private set; }
///
/// Gets the filtered packets.
///
public ReadOnlyObservableCollection FilteredPackets => _packets;
///
/// Gets packet provider.
///
public IPacketProvider Provider { get; } = new DummyPacketProvider();
///
/// Gets whether the pane is open.
///
public bool PaneOpen { get; private set; } = true;
///
/// Gets the toggle pane command.
///
public ReactiveCommand TogglePane { get; }
///
/// Gets command to copy packets.
///
public ReactiveCommand CopyPackets { get; }
///
/// Gets the command for clearing.
///
public ReactiveCommand Clear { get; }
///
/// Gets or sets whether to log received packets.
///
public bool LogReceived { get; set; } = true;
///
/// Gets or sets whether to log sent packets.
///
public bool LogSent { get; set; } = true;
///
/// Gets or sets whether to scroll to teh bottom of the grid.
///
public bool Scroll { get; set; } = true;
///
/// Gets empty string.
///
public string Empty { get; } = string.Empty;
private void CreateSendRecv()
{
IFilter recvFilter = CreateCompound(RecvFilter);
IFilter sendFilter = CreateCompound(SendFilter);
CurrentFilter = new SendRecvFilter(sendFilter, recvFilter);
}
private IFilter CreateCompound(LogFilterTabViewModel logFilterTab)
{
List filters = new List();
foreach (var filter in logFilterTab.Filters)
{
filters.Add(FilterCreator.BuildFilter(filter.Type, filter.Value));
}
return new CompoundFilter(!logFilterTab.Whitelist, filters.ToArray());
}
///
public void Dispose()
{
TogglePane.Dispose();
_packetsSubscription.Dispose();
}
}