Release v0.1.1
This commit is contained in:
@@ -33,10 +33,12 @@ using System.Threading.Tasks;
|
||||
using System.Web.Script.Serialization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
|
||||
@@ -147,7 +149,7 @@ namespace SbLauncher
|
||||
|
||||
_ni = new System.Windows.Forms.NotifyIcon();
|
||||
_ni.Icon = LoadIcon();
|
||||
_ni.Text = "sb launcher";
|
||||
_ni.Text = "SbLauncher";
|
||||
_ni.Visible = true;
|
||||
_ni.DoubleClick += delegate { Restore(); };
|
||||
|
||||
@@ -497,13 +499,12 @@ namespace SbLauncher
|
||||
vm.SetTheme(themeArg != null ? themeArg : Theme.Dark);
|
||||
vm.Load(paths);
|
||||
vm.ShowSettings = settingsTab;
|
||||
vm.AppendLog("демо-рендер интерфейса — sing-box не запускался");
|
||||
vm.ClearLog();
|
||||
vm.AppendLog("демонстрация интерфейса — sing-box не запускался");
|
||||
|
||||
ImageSource logo = LoadLogo();
|
||||
Image li = w.FindName("LogoImg") as Image;
|
||||
if (li != null && logo != null) li.Source = logo;
|
||||
Image statusLogo = w.FindName("StatusLogoImg") as Image;
|
||||
if (statusLogo != null && logo != null) statusLogo.Source = logo;
|
||||
|
||||
// немного «живых» данных, чтобы картинка была честной
|
||||
int i = 0;
|
||||
@@ -526,6 +527,14 @@ namespace SbLauncher
|
||||
root2.UpdateLayout();
|
||||
Pump(); // дать ItemsControl создать карточки
|
||||
root2.UpdateLayout();
|
||||
ToggleButton modeSwitch = w.FindName("WireguardSwitch") as ToggleButton;
|
||||
if (modeSwitch != null) UpdateSwitch(modeSwitch, false);
|
||||
ListBox serverList = w.FindName("ServerList") as ListBox;
|
||||
FrameworkElement serverHost = w.FindName("ServerListHost") as FrameworkElement;
|
||||
Border selection = w.FindName("ServerSelectionWindow") as Border;
|
||||
if (serverList != null && serverHost != null && selection != null)
|
||||
MoveServerSelection(serverList, serverHost, selection, false);
|
||||
root2.UpdateLayout();
|
||||
|
||||
RenderTargetBitmap rtb = new RenderTargetBitmap(
|
||||
(int)(ww * 1.5), (int)(hh * 1.5), 144, 144, PixelFormats.Pbgra32);
|
||||
@@ -608,8 +617,6 @@ namespace SbLauncher
|
||||
{
|
||||
Image li = w.FindName("LogoImg") as Image;
|
||||
if (li != null) li.Source = logo;
|
||||
Image statusLogo = w.FindName("StatusLogoImg") as Image;
|
||||
if (statusLogo != null) statusLogo.Source = logo;
|
||||
try { w.Icon = logo; } catch { }
|
||||
}
|
||||
|
||||
@@ -656,7 +663,127 @@ namespace SbLauncher
|
||||
if (log != null)
|
||||
log.TextChanged += delegate { log.ScrollToEnd(); };
|
||||
|
||||
WireSwitch(w);
|
||||
WireServerSelection(w);
|
||||
w.Loaded += delegate { vm.PingAll(); };
|
||||
}
|
||||
|
||||
static void WireSwitch(Window w)
|
||||
{
|
||||
ToggleButton toggle = w.FindName("WireguardSwitch") as ToggleButton;
|
||||
if (toggle == null) return;
|
||||
|
||||
// При загрузке положение выставляется сразу; последующие изменения
|
||||
// идут от текущего положения, поэтому быстрые клики не дают скачка.
|
||||
toggle.Loaded += delegate { UpdateSwitch(toggle, false); };
|
||||
toggle.Checked += delegate { UpdateSwitch(toggle, true); };
|
||||
toggle.Unchecked += delegate { UpdateSwitch(toggle, true); };
|
||||
}
|
||||
|
||||
static void UpdateSwitch(ToggleButton toggle, bool animate)
|
||||
{
|
||||
if (!toggle.IsLoaded && animate) return;
|
||||
toggle.ApplyTemplate();
|
||||
Border active = toggle.Template.FindName("ActiveTrack", toggle) as Border;
|
||||
System.Windows.Shapes.Ellipse thumb =
|
||||
toggle.Template.FindName("Thumb", toggle) as System.Windows.Shapes.Ellipse;
|
||||
TranslateTransform shift = thumb != null ? thumb.RenderTransform as TranslateTransform : null;
|
||||
if (active == null || shift == null) return;
|
||||
if (shift.IsFrozen)
|
||||
{
|
||||
shift = shift.Clone();
|
||||
thumb.RenderTransform = shift;
|
||||
}
|
||||
|
||||
double targetX = toggle.IsChecked == true ? 22 : 0;
|
||||
double targetOpacity = toggle.IsChecked == true ? 1 : 0;
|
||||
double fromX = shift.X, fromOpacity = active.Opacity;
|
||||
shift.BeginAnimation(TranslateTransform.XProperty, null);
|
||||
active.BeginAnimation(UIElement.OpacityProperty, null);
|
||||
shift.X = targetX;
|
||||
active.Opacity = targetOpacity;
|
||||
if (!animate) return;
|
||||
|
||||
DoubleAnimation slide = new DoubleAnimation(fromX, targetX,
|
||||
TimeSpan.FromMilliseconds(430));
|
||||
slide.EasingFunction = new BackEase { Amplitude = 0.28, EasingMode = EasingMode.EaseOut };
|
||||
slide.FillBehavior = FillBehavior.Stop;
|
||||
shift.BeginAnimation(TranslateTransform.XProperty, slide);
|
||||
|
||||
DoubleAnimation color = new DoubleAnimation(fromOpacity, targetOpacity,
|
||||
TimeSpan.FromMilliseconds(300));
|
||||
color.EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut };
|
||||
color.FillBehavior = FillBehavior.Stop;
|
||||
active.BeginAnimation(UIElement.OpacityProperty, color);
|
||||
}
|
||||
|
||||
static void WireServerSelection(Window w)
|
||||
{
|
||||
ListBox list = w.FindName("ServerList") as ListBox;
|
||||
FrameworkElement host = w.FindName("ServerListHost") as FrameworkElement;
|
||||
Border highlight = w.FindName("ServerSelectionWindow") as Border;
|
||||
if (list == null || host == null || highlight == null) return;
|
||||
|
||||
bool selectionPending = false;
|
||||
int selectionRevision = 0;
|
||||
list.Loaded += delegate { MoveServerSelection(list, host, highlight, false); };
|
||||
list.SelectionChanged += delegate
|
||||
{
|
||||
selectionPending = true;
|
||||
int revision = ++selectionRevision;
|
||||
if (list.SelectedItem != null) list.ScrollIntoView(list.SelectedItem);
|
||||
list.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(delegate
|
||||
{
|
||||
if (revision != selectionRevision) return;
|
||||
try
|
||||
{
|
||||
list.UpdateLayout();
|
||||
MoveServerSelection(list, host, highlight, true);
|
||||
}
|
||||
finally { selectionPending = false; }
|
||||
}));
|
||||
};
|
||||
list.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(
|
||||
delegate { if (!selectionPending) MoveServerSelection(list, host, highlight, false); }));
|
||||
list.SizeChanged += delegate { if (!selectionPending) MoveServerSelection(list, host, highlight, false); };
|
||||
}
|
||||
|
||||
static void MoveServerSelection(ListBox list, FrameworkElement host,
|
||||
Border highlight, bool animate)
|
||||
{
|
||||
ListBoxItem item = list.ItemContainerGenerator.ContainerFromItem(list.SelectedItem) as ListBoxItem;
|
||||
if (item == null || item.ActualHeight <= 10)
|
||||
{
|
||||
highlight.Visibility = Visibility.Collapsed;
|
||||
return;
|
||||
}
|
||||
|
||||
Point p;
|
||||
try { p = item.TransformToAncestor(host).Transform(new Point(0, 0)); }
|
||||
catch (InvalidOperationException) { return; }
|
||||
double height = item.ActualHeight - 10; // промежуток между карточками
|
||||
if (p.Y + height < 0 || p.Y > host.ActualHeight)
|
||||
{
|
||||
highlight.Visibility = Visibility.Collapsed;
|
||||
return;
|
||||
}
|
||||
|
||||
bool wasVisible = highlight.Visibility == Visibility.Visible;
|
||||
double fromY = Canvas.GetTop(highlight);
|
||||
if (double.IsNaN(fromY)) fromY = p.Y;
|
||||
highlight.BeginAnimation(Canvas.TopProperty, null);
|
||||
Canvas.SetLeft(highlight, p.X);
|
||||
Canvas.SetTop(highlight, p.Y);
|
||||
highlight.Width = item.ActualWidth;
|
||||
highlight.Height = height;
|
||||
highlight.Visibility = Visibility.Visible;
|
||||
if (!animate || !wasVisible || Math.Abs(fromY - p.Y) < 0.5) return;
|
||||
|
||||
DoubleAnimation slide = new DoubleAnimation(fromY, p.Y,
|
||||
TimeSpan.FromMilliseconds(520));
|
||||
slide.EasingFunction = new BackEase { Amplitude = 0.32, EasingMode = EasingMode.EaseOut };
|
||||
slide.FillBehavior = FillBehavior.Stop;
|
||||
highlight.BeginAnimation(Canvas.TopProperty, slide);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user