Release v0.1.1

This commit is contained in:
nikit3s
2026-09-27 15:25:46 +03:00
parent 7ac8c78d8b
commit b2ae91b5b3
11 changed files with 315 additions and 91 deletions
+142 -77
View File
@@ -1,7 +1,7 @@
<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="sb launcher · glass preview" Width="1120" Height="790"
Title="SbLauncher" Width="1120" Height="790"
WindowStyle="None" AllowsTransparency="False" Background="{DynamicResource Bg}"
ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
TextOptions.TextFormattingMode="Display"
@@ -338,19 +338,38 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Width="46" Height="26">
<Border x:Name="Track" CornerRadius="13" Background="{DynamicResource SwitchTrack}"
<Grid Width="52" Height="30">
<Border CornerRadius="15" Background="{DynamicResource SwitchTrack}"
BorderBrush="{DynamicResource Stroke}" BorderThickness="1"/>
<Ellipse x:Name="Thumb" Width="18" Height="18" Fill="{DynamicResource SwitchThumb}"
HorizontalAlignment="Left" Margin="4,0,0,0"/>
<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="IsChecked" Value="True">
<Setter TargetName="Track" Property="Background" Value="{DynamicResource Accent}"/>
<Setter TargetName="Track" Property="BorderBrush" Value="{DynamicResource Accent}"/>
<Setter TargetName="Thumb" Property="Fill" Value="{DynamicResource OnAccent}"/>
<Setter TargetName="Thumb" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="Thumb" Property="Margin" Value="0,0,4,0"/>
<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>
@@ -419,10 +438,6 @@
<Trigger SourceName="Card" Property="IsMouseOver" Value="True">
<Setter TargetName="Card" Property="Background" Value="{DynamicResource CardHover}"/>
</Trigger>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter TargetName="Card" Property="Background" Value="{DynamicResource CardSel}"/>
<Setter TargetName="Card" Property="BorderBrush" Value="{DynamicResource Accent}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
@@ -618,12 +633,12 @@
<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="sb launcher" Foreground="{DynamicResource Text}"
<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="glass preview" Foreground="{DynamicResource Muted}"
<TextBlock Text="{Binding VersionText}" Foreground="{DynamicResource Muted}"
FontSize="10" VerticalAlignment="Center"/>
</Border>
</StackPanel>
@@ -662,31 +677,40 @@
Padding="10,4"/>
</Grid>
<ListBox Grid.Row="1" 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>
<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>
@@ -714,8 +738,8 @@
StrokeThickness="1"/>
<Ellipse Width="62" Height="62" Stroke="{DynamicResource HeroRingDim}"
StrokeThickness="2" Margin="2"/>
<!-- После удачного подключения — один спокойный световой импульс. -->
<Ellipse Width="56" Height="56" Fill="{DynamicResource Ok}"
<!-- Мягкое заполнение после подключения вместо резкой вспышки. -->
<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>
@@ -723,15 +747,24 @@
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ConnectionPhase}" Value="connected">
<Setter Property="Opacity" Value="0.18"/>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<Storyboard FillBehavior="Stop">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.36" To="0" Duration="0:0:0.65"/>
From="0" To="0.18" Duration="0:0:0.55"/>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
From="0.8" To="1.2" Duration="0:0:0.65"/>
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.8" To="1.2" Duration="0:0:0.65"/>
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>
@@ -740,44 +773,80 @@
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse Width="62" Height="62" Stroke="{DynamicResource HeroRing}"
StrokeThickness="3" StrokeDashArray="2 5" Margin="2"
<!-- Пока соединение меняется, ободок спокойно «дышит». -->
<Ellipse x:Name="ConnectionBreathRing" Width="58" Height="58" Stroke="{DynamicResource Accent}"
StrokeThickness="2.5" IsHitTestVisible="False"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform><RotateTransform/></Ellipse.RenderTransform>
<Ellipse.RenderTransform><ScaleTransform/></Ellipse.RenderTransform>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Opacity" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ConnectionPhase}" Value="connecting">
<Setter Property="Opacity" Value="1"/>
<DataTrigger Binding="{Binding ConnectionInProgress}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="ConnectOrbit">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
From="0" To="360" Duration="0:0:2"/>
<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="ConnectOrbit"/></DataTrigger.ExitActions>
</DataTrigger>
<DataTrigger Binding="{Binding ConnectionPhase}" Value="disconnecting">
<Setter Property="Opacity" Value="1"/>
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="DisconnectOrbit">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"
From="360" To="0" Duration="0:0:1.4"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions><StopStoryboard BeginStoryboardName="DisconnectOrbit"/></DataTrigger.ExitActions>
<DataTrigger.ExitActions><StopStoryboard BeginStoryboardName="ConnectionBreath"/></DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Image x:Name="StatusLogoImg" Width="38" Height="38"
RenderOptions.BitmapScalingMode="HighQuality"/>
<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">
@@ -808,7 +877,7 @@
<TextBlock Foreground="{DynamicResource Muted}" FontSize="11" Margin="0,3,0,0"
Text="вкл — VLESS поверх WireGuard · выкл — напрямую через сетевой адаптер"/>
</StackPanel>
<ToggleButton Style="{StaticResource Switch}"
<ToggleButton x:Name="WireguardSwitch" Style="{StaticResource Switch}"
IsChecked="{Binding WireguardOn, Mode=TwoWay}"
HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
@@ -822,10 +891,6 @@
<Button x:Name="BtnTabSettings" Style="{StaticResource Tab}" Content="НАСТРОЙКИ"
Foreground="{Binding TabSettingsBrush}"/>
</StackPanel>
<Button Style="{StaticResource Soft}" Content="Очистить лог"
Command="{Binding ClearLogCommand}" Visibility="{Binding LogVis}"
HorizontalAlignment="Right" VerticalAlignment="Center"
ToolTip="Удалить записи из окна лога"/>
</Grid>
<!-- содержимое вкладки: два слоя, видим всегда ровно один -->