1011 lines
57 KiB
XML
1011 lines
57 KiB
XML
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||
Title="SbLauncher" Width="1120" Height="790"
|
||
WindowStyle="None" AllowsTransparency="False" Background="{DynamicResource Bg}"
|
||
ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
|
||
TextOptions.TextFormattingMode="Display"
|
||
FontFamily="Segoe UI" UseLayoutRounding="True" SnapsToDevicePixels="True">
|
||
|
||
<!--
|
||
ТЕМЫ.
|
||
Ниже два словаря — Theme.Dark и Theme.Light. Приложение при старте копирует
|
||
выбранный в Application.Resources, а весь интерфейс ссылается на токены
|
||
через {DynamicResource}. Поэтому смена темы происходит вживую.
|
||
|
||
ВАЖНО: именно DynamicResource, а не StaticResource — последний берёт
|
||
значение один раз при разборе XAML и на подмену палитры не реагирует.
|
||
|
||
Чтобы добавить цвет: заведите ключ в ОБОИХ словарях и ссылайтесь на него.
|
||
-->
|
||
<Window.Resources>
|
||
<ResourceDictionary>
|
||
|
||
<ResourceDictionary x:Key="Theme.Dark">
|
||
<LinearGradientBrush x:Key="Bg" StartPoint="0,0" EndPoint="1,1">
|
||
<GradientStop Color="#101B36" Offset="0"/>
|
||
<GradientStop Color="#1C315C" Offset="0.54"/>
|
||
<GradientStop Color="#323B72" Offset="1"/>
|
||
</LinearGradientBrush>
|
||
<SolidColorBrush x:Key="Panel" Color="#B51D2D50"/>
|
||
<SolidColorBrush x:Key="Card" Color="#8D38527E"/>
|
||
<SolidColorBrush x:Key="CardHover" Color="#B24A6490"/>
|
||
<SolidColorBrush x:Key="CardSel" Color="#BE5274AA"/>
|
||
<SolidColorBrush x:Key="Stroke" Color="#77C4DAFF"/>
|
||
<SolidColorBrush x:Key="GlassEdge" Color="#A6E6F3FF"/>
|
||
<SolidColorBrush x:Key="Text" Color="#F5F9FF"/>
|
||
<SolidColorBrush x:Key="Muted" Color="#B9CBE6"/>
|
||
<SolidColorBrush x:Key="Accent" Color="#6B9FFF"/>
|
||
<SolidColorBrush x:Key="AccentHover" Color="#8AB6FF"/>
|
||
<SolidColorBrush x:Key="AccentDim" Color="#416DC5"/>
|
||
<SolidColorBrush x:Key="OnAccent" Color="#FFFFFF"/>
|
||
<SolidColorBrush x:Key="SoftBg" Color="#703F5B83"/>
|
||
<SolidColorBrush x:Key="SoftHover" Color="#A452709B"/>
|
||
<SolidColorBrush x:Key="SwitchTrack" Color="#66869CC1"/>
|
||
<SolidColorBrush x:Key="SwitchThumb" Color="#F0F7FF"/>
|
||
<SolidColorBrush x:Key="BadgeBg" Color="#82536F9A"/>
|
||
<SolidColorBrush x:Key="PingBg" Color="#7B21375E"/>
|
||
<SolidColorBrush x:Key="LogBg" Color="#A0182B4F"/>
|
||
<SolidColorBrush x:Key="LogText" Color="#D7E5F8"/>
|
||
<SolidColorBrush x:Key="ScrollTrack" Color="#3223375A"/>
|
||
<SolidColorBrush x:Key="ScrollThumb" Color="#9DAFC9EA"/>
|
||
<SolidColorBrush x:Key="ScrollThumbHover" Color="#D5DDECFF"/>
|
||
<SolidColorBrush x:Key="HeroRing" Color="#B2BBDDFF"/>
|
||
<SolidColorBrush x:Key="HeroRingDim" Color="#55A6C8FF"/>
|
||
<RadialGradientBrush x:Key="GlowA">
|
||
<GradientStop Color="#98759CFF" Offset="0"/>
|
||
<GradientStop Color="#00759CFF" Offset="1"/>
|
||
</RadialGradientBrush>
|
||
<RadialGradientBrush x:Key="GlowB">
|
||
<GradientStop Color="#6652C8DC" Offset="0"/>
|
||
<GradientStop Color="#0052C8DC" Offset="1"/>
|
||
</RadialGradientBrush>
|
||
<!-- смысловые цвета: их же читает код для статуса и пинга -->
|
||
<SolidColorBrush x:Key="Ok" Color="#34D399"/>
|
||
<SolidColorBrush x:Key="Warn" Color="#FBBF24"/>
|
||
<SolidColorBrush x:Key="Bad" Color="#F87171"/>
|
||
<SolidColorBrush x:Key="Idle" Color="#8A94A6"/>
|
||
<SolidColorBrush x:Key="Na" Color="#6B7280"/>
|
||
<sys:Double x:Key="ShadowOpacity">0.55</sys:Double>
|
||
</ResourceDictionary>
|
||
|
||
<ResourceDictionary x:Key="Theme.Light">
|
||
<LinearGradientBrush x:Key="Bg" StartPoint="0,0" EndPoint="1,1">
|
||
<GradientStop Color="#DDEEFF" Offset="0"/>
|
||
<GradientStop Color="#BCD6FB" Offset="0.54"/>
|
||
<GradientStop Color="#E2E7FA" Offset="1"/>
|
||
</LinearGradientBrush>
|
||
<SolidColorBrush x:Key="Panel" Color="#B9F8FBFF"/>
|
||
<SolidColorBrush x:Key="Card" Color="#9CFFFFFF"/>
|
||
<SolidColorBrush x:Key="CardHover" Color="#D8FFFFFF"/>
|
||
<SolidColorBrush x:Key="CardSel" Color="#D7DFEDFF"/>
|
||
<SolidColorBrush x:Key="Stroke" Color="#A7FFFFFF"/>
|
||
<SolidColorBrush x:Key="GlassEdge" Color="#EFFFFFFF"/>
|
||
<SolidColorBrush x:Key="Text" Color="#173052"/>
|
||
<SolidColorBrush x:Key="Muted" Color="#577190"/>
|
||
<SolidColorBrush x:Key="Accent" Color="#347CF2"/>
|
||
<SolidColorBrush x:Key="AccentHover" Color="#5291F8"/>
|
||
<SolidColorBrush x:Key="AccentDim" Color="#2466CB"/>
|
||
<SolidColorBrush x:Key="OnAccent" Color="#FFFFFF"/>
|
||
<SolidColorBrush x:Key="SoftBg" Color="#AFFFFFFF"/>
|
||
<SolidColorBrush x:Key="SoftHover" Color="#E5FFFFFF"/>
|
||
<SolidColorBrush x:Key="SwitchTrack" Color="#8CA7BEDD"/>
|
||
<SolidColorBrush x:Key="SwitchThumb" Color="#FFFFFF"/>
|
||
<SolidColorBrush x:Key="BadgeBg" Color="#BDDFEAFA"/>
|
||
<SolidColorBrush x:Key="PingBg" Color="#9AFFFFFF"/>
|
||
<SolidColorBrush x:Key="LogBg" Color="#B6F5F9FF"/>
|
||
<SolidColorBrush x:Key="LogText" Color="#365476"/>
|
||
<SolidColorBrush x:Key="ScrollTrack" Color="#34FFFFFF"/>
|
||
<SolidColorBrush x:Key="ScrollThumb" Color="#8D8FA6C5"/>
|
||
<SolidColorBrush x:Key="ScrollThumbHover" Color="#B37490B5"/>
|
||
<SolidColorBrush x:Key="HeroRing" Color="#C84483EF"/>
|
||
<SolidColorBrush x:Key="HeroRingDim" Color="#665896E7"/>
|
||
<RadialGradientBrush x:Key="GlowA">
|
||
<GradientStop Color="#AA8EC2FF" Offset="0"/>
|
||
<GradientStop Color="#008EC2FF" Offset="1"/>
|
||
</RadialGradientBrush>
|
||
<RadialGradientBrush x:Key="GlowB">
|
||
<GradientStop Color="#99B2A5FF" Offset="0"/>
|
||
<GradientStop Color="#00B2A5FF" Offset="1"/>
|
||
</RadialGradientBrush>
|
||
<SolidColorBrush x:Key="Ok" Color="#0E9F6E"/>
|
||
<SolidColorBrush x:Key="Warn" Color="#B4790B"/>
|
||
<SolidColorBrush x:Key="Bad" Color="#DC2626"/>
|
||
<SolidColorBrush x:Key="Idle" Color="#7A8699"/>
|
||
<SolidColorBrush x:Key="Na" Color="#9AA3B2"/>
|
||
<sys:Double x:Key="ShadowOpacity">0.16</sys:Double>
|
||
</ResourceDictionary>
|
||
|
||
<!-- Одинаковая прокрутка во всех ScrollViewer/ListBox/TextBox. -->
|
||
<Style x:Key="ScrollPageButton" TargetType="RepeatButton">
|
||
<Setter Property="Focusable" Value="False"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="RepeatButton">
|
||
<Border Background="Transparent"/>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<Style x:Key="ScrollGrip" TargetType="Thumb">
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Thumb">
|
||
<Border x:Name="Grip" Margin="2,1" CornerRadius="4"
|
||
Background="{DynamicResource ScrollThumb}"/>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="Grip" Property="Background" Value="{DynamicResource ScrollThumbHover}"/>
|
||
</Trigger>
|
||
<Trigger Property="IsDragging" Value="True">
|
||
<Setter TargetName="Grip" Property="Background" Value="{DynamicResource Accent}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<ControlTemplate x:Key="VerticalScroll" TargetType="ScrollBar">
|
||
<Border Background="{DynamicResource ScrollTrack}" Width="10">
|
||
<Track x:Name="PART_Track" IsDirectionReversed="True"
|
||
Orientation="Vertical" ViewportSize="{TemplateBinding ViewportSize}"
|
||
Minimum="{TemplateBinding Minimum}" Maximum="{TemplateBinding Maximum}"
|
||
Value="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
|
||
<Track.DecreaseRepeatButton>
|
||
<RepeatButton Style="{StaticResource ScrollPageButton}" Command="ScrollBar.PageUpCommand"/>
|
||
</Track.DecreaseRepeatButton>
|
||
<Track.Thumb><Thumb Style="{StaticResource ScrollGrip}"/></Track.Thumb>
|
||
<Track.IncreaseRepeatButton>
|
||
<RepeatButton Style="{StaticResource ScrollPageButton}" Command="ScrollBar.PageDownCommand"/>
|
||
</Track.IncreaseRepeatButton>
|
||
</Track>
|
||
</Border>
|
||
</ControlTemplate>
|
||
|
||
<ControlTemplate x:Key="HorizontalScroll" TargetType="ScrollBar">
|
||
<Border Background="{DynamicResource ScrollTrack}" Height="10">
|
||
<Track x:Name="PART_Track" Orientation="Horizontal"
|
||
ViewportSize="{TemplateBinding ViewportSize}"
|
||
Minimum="{TemplateBinding Minimum}" Maximum="{TemplateBinding Maximum}"
|
||
Value="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
|
||
<Track.DecreaseRepeatButton>
|
||
<RepeatButton Style="{StaticResource ScrollPageButton}" Command="ScrollBar.PageLeftCommand"/>
|
||
</Track.DecreaseRepeatButton>
|
||
<Track.Thumb><Thumb Style="{StaticResource ScrollGrip}"/></Track.Thumb>
|
||
<Track.IncreaseRepeatButton>
|
||
<RepeatButton Style="{StaticResource ScrollPageButton}" Command="ScrollBar.PageRightCommand"/>
|
||
</Track.IncreaseRepeatButton>
|
||
</Track>
|
||
</Border>
|
||
</ControlTemplate>
|
||
|
||
<Style TargetType="ScrollBar">
|
||
<Setter Property="Width" Value="10"/>
|
||
<Setter Property="Template" Value="{StaticResource VerticalScroll}"/>
|
||
<Style.Triggers>
|
||
<Trigger Property="Orientation" Value="Horizontal">
|
||
<Setter Property="Width" Value="Auto"/>
|
||
<Setter Property="Height" Value="10"/>
|
||
<Setter Property="Template" Value="{StaticResource HorizontalScroll}"/>
|
||
</Trigger>
|
||
</Style.Triggers>
|
||
</Style>
|
||
|
||
<!-- ─── кнопка-таблетка (основное действие) ────────────────────────── -->
|
||
<Style x:Key="Pill" TargetType="Button">
|
||
<Setter Property="Foreground" Value="{DynamicResource OnAccent}"/>
|
||
<Setter Property="FontSize" Value="14"/>
|
||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border x:Name="B" CornerRadius="24" Background="{DynamicResource Accent}"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1"
|
||
Padding="30,13">
|
||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource AccentHover}"/>
|
||
</Trigger>
|
||
<Trigger Property="IsPressed" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource AccentDim}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── вторичная кнопка ───────────────────────────────────────────── -->
|
||
<Style x:Key="Soft" TargetType="Button">
|
||
<Setter Property="Foreground" Value="{DynamicResource Muted}"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border x:Name="B" CornerRadius="12" Background="{DynamicResource SoftBg}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1" Padding="14,8">
|
||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource SoftHover}"/>
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── кнопка опасного действия (удаление) ────────────────────────── -->
|
||
<Style x:Key="SoftDanger" TargetType="Button">
|
||
<Setter Property="Foreground" Value="{DynamicResource Muted}"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border x:Name="B" CornerRadius="12" Background="{DynamicResource SoftBg}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1" Padding="14,8">
|
||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource SoftHover}"/>
|
||
<Setter TargetName="B" Property="BorderBrush" Value="{DynamicResource Bad}"/>
|
||
<Setter Property="Foreground" Value="{DynamicResource Bad}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── контекстное меню ───────────────────────────────────────────── -->
|
||
<Style TargetType="ContextMenu">
|
||
<Setter Property="Background" Value="{DynamicResource Panel}"/>
|
||
<Setter Property="BorderBrush" Value="{DynamicResource Stroke}"/>
|
||
<Setter Property="BorderThickness" Value="1"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="ContextMenu">
|
||
<Border CornerRadius="8" Background="{DynamicResource Panel}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1" Padding="4">
|
||
<Border.Effect>
|
||
<DropShadowEffect BlurRadius="14" ShadowDepth="3" Direction="270"
|
||
Opacity="{DynamicResource ShadowOpacity}" Color="Black"/>
|
||
</Border.Effect>
|
||
<StackPanel IsItemsHost="True"/>
|
||
</Border>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<Style TargetType="MenuItem">
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="MenuItem">
|
||
<Border x:Name="B" CornerRadius="6" Background="Transparent" Padding="12,7">
|
||
<ContentPresenter ContentSource="Header" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsHighlighted" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource SoftHover}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── кнопки заголовка ───────────────────────────────────────────── -->
|
||
<Style x:Key="Chrome" TargetType="Button">
|
||
<Setter Property="Foreground" Value="{DynamicResource Muted}"/>
|
||
<Setter Property="FontSize" Value="13"/>
|
||
<Setter Property="Width" Value="40"/>
|
||
<Setter Property="Height" Value="30"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border x:Name="B" CornerRadius="7" Background="Transparent">
|
||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource SoftHover}"/>
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── переключатель ──────────────────────────────────────────────── -->
|
||
<Style x:Key="Switch" TargetType="ToggleButton">
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="ToggleButton">
|
||
<Grid Width="52" Height="30">
|
||
<Border CornerRadius="15" Background="{DynamicResource SwitchTrack}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1"/>
|
||
<Border x:Name="ActiveTrack" CornerRadius="15" Background="{DynamicResource Accent}"
|
||
BorderBrush="{DynamicResource Accent}" BorderThickness="1" Opacity="0"/>
|
||
<Ellipse x:Name="Thumb" Width="22" Height="22" Fill="{DynamicResource SwitchThumb}"
|
||
HorizontalAlignment="Left" VerticalAlignment="Center" Margin="4,0,0,0">
|
||
<Ellipse.RenderTransform><TranslateTransform/></Ellipse.RenderTransform>
|
||
<Ellipse.Effect>
|
||
<DropShadowEffect Color="#50000000" BlurRadius="4" ShadowDepth="1" Opacity="0.35"/>
|
||
</Ellipse.Effect>
|
||
</Ellipse>
|
||
</Grid>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsPressed" Value="True">
|
||
<Setter TargetName="Thumb" Property="Width" Value="26"/>
|
||
<Trigger.EnterActions>
|
||
<BeginStoryboard>
|
||
<Storyboard FillBehavior="Stop">
|
||
<DoubleAnimation Storyboard.TargetName="Thumb" Storyboard.TargetProperty="Width"
|
||
From="22" To="26" Duration="0:0:0.12"/>
|
||
</Storyboard>
|
||
</BeginStoryboard>
|
||
</Trigger.EnterActions>
|
||
<Trigger.ExitActions>
|
||
<BeginStoryboard>
|
||
<Storyboard FillBehavior="Stop">
|
||
<DoubleAnimation Storyboard.TargetName="Thumb" Storyboard.TargetProperty="Width"
|
||
From="26" To="22" Duration="0:0:0.18"/>
|
||
</Storyboard>
|
||
</BeginStoryboard>
|
||
</Trigger.ExitActions>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── карточка сервера ───────────────────────────────────────────── -->
|
||
<DataTemplate x:Key="ServerCard">
|
||
<Border x:Name="Card" CornerRadius="16" Background="{DynamicResource Card}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1" Margin="0,0,0,10">
|
||
<Border.ContextMenu>
|
||
<ContextMenu>
|
||
<MenuItem Header="Удалить сервер" Command="{Binding DeleteCommand}"/>
|
||
</ContextMenu>
|
||
</Border.ContextMenu>
|
||
<Button Command="{Binding SelectCommand}" CommandParameter="{Binding}"
|
||
Cursor="Hand" HorizontalContentAlignment="Stretch">
|
||
<Button.Template>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border Background="Transparent" Padding="14,14">
|
||
<ContentPresenter/>
|
||
</Border>
|
||
</ControlTemplate>
|
||
</Button.Template>
|
||
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="42"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<!-- флаг страны; для незнакомого кода — текстовый бейдж -->
|
||
<Grid Grid.Column="0" Width="34" HorizontalAlignment="Left">
|
||
<Image Source="{Binding Flag}" Width="34" Height="23" Stretch="Fill"
|
||
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||
<Border x:Name="TextBadge" Width="34" Height="34" CornerRadius="9"
|
||
Background="{DynamicResource BadgeBg}" Visibility="Collapsed">
|
||
<TextBlock Text="{Binding Badge}" Foreground="{DynamicResource Text}"
|
||
FontSize="12" FontWeight="Bold"
|
||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
</Grid>
|
||
|
||
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0">
|
||
<TextBlock Text="{Binding Title}" Foreground="{DynamicResource Text}"
|
||
FontSize="13.5" FontWeight="SemiBold"/>
|
||
<TextBlock Text="{Binding Subtitle}" Foreground="{DynamicResource Muted}"
|
||
FontSize="11" Margin="0,2,0,0" TextTrimming="CharacterEllipsis"/>
|
||
</StackPanel>
|
||
|
||
<Border Grid.Column="2" CornerRadius="6" Padding="7,3"
|
||
Background="{DynamicResource PingBg}" VerticalAlignment="Center">
|
||
<TextBlock Text="{Binding PingText}" Foreground="{Binding PingBrush}"
|
||
FontSize="11" FontWeight="SemiBold"/>
|
||
</Border>
|
||
</Grid>
|
||
</Button>
|
||
</Border>
|
||
|
||
<DataTemplate.Triggers>
|
||
<DataTrigger Binding="{Binding Flag}" Value="{x:Null}">
|
||
<Setter TargetName="TextBadge" Property="Visibility" Value="Visible"/>
|
||
</DataTrigger>
|
||
<Trigger SourceName="Card" Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="Card" Property="Background" Value="{DynamicResource CardHover}"/>
|
||
</Trigger>
|
||
</DataTemplate.Triggers>
|
||
</DataTemplate>
|
||
|
||
<!-- ─── поле ввода ─────────────────────────────────────────────────
|
||
Consolas: значения здесь — base64-ключ и IP-адрес, в
|
||
моноширинном их глазом проверять заметно легче. -->
|
||
<Style x:Key="Field" TargetType="TextBox">
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
<Setter Property="CaretBrush" Value="{DynamicResource Text}"/>
|
||
<Setter Property="SelectionBrush" Value="{DynamicResource Accent}"/>
|
||
<Setter Property="FontFamily" Value="Consolas"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="TextBox">
|
||
<Border x:Name="B" CornerRadius="8" Background="{DynamicResource SoftBg}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1"
|
||
Padding="10,7">
|
||
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Stretch"/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource SoftHover}"/>
|
||
</Trigger>
|
||
<Trigger Property="IsFocused" Value="True">
|
||
<Setter TargetName="B" Property="BorderBrush" Value="{DynamicResource Accent}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── элемент выпадающего списка ─────────────────────────────── -->
|
||
<Style x:Key="ComboItem" TargetType="ComboBoxItem">
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
<Setter Property="FontFamily" Value="Consolas"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="ComboBoxItem">
|
||
<Border x:Name="B" Background="Transparent" Padding="10,7" CornerRadius="6">
|
||
<ContentPresenter/>
|
||
</Border>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource CardHover}"/>
|
||
</Trigger>
|
||
<Trigger Property="IsHighlighted" Value="True">
|
||
<Setter TargetName="B" Property="Background" Value="{DynamicResource CardSel}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── редактируемый выпадающий список ────────────────────────────
|
||
Шаблон целиком, а не только цвета: штатный ComboBox рисуется
|
||
темой Windows и в тёмной палитре выглядит белым пятном.
|
||
Обязательные части — PART_EditableTextBox и PART_Popup.
|
||
Редактируемый он намеренно: если адаптера нет в списке
|
||
(отключён, виртуальный), имя можно вписать руками. -->
|
||
<Style x:Key="FieldCombo" TargetType="ComboBox">
|
||
<Setter Property="IsEditable" Value="True"/>
|
||
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboItem}"/>
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
<Setter Property="FontFamily" Value="Consolas"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="ComboBox">
|
||
<Grid>
|
||
<Border x:Name="B" CornerRadius="8" Background="{DynamicResource SoftBg}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1"/>
|
||
<Grid Margin="1">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="30"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<TextBox x:Name="PART_EditableTextBox" Grid.Column="0"
|
||
Background="Transparent" BorderThickness="0"
|
||
Foreground="{DynamicResource Text}"
|
||
CaretBrush="{DynamicResource Text}"
|
||
SelectionBrush="{DynamicResource Accent}"
|
||
Padding="9,6" VerticalContentAlignment="Center"/>
|
||
|
||
<ToggleButton Grid.Column="1" Focusable="False" ClickMode="Press" Cursor="Hand"
|
||
IsChecked="{Binding IsDropDownOpen, Mode=TwoWay,
|
||
RelativeSource={RelativeSource TemplatedParent}}">
|
||
<ToggleButton.Template>
|
||
<ControlTemplate TargetType="ToggleButton">
|
||
<Border Background="Transparent">
|
||
<Path Data="M 0,0 L 8,0 L 4,5 Z" Fill="{DynamicResource Muted}"
|
||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
</ControlTemplate>
|
||
</ToggleButton.Template>
|
||
</ToggleButton>
|
||
</Grid>
|
||
|
||
<Popup x:Name="PART_Popup" Placement="Bottom" AllowsTransparency="True"
|
||
IsOpen="{TemplateBinding IsDropDownOpen}" Focusable="False"
|
||
PopupAnimation="Fade">
|
||
<Border Background="{DynamicResource Panel}" CornerRadius="8"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1"
|
||
Margin="0,4,0,0" Padding="4"
|
||
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource TemplatedParent}}">
|
||
<ScrollViewer MaxHeight="220" VerticalScrollBarVisibility="Auto">
|
||
<ItemsPresenter/>
|
||
</ScrollViewer>
|
||
</Border>
|
||
</Popup>
|
||
</Grid>
|
||
<ControlTemplate.Triggers>
|
||
<Trigger Property="IsKeyboardFocusWithin" Value="True">
|
||
<Setter TargetName="B" Property="BorderBrush" Value="{DynamicResource Accent}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── переключатель вкладок «лог / настройки» ─────────────────
|
||
Цвет активной вкладки приходит из ViewModel ключом палитры,
|
||
поэтому переживает смену темы. -->
|
||
<Style x:Key="Tab" TargetType="Button">
|
||
<Setter Property="FontSize" Value="10.5"/>
|
||
<Setter Property="FontWeight" Value="Bold"/>
|
||
<Setter Property="Cursor" Value="Hand"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="Button">
|
||
<Border Background="Transparent" Padding="0,2,20,8">
|
||
<ContentPresenter/>
|
||
</Border>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
|
||
<!-- ─── подпись поля ───────────────────────────────────────────── -->
|
||
<Style x:Key="FieldLabel" TargetType="TextBlock">
|
||
<Setter Property="Foreground" Value="{DynamicResource Text}"/>
|
||
<Setter Property="FontSize" Value="12"/>
|
||
<!-- Top, а не Center: под полем идёт подсказка, и по центру
|
||
всей колонки подпись уезжала бы ниже самого поля. -->
|
||
<Setter Property="VerticalAlignment" Value="Top"/>
|
||
<Setter Property="Margin" Value="0,9,12,0"/>
|
||
</Style>
|
||
|
||
<!-- ─── заголовок группы ───────────────────────────────────────── -->
|
||
<Style x:Key="GroupLabel" TargetType="TextBlock">
|
||
<Setter Property="Foreground" Value="{DynamicResource Muted}"/>
|
||
<Setter Property="FontSize" Value="10.5"/>
|
||
<Setter Property="FontWeight" Value="Bold"/>
|
||
<Setter Property="Margin" Value="0,0,0,10"/>
|
||
</Style>
|
||
|
||
<!-- ─── подсказка под полем ────────────────────────────────────── -->
|
||
<Style x:Key="Hint" TargetType="TextBlock">
|
||
<Setter Property="FontSize" Value="10.5"/>
|
||
<Setter Property="Margin" Value="0,4,0,0"/>
|
||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||
</Style>
|
||
|
||
</ResourceDictionary>
|
||
</Window.Resources>
|
||
|
||
<!-- ══════════════════════════════════════════════════════════════════ -->
|
||
<Border Background="{DynamicResource Bg}"
|
||
BorderBrush="{DynamicResource Stroke}" BorderThickness="1">
|
||
|
||
<Grid ClipToBounds="True">
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="62"/>
|
||
<RowDefinition Height="*"/>
|
||
</Grid.RowDefinitions>
|
||
|
||
<!-- Цветовые пятна статичны: плавный «стеклянный» вид без дорогого blur. -->
|
||
<Canvas Grid.RowSpan="2" IsHitTestVisible="False" ClipToBounds="True">
|
||
<Ellipse Width="720" Height="720" Fill="{DynamicResource GlowA}"
|
||
Canvas.Left="-240" Canvas.Top="-320"/>
|
||
<Ellipse Width="740" Height="740" Fill="{DynamicResource GlowB}"
|
||
Canvas.Left="570" Canvas.Top="300"/>
|
||
</Canvas>
|
||
|
||
<!-- ─── заголовок ─────────────────────────────────────────────── -->
|
||
<Grid x:Name="TitleBar" Grid.Row="0" Background="Transparent">
|
||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="23,0,0,0">
|
||
<Image x:Name="LogoImg" Width="31" Height="31" VerticalAlignment="Center"
|
||
RenderOptions.BitmapScalingMode="HighQuality"/>
|
||
<TextBlock Text="SbLauncher" Foreground="{DynamicResource Text}"
|
||
FontSize="15" FontWeight="SemiBold" Margin="11,0,0,0"
|
||
VerticalAlignment="Center"/>
|
||
<Border Background="{DynamicResource SoftBg}" BorderBrush="{DynamicResource Stroke}"
|
||
BorderThickness="1" CornerRadius="10" Margin="12,0,0,0" Padding="8,3">
|
||
<TextBlock Text="{Binding VersionText}" Foreground="{DynamicResource Muted}"
|
||
FontSize="10" VerticalAlignment="Center"/>
|
||
</Border>
|
||
</StackPanel>
|
||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"
|
||
VerticalAlignment="Center" Margin="0,0,12,0">
|
||
<Button x:Name="BtnTheme" Style="{StaticResource Chrome}"
|
||
FontFamily="Segoe MDL2 Assets" FontSize="14"
|
||
Content="{Binding ThemeGlyph}" ToolTip="Тема: светлая / тёмная"/>
|
||
<Button x:Name="BtnMin" Style="{StaticResource Chrome}" Content="–"/>
|
||
<Button x:Name="BtnClose" Style="{StaticResource Chrome}" Content="✕"/>
|
||
</StackPanel>
|
||
</Grid>
|
||
|
||
<!-- ─── тело ──────────────────────────────────────────────────── -->
|
||
<Grid Grid.Row="1">
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="335"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<!-- левая колонка: серверы -->
|
||
<Border Grid.Column="0" Background="{DynamicResource Panel}" CornerRadius="22"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1"
|
||
Margin="16,6,0,16">
|
||
<Grid>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="*"/>
|
||
</Grid.RowDefinitions>
|
||
|
||
<Grid Grid.Row="0" Margin="20,20,16,16">
|
||
<TextBlock Text="СЕРВЕРЫ" Foreground="{DynamicResource Muted}"
|
||
FontSize="11" FontWeight="Bold" VerticalAlignment="Center"/>
|
||
<Button Style="{StaticResource Soft}" Content="пинг"
|
||
Command="{Binding PingAllCommand}" HorizontalAlignment="Right"
|
||
Padding="10,4"/>
|
||
</Grid>
|
||
|
||
<Grid x:Name="ServerListHost" Grid.Row="1" ClipToBounds="True">
|
||
<ListBox x:Name="ServerList" ItemsSource="{Binding Servers}"
|
||
SelectedItem="{Binding Selected, Mode=TwoWay}"
|
||
ItemTemplate="{StaticResource ServerCard}"
|
||
Background="Transparent" BorderThickness="0"
|
||
Margin="12,0,12,14" Padding="0,0,4,0"
|
||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||
ScrollViewer.CanContentScroll="True"
|
||
VirtualizingStackPanel.IsVirtualizing="True"
|
||
VirtualizingStackPanel.VirtualizationMode="Recycling">
|
||
<ListBox.ItemContainerStyle>
|
||
<Style TargetType="ListBoxItem">
|
||
<Setter Property="Padding" Value="0"/>
|
||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||
<Setter Property="Template">
|
||
<Setter.Value>
|
||
<ControlTemplate TargetType="ListBoxItem">
|
||
<ContentPresenter ContentSource="Content"
|
||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
|
||
</ControlTemplate>
|
||
</Setter.Value>
|
||
</Setter>
|
||
</Style>
|
||
</ListBox.ItemContainerStyle>
|
||
</ListBox>
|
||
<Canvas IsHitTestVisible="False" ClipToBounds="True">
|
||
<Border x:Name="ServerSelectionWindow" Visibility="Collapsed"
|
||
CornerRadius="16" BorderBrush="{DynamicResource Accent}"
|
||
BorderThickness="1.5">
|
||
<Border CornerRadius="15" Background="{DynamicResource Accent}" Opacity="0.16"/>
|
||
</Border>
|
||
</Canvas>
|
||
</Grid>
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- правая колонка -->
|
||
<Grid Grid.Column="1" Margin="18,6,18,16">
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/> <!-- статус -->
|
||
<RowDefinition Height="Auto"/> <!-- режим -->
|
||
<RowDefinition Height="Auto"/> <!-- вкладки -->
|
||
<RowDefinition Height="*"/> <!-- лог/настройки-->
|
||
</Grid.RowDefinitions>
|
||
|
||
<!-- статус -->
|
||
<Border Grid.Row="0" CornerRadius="24" Background="{DynamicResource Panel}"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1" Padding="23,22">
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="78"/>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
|
||
<Grid Grid.Column="0" Width="66" Height="66" VerticalAlignment="Center">
|
||
<Ellipse Fill="{DynamicResource SoftBg}" Stroke="{DynamicResource GlassEdge}"
|
||
StrokeThickness="1"/>
|
||
<Ellipse Width="62" Height="62" Stroke="{DynamicResource HeroRingDim}"
|
||
StrokeThickness="2" Margin="2"/>
|
||
<!-- Мягкое заполнение после подключения вместо резкой вспышки. -->
|
||
<Ellipse x:Name="ConnectionGlow" Width="58" Height="58" Fill="{DynamicResource Ok}"
|
||
RenderTransformOrigin="0.5,0.5" IsHitTestVisible="False">
|
||
<Ellipse.RenderTransform><ScaleTransform/></Ellipse.RenderTransform>
|
||
<Ellipse.Style>
|
||
<Style TargetType="Ellipse">
|
||
<Setter Property="Opacity" Value="0"/>
|
||
<Style.Triggers>
|
||
<DataTrigger Binding="{Binding ConnectionPhase}" Value="connected">
|
||
<Setter Property="Opacity" Value="0.18"/>
|
||
<DataTrigger.EnterActions>
|
||
<BeginStoryboard>
|
||
<Storyboard FillBehavior="Stop">
|
||
<DoubleAnimation Storyboard.TargetProperty="Opacity"
|
||
From="0" To="0.18" Duration="0:0:0.55"/>
|
||
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
|
||
From="0.82" To="1" Duration="0:0:0.55">
|
||
<DoubleAnimation.EasingFunction>
|
||
<BackEase Amplitude="0.28" EasingMode="EaseOut"/>
|
||
</DoubleAnimation.EasingFunction>
|
||
</DoubleAnimation>
|
||
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
|
||
From="0.82" To="1" Duration="0:0:0.55">
|
||
<DoubleAnimation.EasingFunction>
|
||
<BackEase Amplitude="0.28" EasingMode="EaseOut"/>
|
||
</DoubleAnimation.EasingFunction>
|
||
</DoubleAnimation>
|
||
</Storyboard>
|
||
</BeginStoryboard>
|
||
</DataTrigger.EnterActions>
|
||
</DataTrigger>
|
||
</Style.Triggers>
|
||
</Style>
|
||
</Ellipse.Style>
|
||
</Ellipse>
|
||
<!-- Пока соединение меняется, ободок спокойно «дышит». -->
|
||
<Ellipse x:Name="ConnectionBreathRing" Width="58" Height="58" Stroke="{DynamicResource Accent}"
|
||
StrokeThickness="2.5" IsHitTestVisible="False"
|
||
RenderTransformOrigin="0.5,0.5">
|
||
<Ellipse.RenderTransform><ScaleTransform/></Ellipse.RenderTransform>
|
||
<Ellipse.Style>
|
||
<Style TargetType="Ellipse">
|
||
<Setter Property="Opacity" Value="0"/>
|
||
<Style.Triggers>
|
||
<DataTrigger Binding="{Binding ConnectionInProgress}" Value="True">
|
||
<DataTrigger.EnterActions>
|
||
<BeginStoryboard x:Name="ConnectionBreath">
|
||
<Storyboard RepeatBehavior="Forever" AutoReverse="True">
|
||
<DoubleAnimation Storyboard.TargetProperty="Opacity"
|
||
From="0.25" To="0.72" Duration="0:0:0.9">
|
||
<DoubleAnimation.EasingFunction><SineEase EasingMode="EaseInOut"/></DoubleAnimation.EasingFunction>
|
||
</DoubleAnimation>
|
||
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
|
||
From="0.9" To="1.08" Duration="0:0:0.9">
|
||
<DoubleAnimation.EasingFunction><SineEase EasingMode="EaseInOut"/></DoubleAnimation.EasingFunction>
|
||
</DoubleAnimation>
|
||
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
|
||
From="0.9" To="1.08" Duration="0:0:0.9">
|
||
<DoubleAnimation.EasingFunction><SineEase EasingMode="EaseInOut"/></DoubleAnimation.EasingFunction>
|
||
</DoubleAnimation>
|
||
</Storyboard>
|
||
</BeginStoryboard>
|
||
</DataTrigger.EnterActions>
|
||
<DataTrigger.ExitActions><StopStoryboard BeginStoryboardName="ConnectionBreath"/></DataTrigger.ExitActions>
|
||
</DataTrigger>
|
||
</Style.Triggers>
|
||
</Style>
|
||
</Ellipse.Style>
|
||
</Ellipse>
|
||
<Button x:Name="BtnPower" Width="66" Height="66"
|
||
Command="{Binding ConnectCommand}" Cursor="Hand"
|
||
ToolTip="{Binding ConnectText}"
|
||
AutomationProperties.Name="{Binding ConnectText}">
|
||
<Button.Template>
|
||
<ControlTemplate TargetType="Button">
|
||
<Grid Background="Transparent">
|
||
<Viewbox Width="32" Height="32">
|
||
<Canvas Width="32" Height="32">
|
||
<Path x:Name="PowerRing"
|
||
Data="M 9,8 C 5,10 4,14 4,17 C 4,24 9,29 16,29 C 23,29 28,24 28,17 C 28,14 27,10 23,8"
|
||
Stroke="{DynamicResource Text}" StrokeThickness="3"
|
||
StrokeStartLineCap="Round" StrokeEndLineCap="Round"/>
|
||
<Path x:Name="PowerStem" Data="M 16,3 L 16,17"
|
||
Stroke="{DynamicResource Text}" StrokeThickness="3"
|
||
StrokeStartLineCap="Round" StrokeEndLineCap="Round"/>
|
||
</Canvas>
|
||
</Viewbox>
|
||
</Grid>
|
||
<ControlTemplate.Triggers>
|
||
<DataTrigger Binding="{Binding ConnectionPhase}" Value="connected">
|
||
<Setter TargetName="PowerRing" Property="Stroke" Value="{DynamicResource Ok}"/>
|
||
<Setter TargetName="PowerStem" Property="Stroke" Value="{DynamicResource Ok}"/>
|
||
</DataTrigger>
|
||
<DataTrigger Binding="{Binding ConnectionPhase}" Value="connecting">
|
||
<Setter TargetName="PowerRing" Property="Stroke" Value="{DynamicResource Accent}"/>
|
||
<Setter TargetName="PowerStem" Property="Stroke" Value="{DynamicResource Accent}"/>
|
||
</DataTrigger>
|
||
<Trigger Property="IsMouseOver" Value="True">
|
||
<Setter TargetName="PowerRing" Property="Stroke" Value="{DynamicResource Accent}"/>
|
||
<Setter TargetName="PowerStem" Property="Stroke" Value="{DynamicResource Accent}"/>
|
||
</Trigger>
|
||
<Trigger Property="IsPressed" Value="True">
|
||
<Setter TargetName="PowerRing" Property="Stroke" Value="{DynamicResource AccentDim}"/>
|
||
<Setter TargetName="PowerStem" Property="Stroke" Value="{DynamicResource AccentDim}"/>
|
||
</Trigger>
|
||
</ControlTemplate.Triggers>
|
||
</ControlTemplate>
|
||
</Button.Template>
|
||
</Button>
|
||
</Grid>
|
||
|
||
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="6,0,10,0">
|
||
<TextBlock Text="СОЕДИНЕНИЕ" Foreground="{DynamicResource Muted}"
|
||
FontSize="10" FontWeight="SemiBold" Margin="0,0,0,4"/>
|
||
<StackPanel Orientation="Horizontal">
|
||
<Ellipse Width="8" Height="8" Fill="{Binding StatusBrush}" VerticalAlignment="Center"/>
|
||
<TextBlock Text="{Binding StatusTitle}" Foreground="{DynamicResource Text}"
|
||
FontSize="23" FontWeight="Light" Margin="9,0,0,0"/>
|
||
</StackPanel>
|
||
<TextBlock Text="{Binding StatusSub}" Foreground="{DynamicResource Muted}"
|
||
FontSize="11.5" Margin="0,5,0,0" TextTrimming="CharacterEllipsis"/>
|
||
</StackPanel>
|
||
<Button Style="{StaticResource Pill}" Content="{Binding ConnectText}"
|
||
Command="{Binding ConnectCommand}"
|
||
Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- режим: через WireGuard или напрямую через адаптер -->
|
||
<Border Grid.Row="1" CornerRadius="21" Background="{DynamicResource Panel}"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1"
|
||
Padding="24,18" Margin="0,13,0,0">
|
||
<Grid>
|
||
<StackPanel VerticalAlignment="Center">
|
||
<TextBlock Text="WireGuard для .ru-трафика" Foreground="{DynamicResource Text}"
|
||
FontSize="13" FontWeight="SemiBold"/>
|
||
<TextBlock Foreground="{DynamicResource Muted}" FontSize="11" Margin="0,3,0,0"
|
||
Text="вкл — VLESS поверх WireGuard · выкл — напрямую через сетевой адаптер"/>
|
||
</StackPanel>
|
||
<ToggleButton x:Name="WireguardSwitch" Style="{StaticResource Switch}"
|
||
IsChecked="{Binding WireguardOn, Mode=TwoWay}"
|
||
HorizontalAlignment="Right" VerticalAlignment="Center"/>
|
||
</Grid>
|
||
</Border>
|
||
|
||
<!-- вкладки -->
|
||
<Grid Grid.Row="2" Margin="6,14,4,3">
|
||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||
<Button x:Name="BtnTabLog" Style="{StaticResource Tab}" Content="ЛОГ"
|
||
Foreground="{Binding TabLogBrush}"/>
|
||
<Button x:Name="BtnTabSettings" Style="{StaticResource Tab}" Content="НАСТРОЙКИ"
|
||
Foreground="{Binding TabSettingsBrush}"/>
|
||
</StackPanel>
|
||
</Grid>
|
||
|
||
<!-- содержимое вкладки: два слоя, видим всегда ровно один -->
|
||
<Grid Grid.Row="3">
|
||
|
||
<!-- ── лог ─────────────────────────────────────────────── -->
|
||
<Border Visibility="{Binding LogVis}"
|
||
CornerRadius="21" Background="{DynamicResource LogBg}"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1" Padding="4">
|
||
<TextBox x:Name="LogBox" Text="{Binding LogText, Mode=OneWay}"
|
||
IsReadOnly="True" BorderThickness="0" Background="Transparent"
|
||
Foreground="{Binding LogBrush}" SelectionBrush="{DynamicResource Accent}"
|
||
IsInactiveSelectionHighlightEnabled="False"
|
||
FontFamily="Consolas" FontSize="11.5"
|
||
Padding="14,10" TextWrapping="NoWrap"
|
||
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
|
||
</Border>
|
||
|
||
<!-- ── настройки ───────────────────────────────────────── -->
|
||
<Border Visibility="{Binding SettingsVis}"
|
||
CornerRadius="21" Background="{DynamicResource Panel}"
|
||
BorderBrush="{DynamicResource GlassEdge}" BorderThickness="1" Padding="22,18">
|
||
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="0,0,6,0">
|
||
<StackPanel>
|
||
|
||
<TextBlock Style="{StaticResource GroupLabel}" Text="WIREGUARD"/>
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="128"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
<Grid.RowDefinitions>
|
||
<RowDefinition Height="Auto"/>
|
||
<RowDefinition Height="Auto"/>
|
||
</Grid.RowDefinitions>
|
||
|
||
<TextBlock Grid.Row="0" Grid.Column="0" Style="{StaticResource FieldLabel}"
|
||
Text="Приватный ключ"/>
|
||
<StackPanel Grid.Row="0" Grid.Column="1">
|
||
<TextBox Style="{StaticResource Field}"
|
||
Text="{Binding PrivateKey, Mode=TwoWay}"/>
|
||
<TextBlock Style="{StaticResource Hint}" Text="{Binding PrivateKeyHint}"
|
||
Foreground="{Binding PrivateKeyHintBrush}"/>
|
||
</StackPanel>
|
||
|
||
<TextBlock Grid.Row="1" Grid.Column="0" Style="{StaticResource FieldLabel}"
|
||
Text="Локальный IP" Margin="0,21,12,0"/>
|
||
<StackPanel Grid.Row="1" Grid.Column="1" Margin="0,12,0,0">
|
||
<TextBox Style="{StaticResource Field}"
|
||
Text="{Binding LocalAddress, Mode=TwoWay}"/>
|
||
<TextBlock Style="{StaticResource Hint}" Text="{Binding LocalAddressHint}"
|
||
Foreground="{Binding LocalAddressHintBrush}"/>
|
||
</StackPanel>
|
||
</Grid>
|
||
|
||
<TextBlock Style="{StaticResource GroupLabel}" Text="СЕТЕВОЙ АДАПТЕР"
|
||
Margin="0,20,0,10"/>
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="128"/>
|
||
<ColumnDefinition Width="*"/>
|
||
</Grid.ColumnDefinitions>
|
||
<TextBlock Grid.Column="0" Style="{StaticResource FieldLabel}"
|
||
Text="Имя адаптера"/>
|
||
<StackPanel Grid.Column="1">
|
||
<ComboBox x:Name="AdapterBox" Style="{StaticResource FieldCombo}"
|
||
ItemsSource="{Binding AdapterNames}"
|
||
Text="{Binding Adapter, Mode=TwoWay}"/>
|
||
<TextBlock Style="{StaticResource Hint}" Text="{Binding AdapterHint}"
|
||
Foreground="{Binding AdapterHintBrush}"/>
|
||
<TextBlock Style="{StaticResource Hint}" Foreground="{DynamicResource Muted}"
|
||
Text="нужен, только когда WireGuard выключен"/>
|
||
</StackPanel>
|
||
</Grid>
|
||
|
||
<TextBlock Style="{StaticResource GroupLabel}" Text="ДОБАВИТЬ СЕРВЕР"
|
||
Margin="0,20,0,10"/>
|
||
<Grid>
|
||
<Grid.ColumnDefinitions>
|
||
<ColumnDefinition Width="*"/>
|
||
<ColumnDefinition Width="Auto"/>
|
||
</Grid.ColumnDefinitions>
|
||
<TextBox x:Name="LinkBox" Grid.Column="0" Style="{StaticResource Field}"
|
||
Height="88" AcceptsReturn="True" TextWrapping="NoWrap"
|
||
VerticalScrollBarVisibility="Auto" MaxLength="2000000"/>
|
||
<Button x:Name="BtnAddLink" Grid.Column="1" Style="{StaticResource Soft}"
|
||
Content="импортировать" Margin="8,0,0,0" VerticalAlignment="Top"/>
|
||
</Grid>
|
||
<TextBlock Style="{StaticResource Hint}" Foreground="{DynamicResource Muted}"
|
||
Text="Ссылки, текст/base64, URL подписки или sing-box JSON"/>
|
||
<TextBlock Style="{StaticResource Hint}" Foreground="{DynamicResource Muted}"
|
||
Text="{Binding ImportStatus}" TextWrapping="Wrap"/>
|
||
|
||
<WrapPanel Margin="0,20,0,0">
|
||
<Button Style="{StaticResource Soft}" Content="проверить конфиг"
|
||
Command="{Binding CheckConfigCommand}" Margin="0,0,8,8"/>
|
||
<Button Style="{StaticResource Soft}" Content="показать конфиг"
|
||
Command="{Binding OpenConfigCommand}" Margin="0,0,8,8"/>
|
||
<Button Style="{StaticResource Soft}" Content="папка"
|
||
Command="{Binding OpenFolderCommand}" Margin="0,0,8,8"/>
|
||
<Button Style="{StaticResource Soft}" Content="убить sb.exe"
|
||
Command="{Binding KillStrayCommand}" Margin="0,0,8,8"
|
||
ToolTip="Прибить зависшие процессы sb.exe, оставшиеся от прошлых запусков"/>
|
||
<Button Style="{StaticResource SoftDanger}" Content="удалить сервер"
|
||
Command="{Binding DeleteSelectedCommand}" Margin="0,0,8,8"
|
||
ToolTip="Удалить выбранный сервер из profiles.json"/>
|
||
</WrapPanel>
|
||
|
||
</StackPanel>
|
||
</ScrollViewer>
|
||
</Border>
|
||
</Grid>
|
||
</Grid>
|
||
</Grid>
|
||
</Grid>
|
||
</Border>
|
||
</Window>
|