Add clash display in the main interface

pull/5377/head
2dust 2024-06-28 16:14:19 +08:00
parent e3c2a4b8da
commit e963f9e349
10 changed files with 297 additions and 264 deletions

View File

@ -10,7 +10,6 @@ namespace v2rayN.Handler
private Dictionary<String, ProxiesItem> _proxies; private Dictionary<String, ProxiesItem> _proxies;
public Dictionary<string, object> ProfileContent { get; set; } public Dictionary<string, object> ProfileContent { get; set; }
public bool ShowInTaskbar { get; set; } = true;
public void SetProxies(Dictionary<String, ProxiesItem> proxies) public void SetProxies(Dictionary<String, ProxiesItem> proxies)
{ {

View File

@ -216,11 +216,12 @@ namespace v2rayN.Models
public class ClashUIItem public class ClashUIItem
{ {
public ERuleMode ruleMode { get; set; } public ERuleMode ruleMode { get; set; }
public bool showInTaskbar { get; set; }
public int proxiesSorting { get; set; } public int proxiesSorting { get; set; }
public bool proxiesAutoRefresh { get; set; } public bool proxiesAutoRefresh { get; set; }
public int AutoDelayTestInterval { get; set; } = 10; public int proxiesAutoDelayTestInterval { get; set; } = 10;
public int connectionsSorting { get; set; } public int connectionsSorting { get; set; }
public bool connectionsAutoRefresh { get; set; } public bool connectionsAutoRefresh { get; set; }
public int connectionsRefreshInterval { get; set; } = 2;
} }
} }

View File

@ -36,11 +36,8 @@ namespace v2rayN.ViewModels
[Reactive] [Reactive]
public bool AutoRefresh { get; set; } public bool AutoRefresh { get; set; }
private int AutoRefreshInterval;
public ClashConnectionsViewModel() public ClashConnectionsViewModel()
{ {
AutoRefreshInterval = 10;
SortingSelected = _config.clashUIItem.connectionsSorting; SortingSelected = _config.clashUIItem.connectionsSorting;
AutoRefresh = _config.clashUIItem.connectionsAutoRefresh; AutoRefresh = _config.clashUIItem.connectionsAutoRefresh;
@ -87,15 +84,26 @@ namespace v2rayN.ViewModels
private void Init() private void Init()
{ {
Observable.Interval(TimeSpan.FromSeconds(AutoRefreshInterval)) var lastTime = DateTime.Now;
.Subscribe(x =>
{ Observable.Interval(TimeSpan.FromSeconds(10))
if (!(AutoRefresh && ClashApiHandler.Instance.ShowInTaskbar)) .Subscribe(x =>
{ {
return; if (!(AutoRefresh && _config.clashUIItem.showInTaskbar))
} {
GetClashConnections(); return;
}); }
var dtNow = DateTime.Now;
if (_config.clashUIItem.connectionsRefreshInterval > 0)
{
if ((dtNow - lastTime).Minutes % _config.clashUIItem.connectionsRefreshInterval == 0)
{
GetClashConnections();
lastTime = dtNow;
}
Thread.Sleep(1000);
}
});
} }
private void GetClashConnections() private void GetClashConnections()

View File

@ -434,8 +434,8 @@ namespace v2rayN.ViewModels
var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result); var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result);
if (dicResult != null && dicResult.ContainsKey("delay")) if (dicResult != null && dicResult.ContainsKey("delay"))
{ {
detail.delay = Convert.ToInt32(dicResult["delay"]); detail.delay = Convert.ToInt32(dicResult["delay"].ToString());
detail.delayName = $"{dicResult["delay"]}ms"; detail.delayName = $"{detail.delay}ms";
} }
else if (dicResult != null && dicResult.ContainsKey("message")) else if (dicResult != null && dicResult.ContainsKey("message"))
{ {
@ -459,27 +459,26 @@ namespace v2rayN.ViewModels
public void DelayTestTask() public void DelayTestTask()
{ {
var autoDelayTestTime = DateTime.Now; var lastTime = DateTime.Now;
Observable.Interval(TimeSpan.FromSeconds(60)) Observable.Interval(TimeSpan.FromSeconds(60))
.Subscribe(x => .Subscribe(x =>
{ {
if (!(AutoRefresh && ClashApiHandler.Instance.ShowInTaskbar)) if (!(AutoRefresh && _config.clashUIItem.showInTaskbar))
{ {
return; return;
} }
var dtNow = DateTime.Now; var dtNow = DateTime.Now;
if (_config.clashUIItem.proxiesAutoDelayTestInterval > 0)
if (_config.clashUIItem.AutoDelayTestInterval > 0)
{ {
if ((dtNow - autoDelayTestTime).Minutes % _config.clashUIItem.AutoDelayTestInterval == 0) if ((dtNow - lastTime).Minutes % _config.clashUIItem.proxiesAutoDelayTestInterval == 0)
{ {
ProxiesDelayTest(); ProxiesDelayTest();
autoDelayTestTime = dtNow; lastTime = dtNow;
} }
Thread.Sleep(1000); Thread.Sleep(1000);
} }
}); });
} }
#endregion task #endregion task

View File

@ -243,6 +243,9 @@ namespace v2rayN.ViewModels
[Reactive] [Reactive]
public string CurrentLanguage { get; set; } public string CurrentLanguage { get; set; }
[Reactive]
public bool ShowCalshUI { get; set; }
#endregion UI #endregion UI
#region Init #region Init
@ -569,6 +572,7 @@ namespace v2rayN.ViewModels
AutoHideStartup(); AutoHideStartup();
_showInTaskbar = true; _showInTaskbar = true;
_config.clashUIItem.showInTaskbar = _showInTaskbar;
} }
private void Init() private void Init()
@ -1509,7 +1513,12 @@ namespace v2rayN.ViewModels
Application.Current?.Dispatcher.Invoke((Action)(() => Application.Current?.Dispatcher.Invoke((Action)(() =>
{ {
BlReloadEnabled = true; BlReloadEnabled = true;
ShowCalshUI = (_config.runningCoreType is ECoreType.clash or ECoreType.clash_meta or ECoreType.mihomo);
if (ShowCalshUI) {
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
}
})); }));
}); });
} }
@ -1680,6 +1689,7 @@ namespace v2rayN.ViewModels
//Utile.RegWriteValue(Global.MyRegPath, Utile.WindowHwndKey, Convert.ToString((long)windowHandle)); //Utile.RegWriteValue(Global.MyRegPath, Utile.WindowHwndKey, Convert.ToString((long)windowHandle));
} }
_showInTaskbar = bl; _showInTaskbar = bl;
_config.clashUIItem.showInTaskbar = _showInTaskbar;
} }
private void RestoreUI() private void RestoreUI()

View File

@ -13,19 +13,7 @@
d:DesignWidth="800" d:DesignWidth="800"
x:TypeArguments="vms:ClashConnectionsViewModel" x:TypeArguments="vms:ClashConnectionsViewModel"
mc:Ignorable="d"> mc:Ignorable="d">
<DockPanel Margin="8"> <DockPanel>
<StackPanel
Margin="8,0,8,8"
HorizontalAlignment="Left"
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBlock Style="{StaticResource ModuleTitle}" Text="{x:Static resx:ResUI.TbConnections}" />
<materialDesign:Chip
x:Name="chipCount"
Height="20"
IsEnabled="False"
Style="{StaticResource ListItemChip}" />
</StackPanel>
<ToolBarTray Margin="0,8,0,8" DockPanel.Dock="Top"> <ToolBarTray Margin="0,8,0,8" DockPanel.Dock="Top">
<ToolBar ClipToBounds="True" Style="{StaticResource MaterialDesignToolBar}"> <ToolBar ClipToBounds="True" Style="{StaticResource MaterialDesignToolBar}">
<Button Width="1" Visibility="Hidden"> <Button Width="1" Visibility="Hidden">

View File

@ -18,7 +18,6 @@ namespace v2rayN.Views
{ {
this.OneWayBind(ViewModel, vm => vm.ConnectionItems, v => v.lstConnections.ItemsSource).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.ConnectionItems, v => v.lstConnections.ItemsSource).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstConnections.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstConnections.SelectedItem).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ConnectionItems.Count, v => v.chipCount.Content).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables); this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables);

View File

@ -20,13 +20,7 @@
<converters:DelayColorConverter x:Key="DelayColorConverter" /> <converters:DelayColorConverter x:Key="DelayColorConverter" />
</UserControl.Resources> </UserControl.Resources>
<DockPanel Margin="8"> <DockPanel>
<TextBlock
Margin="8,0,8,8"
DockPanel.Dock="Top"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.TbProxies}" />
<ToolBarTray DockPanel.Dock="Top"> <ToolBarTray DockPanel.Dock="Top">
<ToolBar <ToolBar
HorizontalAlignment="Center" HorizontalAlignment="Center"

View File

@ -437,6 +437,14 @@
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}" materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True" materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" /> Style="{StaticResource DefTextBox}" />
<Button
x:Name="btnShowCalshUI"
Width="30"
Height="30"
Margin="20,0"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="EyeOutline" />
</Button>
</WrapPanel> </WrapPanel>
<materialDesign:ColorZone <materialDesign:ColorZone
@ -524,237 +532,240 @@
<RowDefinition Height="10" /> <RowDefinition Height="10" />
<RowDefinition Height="1*" /> <RowDefinition Height="1*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<DataGrid <DockPanel Grid.Row="0">
x:Name="lstProfiles" <ContentControl x:Name="tabClashUI" DockPanel.Dock="Right" />
Grid.Row="0" <DataGrid
materialDesign:DataGridAssist.CellPadding="2,2" x:Name="lstProfiles"
AutoGenerateColumns="False" materialDesign:DataGridAssist.CellPadding="2,2"
BorderThickness="1" AutoGenerateColumns="False"
CanUserAddRows="False" BorderThickness="1"
CanUserResizeRows="False" CanUserAddRows="False"
CanUserSortColumns="False" CanUserResizeRows="False"
EnableRowVirtualization="True" CanUserSortColumns="False"
Focusable="True" EnableRowVirtualization="True"
GridLinesVisibility="All" Focusable="True"
HeadersVisibility="All" GridLinesVisibility="All"
IsReadOnly="True" HeadersVisibility="All"
RowHeaderWidth="40" IsReadOnly="True"
Style="{StaticResource DefDataGrid}"> RowHeaderWidth="40"
<DataGrid.InputBindings> Style="{StaticResource DefDataGrid}">
<KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Ctrl+C" /> <DataGrid.InputBindings>
<KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Ctrl+V" /> <KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Ctrl+C" />
<KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Delete" /> <KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Ctrl+V" />
<KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Enter" /> <KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Delete" />
</DataGrid.InputBindings> <KeyBinding Command="ApplicationCommands.NotACommand" Gesture="Enter" />
<DataGrid.ContextMenu> </DataGrid.InputBindings>
<ContextMenu Style="{StaticResource DefContextMenu}"> <DataGrid.ContextMenu>
<MenuItem <ContextMenu Style="{StaticResource DefContextMenu}">
x:Name="menuEditServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuEditServer"
Header="{x:Static resx:ResUI.menuEditServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuEditServer}" />
x:Name="menuSetDefaultServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuSetDefaultServer"
Header="{x:Static resx:ResUI.menuSetDefaultServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuSetDefaultServer}" />
x:Name="menuRemoveServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuRemoveServer"
Header="{x:Static resx:ResUI.menuRemoveServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuRemoveServer}" />
x:Name="menuRemoveDuplicateServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuRemoveDuplicateServer"
Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuRemoveDuplicateServer}" />
x:Name="menuCopyServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuCopyServer"
Header="{x:Static resx:ResUI.menuCopyServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuCopyServer}" />
x:Name="menuShareServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuShareServer"
Header="{x:Static resx:ResUI.menuShareServer}" /> Height="{StaticResource MenuItemHeight}"
<Separator /> Header="{x:Static resx:ResUI.menuShareServer}" />
<MenuItem <Separator />
x:Name="menuMixedTestServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuMixedTestServer"
Header="{x:Static resx:ResUI.menuMixedTestServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuMixedTestServer}" />
x:Name="menuTcpingServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuTcpingServer"
Header="{x:Static resx:ResUI.menuTcpingServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuTcpingServer}" />
x:Name="menuRealPingServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuRealPingServer"
Header="{x:Static resx:ResUI.menuRealPingServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuRealPingServer}" />
x:Name="menuSpeedServer" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuSpeedServer"
Header="{x:Static resx:ResUI.menuSpeedServer}" /> Height="{StaticResource MenuItemHeight}"
<MenuItem Header="{x:Static resx:ResUI.menuSpeedServer}" />
x:Name="menuSortServerResult" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuSortServerResult"
Header="{x:Static resx:ResUI.menuSortServerResult}" /> Height="{StaticResource MenuItemHeight}"
<Separator /> Header="{x:Static resx:ResUI.menuSortServerResult}" />
<MenuItem <Separator />
x:Name="menuMoveToGroup" <MenuItem
Height="{StaticResource MenuItemHeight}" x:Name="menuMoveToGroup"
Header="{x:Static resx:ResUI.menuMoveToGroup}"> Height="{StaticResource MenuItemHeight}"
<MenuItem Height="Auto"> Header="{x:Static resx:ResUI.menuMoveToGroup}">
<MenuItem.Header> <MenuItem Height="Auto">
<DockPanel> <MenuItem.Header>
<ComboBox <DockPanel>
x:Name="cmbMoveToGroup" <ComboBox
Width="200" x:Name="cmbMoveToGroup"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuSubscription}" Width="200"
DisplayMemberPath="remarks" materialDesign:HintAssist.Hint="{x:Static resx:ResUI.menuSubscription}"
FontSize="{DynamicResource StdFontSize}" DisplayMemberPath="remarks"
Style="{StaticResource MaterialDesignFilledComboBox}" /> FontSize="{DynamicResource StdFontSize}"
</DockPanel> Style="{StaticResource MaterialDesignFilledComboBox}" />
</MenuItem.Header> </DockPanel>
</MenuItem.Header>
</MenuItem>
</MenuItem>
<MenuItem Header="{x:Static resx:ResUI.menuMoveTo}">
<MenuItem
x:Name="menuMoveTop"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveTop}" />
<MenuItem
x:Name="menuMoveUp"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveUp}" />
<MenuItem
x:Name="menuMoveDown"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveDown}" />
<MenuItem
x:Name="menuMoveBottom"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveBottom}" />
</MenuItem> </MenuItem>
</MenuItem>
<MenuItem Header="{x:Static resx:ResUI.menuMoveTo}">
<MenuItem <MenuItem
x:Name="menuMoveTop" x:Name="menuSelectAll"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveTop}" /> Click="menuSelectAll_Click"
Header="{x:Static resx:ResUI.menuSelectAll}" />
<Separator />
<MenuItem <MenuItem
x:Name="menuMoveUp" x:Name="menuExport2ClientConfig"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveUp}" /> Header="{x:Static resx:ResUI.menuExport2ClientConfig}" />
<MenuItem <MenuItem
x:Name="menuMoveDown" x:Name="menuExport2ShareUrl"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveDown}" /> Header="{x:Static resx:ResUI.menuExport2ShareUrl}" />
<MenuItem <MenuItem
x:Name="menuMoveBottom" x:Name="menuExport2SubContent"
Height="{StaticResource MenuItemHeight}" Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuMoveBottom}" /> Header="{x:Static resx:ResUI.menuExport2SubContent}" />
</MenuItem> </ContextMenu>
<MenuItem </DataGrid.ContextMenu>
x:Name="menuSelectAll" <DataGrid.Resources>
Height="{StaticResource MenuItemHeight}" <Style BasedOn="{StaticResource MaterialDesignDataGridRow}" TargetType="DataGridRow">
Click="menuSelectAll_Click" <EventSetter Event="MouseDoubleClick" Handler="LstProfiles_MouseDoubleClick" />
Header="{x:Static resx:ResUI.menuSelectAll}" /> </Style>
<Separator /> <Style BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}" TargetType="DataGridColumnHeader">
<MenuItem <EventSetter Event="Click" Handler="LstProfiles_ColumnHeader_Click" />
x:Name="menuExport2ClientConfig" </Style>
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuExport2ClientConfig}" />
<MenuItem
x:Name="menuExport2ShareUrl"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuExport2ShareUrl}" />
<MenuItem
x:Name="menuExport2SubContent"
Height="{StaticResource MenuItemHeight}"
Header="{x:Static resx:ResUI.menuExport2SubContent}" />
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Resources>
<Style BasedOn="{StaticResource MaterialDesignDataGridRow}" TargetType="DataGridRow">
<EventSetter Event="MouseDoubleClick" Handler="LstProfiles_MouseDoubleClick" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignDataGridColumnHeader}" TargetType="DataGridColumnHeader">
<EventSetter Event="Click" Handler="LstProfiles_ColumnHeader_Click" />
</Style>
<Style BasedOn="{StaticResource MaterialDesignDataGridCell}" TargetType="DataGridCell"> <Style BasedOn="{StaticResource MaterialDesignDataGridCell}" TargetType="DataGridCell">
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding isActive}" Value="True"> <DataTrigger Binding="{Binding isActive}" Value="True">
<Setter Property="Background" Value="{DynamicResource MaterialDesign.Brush.Primary.Light}" /> <Setter Property="Background" Value="{DynamicResource MaterialDesign.Brush.Primary.Light}" />
<Setter Property="Foreground" Value="Black" /> <Setter Property="Foreground" Value="Black" />
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesign.Brush.Primary.Light}" /> <Setter Property="BorderBrush" Value="{DynamicResource MaterialDesign.Brush.Primary.Light}" />
</DataTrigger> </DataTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</DataGrid.Resources> </DataGrid.Resources>
<DataGrid.Columns> <DataGrid.Columns>
<base:MyDGTextColumn <base:MyDGTextColumn
Width="80" Width="80"
Binding="{Binding configType}" Binding="{Binding configType}"
ExName="configType" ExName="configType"
Header="{x:Static resx:ResUI.LvServiceType}" /> Header="{x:Static resx:ResUI.LvServiceType}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="150" Width="150"
Binding="{Binding remarks}" Binding="{Binding remarks}"
ExName="remarks" ExName="remarks"
Header="{x:Static resx:ResUI.LvRemarks}" /> Header="{x:Static resx:ResUI.LvRemarks}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="120" Width="120"
Binding="{Binding address}" Binding="{Binding address}"
ExName="address" ExName="address"
Header="{x:Static resx:ResUI.LvAddress}" /> Header="{x:Static resx:ResUI.LvAddress}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="60" Width="60"
Binding="{Binding port}" Binding="{Binding port}"
ExName="port" ExName="port"
Header="{x:Static resx:ResUI.LvPort}" /> Header="{x:Static resx:ResUI.LvPort}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="100" Width="100"
Binding="{Binding network}" Binding="{Binding network}"
ExName="network" ExName="network"
Header="{x:Static resx:ResUI.LvTransportProtocol}" /> Header="{x:Static resx:ResUI.LvTransportProtocol}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="100" Width="100"
Binding="{Binding streamSecurity}" Binding="{Binding streamSecurity}"
ExName="streamSecurity" ExName="streamSecurity"
Header="{x:Static resx:ResUI.LvTLS}" /> Header="{x:Static resx:ResUI.LvTLS}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="100" Width="100"
Binding="{Binding subRemarks}" Binding="{Binding subRemarks}"
ExName="subRemarks" ExName="subRemarks"
Header="{x:Static resx:ResUI.LvSubscription}" /> Header="{x:Static resx:ResUI.LvSubscription}" />
<base:MyDGTextColumn <base:MyDGTextColumn
Width="100" Width="100"
Binding="{Binding delayVal}" Binding="{Binding delayVal}"
ExName="delayVal" ExName="delayVal"
Header="{x:Static resx:ResUI.LvTestDelay}"> Header="{x:Static resx:ResUI.LvTestDelay}">
<DataGridTextColumn.ElementStyle> <DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}"> <Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="Foreground" Value="{Binding delay, Converter={StaticResource DelayColorConverter}}" /> <Setter Property="Foreground" Value="{Binding delay, Converter={StaticResource DelayColorConverter}}" />
</Style> </Style>
</DataGridTextColumn.ElementStyle> </DataGridTextColumn.ElementStyle>
</base:MyDGTextColumn> </base:MyDGTextColumn>
<base:MyDGTextColumn <base:MyDGTextColumn
Width="100" Width="100"
Binding="{Binding speedVal}" Binding="{Binding speedVal}"
ExName="speedVal" ExName="speedVal"
Header="{x:Static resx:ResUI.LvTestSpeed}"> Header="{x:Static resx:ResUI.LvTestSpeed}">
<DataGridTextColumn.ElementStyle> <DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}"> <Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Right" /> <Setter Property="HorizontalAlignment" Value="Right" />
</Style> </Style>
</DataGridTextColumn.ElementStyle> </DataGridTextColumn.ElementStyle>
</base:MyDGTextColumn> </base:MyDGTextColumn>
<base:MyDGTextColumn
x:Name="colTodayUp"
Width="100"
Binding="{Binding todayUp}"
ExName="todayUp"
Header="{x:Static resx:ResUI.LvTodayUploadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTodayDown"
Width="100"
Binding="{Binding todayDown}"
ExName="todayDown"
Header="{x:Static resx:ResUI.LvTodayDownloadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTotalUp"
Width="100"
Binding="{Binding totalUp}"
ExName="totalUp"
Header="{x:Static resx:ResUI.LvTotalUploadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTotalDown"
Width="100"
Binding="{Binding totalDown}"
ExName="totalDown"
Header="{x:Static resx:ResUI.LvTotalDownloadDataAmount}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
<base:MyDGTextColumn
x:Name="colTodayUp"
Width="100"
Binding="{Binding todayUp}"
ExName="todayUp"
Header="{x:Static resx:ResUI.LvTodayUploadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTodayDown"
Width="100"
Binding="{Binding todayDown}"
ExName="todayDown"
Header="{x:Static resx:ResUI.LvTodayDownloadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTotalUp"
Width="100"
Binding="{Binding totalUp}"
ExName="totalUp"
Header="{x:Static resx:ResUI.LvTotalUploadDataAmount}" />
<base:MyDGTextColumn
x:Name="colTotalDown"
Width="100"
Binding="{Binding totalDown}"
ExName="totalDown"
Header="{x:Static resx:ResUI.LvTotalDownloadDataAmount}" />
</DataGrid.Columns>
</DataGrid>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" /> <GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" />
<local:MsgView Grid.Row="2" /> <local:MsgView Grid.Row="2" />
<materialDesign:Snackbar <materialDesign:Snackbar

View File

@ -46,6 +46,7 @@ namespace v2rayN.Views
this.PreviewKeyDown += MainWindow_PreviewKeyDown; this.PreviewKeyDown += MainWindow_PreviewKeyDown;
btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click; btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;
txtServerFilter.PreviewKeyDown += TxtServerFilter_PreviewKeyDown; txtServerFilter.PreviewKeyDown += TxtServerFilter_PreviewKeyDown;
btnShowCalshUI.Click += BtnShowCalshUI_Click;
lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown; lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;
lstProfiles.SelectionChanged += lstProfiles_SelectionChanged; lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;
lstProfiles.LoadingRow += LstProfiles_LoadingRow; lstProfiles.LoadingRow += LstProfiles_LoadingRow;
@ -205,6 +206,8 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowCalshUI, v => v.btnShowCalshUI.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowCalshUI, v => v.tabClashUI.Visibility).DisposeWith(disposables);
}); });
RestoreUI(); RestoreUI();
@ -455,6 +458,27 @@ namespace v2rayN.Views
} }
} }
private bool blShowClashUI = false;
private void BtnShowCalshUI_Click(object sender, RoutedEventArgs e)
{
if (blShowClashUI)
{
tabClashUI.Visibility = Visibility.Hidden;
tabClashUI.Width = 0;
}
else
{
tabClashUI.Visibility = Visibility.Visible;
if (tabClashUI.Content is null)
{
tabClashUI.Content = new ClashProxiesView();
}
tabClashUI.Width = this.ActualWidth * 5 / 6;
}
blShowClashUI = !blShowClashUI;
}
#endregion Event #endregion Event
#region UI #region UI