Files
2026-05-08 11:59:26 +08:00

244 lines
13 KiB
XML

<Window x:Class="ClashWidget.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:ClashWidget.Converters"
WindowStyle="None"
Background="#AAFFFFFF"
Topmost="True"
ResizeMode="CanResizeWithGrip"
Width="320" Height="210"
MinWidth="280" MinHeight="190"
MouseLeftButtonDown="OnMouseLeftButtonDown"
PreviewMouseLeftButtonDown="OnWindowPreviewClick">
<Window.Resources>
<converters:SpeedConverter x:Key="SpeedConverter" />
<converters:NodeMatchConverter x:Key="NodeMatch" />
</Window.Resources>
<Grid Margin="16,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Row 0: traffic lights (left) + gear (right) -->
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,0,0,6">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button Width="12" Height="12" Margin="0,0,8,0"
Click="OnCloseClick" Cursor="Hand" Focusable="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Ellipse x:Name="Dot" Fill="#FF5F57" Width="12" Height="12" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Dot" Property="Fill" Value="#EE4B44" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button Width="12" Height="12" Margin="0,0,8,0"
Click="OnMinimizeClick" Cursor="Hand" Focusable="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Ellipse x:Name="Dot" Fill="#FFBD2E" Width="12" Height="12" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Dot" Property="Fill" Value="#E5A820" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button Width="12" Height="12" Margin="0,0,8,0"
Click="OnMaximizeClick" Cursor="Hand" Focusable="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Ellipse x:Name="Dot" Fill="#28C840" Width="12" Height="12" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Dot" Property="Fill" Value="#1FB530" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<Button Width="22" Height="22" HorizontalAlignment="Right"
Click="OnSettingsClick" Cursor="Hand" Focusable="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Bg" CornerRadius="5" Background="Transparent">
<TextBlock Text="⚙" FontSize="14"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bg" Property="Background" Value="#F1F5F9" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
<!-- Row 1: Download speed -->
<TextBlock Grid.Row="1" Grid.Column="0"
Text="▼" FontSize="18" Foreground="#FF3B82F6"
VerticalAlignment="Center" Margin="0,-2,10,0" />
<TextBlock Grid.Row="1" Grid.Column="1"
Text="{Binding DownloadSpeed, Converter={StaticResource SpeedConverter}}"
FontSize="32" FontWeight="SemiBold" Foreground="#FF1E293B"
LineHeight="36" VerticalAlignment="Bottom" />
<!-- Row 2: Upload speed -->
<TextBlock Grid.Row="2" Grid.Column="0"
Text="▲" FontSize="12" Foreground="#FF10B981"
VerticalAlignment="Center" Margin="2,4,10,0" />
<TextBlock Grid.Row="2" Grid.Column="1"
Text="{Binding UploadSpeed, Converter={StaticResource SpeedConverter}}"
FontSize="14" Foreground="#FF64748B"
VerticalAlignment="Center" Margin="0,2,0,0" />
<!-- Row 3: Sparkline -->
<Border Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
Margin="0,6,0,2" ClipToBounds="True">
<Canvas x:Name="SparklineCanvas" Height="34" Background="Transparent" />
</Border>
<!-- Row 4: Divider -->
<Border Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"
Height="0.5" Background="#18000000" Margin="0,2,0,6" />
<!-- Row 5: Node + latency + dropdown trigger -->
<StackPanel Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<Ellipse x:Name="StatusDot" Width="8" Height="8"
VerticalAlignment="Center" Margin="2,0,8,0" />
<!-- Clickable node area -->
<Border x:Name="NodeArea" Cursor="Hand"
PreviewMouseLeftButtonDown="OnNodeAreaClick"
Background="Transparent"
Padding="0,2,6,2">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CurrentNode}" FontSize="13"
Foreground="#FF475569" TextTrimming="CharacterEllipsis"
MaxWidth="140" VerticalAlignment="Center"
FontFamily="Segoe UI Emoji, Segoe UI, Microsoft YaHei UI"
TextOptions.TextFormattingMode="Display" />
<TextBlock Text=" ▾" FontSize="10" Foreground="#FF94A3B8"
VerticalAlignment="Center" Margin="2,0,0,0" />
</StackPanel>
</Border>
<TextBlock Text="{Binding LatencyText}" FontSize="11"
Foreground="#FF94A3B8" Margin="6,0,4,0"
VerticalAlignment="Center" />
<Button x:Name="BtnRefreshLatency" Width="22" Height="22"
Click="OnRefreshLatencyClick" Cursor="Hand" Focusable="False">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="Border" CornerRadius="5"
Background="#F1F5F9" BorderBrush="#E2E8F0" BorderThickness="1">
<TextBlock Text="⚡" FontSize="11"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="#E2E8F0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<!-- Proxy dropdown popup -->
<Popup x:Name="NodePopup"
PlacementTarget="{Binding ElementName=NodeArea}"
Placement="Top" StaysOpen="True"
AllowsTransparency="True"
PopupAnimation="Slide"
Closed="OnPopupClosed"
Opened="OnPopupOpened">
<Border x:Name="PopupBorder"
Background="#FEFEFE" BorderBrush="#E2E8F0" BorderThickness="1"
CornerRadius="8" Padding="4" Margin="0,0,0,4"
MaxHeight="220" MinWidth="170"
MouseLeftButtonDown="OnPopupBorderClick">
<Border.Effect>
<DropShadowEffect BlurRadius="12" ShadowDepth="2"
Opacity="0.12" Color="Black" />
</Border.Effect>
<ListBox x:Name="NodeListBox"
ItemsSource="{Binding AvailableNodes}"
SelectionChanged="OnNodeItemClick"
BorderThickness="0" Background="Transparent"
FontSize="13" Foreground="#FF1E293B">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Ellipse Grid.Column="0" Width="6" Height="6"
Fill="#10B981" VerticalAlignment="Center"
Margin="0,0,6,0"
Visibility="Collapsed"
x:Name="SelectedDot" />
<TextBlock Grid.Column="1" Text="{Binding}"
VerticalAlignment="Center" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource NodeMatch}">
<Binding Path="." />
<Binding Path="DataContext.CurrentNode"
RelativeSource="{RelativeSource AncestorType=Window}" />
</MultiBinding>
</DataTrigger.Binding>
<Setter TargetName="SelectedDot"
Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="ItemBorder"
Background="Transparent"
CornerRadius="5"
Padding="8,6">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ItemBorder"
Property="Background" Value="#F1F5F9" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Border>
</Popup>
</Grid>
</Window>