diff --git a/FasdDesktopUi/Basics/UserControls/Badge.xaml b/FasdDesktopUi/Basics/UserControls/Badge.xaml
index c85f5f4..10b98b4 100644
--- a/FasdDesktopUi/Basics/UserControls/Badge.xaml
+++ b/FasdDesktopUi/Basics/UserControls/Badge.xaml
@@ -3,25 +3,70 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:local="clr-namespace:FasdDesktopUi.Basics.UserControls"
- xmlns:ico="clr-namespace:FasdDesktopUi.Basics.UserControls.AdaptableIcon;assembly=F4SD-AdaptableIcon"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="40"
- x:Name="BadgeControl">
+ x:Name="BadgeControl"
+ Loaded="BadgeControl_Loaded"
+ Unloaded="BadgeControl_Unloaded">
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/FasdDesktopUi/Basics/UserControls/Badge.xaml.cs b/FasdDesktopUi/Basics/UserControls/Badge.xaml.cs
index 8c095aa..2eb9e0c 100644
--- a/FasdDesktopUi/Basics/UserControls/Badge.xaml.cs
+++ b/FasdDesktopUi/Basics/UserControls/Badge.xaml.cs
@@ -1,10 +1,16 @@
-using System.Windows;
+using System;
+using System.Windows;
using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
namespace FasdDesktopUi.Basics.UserControls
{
public partial class Badge : UserControl
{
+ private readonly Storyboard _sparkleStoryboard;
+ private const double SparkleBaseScale = 0.6;
+
public string Text
{
get { return (string)GetValue(TextProperty); }
@@ -14,10 +20,118 @@ namespace FasdDesktopUi.Basics.UserControls
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(Badge), new PropertyMetadata("Beta"));
+ public bool IsSparkleEnabled
+ {
+ get { return (bool)GetValue(IsSparkleEnabledProperty); }
+ set { SetValue(IsSparkleEnabledProperty, value); }
+ }
+
+ public static readonly DependencyProperty IsSparkleEnabledProperty =
+ DependencyProperty.Register(nameof(IsSparkleEnabled), typeof(bool), typeof(Badge), new PropertyMetadata(false, OnIsSparkleEnabledChanged));
+
public Badge()
{
InitializeComponent();
+ _sparkleStoryboard = CreateSparkleStoryboard();
+ UpdateSparkleState();
+ }
+
+ private static void OnIsSparkleEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var control = d as Badge;
+ control?.UpdateSparkleState();
+ }
+
+ private void BadgeControl_Loaded(object sender, RoutedEventArgs e)
+ {
+ UpdateSparkleState();
+ }
+
+ private void BadgeControl_Unloaded(object sender, RoutedEventArgs e)
+ {
+ StopSparkles();
+ }
+
+ private void UpdateSparkleState()
+ {
+ if (SparkleCanvas == null || _sparkleStoryboard == null)
+ {
+ return;
+ }
+
+ if (IsSparkleEnabled)
+ {
+ SparkleCanvas.Visibility = Visibility.Visible;
+ _sparkleStoryboard.Begin(this, true);
+ return;
+ }
+
+ SparkleCanvas.Visibility = Visibility.Collapsed;
+ StopSparkles();
+ }
+
+ private void StopSparkles()
+ {
+ _sparkleStoryboard?.Stop(this);
+
+ if (SparkleTopRight != null)
+ {
+ SparkleTopRight.Opacity = 0;
+ if (SparkleTopRight.RenderTransform is ScaleTransform topTransform)
+ {
+ topTransform.ScaleX = SparkleBaseScale;
+ topTransform.ScaleY = SparkleBaseScale;
+ }
+ }
+
+ if (SparkleBottomLeft != null)
+ {
+ SparkleBottomLeft.Opacity = 0;
+ if (SparkleBottomLeft.RenderTransform is ScaleTransform bottomTransform)
+ {
+ bottomTransform.ScaleX = SparkleBaseScale;
+ bottomTransform.ScaleY = SparkleBaseScale;
+ }
+ }
+ }
+
+ private Storyboard CreateSparkleStoryboard()
+ {
+ var storyboard = new Storyboard
+ {
+ RepeatBehavior = RepeatBehavior.Forever
+ };
+
+ AddKeyFrames(storyboard, SparkleTopRight, "Opacity",
+ (0.00, 0.0), (0.18, 1.0), (0.42, 0.0), (2.20, 0.0));
+ AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)",
+ (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale));
+ AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)",
+ (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale));
+
+ AddKeyFrames(storyboard, SparkleBottomLeft, "Opacity",
+ (0.00, 0.0), (1.00, 0.0), (1.18, 1.0), (1.42, 0.0), (2.20, 0.0));
+ AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)",
+ (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale));
+ AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)",
+ (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale));
+
+ return storyboard;
+ }
+
+ private static void AddKeyFrames(Storyboard storyboard, DependencyObject target, string targetProperty, params (double TimeSeconds, double Value)[] frames)
+ {
+ var animation = new DoubleAnimationUsingKeyFrames();
+
+ foreach (var frame in frames)
+ {
+ animation.KeyFrames.Add(new LinearDoubleKeyFrame(frame.Value, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(frame.TimeSeconds))));
+ }
+
+ Storyboard.SetTarget(animation, target);
+ Storyboard.SetTargetProperty(animation, new PropertyPath(targetProperty));
+ storyboard.Children.Add(animation);
}
}
}
diff --git a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml
index c4a2144..f63532e 100644
--- a/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml
+++ b/FasdDesktopUi/Pages/SearchPage/SearchPageView.xaml
@@ -120,6 +120,7 @@
FontWeight="Bold"
Visibility="Visible" />