335 lines
8.7 KiB
C#
335 lines
8.7 KiB
C#
using System;
|
|
using System.CodeDom.Compiler;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Markup;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
using System.Windows.Threading;
|
|
using Crysome.Common.Network;
|
|
using Crysome.Server.Model;
|
|
using Crysome.Server.ViewModel;
|
|
|
|
namespace Crysome.Server.View;
|
|
|
|
public class ManageClients : UserControl, IComponentConnector
|
|
{
|
|
private readonly DispatcherTimer _animTimer = new DispatcherTimer
|
|
{
|
|
Interval = TimeSpan.FromMilliseconds(16L, 0L)
|
|
};
|
|
|
|
private readonly DispatcherTimer _statsTimer = new DispatcherTimer
|
|
{
|
|
Interval = TimeSpan.FromMilliseconds(800L, 0L)
|
|
};
|
|
|
|
private readonly double[] _dotX = new double[5] { 0.0, 30.0, 60.0, 90.0, 120.0 };
|
|
|
|
private readonly double[] _dotSpeed = new double[5] { 2.8, 2.1, 3.3, 1.9, 2.5 };
|
|
|
|
private const double CanvasWidth = 170.0;
|
|
|
|
private readonly TranslateTransform[] _dotTx;
|
|
|
|
internal ManageClients TheControl;
|
|
|
|
internal Canvas PacketCanvas;
|
|
|
|
internal Ellipse Dot0;
|
|
|
|
internal TranslateTransform DotTx0;
|
|
|
|
internal Ellipse Dot1;
|
|
|
|
internal TranslateTransform DotTx1;
|
|
|
|
internal Ellipse Dot2;
|
|
|
|
internal TranslateTransform DotTx2;
|
|
|
|
internal Ellipse Dot3;
|
|
|
|
internal TranslateTransform DotTx3;
|
|
|
|
internal Ellipse Dot4;
|
|
|
|
internal TranslateTransform DotTx4;
|
|
|
|
internal Border ThroughputBar;
|
|
|
|
internal TextBlock ThroughputText;
|
|
|
|
internal Border QualityBar;
|
|
|
|
internal TextBlock QualityBarText;
|
|
|
|
internal TextBlock RttText;
|
|
|
|
internal TextBlock LossText;
|
|
|
|
internal TextBlock TxText;
|
|
|
|
internal TextBlock RxText;
|
|
|
|
internal TextBlock ClientsCountText;
|
|
|
|
internal TextBlock AdaptiveLevelText;
|
|
|
|
internal DataGrid ClientsGrid;
|
|
|
|
private bool _contentLoaded;
|
|
|
|
public ManageClients()
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Expected O, but got Unknown
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0039: Expected O, but got Unknown
|
|
InitializeComponent();
|
|
_dotTx = new TranslateTransform[5] { DotTx0, DotTx1, DotTx2, DotTx3, DotTx4 };
|
|
_animTimer.Tick += AnimTimer_Tick;
|
|
_statsTimer.Tick += StatsTimer_Tick;
|
|
_animTimer.Start();
|
|
_statsTimer.Start();
|
|
base.Unloaded += delegate
|
|
{
|
|
_animTimer.Stop();
|
|
_statsTimer.Stop();
|
|
};
|
|
}
|
|
|
|
private void AnimTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
for (int i = 0; i < _dotTx.Length; i++)
|
|
{
|
|
_dotX[i] += _dotSpeed[i];
|
|
if (_dotX[i] > 180.0)
|
|
{
|
|
_dotX[i] = -10.0;
|
|
}
|
|
_dotTx[i].X = _dotX[i];
|
|
}
|
|
}
|
|
|
|
private void StatsTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
if (!(base.DataContext is ManageClientsViewModel manageClientsViewModel))
|
|
{
|
|
return;
|
|
}
|
|
List<CrysomeClient> clientSnapshot = manageClientsViewModel.GetClientSnapshot();
|
|
ClientsCountText.Text = clientSnapshot.Count.ToString();
|
|
if (clientSnapshot.Count == 0)
|
|
{
|
|
RttText.Text = "— ms";
|
|
LossText.Text = "0.0 %";
|
|
TxText.Text = "0 B";
|
|
RxText.Text = "0 B";
|
|
ThroughputBar.Width = 0.0;
|
|
ThroughputText.Text = "0 KB/s";
|
|
QualityBar.Width = 170.0;
|
|
QualityBarText.Text = "Idle";
|
|
AdaptiveLevelText.Text = " · —";
|
|
return;
|
|
}
|
|
double num = 0.0;
|
|
double num2 = 0.0;
|
|
long num3 = 0L;
|
|
long num4 = 0L;
|
|
foreach (CrysomeClient item in clientSnapshot)
|
|
{
|
|
num += item.RttMs;
|
|
num2 += item.LossRate;
|
|
num3 += item.BytesSent;
|
|
num4 += item.BytesRecv;
|
|
}
|
|
double num5 = num / (double)clientSnapshot.Count;
|
|
double num6 = num2 / (double)clientSnapshot.Count * 100.0;
|
|
RttText.Text = $"{num5:F0} ms";
|
|
LossText.Text = $"{num6:F1} %";
|
|
TxText.Text = FormatBytes(num3);
|
|
RxText.Text = FormatBytes(num4);
|
|
double num7 = (double)(num3 + num4) / 1024.0 / 0.8;
|
|
double val = Math.Min(170.0, num7 / 500.0 * 170.0);
|
|
ThroughputBar.Width = Math.Max(0.0, val);
|
|
ThroughputText.Text = $"{num7:F0} KB/s";
|
|
double num8 = Math.Min(1.0, num6 / 100.0 * 0.6 + num5 / 2000.0 * 0.4);
|
|
double width = Math.Max(10.0, (1.0 - num8) * 170.0);
|
|
QualityBar.Width = width;
|
|
if (num8 < 0.1)
|
|
{
|
|
QualityBar.Background = new SolidColorBrush(Color.FromRgb(129, 199, 132));
|
|
QualityBarText.Text = "Excellent";
|
|
AdaptiveLevelText.Text = " · HD";
|
|
}
|
|
else if (num8 < 0.3)
|
|
{
|
|
QualityBar.Background = new SolidColorBrush(Color.FromRgb(79, 195, 247));
|
|
QualityBarText.Text = "Good";
|
|
AdaptiveLevelText.Text = " · Good";
|
|
}
|
|
else if (num8 < 0.6)
|
|
{
|
|
QualityBar.Background = new SolidColorBrush(Color.FromRgb(byte.MaxValue, 183, 77));
|
|
QualityBarText.Text = "Fair";
|
|
AdaptiveLevelText.Text = " · Fair";
|
|
}
|
|
else
|
|
{
|
|
QualityBar.Background = new SolidColorBrush(Color.FromRgb(239, 83, 80));
|
|
QualityBarText.Text = "Poor";
|
|
AdaptiveLevelText.Text = " · Low";
|
|
}
|
|
LossText.Foreground = ((num6 < 1.0) ? new SolidColorBrush(Color.FromRgb(129, 199, 132)) : ((num6 < 5.0) ? new SolidColorBrush(Color.FromRgb(byte.MaxValue, 183, 77)) : new SolidColorBrush(Color.FromRgb(239, 83, 80))));
|
|
double num9 = 1.0 + Math.Min(2.0, num7 / 100.0);
|
|
for (int i = 0; i < _dotSpeed.Length; i++)
|
|
{
|
|
_dotSpeed[i] = (1.5 + (double)i * 0.4) * num9;
|
|
}
|
|
}
|
|
|
|
private static string FormatBytes(long b)
|
|
{
|
|
if (b < 1024)
|
|
{
|
|
return b + " B";
|
|
}
|
|
if (b < 1048576)
|
|
{
|
|
return ((double)b / 1024.0).ToString("F1") + " KB";
|
|
}
|
|
return ((double)b / 1024.0 / 1024.0).ToString("F1") + " MB";
|
|
}
|
|
|
|
private void ClientsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
if (base.DataContext is ManageClientsViewModel manageClientsViewModel && sender is DataGrid dataGrid)
|
|
{
|
|
List<ClientInfo> items = dataGrid.SelectedItems.Cast<ClientInfo>().ToList();
|
|
manageClientsViewModel.SyncSelectedClients(items);
|
|
}
|
|
}
|
|
|
|
private void ClientsGrid_PreviewKeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0010: Invalid comparison between Unknown and I4
|
|
if ((int)e.Key == 44 && (int)Keyboard.Modifiers == 2 && sender is DataGrid dataGrid)
|
|
{
|
|
dataGrid.SelectAll();
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void ClientsGrid_LostFocus(object sender, RoutedEventArgs e)
|
|
{
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
|
|
public void InitializeComponent()
|
|
{
|
|
if (!_contentLoaded)
|
|
{
|
|
_contentLoaded = true;
|
|
Uri resourceLocator = new Uri("/Crysome.Server;component/view/manageclients.xaml", UriKind.Relative);
|
|
Application.LoadComponent(this, resourceLocator);
|
|
}
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
void IComponentConnector.Connect(int connectionId, object target)
|
|
{
|
|
switch (connectionId)
|
|
{
|
|
case 1:
|
|
TheControl = (ManageClients)target;
|
|
break;
|
|
case 2:
|
|
PacketCanvas = (Canvas)target;
|
|
break;
|
|
case 3:
|
|
Dot0 = (Ellipse)target;
|
|
break;
|
|
case 4:
|
|
DotTx0 = (TranslateTransform)target;
|
|
break;
|
|
case 5:
|
|
Dot1 = (Ellipse)target;
|
|
break;
|
|
case 6:
|
|
DotTx1 = (TranslateTransform)target;
|
|
break;
|
|
case 7:
|
|
Dot2 = (Ellipse)target;
|
|
break;
|
|
case 8:
|
|
DotTx2 = (TranslateTransform)target;
|
|
break;
|
|
case 9:
|
|
Dot3 = (Ellipse)target;
|
|
break;
|
|
case 10:
|
|
DotTx3 = (TranslateTransform)target;
|
|
break;
|
|
case 11:
|
|
Dot4 = (Ellipse)target;
|
|
break;
|
|
case 12:
|
|
DotTx4 = (TranslateTransform)target;
|
|
break;
|
|
case 13:
|
|
ThroughputBar = (Border)target;
|
|
break;
|
|
case 14:
|
|
ThroughputText = (TextBlock)target;
|
|
break;
|
|
case 15:
|
|
QualityBar = (Border)target;
|
|
break;
|
|
case 16:
|
|
QualityBarText = (TextBlock)target;
|
|
break;
|
|
case 17:
|
|
RttText = (TextBlock)target;
|
|
break;
|
|
case 18:
|
|
LossText = (TextBlock)target;
|
|
break;
|
|
case 19:
|
|
TxText = (TextBlock)target;
|
|
break;
|
|
case 20:
|
|
RxText = (TextBlock)target;
|
|
break;
|
|
case 21:
|
|
ClientsCountText = (TextBlock)target;
|
|
break;
|
|
case 22:
|
|
AdaptiveLevelText = (TextBlock)target;
|
|
break;
|
|
case 23:
|
|
ClientsGrid = (DataGrid)target;
|
|
ClientsGrid.SelectionChanged += ClientsGrid_SelectionChanged;
|
|
ClientsGrid.PreviewKeyDown += ClientsGrid_PreviewKeyDown;
|
|
ClientsGrid.LostFocus += ClientsGrid_LostFocus;
|
|
break;
|
|
default:
|
|
_contentLoaded = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|