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