diff --git a/CollapseLauncher/App.xaml b/CollapseLauncher/App.xaml
index 066e3cad2..ec8e4a46e 100644
--- a/CollapseLauncher/App.xaml
+++ b/CollapseLauncher/App.xaml
@@ -31,6 +31,15 @@
+
+
+
+
+
+
+
+
+
@@ -69,11 +78,6 @@
Color="#000000" />
-
-
-
-
-
#ffd52a
-
-
-
-
-
-
#693758
-
(Brush)GetValue(ForegroundProperty);
+ set => SetValue(ForegroundProperty, value);
+ }
+
+ ///
+ /// Dependency property for Foreground.
+ ///
+ public static readonly DependencyProperty ForegroundProperty =
+ DependencyProperty.Register(nameof(Foreground), typeof(Brush), typeof(BindableThemeChangeAnimation),
+ new PropertyMetadata(null!, OnForegroundChanged));
+
+ protected static void OnForegroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ => ((BindableThemeChangeAnimation)d).OnForegroundChanged(args.NewValue as Brush);
+
+ protected abstract void OnForegroundChanged(Brush? brush);
+}
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs
index 59d0c86ba..67b789ebb 100644
--- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.cs
@@ -3,13 +3,13 @@
// This code was generated by a tool.
//
// LottieGen version:
-// 8.0.280225.1+7cd366a738
+// 8.2.250604.1+b02a3ee244
//
// Command:
-// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile DownloadIcon.lottie
+// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile DownloadIcon.json
//
// Input file:
-// DownloadIcon.lottie (1623 bytes created 23:20+07:00 Jun 1 2024)
+// DownloadIcon.json (7800 bytes created 16:59+07:00 Jan 4 2026)
//
// LottieGen source:
// http://aka.ms/Lottie
@@ -21,16 +21,16 @@
// ____________________________________
// | Object stats | Count |
// |__________________________|_______|
-// | All CompositionObjects | 118 |
+// | All CompositionObjects | 121 |
// |--------------------------+-------|
-// | Expression animators | 8 |
+// | Expression animators | 9 |
// | KeyFrame animators | 15 |
-// | Reference parameters | 8 |
-// | Expression operations | 6 |
+// | Reference parameters | 9 |
+// | Expression operations | 10 |
// |--------------------------+-------|
-// | Animated brushes | - |
+// | Animated brushes | 1 |
// | Animated gradient stops | - |
-// | ExpressionAnimations | 8 |
+// | ExpressionAnimations | 9 |
// | PathKeyFrameAnimations | 1 |
// |--------------------------+-------|
// | ContainerVisuals | 5 |
@@ -48,6 +48,8 @@
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -59,13 +61,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie
// Frame rate: 60 fps
// Frame count: 300
// Duration: 5000.0 mS
- sealed partial class DownloadIcon
- : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
+ public sealed partial class DownloadIcon
+ : BindableThemeChangeAnimation
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
, Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2
{
+ protected override void OnForegroundChanged(Brush brush)
+ {
+ if (brush is SolidColorBrush colorBrush)
+ {
+ Color_FFFFFF = colorBrush.Color;
+ return;
+ }
+
+ if (brush is AcrylicBrush acrylicBrush)
+ {
+ Color_FFFFFF = acrylicBrush.TintColor;
+ return;
+ }
+ }
+
+ private static Color GetForegroundColor(bool isLightTheme) =>
+ isLightTheme
+ ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00)
+ : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
+
// Animation duration: 5.000 seconds.
internal const long c_durationTicks = 50000000;
+ CompositionPropertySet _themeProperties;
+
+ ///
+ /// Dependency property for Color_FFFFFF.
+ ///
+ public static readonly DependencyProperty Color_FFFFFFProperty =
+ DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(DownloadIcon),
+ new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged));
+
+ // Theme properties.
+ public Color Color_FFFFFF
+ {
+ get => (Color)GetValue(Color_FFFFFFProperty);
+ set => SetValue(Color_FFFFFFProperty, value);
+ }
+
+ static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A);
+
+ static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ {
+ ((DownloadIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue));
+ }
+
+ CompositionPropertySet EnsureThemeProperties(Compositor compositor)
+ {
+ if (_themeProperties == null)
+ {
+ _themeProperties = compositor.CreatePropertySet();
+ _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF));
+ }
+ return _themeProperties;
+ }
+
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
{
object ignored = null;
@@ -75,10 +131,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
{
diagnostics = null;
+ EnsureThemeProperties(compositor);
var res =
new DownloadIcon_AnimatedVisual(
- compositor
+ compositor,
+ _themeProperties
);
res.CreateAnimations();
return res;
@@ -122,6 +180,19 @@ public double FrameToProgress(double frameNumber)
///
public void SetColorProperty(string propertyName, Color value)
{
+ if (propertyName == "Color_FFFFFF")
+ {
+ Color_FFFFFF = value;
+ }
+ else
+ {
+ return;
+ }
+
+ if (_themeProperties != null)
+ {
+ _themeProperties.InsertVector4(propertyName, ColorAsVector4(value));
+ }
}
///
@@ -139,8 +210,9 @@ sealed partial class DownloadIcon_AnimatedVisual
const long c_durationTicks = 50000000;
readonly Compositor _c;
readonly ExpressionAnimation _reusableExpressionAnimation;
+ readonly CompositionPropertySet _themeProperties;
AnimationController _animationController_0;
- CompositionColorBrush _colorBrush_White;
+ CompositionColorBrush _themeColor_Color_FFFFFF;
CompositionContainerShape _containerShape_0;
CompositionContainerShape _containerShape_1;
CompositionContainerShape _containerShape_2;
@@ -155,7 +227,7 @@ sealed partial class DownloadIcon_AnimatedVisual
CubicBezierEasingFunction _cubicBezierEasingFunction_0;
CubicBezierEasingFunction _cubicBezierEasingFunction_1;
ScalarKeyFrameAnimation _opacityScalarAnimation_1_to_0;
- ScalarKeyFrameAnimation _positionYScalarAnimation_1025_to_2350;
+ ScalarKeyFrameAnimation _positionYScalarAnimation_128p125_to_293p75;
ScalarKeyFrameAnimation _rotationAngleInDegreesScalarAnimation_0_to_0_0;
ShapeVisual _shapeVisual_2;
StepEasingFunction _holdThenStepEasingFunction;
@@ -245,11 +317,11 @@ CanvasGeometry Geometry_2()
CanvasGeometry result;
using (var builder = new CanvasPathBuilder(null))
{
- builder.BeginFigure(new Vector2(2316F, -196F));
- builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F));
- builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 2132F), new Vector2(-336F, 2132F));
- builder.AddCubicBezier(new Vector2(-336F, 2132F), new Vector2(2316F, 2132F), new Vector2(2316F, 2132F));
- builder.AddCubicBezier(new Vector2(2316F, 2132F), new Vector2(2316F, -196F), new Vector2(2316F, -196F));
+ builder.BeginFigure(new Vector2(289.5F, -24.5F));
+ builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F));
+ builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 266.5F), new Vector2(-42F, 266.5F));
+ builder.AddCubicBezier(new Vector2(-42F, 266.5F), new Vector2(289.5F, 266.5F), new Vector2(289.5F, 266.5F));
+ builder.AddCubicBezier(new Vector2(289.5F, 266.5F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F));
builder.EndFigure(CanvasFigureLoop.Closed);
result = CanvasGeometry.CreatePath(builder);
}
@@ -264,11 +336,11 @@ CanvasGeometry Geometry_3()
CanvasGeometry result;
using (var builder = new CanvasPathBuilder(null))
{
- builder.BeginFigure(new Vector2(2316F, -196F));
- builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F));
- builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 1532F), new Vector2(-336F, 1532F));
- builder.AddCubicBezier(new Vector2(-336F, 1532F), new Vector2(2316F, 1532F), new Vector2(2316F, 1532F));
- builder.AddCubicBezier(new Vector2(2316F, 1532F), new Vector2(2316F, -196F), new Vector2(2316F, -196F));
+ builder.BeginFigure(new Vector2(289.5F, -24.5F));
+ builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F));
+ builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 191.5F), new Vector2(-42F, 191.5F));
+ builder.AddCubicBezier(new Vector2(-42F, 191.5F), new Vector2(289.5F, 191.5F), new Vector2(289.5F, 191.5F));
+ builder.AddCubicBezier(new Vector2(289.5F, 191.5F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F));
builder.EndFigure(CanvasFigureLoop.Closed);
result = CanvasGeometry.CreatePath(builder);
}
@@ -283,11 +355,11 @@ CanvasGeometry Geometry_4()
CanvasGeometry result;
using (var builder = new CanvasPathBuilder(null))
{
- builder.BeginFigure(new Vector2(2316F, -196F));
- builder.AddCubicBezier(new Vector2(2316F, -196F), new Vector2(-336F, -196F), new Vector2(-336F, -196F));
- builder.AddCubicBezier(new Vector2(-336F, -196F), new Vector2(-336F, 1432F), new Vector2(-336F, 1432F));
- builder.AddCubicBezier(new Vector2(-336F, 1432F), new Vector2(2316F, 1432F), new Vector2(2316F, 1432F));
- builder.AddCubicBezier(new Vector2(2316F, 1432F), new Vector2(2316F, -196F), new Vector2(2316F, -196F));
+ builder.BeginFigure(new Vector2(289.5F, -24.5F));
+ builder.AddCubicBezier(new Vector2(289.5F, -24.5F), new Vector2(-42F, -24.5F), new Vector2(-42F, -24.5F));
+ builder.AddCubicBezier(new Vector2(-42F, -24.5F), new Vector2(-42F, 179F), new Vector2(-42F, 179F));
+ builder.AddCubicBezier(new Vector2(-42F, 179F), new Vector2(289.5F, 179F), new Vector2(289.5F, 179F));
+ builder.AddCubicBezier(new Vector2(289.5F, 179F), new Vector2(289.5F, -24.5F), new Vector2(289.5F, -24.5F));
builder.EndFigure(CanvasFigureLoop.Closed);
result = CanvasGeometry.CreatePath(builder);
}
@@ -314,11 +386,13 @@ CompositionColorBrush ColorBrush_Black()
return _c.CreateColorBrush(Color.FromArgb(0xFF, 0x00, 0x00, 0x00));
}
- CompositionColorBrush ColorBrush_White()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF()
{
- return (_colorBrush_White == null)
- ? _colorBrush_White = _c.CreateColorBrush(InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00))
- : _colorBrush_White;
+ if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; }
+ var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush();
+ BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties);
+ return result;
}
CompositionContainerShape ContainerShape_0()
@@ -326,7 +400,9 @@ CompositionContainerShape ContainerShape_0()
if (_containerShape_0 != null) { return _containerShape_0; }
var result = _containerShape_0 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(1024F, 1025F));
+ propertySet.InsertVector2("Position", new Vector2(128F, 128.125F));
+ result.CenterPoint = new Vector2(50F, 50F);
+ result.Scale = new Vector2(0.125F, 0.125F);
// Transforms: Shape Layer 1 Offset:<50, 50>
result.Shapes.Add(SpriteShape_0());
BindProperty(_containerShape_0, "Offset", "Vector2(my.Position.X-50,my.Position.Y-50)", "my", _containerShape_0);
@@ -338,7 +414,9 @@ CompositionContainerShape ContainerShape_1()
if (_containerShape_1 != null) { return _containerShape_1; }
var result = _containerShape_1 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(1024F, 1025F));
+ propertySet.InsertVector2("Position", new Vector2(128F, 128.125F));
+ result.CenterPoint = new Vector2(50F, 50F);
+ result.Scale = new Vector2(0.125F, 0.125F);
// Transforms: Shape Layer 2 Offset:<50, 50>
result.Shapes.Add(SpriteShape_1());
BindProperty(_containerShape_1, "Offset", "Vector2(my.Position.X-50,my.Position.Y-50)", "my", _containerShape_1);
@@ -350,8 +428,9 @@ CompositionContainerShape ContainerShape_2()
if (_containerShape_2 != null) { return _containerShape_2; }
var result = _containerShape_2 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(1024F, 1264F));
+ propertySet.InsertVector2("Position", new Vector2(128F, 179.125F));
result.CenterPoint = new Vector2(4F, 344F);
+ result.Scale = new Vector2(0.125F, 0.125F);
// ShapeGroup: Shape 1
result.Shapes.Add(SpriteShape_3());
BindProperty(_containerShape_2, "Offset", "Vector2(my.Position.X-4,my.Position.Y-344)", "my", _containerShape_2);
@@ -433,7 +512,7 @@ CompositionSpriteShape SpriteShape_0()
{
// Offset:<50, 50>
var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(1F, 0F, 0F, 1F, 50F, 50F));;
- result.StrokeBrush = ColorBrush_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -448,7 +527,7 @@ CompositionSpriteShape SpriteShape_1()
{
// Offset:<50, 50>
var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(1F, 0F, 0F, 1F, 50F, 50F));;
- result.StrokeBrush = ColorBrush_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -464,7 +543,7 @@ CompositionSpriteShape SpriteShape_2()
{
if (_spriteShape_2 != null) { return _spriteShape_2; }
var result = _spriteShape_2 = _c.CreateSpriteShape(PathGeometry_2());
- result.CenterPoint = new Vector2(1024F, 1024F);
+ result.CenterPoint = new Vector2(128F, 128F);
result.FillBrush = ColorBrush_Black();
return result;
}
@@ -473,7 +552,7 @@ CompositionSpriteShape SpriteShape_2()
CompositionSpriteShape SpriteShape_3()
{
var result = _c.CreateSpriteShape(PathGeometry_3());
- result.StrokeBrush = ColorBrush_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -500,7 +579,7 @@ CompositionVisualSurface VisualSurface_0()
{
var result = _c.CreateVisualSurface();
result.SourceVisual = ContainerVisual_0();
- result.SourceSize = new Vector2(2048F, 2048F);
+ result.SourceSize = new Vector2(256F, 256F);
return result;
}
@@ -509,7 +588,7 @@ CompositionVisualSurface VisualSurface_1()
{
var result = _c.CreateVisualSurface();
result.SourceVisual = ContainerVisual_3();
- result.SourceSize = new Vector2(2048F, 2048F);
+ result.SourceSize = new Vector2(256F, 256F);
return result;
}
@@ -529,7 +608,7 @@ ContainerVisual ContainerVisual_1()
{
if (_containerVisual_1 != null) { return _containerVisual_1; }
var result = _containerVisual_1 = _c.CreateContainerVisual();
- result.CenterPoint = new Vector3(1024F, 1024F, 0F);
+ result.CenterPoint = new Vector3(128F, 128F, 0F);
result.Scale = new Vector3(1F, 1F, 0F);
// Transforms for DownloadIcon
result.Children.InsertAtTop(ContainerVisual_2());
@@ -543,7 +622,7 @@ ContainerVisual ContainerVisual_2()
{
var result = _c.CreateContainerVisual();
result.Clip = InsetClip_0();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
// Layer aggregator
result.Children.InsertAtTop(ShapeVisual_0());
return result;
@@ -627,43 +706,43 @@ ScalarKeyFrameAnimation OpacityScalarAnimation_1_to_0()
}
// Position.Y
- ScalarKeyFrameAnimation PositionYScalarAnimation_1025_to_2350()
+ ScalarKeyFrameAnimation PositionYScalarAnimation_128p125_to_293p75()
{
// Frame 0.
- if (_positionYScalarAnimation_1025_to_2350 != null) { return _positionYScalarAnimation_1025_to_2350; }
- var result = _positionYScalarAnimation_1025_to_2350 = CreateScalarKeyFrameAnimation(0F, 1025F, StepThenHoldEasingFunction());
+ if (_positionYScalarAnimation_128p125_to_293p75 != null) { return _positionYScalarAnimation_128p125_to_293p75; }
+ var result = _positionYScalarAnimation_128p125_to_293p75 = CreateScalarKeyFrameAnimation(0F, 128.125F, StepThenHoldEasingFunction());
// Frame 50.
- result.InsertKeyFrame(0.166666672F, 1025F, HoldThenStepEasingFunction());
+ result.InsertKeyFrame(0.166666672F, 128.125F, HoldThenStepEasingFunction());
// Frame 90.
- result.InsertKeyFrame(0.300000012F, 1009F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.300000012F, 126.125F, CubicBezierEasingFunction_0());
// Frame 165.
- result.InsertKeyFrame(0.550000012F, 1009F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.550000012F, 126.125F, CubicBezierEasingFunction_0());
// Frame 200.
- result.InsertKeyFrame(0.666666687F, 876F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.666666687F, 109.5F, CubicBezierEasingFunction_0());
// Frame 210.
- result.InsertKeyFrame(0.699999988F, 876F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.167999998F, 1F)));
+ result.InsertKeyFrame(0.699999988F, 109.5F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.167999998F, 1F)));
// Frame 255.
- result.InsertKeyFrame(0.850000024F, 2350F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.850000024F, 293.75F, CubicBezierEasingFunction_0());
return result;
}
// Position.Y
- ScalarKeyFrameAnimation PositionYScalarAnimation_1264_to_1433()
+ ScalarKeyFrameAnimation PositionYScalarAnimation_179p125_to_179p125()
{
// Frame 0.
- var result = CreateScalarKeyFrameAnimation(0F, 1264F, StepThenHoldEasingFunction());
+ var result = CreateScalarKeyFrameAnimation(0F, 179.125F, StepThenHoldEasingFunction());
// Frame 30.
- result.InsertKeyFrame(0.100000001F, 1264F, HoldThenStepEasingFunction());
+ result.InsertKeyFrame(0.100000001F, 179.125F, HoldThenStepEasingFunction());
// Frame 70.
- result.InsertKeyFrame(0.233333334F, 1433F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.233333334F, 179.125F, CubicBezierEasingFunction_0());
// Frame 167.
- result.InsertKeyFrame(0.556666672F, 1433F, _c.CreateCubicBezierEasingFunction(new Vector2(0.157000005F, 0F), new Vector2(0.0299999993F, 1F)));
+ result.InsertKeyFrame(0.556666672F, 179.125F, _c.CreateCubicBezierEasingFunction(new Vector2(0.157000005F, 0F), new Vector2(0.0299999993F, 1F)));
// Frame 188.
- result.InsertKeyFrame(0.626666665F, 1577F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.626666665F, 197.125F, CubicBezierEasingFunction_0());
// Frame 210.
- result.InsertKeyFrame(0.699999988F, 1577F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.699999988F, 197.125F, CubicBezierEasingFunction_0());
// Frame 240.
- result.InsertKeyFrame(0.800000012F, 1433F, CubicBezierEasingFunction_0());
+ result.InsertKeyFrame(0.800000012F, 179.125F, CubicBezierEasingFunction_0());
return result;
}
@@ -785,7 +864,7 @@ ScalarKeyFrameAnimation TStartScalarAnimation_0p855_to_0()
ShapeVisual ShapeVisual_0()
{
var result = _c.CreateShapeVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
var shapes = result.Shapes;
shapes.Add(ContainerShape_0());
shapes.Add(ContainerShape_1());
@@ -797,7 +876,7 @@ ShapeVisual ShapeVisual_0()
ShapeVisual ShapeVisual_1()
{
var result = _c.CreateShapeVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
result.Shapes.Add(SpriteShape_2());
return result;
}
@@ -807,7 +886,7 @@ ShapeVisual ShapeVisual_2()
{
if (_shapeVisual_2 != null) { return _shapeVisual_2; }
var result = _shapeVisual_2 = _c.CreateShapeVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
result.Shapes.Add(ContainerShape_2());
return result;
}
@@ -816,7 +895,7 @@ ShapeVisual ShapeVisual_2()
SpriteVisual SpriteVisual_0()
{
var result = _c.CreateSpriteVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
result.Brush = EffectBrush();
return result;
}
@@ -838,25 +917,27 @@ StepEasingFunction StepThenHoldEasingFunction()
}
internal DownloadIcon_AnimatedVisual(
- Compositor compositor
+ Compositor compositor,
+ CompositionPropertySet themeProperties
)
{
_c = compositor;
+ _themeProperties = themeProperties;
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
Root();
}
public Visual RootVisual => _root;
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
- public Vector2 Size => new Vector2(2048F, 2048F);
+ public Vector2 Size => new Vector2(256F, 256F);
void IDisposable.Dispose() => _root?.Dispose();
public void CreateAnimations()
{
- _containerShape_0.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1025_to_2350(), AnimationController_0());
- _containerShape_1.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1025_to_2350(), AnimationController_0());
+ _containerShape_0.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_128p125_to_293p75(), AnimationController_0());
+ _containerShape_1.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_128p125_to_293p75(), AnimationController_0());
_containerShape_2.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_0_to_0_1(), AnimationController_0());
- _containerShape_2.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_1264_to_1433(), AnimationController_0());
+ _containerShape_2.Properties.StartAnimation("Position.Y", PositionYScalarAnimation_179p125_to_179p125(), AnimationController_0());
_pathGeometry_0.StartAnimation("TStart", TStartScalarAnimation_0p855_to_0(), AnimationController_0());
_pathGeometry_0.StartAnimation("TEnd", TEndScalarAnimation_0p855_to_0p1(), AnimationController_0());
_pathGeometry_1.StartAnimation("TrimStart", TrimStartScalarAnimation_0p585_to_0(), AnimationController_0());
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json
new file mode 100644
index 000000000..2810c9899
--- /dev/null
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.json
@@ -0,0 +1 @@
+{"v":"5.12.2","fr":60,"ip":0,"op":300,"w":256,"h":256,"nm":"DownloadIconMasterComp","ddd":0,"assets":[{"id":"comp_0","nm":"DownloadIcon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[360.517,-180.5],[0,180.017],[-360.517,-180.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[58.5]},{"t":83,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[58.5]},{"t":83,"s":[58.5]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[-101.6]},{"t":83,"s":[0]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":-7,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,-459.501],[-459.501,0],[0,459.501],[0,0]],"o":[[0,0],[-459.501,0],[0,459.501],[459.501,0],[0,-459.501],[0,0]],"v":[[0,116],[0,-832],[-832,0],[0,832],[832,0],[515,-688]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[85.5]},{"t":60,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[85.5]},{"t":80,"s":[10]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"t":60,"s":[0]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":50,"s":[128]},{"t":90,"s":[128]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[128.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[126.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":165,"s":[126.125]},{"i":{"x":[0.168],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":200,"s":[109.5]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210,"s":[109.5]},{"t":255,"s":[293.75]}],"ix":4}},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":300,"st":-10,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":260,"s":[100]},{"t":280,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[8]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":167,"s":[-8]},{"t":184,"s":[0]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[128]},{"t":70,"s":[128]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[179.125]},{"i":{"x":[0.03],"y":[1]},"o":{"x":[0.157],"y":[0]},"t":70,"s":[179.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":167,"s":[179.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":188,"s":[197.125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210,"s":[197.125]},{"t":240,"s":[179.125]}],"ix":4}},"a":{"a":0,"k":[4,344,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-460,344],[468,344]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0]},{"i":{"x":[0.586],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":70,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":260,"s":[0]},{"t":280,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":70,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":260,"s":[100]},{"t":280,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":2,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":-15,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"DownloadIcon","refId":"comp_0","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":260,"s":[100]},{"t":280,"s":[0]}],"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[-9]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":160,"s":[11]},{"t":179,"s":[0]}],"ix":10},"p":{"s":true,"x":{"a":0,"k":128,"ix":3},"y":{"a":0,"k":128,"ix":4}},"a":{"a":0,"k":[128,128,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":150,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,266.5],[289.5,266.5]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":189,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,191.5],[289.5,191.5]],"c":true}]},{"t":230,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[289.5,-24.5],[-42,-24.5],[-42,179],[289.5,179]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"w":256,"h":256,"ip":0,"op":300,"st":0,"bm":0}],"markers":[],"props":{}}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie
deleted file mode 100644
index d40ef8c19..000000000
Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/DownloadIcon.lottie and /dev/null differ
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs
index 3d1e74178..45c1ba614 100644
--- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.cs
@@ -3,13 +3,13 @@
// This code was generated by a tool.
//
// LottieGen version:
-// 8.0.280225.1+7cd366a738
+// 8.2.250604.1+b02a3ee244
//
// Command:
-// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile LoadingSprite.lottie
+// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile LoadingSprite.json
//
// Input file:
-// LoadingSprite.lottie (1342 bytes created 20:17+07:00 May 23 2024)
+// LoadingSprite.json (5570 bytes created 16:59+07:00 Jan 4 2026)
//
// LottieGen source:
// http://aka.ms/Lottie
@@ -21,16 +21,16 @@
// ____________________________________
// | Object stats | Count |
// |__________________________|_______|
-// | All CompositionObjects | 92 |
+// | All CompositionObjects | 97 |
// |--------------------------+-------|
-// | Expression animators | 6 |
+// | Expression animators | 8 |
// | KeyFrame animators | 17 |
-// | Reference parameters | 6 |
-// | Expression operations | 0 |
+// | Reference parameters | 8 |
+// | Expression operations | 8 |
// |--------------------------+-------|
-// | Animated brushes | - |
+// | Animated brushes | 2 |
// | Animated gradient stops | - |
-// | ExpressionAnimations | 6 |
+// | ExpressionAnimations | 8 |
// | PathKeyFrameAnimations | - |
// |--------------------------+-------|
// | ContainerVisuals | 1 |
@@ -44,6 +44,7 @@
// | CompositionVisualSurface | - |
// ------------------------------------
using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -55,13 +56,72 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie
// Frame rate: 60 fps
// Frame count: 180
// Duration: 3000.0 mS
- sealed partial class LoadingSprite
- : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
+ public sealed partial class LoadingSprite :
+ DependencyObject
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
, Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2
{
// Animation duration: 3.000 seconds.
internal const long c_durationTicks = 30000000;
+ // Theme property: Color_000000.
+ internal static readonly Color c_themeColor_000000 = Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
+
+ // Theme property: Color_FFFFFF.
+ internal static readonly Color c_themeColor_FFFFFF = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
+
+ CompositionPropertySet _themeProperties;
+
+ ///
+ /// Dependency property for Color_000000.
+ ///
+ public static readonly DependencyProperty Color_000000Property =
+ DependencyProperty.Register("Color_000000", typeof(Color), typeof(LoadingSprite),
+ new PropertyMetadata(Color.FromArgb(0xFF, 0x00, 0x00, 0x00), OnColor_000000Changed));
+
+ ///
+ /// Dependency property for Color_FFFFFF.
+ ///
+ public static readonly DependencyProperty Color_FFFFFFProperty =
+ DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(LoadingSprite),
+ new PropertyMetadata(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF), OnColor_FFFFFFChanged));
+
+ // Theme properties.
+ public Color Color_000000
+ {
+ get => (Color)GetValue(Color_000000Property);
+ set => SetValue(Color_000000Property, value);
+ }
+
+ public Color Color_FFFFFF
+ {
+ get => (Color)GetValue(Color_FFFFFFProperty);
+ set => SetValue(Color_FFFFFFProperty, value);
+ }
+
+ static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A);
+
+ static void OnColor_000000Changed(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ {
+ ((LoadingSprite)d)._themeProperties?.InsertVector4("Color_000000", ColorAsVector4((Color)(Color)args.NewValue));
+ }
+
+ static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ {
+ ((LoadingSprite)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue));
+ }
+
+ CompositionPropertySet EnsureThemeProperties(Compositor compositor)
+ {
+ if (_themeProperties == null)
+ {
+ _themeProperties = compositor.CreatePropertySet();
+ _themeProperties.InsertVector4("Color_000000", ColorAsVector4((Color)Color_000000));
+ _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF));
+ }
+ return _themeProperties;
+ }
+
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
{
object ignored = null;
@@ -71,10 +131,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
{
diagnostics = null;
+ EnsureThemeProperties(compositor);
var res =
new LoadingSprite_AnimatedVisual(
- compositor
+ compositor,
+ _themeProperties
);
res.CreateAnimations();
return res;
@@ -118,6 +180,23 @@ public double FrameToProgress(double frameNumber)
///
public void SetColorProperty(string propertyName, Color value)
{
+ if (propertyName == "Color_000000")
+ {
+ Color_000000 = value;
+ }
+ else if (propertyName == "Color_FFFFFF")
+ {
+ Color_FFFFFF = value;
+ }
+ else
+ {
+ return;
+ }
+
+ if (_themeProperties != null)
+ {
+ _themeProperties.InsertVector4(propertyName, ColorAsVector4(value));
+ }
}
///
@@ -135,8 +214,10 @@ sealed partial class LoadingSprite_AnimatedVisual
const long c_durationTicks = 30000000;
readonly Compositor _c;
readonly ExpressionAnimation _reusableExpressionAnimation;
+ readonly CompositionPropertySet _themeProperties;
AnimationController _animationController_0;
- CompositionColorBrush _colorBrush_White;
+ CompositionColorBrush _themeColor_Color_000000;
+ CompositionColorBrush _themeColor_Color_FFFFFF;
CompositionContainerShape _containerShape_0;
CompositionContainerShape _containerShape_1;
CompositionContainerShape _containerShape_2;
@@ -150,9 +231,9 @@ sealed partial class LoadingSprite_AnimatedVisual
CubicBezierEasingFunction _cubicBezierEasingFunction_2;
CubicBezierEasingFunction _cubicBezierEasingFunction_3;
CubicBezierEasingFunction _cubicBezierEasingFunction_4;
- ScalarKeyFrameAnimation _scalarAnimation_0p85_to_1;
- ScalarKeyFrameAnimation _scalarAnimation_1_to_1_0;
- ScalarKeyFrameAnimation _scalarAnimation_1_to_1_1;
+ ScalarKeyFrameAnimation _scalarAnimation_0p2_to_0p2_0;
+ ScalarKeyFrameAnimation _scalarAnimation_0p2_to_0p2_1;
+ ScalarKeyFrameAnimation _scalarAnimation_0p17_to_0p2;
StepEasingFunction _holdThenStepEasingFunction;
StepEasingFunction _stepThenHoldEasingFunction;
@@ -211,16 +292,22 @@ AnimationController AnimationController_0()
// - - Layer aggregator
// ShapeGroup: Rectangle 1 Offset:<-2.5, -4>
- CompositionColorBrush ColorBrush_SemiTransparentBlack()
+ // Color bound to theme property value: Color_000000
+ CompositionColorBrush ThemeColor_Color_000000()
{
- return _c.CreateColorBrush(Color.FromArgb(0x4C, 0x00, 0x00, 0x00));
+ if (_themeColor_Color_000000 != null) { return _themeColor_Color_000000; }
+ var result = _themeColor_Color_000000 = _c.CreateColorBrush();
+ BindProperty(_themeColor_Color_000000, "Color", "ColorRGB(_theme.Color_000000.W*0.3,_theme.Color_000000.X,_theme.Color_000000.Y,_theme.Color_000000.Z)", "_theme", _themeProperties);
+ return result;
}
- CompositionColorBrush ColorBrush_White()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF()
{
- return (_colorBrush_White == null)
- ? _colorBrush_White = _c.CreateColorBrush(Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF))
- : _colorBrush_White;
+ if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; }
+ var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush();
+ BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties);
+ return result;
}
// Layer aggregator
@@ -229,7 +316,7 @@ CompositionContainerShape ContainerShape_0()
if (_containerShape_0 != null) { return _containerShape_0; }
var result = _containerShape_0 = _c.CreateContainerShape();
result.CenterPoint = new Vector2(-2.5F, -4F);
- result.Offset = new Vector2(322.5F, 324F);
+ result.Offset = new Vector2(66.5F, 68F);
// ShapeGroup: Rectangle 1 Offset:<-2.5, -4>
result.Shapes.Add(SpriteShape_0());
return result;
@@ -241,7 +328,7 @@ CompositionContainerShape ContainerShape_1()
if (_containerShape_1 != null) { return _containerShape_1; }
var result = _containerShape_1 = _c.CreateContainerShape();
result.CenterPoint = new Vector2(15.75F, 4.75F);
- result.Offset = new Vector2(304.25F, 315.25F);
+ result.Offset = new Vector2(48.25F, 59.25F);
// ShapeGroup: Ellipse 1 Offset:<15.75, 4.75>
result.Shapes.Add(SpriteShape_1());
return result;
@@ -265,7 +352,7 @@ CompositionContainerShape ContainerShape_3()
if (_containerShape_3 != null) { return _containerShape_3; }
var result = _containerShape_3 = _c.CreateContainerShape();
result.CenterPoint = new Vector2(15.75F, 4.75F);
- result.Offset = new Vector2(304.25F, 315.25F);
+ result.Offset = new Vector2(48.25F, 59.25F);
// ShapeGroup: Ellipse 1 Offset:<15.75, 4.75>
result.Shapes.Add(SpriteShape_2());
return result;
@@ -319,7 +406,7 @@ CompositionSpriteShape SpriteShape_0()
{
// Offset:<-2.5, -4>
var geometry = RoundedRectangle_291();
- var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, -2.5F, -4F), ColorBrush_SemiTransparentBlack());;
+ var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, -2.5F, -4F), ThemeColor_Color_000000());;
return result;
}
@@ -329,7 +416,7 @@ CompositionSpriteShape SpriteShape_1()
{
// Offset:<15.75, 4.75>
var result = CreateSpriteShape(Ellipse_84p25_0(), new Matrix3x2(1F, 0F, 0F, 1F, 15.75F, 4.75F));;
- result.StrokeBrush = ColorBrush_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -344,7 +431,7 @@ CompositionSpriteShape SpriteShape_2()
{
// Offset:<15.75, 4.75>
var result = CreateSpriteShape(Ellipse_84p25_1(), new Matrix3x2(1F, 0F, 0F, 1F, 15.75F, 4.75F));;
- result.StrokeBrush = ColorBrush_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -455,47 +542,47 @@ ScalarKeyFrameAnimation RoundnessScalarAnimation_25_to_25()
}
// Scale
- ScalarKeyFrameAnimation ScalarAnimation_0p85_to_1()
+ ScalarKeyFrameAnimation ScalarAnimation_0p2_to_0p2_0()
{
// Frame 0.
- if (_scalarAnimation_0p85_to_1 != null) { return _scalarAnimation_0p85_to_1; }
- var result = _scalarAnimation_0p85_to_1 = CreateScalarKeyFrameAnimation(0F, 0.850000024F, StepThenHoldEasingFunction());
- // Frame 100.
- result.InsertKeyFrame(0.555555582F, 0.850000024F, HoldThenStepEasingFunction());
- // Frame 120.
- result.InsertKeyFrame(0.666666687F, 1F, CubicBezierEasingFunction_0());
+ if (_scalarAnimation_0p2_to_0p2_0 != null) { return _scalarAnimation_0p2_to_0p2_0; }
+ var result = _scalarAnimation_0p2_to_0p2_0 = CreateScalarKeyFrameAnimation(0F, 0.200000003F, StepThenHoldEasingFunction());
+ // Frame 10.
+ result.InsertKeyFrame(0.055555556F, 0.200000003F, HoldThenStepEasingFunction());
+ // Frame 30.
+ result.InsertKeyFrame(0.166666672F, 0.150000006F, CubicBezierEasingFunction_0());
+ // Frame 90.
+ result.InsertKeyFrame(0.5F, 0.150000006F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.666999996F, 1F)));
+ // Frame 110.
+ result.InsertKeyFrame(0.611111104F, 0.200000003F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.666999996F, 1F)));
return result;
}
// Scale
- ScalarKeyFrameAnimation ScalarAnimation_1_to_1_0()
+ ScalarKeyFrameAnimation ScalarAnimation_0p2_to_0p2_1()
{
// Frame 0.
- if (_scalarAnimation_1_to_1_0 != null) { return _scalarAnimation_1_to_1_0; }
- var result = _scalarAnimation_1_to_1_0 = CreateScalarKeyFrameAnimation(0F, 1F, StepThenHoldEasingFunction());
- // Frame 10.
- result.InsertKeyFrame(0.055555556F, 1F, HoldThenStepEasingFunction());
- // Frame 30.
- result.InsertKeyFrame(0.166666672F, 0.75F, CubicBezierEasingFunction_0());
+ if (_scalarAnimation_0p2_to_0p2_1 != null) { return _scalarAnimation_0p2_to_0p2_1; }
+ var result = _scalarAnimation_0p2_to_0p2_1 = CreateScalarKeyFrameAnimation(0F, 0.200000003F, HoldThenStepEasingFunction());
+ // Frame 20.
+ result.InsertKeyFrame(0.111111112F, 0.170000002F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.833000004F, 0.833000004F)));
// Frame 90.
- result.InsertKeyFrame(0.5F, 0.75F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.666999996F, 1F)));
+ result.InsertKeyFrame(0.5F, 0.170000002F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.460000008F, 1F)));
// Frame 110.
- result.InsertKeyFrame(0.611111104F, 1F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.666999996F, 1F)));
+ result.InsertKeyFrame(0.611111104F, 0.200000003F, CubicBezierEasingFunction_0());
return result;
}
// Scale
- ScalarKeyFrameAnimation ScalarAnimation_1_to_1_1()
+ ScalarKeyFrameAnimation ScalarAnimation_0p17_to_0p2()
{
// Frame 0.
- if (_scalarAnimation_1_to_1_1 != null) { return _scalarAnimation_1_to_1_1; }
- var result = _scalarAnimation_1_to_1_1 = CreateScalarKeyFrameAnimation(0F, 1F, HoldThenStepEasingFunction());
- // Frame 20.
- result.InsertKeyFrame(0.111111112F, 0.850000024F, _c.CreateCubicBezierEasingFunction(new Vector2(0.333000004F, 0F), new Vector2(0.833000004F, 0.833000004F)));
- // Frame 90.
- result.InsertKeyFrame(0.5F, 0.850000024F, _c.CreateCubicBezierEasingFunction(new Vector2(0.166999996F, 0F), new Vector2(0.460000008F, 1F)));
- // Frame 110.
- result.InsertKeyFrame(0.611111104F, 1F, CubicBezierEasingFunction_0());
+ if (_scalarAnimation_0p17_to_0p2 != null) { return _scalarAnimation_0p17_to_0p2; }
+ var result = _scalarAnimation_0p17_to_0p2 = CreateScalarKeyFrameAnimation(0F, 0.170000002F, StepThenHoldEasingFunction());
+ // Frame 100.
+ result.InsertKeyFrame(0.555555582F, 0.170000002F, HoldThenStepEasingFunction());
+ // Frame 120.
+ result.InsertKeyFrame(0.666666687F, 0.200000003F, CubicBezierEasingFunction_0());
return result;
}
@@ -587,7 +674,7 @@ ScalarKeyFrameAnimation TStartScalarAnimation_0_to_0p5_1()
ShapeVisual ShapeVisual_0()
{
var result = _c.CreateShapeVisual();
- result.Size = new Vector2(640F, 640F);
+ result.Size = new Vector2(128F, 128F);
var shapes = result.Shapes;
shapes.Add(ContainerShape_0());
shapes.Add(ContainerShape_1());
@@ -624,31 +711,33 @@ Vector2KeyFrameAnimation ShapeVisibilityAnimation()
}
internal LoadingSprite_AnimatedVisual(
- Compositor compositor
+ Compositor compositor,
+ CompositionPropertySet themeProperties
)
{
_c = compositor;
+ _themeProperties = themeProperties;
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
Root();
}
public Visual RootVisual => _root;
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
- public Vector2 Size => new Vector2(640F, 640F);
+ public Vector2 Size => new Vector2(128F, 128F);
void IDisposable.Dispose() => _root?.Dispose();
public void CreateAnimations()
{
_containerShape_0.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_45_to_135(), AnimationController_0());
- _containerShape_0.StartAnimation("Scale.X", ScalarAnimation_1_to_1_0(), AnimationController_0());
- _containerShape_0.StartAnimation("Scale.Y", ScalarAnimation_1_to_1_0(), AnimationController_0());
+ _containerShape_0.StartAnimation("Scale.X", ScalarAnimation_0p2_to_0p2_0(), AnimationController_0());
+ _containerShape_0.StartAnimation("Scale.Y", ScalarAnimation_0p2_to_0p2_0(), AnimationController_0());
_containerShape_1.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_180_to_900_0(), AnimationController_0());
- _containerShape_1.StartAnimation("Scale.X", ScalarAnimation_1_to_1_1(), AnimationController_0());
- _containerShape_1.StartAnimation("Scale.Y", ScalarAnimation_1_to_1_1(), AnimationController_0());
+ _containerShape_1.StartAnimation("Scale.X", ScalarAnimation_0p2_to_0p2_1(), AnimationController_0());
+ _containerShape_1.StartAnimation("Scale.Y", ScalarAnimation_0p2_to_0p2_1(), AnimationController_0());
_containerShape_2.StartAnimation("Scale", ShapeVisibilityAnimation(), AnimationController_0());
_containerShape_3.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_180_to_900_1(), AnimationController_0());
- _containerShape_3.StartAnimation("Scale.X", ScalarAnimation_0p85_to_1(), AnimationController_0());
- _containerShape_3.StartAnimation("Scale.Y", ScalarAnimation_0p85_to_1(), AnimationController_0());
+ _containerShape_3.StartAnimation("Scale.X", ScalarAnimation_0p17_to_0p2(), AnimationController_0());
+ _containerShape_3.StartAnimation("Scale.Y", ScalarAnimation_0p17_to_0p2(), AnimationController_0());
_ellipse_84p25_0.StartAnimation("TStart", TStartScalarAnimation_0_to_0p5_0(), AnimationController_0());
_ellipse_84p25_0.StartAnimation("TEnd", TEndScalarAnimation_0_to_0p5_0(), AnimationController_0());
_ellipse_84p25_0.StartAnimation("TrimOffset", TrimOffsetScalarAnimation_0_to_0p5_0(), AnimationController_0());
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json
new file mode 100644
index 000000000..066b5ce05
--- /dev/null
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.json
@@ -0,0 +1 @@
+{"v":"5.12.2","fr":60,"ip":0,"op":180,"w":128,"h":128,"nm":"LoadingSprite","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":90,"s":[180]},{"t":180,"s":[900]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[15.75,4.75,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":100,"s":[17,17,100]},{"t":120,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[168.5,168.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[15.75,4.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[50]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":150,"s":[50]},{"t":180,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[0]},{"t":180,"s":[50]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":120,"s":[0]},{"t":150,"s":[180]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":90,"op":271,"st":90,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[180]},{"t":90,"s":[900]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[15.75,4.75,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[20,20,100]},{"i":{"x":[0.46,0.46,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":20,"s":[17,17,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":90,"s":[17,17,100]},{"t":110,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[168.5,168.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[15.75,4.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[50]},{"t":90,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"t":90,"s":[50]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"t":60,"s":[180]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":181,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[45]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[90]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[90]},{"t":150,"s":[135]}],"ix":10},"p":{"a":0,"k":[64,64,0],"ix":2,"l":2},"a":{"a":0,"k":[-2.5,-4,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[20,20,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":30,"s":[15,15,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":90,"s":[15,15,100]},{"t":110,"s":[20,20,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[291,291],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[25]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[125]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[125]},{"t":150,"s":[25]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-2.5,-4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":182,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie
deleted file mode 100644
index 357515fa6..000000000
Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/LoadingSprite.lottie and /dev/null differ
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs
index 8478138ac..fdbcf99b2 100644
--- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.cs
@@ -3,13 +3,13 @@
// This code was generated by a tool.
//
// LottieGen version:
-// 8.0.280225.1+7cd366a738
+// 8.2.250604.1+b02a3ee244
//
// Command:
-// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile StartGameIcon.lottie
+// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile StartGameIcon.json
//
// Input file:
-// StartGameIcon.lottie (1259 bytes created 0:25+07:00 Jun 2 2024)
+// StartGameIcon.json (8234 bytes created 16:59+07:00 Jan 4 2026)
//
// LottieGen source:
// http://aka.ms/Lottie
@@ -21,16 +21,16 @@
// ____________________________________
// | Object stats | Count |
// |__________________________|_______|
-// | All CompositionObjects | 70 |
+// | All CompositionObjects | 77 |
// |--------------------------+-------|
-// | Expression animators | 9 |
+// | Expression animators | 12 |
// | KeyFrame animators | 6 |
-// | Reference parameters | 9 |
-// | Expression operations | 6 |
+// | Reference parameters | 15 |
+// | Expression operations | 18 |
// |--------------------------+-------|
// | Animated brushes | 3 |
// | Animated gradient stops | - |
-// | ExpressionAnimations | 9 |
+// | ExpressionAnimations | 12 |
// | PathKeyFrameAnimations | - |
// |--------------------------+-------|
// | ContainerVisuals | 1 |
@@ -44,6 +44,8 @@
// | CompositionVisualSurface | - |
// ------------------------------------
using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -55,13 +57,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie
// Frame rate: 60 fps
// Frame count: 40
// Duration: 666.7 mS
- sealed partial class StartGameIcon
- : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
+ public sealed partial class StartGameIcon
+ : BindableThemeChangeAnimation
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
, Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2
{
+ protected override void OnForegroundChanged(Brush brush)
+ {
+ if (brush is SolidColorBrush colorBrush)
+ {
+ Color_FFFFFF = colorBrush.Color;
+ return;
+ }
+
+ if (brush is AcrylicBrush acrylicBrush)
+ {
+ Color_FFFFFF = acrylicBrush.TintColor;
+ return;
+ }
+ }
+
+ private static Color GetForegroundColor(bool isLightTheme) =>
+ isLightTheme
+ ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00)
+ : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
+
// Animation duration: 0.667 seconds.
internal const long c_durationTicks = 6666666;
+ CompositionPropertySet _themeProperties;
+
+ ///
+ /// Dependency property for Color_FFFFFF.
+ ///
+ public static readonly DependencyProperty Color_FFFFFFProperty =
+ DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(StartGameIcon),
+ new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged));
+
+ // Theme properties.
+ public Color Color_FFFFFF
+ {
+ get => (Color)GetValue(Color_FFFFFFProperty);
+ set => SetValue(Color_FFFFFFProperty, value);
+ }
+
+ static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A);
+
+ static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ {
+ ((StartGameIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue));
+ }
+
+ CompositionPropertySet EnsureThemeProperties(Compositor compositor)
+ {
+ if (_themeProperties == null)
+ {
+ _themeProperties = compositor.CreatePropertySet();
+ _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF));
+ }
+ return _themeProperties;
+ }
+
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
{
object ignored = null;
@@ -71,10 +127,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
{
diagnostics = null;
+ EnsureThemeProperties(compositor);
var res =
new StartGameIcon_AnimatedVisual(
- compositor
+ compositor,
+ _themeProperties
);
res.CreateAnimations();
return res;
@@ -118,6 +176,19 @@ public double FrameToProgress(double frameNumber)
///
public void SetColorProperty(string propertyName, Color value)
{
+ if (propertyName == "Color_FFFFFF")
+ {
+ Color_FFFFFF = value;
+ }
+ else
+ {
+ return;
+ }
+
+ if (_themeProperties != null)
+ {
+ _themeProperties.InsertVector4(propertyName, ColorAsVector4(value));
+ }
}
///
@@ -133,19 +204,18 @@ sealed partial class StartGameIcon_AnimatedVisual
, Microsoft.UI.Xaml.Controls.IAnimatedVisual2
{
const long c_durationTicks = 6666666;
- readonly Color _color = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
- readonly Color _colorTransparent = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0x00, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0x00, 0x00, 0x00, 0x00);
readonly Compositor _c;
readonly ExpressionAnimation _reusableExpressionAnimation;
+ readonly CompositionPropertySet _themeProperties;
AnimationController _animationController_0;
AnimationController _animationController_1;
AnimationController _animationController_2;
AnimationController _animationController_3;
AnimationController _animationController_4;
AnimationController _animationController_5;
- CompositionColorBrush _animatedColorBrush_TransparentWhite_to_White;
- CompositionColorBrush _animatedColorBrush_White_to_TransparentWhite;
- CompositionColorBrush _animatedColorBrush_White_to_White;
+ CompositionColorBrush _themeColor_Color_FFFFFF_0;
+ CompositionColorBrush _themeColor_Color_FFFFFF_1;
+ CompositionColorBrush _themeColor_Color_FFFFFF_2;
CompositionContainerShape _containerShape_0;
CompositionContainerShape _containerShape_1;
CompositionContainerShape _containerShape_2;
@@ -153,7 +223,7 @@ sealed partial class StartGameIcon_AnimatedVisual
ContainerVisual _root;
CubicBezierEasingFunction _cubicBezierEasingFunction_0;
CubicBezierEasingFunction _cubicBezierEasingFunction_1;
- ScalarKeyFrameAnimation _positionXScalarAnimation_m92_to_993;
+ ScalarKeyFrameAnimation _positionXScalarAnimation_m11p5_to_124p125;
StepEasingFunction _holdThenStepEasingFunction;
void BindProperty(
@@ -169,13 +239,20 @@ void BindProperty(
target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation);
}
- ColorKeyFrameAnimation CreateColorKeyFrameAnimation(float initialProgress, Color initialValue, CompositionEasingFunction initialEasingFunction)
+ void BindProperty2(
+ CompositionObject target,
+ string animatedPropertyName,
+ string expression,
+ string referenceParameterName0,
+ CompositionObject referencedObject0,
+ string referenceParameterName1,
+ CompositionObject referencedObject1)
{
- var result = _c.CreateColorKeyFrameAnimation();
- result.Duration = TimeSpan.FromTicks(c_durationTicks);
- result.InterpolationColorSpace = CompositionColorSpace.Rgb;
- result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
- return result;
+ _reusableExpressionAnimation.ClearAllParameters();
+ _reusableExpressionAnimation.Expression = expression;
+ _reusableExpressionAnimation.SetReferenceParameter(referenceParameterName0, referencedObject0);
+ _reusableExpressionAnimation.SetReferenceParameter(referenceParameterName1, referencedObject1);
+ target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation);
}
ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(float initialProgress, float initialValue, CompositionEasingFunction initialEasingFunction)
@@ -193,7 +270,6 @@ CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2
return result;
}
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
AnimationController AnimationController_0()
{
if (_animationController_0 != null) { return _animationController_0; }
@@ -212,7 +288,6 @@ AnimationController AnimationController_1()
return result;
}
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
AnimationController AnimationController_2()
{
if (_animationController_2 != null) { return _animationController_2; }
@@ -231,7 +306,6 @@ AnimationController AnimationController_3()
return result;
}
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
AnimationController AnimationController_4()
{
if (_animationController_4 != null) { return _animationController_4; }
@@ -250,69 +324,39 @@ AnimationController AnimationController_5()
return result;
}
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
- // Color
- ColorKeyFrameAnimation ColorAnimation_TransparentWhite_to_White()
- {
- // Frame 0.
- var result = CreateColorKeyFrameAnimation(0F, _colorTransparent, HoldThenStepEasingFunction());
- // Frame 8.91.
- // White
- result.InsertKeyFrame(0.222662598F, _color, CubicBezierEasingFunction_0());
- // Frame 40.
- // White
- result.InsertKeyFrame(1F, _color, CubicBezierEasingFunction_1());
- return result;
- }
-
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
- // Color
- ColorKeyFrameAnimation ColorAnimation_White_to_TransparentWhite()
- {
- // Frame 0.
- var result = CreateColorKeyFrameAnimation(0F, _color, CubicBezierEasingFunction_0());
- // Frame 27.93.
- // White
- result.InsertKeyFrame(0.698220015F, _color, CubicBezierEasingFunction_1());
- // Frame 40.
- // TransparentWhite
- result.InsertKeyFrame(0.99998045F, _colorTransparent, CubicBezierEasingFunction_0());
- return result;
- }
-
- // - ShapeGroup: Rectangle 1 Offset:<30, 198>
- // Color
- ColorKeyFrameAnimation ColorAnimation_White_to_White()
- {
- // Frame 0.
- var result = CreateColorKeyFrameAnimation(0F, _color, CubicBezierEasingFunction_0());
- // Frame 40.
- // White
- result.InsertKeyFrame(1F, _color, CubicBezierEasingFunction_1());
- return result;
- }
-
// ShapeGroup: Rectangle 1 Offset:<30, 198>
- CompositionColorBrush AnimatedColorBrush_TransparentWhite_to_White()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF_0()
{
- if (_animatedColorBrush_TransparentWhite_to_White != null) { return _animatedColorBrush_TransparentWhite_to_White; }
- var result = _animatedColorBrush_TransparentWhite_to_White = _c.CreateColorBrush();
+ if (_themeColor_Color_FFFFFF_0 != null) { return _themeColor_Color_FFFFFF_0; }
+ var result = _themeColor_Color_FFFFFF_0 = _c.CreateColorBrush();
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("Opacity0", 1F);
+ BindProperty2(_themeColor_Color_FFFFFF_0, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet);
return result;
}
// ShapeGroup: Rectangle 1 Offset:<30, 198>
- CompositionColorBrush AnimatedColorBrush_White_to_TransparentWhite()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF_1()
{
- if (_animatedColorBrush_White_to_TransparentWhite != null) { return _animatedColorBrush_White_to_TransparentWhite; }
- var result = _animatedColorBrush_White_to_TransparentWhite = _c.CreateColorBrush();
+ if (_themeColor_Color_FFFFFF_1 != null) { return _themeColor_Color_FFFFFF_1; }
+ var result = _themeColor_Color_FFFFFF_1 = _c.CreateColorBrush();
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("Opacity0", 1F);
+ BindProperty2(_themeColor_Color_FFFFFF_1, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet);
return result;
}
// ShapeGroup: Rectangle 1 Offset:<30, 198>
- CompositionColorBrush AnimatedColorBrush_White_to_White()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF_2()
{
- if (_animatedColorBrush_White_to_White != null) { return _animatedColorBrush_White_to_White; }
- var result = _animatedColorBrush_White_to_White = _c.CreateColorBrush();
+ if (_themeColor_Color_FFFFFF_2 != null) { return _themeColor_Color_FFFFFF_2; }
+ var result = _themeColor_Color_FFFFFF_2 = _c.CreateColorBrush();
+ var propertySet = result.Properties;
+ propertySet.InsertScalar("Opacity0", 0F);
+ BindProperty2(_themeColor_Color_FFFFFF_2, "Color", "ColorRGB(_theme.Color_FFFFFF.W*my.Opacity0,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties, "my", propertySet);
return result;
}
@@ -321,9 +365,10 @@ CompositionContainerShape ContainerShape_0()
if (_containerShape_0 != null) { return _containerShape_0; }
var result = _containerShape_0 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(-92F, 1024F));
+ propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F));
result.CenterPoint = new Vector2(30F, 198F);
result.RotationAngleInDegrees = 45F;
+ result.Scale = new Vector2(0.125F, 0.125F);
// ShapeGroup: Rectangle 1 Offset:<30, 198>
result.Shapes.Add(SpriteShape_0());
BindProperty(_containerShape_0, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_0);
@@ -335,9 +380,10 @@ CompositionContainerShape ContainerShape_1()
if (_containerShape_1 != null) { return _containerShape_1; }
var result = _containerShape_1 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(-92F, 1024F));
+ propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F));
result.CenterPoint = new Vector2(30F, 198F);
result.RotationAngleInDegrees = 45F;
+ result.Scale = new Vector2(0.125F, 0.125F);
// ShapeGroup: Rectangle 1 Offset:<30, 198>
result.Shapes.Add(SpriteShape_1());
BindProperty(_containerShape_1, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_1);
@@ -349,9 +395,10 @@ CompositionContainerShape ContainerShape_2()
if (_containerShape_2 != null) { return _containerShape_2; }
var result = _containerShape_2 = _c.CreateContainerShape();
var propertySet = result.Properties;
- propertySet.InsertVector2("Position", new Vector2(-92F, 1024F));
+ propertySet.InsertVector2("Position", new Vector2(-11.5F, 128F));
result.CenterPoint = new Vector2(30F, 198F);
result.RotationAngleInDegrees = 45F;
+ result.Scale = new Vector2(0.125F, 0.125F);
// ShapeGroup: Rectangle 1 Offset:<30, 198>
result.Shapes.Add(SpriteShape_2());
BindProperty(_containerShape_2, "Offset", "Vector2(my.Position.X-30,my.Position.Y-198)", "my", _containerShape_2);
@@ -376,7 +423,7 @@ CompositionSpriteShape SpriteShape_0()
{
// Offset:<30, 198>
var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));;
- result.StrokeBrush = AnimatedColorBrush_White_to_TransparentWhite();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF_0();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -390,7 +437,7 @@ CompositionSpriteShape SpriteShape_1()
{
// Offset:<30, 198>
var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));;
- result.StrokeBrush = AnimatedColorBrush_White_to_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF_1();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -404,7 +451,7 @@ CompositionSpriteShape SpriteShape_2()
{
// Offset:<30, 198>
var result = CreateSpriteShape(Rectangle_1036(), new Matrix3x2(1F, 0F, 0F, 1F, 30F, 198F));;
- result.StrokeBrush = AnimatedColorBrush_TransparentWhite_to_White();
+ result.StrokeBrush = ThemeColor_Color_FFFFFF_2();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -439,14 +486,48 @@ CubicBezierEasingFunction CubicBezierEasingFunction_1()
: _cubicBezierEasingFunction_1;
}
+ // Opacity0
+ ScalarKeyFrameAnimation Opacity0ScalarAnimation_0_to_1()
+ {
+ // Frame 0.
+ var result = CreateScalarKeyFrameAnimation(0F, 0F, HoldThenStepEasingFunction());
+ // Frame 8.91.
+ result.InsertKeyFrame(0.222662598F, 1F, CubicBezierEasingFunction_0());
+ // Frame 40.
+ result.InsertKeyFrame(1F, 1F, CubicBezierEasingFunction_1());
+ return result;
+ }
+
+ // Opacity0
+ ScalarKeyFrameAnimation Opacity0ScalarAnimation_1_to_0()
+ {
+ // Frame 0.
+ var result = CreateScalarKeyFrameAnimation(0F, 1F, CubicBezierEasingFunction_0());
+ // Frame 27.93.
+ result.InsertKeyFrame(0.698220015F, 1F, CubicBezierEasingFunction_1());
+ // Frame 40.
+ result.InsertKeyFrame(0.99998045F, 0F, CubicBezierEasingFunction_0());
+ return result;
+ }
+
+ // Opacity0
+ ScalarKeyFrameAnimation Opacity0ScalarAnimation_1_to_1()
+ {
+ // Frame 0.
+ var result = CreateScalarKeyFrameAnimation(0F, 1F, CubicBezierEasingFunction_0());
+ // Frame 40.
+ result.InsertKeyFrame(1F, 1F, CubicBezierEasingFunction_1());
+ return result;
+ }
+
// Position.X
- ScalarKeyFrameAnimation PositionXScalarAnimation_m92_to_993()
+ ScalarKeyFrameAnimation PositionXScalarAnimation_m11p5_to_124p125()
{
// Frame 0.
- if (_positionXScalarAnimation_m92_to_993 != null) { return _positionXScalarAnimation_m92_to_993; }
- var result = _positionXScalarAnimation_m92_to_993 = CreateScalarKeyFrameAnimation(0F, -92F, HoldThenStepEasingFunction());
+ if (_positionXScalarAnimation_m11p5_to_124p125 != null) { return _positionXScalarAnimation_m11p5_to_124p125; }
+ var result = _positionXScalarAnimation_m11p5_to_124p125 = CreateScalarKeyFrameAnimation(0F, -11.5F, HoldThenStepEasingFunction());
// Frame 40.
- result.InsertKeyFrame(1F, 993F, _c.CreateCubicBezierEasingFunction(new Vector2(0.47299999F, 0.0659999996F), new Vector2(0.521000028F, 1F)));
+ result.InsertKeyFrame(1F, 124.125F, _c.CreateCubicBezierEasingFunction(new Vector2(0.47299999F, 0.523999989F), new Vector2(0.521000028F, 1F)));
return result;
}
@@ -454,7 +535,7 @@ ScalarKeyFrameAnimation PositionXScalarAnimation_m92_to_993()
ShapeVisual ShapeVisual_0()
{
var result = _c.CreateShapeVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
var shapes = result.Shapes;
shapes.Add(ContainerShape_0());
shapes.Add(ContainerShape_1());
@@ -471,34 +552,36 @@ StepEasingFunction HoldThenStepEasingFunction()
}
internal StartGameIcon_AnimatedVisual(
- Compositor compositor
+ Compositor compositor,
+ CompositionPropertySet themeProperties
)
{
_c = compositor;
+ _themeProperties = themeProperties;
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
Root();
}
public Visual RootVisual => _root;
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
- public Vector2 Size => new Vector2(2048F, 2048F);
+ public Vector2 Size => new Vector2(256F, 256F);
void IDisposable.Dispose() => _root?.Dispose();
public void CreateAnimations()
{
- _animatedColorBrush_TransparentWhite_to_White.StartAnimation("Color", ColorAnimation_TransparentWhite_to_White(), AnimationController_4());
- _animatedColorBrush_White_to_TransparentWhite.StartAnimation("Color", ColorAnimation_White_to_TransparentWhite(), AnimationController_0());
- _animatedColorBrush_White_to_White.StartAnimation("Color", ColorAnimation_White_to_White(), AnimationController_2());
- _containerShape_0.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_1());
- _containerShape_1.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_3());
- _containerShape_2.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m92_to_993(), AnimationController_5());
+ _themeColor_Color_FFFFFF_0.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_1_to_0(), AnimationController_0());
+ _themeColor_Color_FFFFFF_1.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_1_to_1(), AnimationController_2());
+ _themeColor_Color_FFFFFF_2.Properties.StartAnimation("Opacity0", Opacity0ScalarAnimation_0_to_1(), AnimationController_4());
+ _containerShape_0.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_1());
+ _containerShape_1.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_3());
+ _containerShape_2.Properties.StartAnimation("Position.X", PositionXScalarAnimation_m11p5_to_124p125(), AnimationController_5());
}
public void DestroyAnimations()
{
- _animatedColorBrush_TransparentWhite_to_White.StopAnimation("Color");
- _animatedColorBrush_White_to_TransparentWhite.StopAnimation("Color");
- _animatedColorBrush_White_to_White.StopAnimation("Color");
+ _themeColor_Color_FFFFFF_0.Properties.StopAnimation("Opacity0");
+ _themeColor_Color_FFFFFF_1.Properties.StopAnimation("Opacity0");
+ _themeColor_Color_FFFFFF_2.Properties.StopAnimation("Opacity0");
_containerShape_0.Properties.StopAnimation("Position.X");
_containerShape_1.Properties.StopAnimation("Position.X");
_containerShape_2.Properties.StopAnimation("Position.X");
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json
new file mode 100644
index 000000000..90563bd90
--- /dev/null
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.json
@@ -0,0 +1 @@
+{"v":"5.12.2","fr":60,"ip":0,"op":40,"w":256,"h":256,"nm":"StartGameIcon","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":79,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":99,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168.822,"s":[100]},{"t":198.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":79,"s":[-11.5]},{"t":199,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":79,"s":[128]},{"t":99,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":79,"op":79.6060606060606,"st":79,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":129.822,"s":[100]},{"t":159.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":40,"s":[-11.5]},{"t":160,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":40,"s":[128]},{"t":60,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":40,"op":40.6060606060606,"st":40,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":89.822,"s":[100]},{"t":119.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":0,"s":[-11.5]},{"t":120,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[128]},{"t":20,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-40,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-20,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":49.822,"s":[100]},{"t":79.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":-40,"s":[-11.5]},{"t":80,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-40,"s":[128]},{"t":-20,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":-40,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-80,"s":[0]},{"i":{"x":[0.413],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":-60,"s":[100]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":9.822,"s":[100]},{"t":39.998046875,"s":[0]}],"ix":11},"r":{"a":0,"k":45,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.521],"y":[1]},"o":{"x":[0.473],"y":[0.524]},"t":-80,"s":[-11.5]},{"t":40,"s":[124.125]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-80,"s":[128]},{"t":-60,"s":[128]}],"ix":4}},"a":{"a":0,"k":[30,198,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[1036,1036],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tm","s":{"a":0,"k":37,"ix":1},"e":{"a":0,"k":63,"ix":2},"o":{"a":0,"k":180,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[30,198],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":-80,"ct":1,"bm":0}],"markers":[],"props":{}}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie
deleted file mode 100644
index 22323e1b1..000000000
Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/StartGameIcon.lottie and /dev/null differ
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs
index f41006052..13ecb8fde 100644
--- a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.cs
@@ -3,13 +3,13 @@
// This code was generated by a tool.
//
// LottieGen version:
-// 8.0.280225.1+7cd366a738
+// 8.2.250604.1+b02a3ee244
//
// Command:
-// LottieGen -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile UpdateIcon.lottie
+// LottieGen -GenerateColorBindings -GenerateDependencyObject -Language CSharp -Namespace CollapseLauncher.AnimatedVisuals.Lottie -Public -WinUIVersion 3.0 -InputFile UpdateIcon.json
//
// Input file:
-// UpdateIcon.lottie (1532 bytes created 20:12+07:00 Jun 2 2024)
+// UpdateIcon.json (5270 bytes created 16:59+07:00 Jan 4 2026)
//
// LottieGen source:
// http://aka.ms/Lottie
@@ -21,16 +21,16 @@
// ____________________________________
// | Object stats | Count |
// |__________________________|_______|
-// | All CompositionObjects | 42 |
+// | All CompositionObjects | 45 |
// |--------------------------+-------|
-// | Expression animators | 1 |
+// | Expression animators | 2 |
// | KeyFrame animators | 3 |
-// | Reference parameters | 1 |
-// | Expression operations | 0 |
+// | Reference parameters | 2 |
+// | Expression operations | 4 |
// |--------------------------+-------|
-// | Animated brushes | - |
+// | Animated brushes | 1 |
// | Animated gradient stops | - |
-// | ExpressionAnimations | 1 |
+// | ExpressionAnimations | 2 |
// | PathKeyFrameAnimations | - |
// |--------------------------+-------|
// | ContainerVisuals | 3 |
@@ -43,8 +43,11 @@
// | Gradient stops | - |
// | CompositionVisualSurface | - |
// ------------------------------------
+using Microsoft.Graphics;
using Microsoft.Graphics.Canvas.Geometry;
using Microsoft.UI.Composition;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Numerics;
@@ -56,13 +59,67 @@ namespace CollapseLauncher.AnimatedVisuals.Lottie
// Frame rate: 60 fps
// Frame count: 240
// Duration: 4000.0 mS
- sealed partial class UpdateIcon
- : Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
+ public sealed partial class UpdateIcon
+ : BindableThemeChangeAnimation
+ , Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
, Microsoft.UI.Xaml.Controls.IAnimatedVisualSource2
{
+ protected override void OnForegroundChanged(Brush brush)
+ {
+ if (brush is SolidColorBrush colorBrush)
+ {
+ Color_FFFFFF = colorBrush.Color;
+ return;
+ }
+
+ if (brush is AcrylicBrush acrylicBrush)
+ {
+ Color_FFFFFF = acrylicBrush.TintColor;
+ return;
+ }
+ }
+
+ private static Color GetForegroundColor(bool isLightTheme) =>
+ isLightTheme
+ ? Color.FromArgb(0xFF, 0x00, 0x00, 0x00)
+ : Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF);
+
// Animation duration: 4.000 seconds.
internal const long c_durationTicks = 40000000;
+ CompositionPropertySet _themeProperties;
+
+ ///
+ /// Dependency property for Color_FFFFFF.
+ ///
+ public static readonly DependencyProperty Color_FFFFFFProperty =
+ DependencyProperty.Register("Color_FFFFFF", typeof(Color), typeof(UpdateIcon),
+ new PropertyMetadata(GetForegroundColor(InnerLauncherConfig.IsAppThemeLight), OnColor_FFFFFFChanged));
+
+ // Theme properties.
+ public Color Color_FFFFFF
+ {
+ get => (Color)GetValue(Color_FFFFFFProperty);
+ set => SetValue(Color_FFFFFFProperty, value);
+ }
+
+ static Vector4 ColorAsVector4(Color color) => new Vector4(color.R, color.G, color.B, color.A);
+
+ static void OnColor_FFFFFFChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
+ {
+ ((UpdateIcon)d)._themeProperties?.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)(Color)args.NewValue));
+ }
+
+ CompositionPropertySet EnsureThemeProperties(Compositor compositor)
+ {
+ if (_themeProperties == null)
+ {
+ _themeProperties = compositor.CreatePropertySet();
+ _themeProperties.InsertVector4("Color_FFFFFF", ColorAsVector4((Color)Color_FFFFFF));
+ }
+ return _themeProperties;
+ }
+
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
{
object ignored = null;
@@ -72,10 +129,12 @@ public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compos
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
{
diagnostics = null;
+ EnsureThemeProperties(compositor);
var res =
new UpdateIcon_AnimatedVisual(
- compositor
+ compositor,
+ _themeProperties
);
res.CreateAnimations();
return res;
@@ -119,6 +178,19 @@ public double FrameToProgress(double frameNumber)
///
public void SetColorProperty(string propertyName, Color value)
{
+ if (propertyName == "Color_FFFFFF")
+ {
+ Color_FFFFFF = value;
+ }
+ else
+ {
+ return;
+ }
+
+ if (_themeProperties != null)
+ {
+ _themeProperties.InsertVector4(propertyName, ColorAsVector4(value));
+ }
}
///
@@ -134,11 +206,11 @@ sealed partial class UpdateIcon_AnimatedVisual
, Microsoft.UI.Xaml.Controls.IAnimatedVisual2
{
const long c_durationTicks = 40000000;
- readonly Color _color = InnerLauncherConfig.IsAppThemeLight ? Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF) : Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
readonly Compositor _c;
readonly ExpressionAnimation _reusableExpressionAnimation;
+ readonly CompositionPropertySet _themeProperties;
AnimationController _animationController_0;
- CompositionColorBrush _colorBrush_White;
+ CompositionColorBrush _themeColor_Color_FFFFFF;
CompositionPathGeometry _pathGeometry_2;
CompositionPathGeometry _pathGeometry_3;
ContainerVisual _containerVisual_0;
@@ -186,7 +258,7 @@ AnimationController AnimationController_0()
// - - - - - PreComp layer: UpdateIcon
// - - - Layer aggregator
- // - - Offset:<1543, 561>
+ // - - Scale:0.125,0.125, Offset:<192.875, 70.125>
CanvasGeometry Geometry_0()
{
CanvasGeometry result;
@@ -203,7 +275,7 @@ CanvasGeometry Geometry_0()
// - - - - - PreComp layer: UpdateIcon
// - - - Layer aggregator
- // - - Offset:<505.5, 1488>
+ // - - Scale:0.125,0.125, Offset:<63.188, 186>
CanvasGeometry Geometry_1()
{
CanvasGeometry result;
@@ -220,7 +292,7 @@ CanvasGeometry Geometry_1()
// - - - - - PreComp layer: UpdateIcon
// - - - Layer aggregator
- // - - Offset:<1024, 1024>
+ // - - Scale:0.125,0.125, Offset:<128, 128>
CanvasGeometry Geometry_2()
{
CanvasGeometry result;
@@ -241,7 +313,7 @@ CanvasGeometry Geometry_2()
// - - - - - PreComp layer: UpdateIcon
// - - - Layer aggregator
- // - - Offset:<1024, 1024>
+ // - - Scale:0.125,0.125, Offset:<128, 128>
CanvasGeometry Geometry_3()
{
CanvasGeometry result;
@@ -259,16 +331,18 @@ CanvasGeometry Geometry_3()
return result;
}
- CompositionColorBrush ColorBrush_White()
+ // Color bound to theme property value: Color_FFFFFF
+ CompositionColorBrush ThemeColor_Color_FFFFFF()
{
- return (_colorBrush_White == null)
- ? _colorBrush_White = _c.CreateColorBrush(_color)
- : _colorBrush_White;
+ if (_themeColor_Color_FFFFFF != null) { return _themeColor_Color_FFFFFF; }
+ var result = _themeColor_Color_FFFFFF = _c.CreateColorBrush();
+ BindProperty(_themeColor_Color_FFFFFF, "Color", "ColorRGB(_theme.Color_FFFFFF.W,_theme.Color_FFFFFF.X,_theme.Color_FFFFFF.Y,_theme.Color_FFFFFF.Z)", "_theme", _themeProperties);
+ return result;
}
// - - - PreComp layer: UpdateIcon
// - Layer aggregator
- // Offset:<1543, 561>
+ // Scale:0.125,0.125, Offset:<192.875, 70.125>
CompositionPathGeometry PathGeometry_0()
{
return _c.CreatePathGeometry(new CompositionPath(Geometry_0()));
@@ -276,7 +350,7 @@ CompositionPathGeometry PathGeometry_0()
// - - - PreComp layer: UpdateIcon
// - Layer aggregator
- // Offset:<505.5, 1488>
+ // Scale:0.125,0.125, Offset:<63.188, 186>
CompositionPathGeometry PathGeometry_1()
{
return _c.CreatePathGeometry(new CompositionPath(Geometry_1()));
@@ -284,7 +358,7 @@ CompositionPathGeometry PathGeometry_1()
// - - - PreComp layer: UpdateIcon
// - Layer aggregator
- // Offset:<1024, 1024>
+ // Scale:0.125,0.125, Offset:<128, 128>
CompositionPathGeometry PathGeometry_2()
{
if (_pathGeometry_2 != null) { return _pathGeometry_2; }
@@ -294,7 +368,7 @@ CompositionPathGeometry PathGeometry_2()
// - - - PreComp layer: UpdateIcon
// - Layer aggregator
- // Offset:<1024, 1024>
+ // Scale:0.125,0.125, Offset:<128, 128>
CompositionPathGeometry PathGeometry_3()
{
if (_pathGeometry_3 != null) { return _pathGeometry_3; }
@@ -307,9 +381,9 @@ CompositionPathGeometry PathGeometry_3()
// Path 1
CompositionSpriteShape SpriteShape_0()
{
- // Offset:<1543, 561>
- var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(1F, 0F, 0F, 1F, 1543F, 561F));;
- result.StrokeBrush = ColorBrush_White();
+ // Offset:<192.875, 70.125>, Scale:<0.125, 0.125>
+ var result = CreateSpriteShape(PathGeometry_0(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 192.875F, 70.125F));;
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -323,9 +397,9 @@ CompositionSpriteShape SpriteShape_0()
// Path 1
CompositionSpriteShape SpriteShape_1()
{
- // Offset:<505.5, 1488>
- var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(1F, 0F, 0F, 1F, 505.5F, 1488F));;
- result.StrokeBrush = ColorBrush_White();
+ // Offset:<63.188, 186>, Scale:<0.125, 0.125>
+ var result = CreateSpriteShape(PathGeometry_1(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 63.1879997F, 186F));;
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -339,9 +413,9 @@ CompositionSpriteShape SpriteShape_1()
// Path 1
CompositionSpriteShape SpriteShape_2()
{
- // Offset:<1024, 1024>
- var result = CreateSpriteShape(PathGeometry_2(), new Matrix3x2(1F, 0F, 0F, 1F, 1024F, 1024F));;
- result.StrokeBrush = ColorBrush_White();
+ // Offset:<128, 128>, Scale:<0.125, 0.125>
+ var result = CreateSpriteShape(PathGeometry_2(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 128F, 128F));;
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -356,9 +430,9 @@ CompositionSpriteShape SpriteShape_2()
// Path 1
CompositionSpriteShape SpriteShape_3()
{
- // Offset:<1024, 1024>
- var result = CreateSpriteShape(PathGeometry_3(), new Matrix3x2(1F, 0F, 0F, 1F, 1024F, 1024F));;
- result.StrokeBrush = ColorBrush_White();
+ // Offset:<128, 128>, Scale:<0.125, 0.125>
+ var result = CreateSpriteShape(PathGeometry_3(), new Matrix3x2(0.125F, 0F, 0F, 0.125F, 128F, 128F));;
+ result.StrokeBrush = ThemeColor_Color_FFFFFF();
result.StrokeDashCap = CompositionStrokeCap.Round;
result.StrokeStartCap = CompositionStrokeCap.Round;
result.StrokeEndCap = CompositionStrokeCap.Round;
@@ -373,8 +447,7 @@ ContainerVisual ContainerVisual_0()
{
if (_containerVisual_0 != null) { return _containerVisual_0; }
var result = _containerVisual_0 = _c.CreateContainerVisual();
- result.CenterPoint = new Vector3(1024F, 1024F, 0F);
- result.Offset = new Vector3(176F, 176F, 0F);
+ result.CenterPoint = new Vector3(128F, 128F, 0F);
result.Scale = new Vector3(1F, 1F, 0F);
result.Children.InsertAtTop(ContainerVisual_1());
return result;
@@ -385,7 +458,7 @@ ContainerVisual ContainerVisual_1()
{
var result = _c.CreateContainerVisual();
result.Clip = InsetClip_0();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
// Layer aggregator
result.Children.InsertAtTop(ShapeVisual_0());
return result;
@@ -448,15 +521,15 @@ ScalarKeyFrameAnimation TrimStartScalarAnimation_0_to_0()
ShapeVisual ShapeVisual_0()
{
var result = _c.CreateShapeVisual();
- result.Size = new Vector2(2048F, 2048F);
+ result.Size = new Vector2(256F, 256F);
var shapes = result.Shapes;
- // Offset:<1543, 561>
+ // Scale:0.125,0.125, Offset:<192.875, 70.125>
shapes.Add(SpriteShape_0());
- // Offset:<505.5, 1488>
+ // Scale:0.125,0.125, Offset:<63.188, 186>
shapes.Add(SpriteShape_1());
- // Offset:<1024, 1024>
+ // Scale:0.125,0.125, Offset:<128, 128>
shapes.Add(SpriteShape_2());
- // Offset:<1024, 1024>
+ // Scale:0.125,0.125, Offset:<128, 128>
shapes.Add(SpriteShape_3());
return result;
}
@@ -470,17 +543,19 @@ StepEasingFunction HoldThenStepEasingFunction()
}
internal UpdateIcon_AnimatedVisual(
- Compositor compositor
+ Compositor compositor,
+ CompositionPropertySet themeProperties
)
{
_c = compositor;
+ _themeProperties = themeProperties;
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
Root();
}
public Visual RootVisual => _root;
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
- public Vector2 Size => new Vector2(2400F, 2400F);
+ public Vector2 Size => new Vector2(256F, 256F);
void IDisposable.Dispose() => _root?.Dispose();
public void CreateAnimations()
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json
new file mode 100644
index 000000000..e57b78cd8
--- /dev/null
+++ b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.json
@@ -0,0 +1 @@
+{"v":"5.12.2","fr":60,"ip":0,"op":240,"w":256,"h":256,"nm":"UpdateIconMasterComp","ddd":0,"assets":[{"id":"comp_0","nm":"UpdateIcon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-14.666,56.266],[-31.132,53.758],[-105.895,61.521],[-128.947,-0.321],[-103.436,-60.448],[-61.24,-107.197]],"o":[[16.051,-61.58],[61.391,-106.008],[103.968,-60.401],[128.408,0.32],[106.564,62.276],[14.259,24.959]],"v":[[-679.411,-177.885],[-608.024,-351.501],[-352.405,-607.463],[1.406,-702.002],[353.538,-606.465],[610.018,-347.459]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"t":80,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[11.129,-42.34],[31.671,-54.12],[104.889,-60.982],[129.029,0.321],[102.932,59.646],[61.568,105.903],[11.121,25.826]],"o":[[-16.328,62.123],[-61.282,104.72],[-104.012,60.472],[-127.485,-0.317],[-106.028,-61.44],[-14.021,-24.117],[-3.58,-8.314]],"v":[[679.076,179.264],[606.447,354.255],[352.629,607.348],[-1.38,702.002],[-351.277,607.765],[-607.341,352.059],[-645.109,277.089]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[50]},{"t":80,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[63.188,186,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-244.242,122.011],[-123.464,-207.693],[206.416,-86.902]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[192.875,70.125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[12.5,12.5,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[244.229,-121.905],[123.49,207.693],[-206.2,86.799]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":128,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":242,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"UpdateIcon","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.024],"y":[1]},"o":{"x":[0.158],"y":[0]},"t":30,"s":[-65]},{"t":220,"s":[2160]}],"ix":10},"p":{"a":0,"k":[128,128,0],"ix":2,"l":2},"a":{"a":0,"k":[128,128,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":256,"h":256,"ip":0,"op":240,"st":0,"bm":0}],"markers":[],"props":{}}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie b/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie
deleted file mode 100644
index 23168ac30..000000000
Binary files a/CollapseLauncher/Classes/AnimatedVisuals/Lottie/UpdateIcon.lottie and /dev/null differ
diff --git a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
index 5f891f117..fcaf47cec 100644
--- a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
+++ b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
@@ -304,50 +304,6 @@ public class NotificationInvokerProp
}
#endregion
- #region BackgroundRegion
- internal static class BackgroundImgChanger
- {
- private static readonly BackgroundImgChangerInvoker Invoker = new();
- public static void ChangeBackground(string imgPath, Action actionAfterLoaded,
- bool isCustom = true, bool isForceRecreateCache = false, bool isRequestInit = false)
- {
- Invoker!.ChangeBackground(imgPath, actionAfterLoaded, isCustom, isForceRecreateCache, isRequestInit);
- }
- public static void ToggleBackground(bool hide) => Invoker!.ToggleBackground(hide);
- }
-
- internal class BackgroundImgChangerInvoker
- {
- public static event EventHandler ImgEvent;
- public static event EventHandler IsImageHide;
-
- public void ChangeBackground(string imgPath, Action actionAfterLoaded,
- bool isCustom, bool isForceRecreateCache = false, bool isRequestInit = false)
- {
- ImgEvent?.Invoke(this, new BackgroundImgProperty(imgPath, isCustom, isForceRecreateCache, isRequestInit, actionAfterLoaded));
- }
-
- public void ToggleBackground(bool hide) => IsImageHide?.Invoke(this, hide);
- }
-
- internal class BackgroundImgProperty
- {
- internal BackgroundImgProperty(string imgPath, bool isCustom, bool isForceRecreateCache, bool isRequestInit, Action actionAfterLoaded)
- {
- ImgPath = imgPath;
- IsCustom = isCustom;
- IsForceRecreateCache = isForceRecreateCache;
- IsRequestInit = isRequestInit;
- ActionAfterLoaded = actionAfterLoaded;
- }
-
- public Action ActionAfterLoaded { get; }
- public bool IsRequestInit { get; }
- public bool IsForceRecreateCache { get; }
- public string ImgPath { get; }
- public bool IsCustom { get; }
- }
- #endregion
#region SpawnWebView2Region
internal static class SpawnWebView2
{
diff --git a/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs b/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs
index 19e705f40..d35567fc8 100644
--- a/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs
+++ b/CollapseLauncher/Classes/Extension/DispatcherQueueExtensions.cs
@@ -1,11 +1,24 @@
using Microsoft.UI.Dispatching;
using System;
+using System.Threading.Tasks;
+#nullable enable
namespace CollapseLauncher.Extension
{
public static class DispatcherQueueExtensions
{
- public static bool HasThreadAccessSafe(this DispatcherQueue queue)
+ static DispatcherQueueExtensions()
+ {
+ CurrentDispatcherQueue ??= DispatcherQueue.GetForCurrentThread();
+ }
+
+ public static DispatcherQueue CurrentDispatcherQueue
+ {
+ get;
+ set;
+ }
+
+ public static bool HasThreadAccessSafe(this DispatcherQueue? queue)
{
if (queue == null) return false;
@@ -18,5 +31,31 @@ public static bool HasThreadAccessSafe(this DispatcherQueue queue)
return false; // Return false if an exception occurs
}
}
+
+ public static Task CreateObjectFromUIThread()
+ where T : new()
+ {
+ if (CurrentDispatcherQueue.HasThreadAccessSafe())
+ {
+ return Task.FromResult(new T());
+ }
+
+ TaskCompletionSource tcs = new();
+ Impl();
+
+ return tcs.Task;
+
+ void Impl()
+ {
+ try
+ {
+ CurrentDispatcherQueue.TryEnqueue(() => tcs.SetResult(new T()));
+ }
+ catch (Exception e)
+ {
+ tcs.SetException(e);
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs
new file mode 100644
index 000000000..b5acabe70
--- /dev/null
+++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetCursor.cs
@@ -0,0 +1,50 @@
+using Microsoft.UI.Input;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System;
+using System.Runtime.CompilerServices;
+
+#nullable enable
+#pragma warning disable IDE0130
+namespace CollapseLauncher.Extension;
+
+public static partial class UIElementExtensions
+{
+ public static readonly DependencyProperty CursorTypeProperty =
+ DependencyProperty.RegisterAttached("CursorType", typeof(InputSystemCursorShape),
+ typeof(UIElement), new PropertyMetadata(InputSystemCursorShape.Arrow));
+
+ public static InputSystemCursorShape GetCursorType(DependencyObject obj) => (InputSystemCursorShape)obj.GetValue(CursorTypeProperty);
+
+ public static void SetCursorType(DependencyObject obj, InputSystemCursorShape value)
+ {
+ InputSystemCursor? cursor = InputSystemCursor.Create(value);
+ if (cursor is null ||
+ obj is not UIElement asElement)
+ {
+ return;
+ }
+
+ asElement.SetCursor(cursor);
+ asElement.SetValue(CursorTypeProperty, value);
+ }
+
+ extension(Control source)
+ {
+ [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTemplateChild")]
+ private extern DependencyObject GetTemplateChildAccessor(string name);
+
+ internal T GetTemplateChild(string name)
+ where T : class
+ {
+ DependencyObject obj = source.GetTemplateChildAccessor(name);
+ if (obj is not T castObj)
+ {
+ throw new
+ InvalidCastException($"Cannot cast type to: {typeof(T).Name} as the object expects type: {obj.GetType().Name}");
+ }
+
+ return castObj;
+ }
+ }
+}
diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs
new file mode 100644
index 000000000..860ca02da
--- /dev/null
+++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.SetIsTranslationEnabled.cs
@@ -0,0 +1,21 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Hosting;
+
+#nullable enable
+#pragma warning disable IDE0130
+namespace CollapseLauncher.Extension;
+
+public static partial class UIElementExtensions
+{
+ public static readonly DependencyProperty IsTranslationEnabledProperty =
+ DependencyProperty.RegisterAttached("IsTranslationEnabled", typeof(bool),
+ typeof(UIElement), new PropertyMetadata(false));
+
+ public static bool GetIsTranslationEnabled(DependencyObject obj) => (bool)((UIElement)obj).GetValue(IsTranslationEnabledProperty);
+
+ public static void SetIsTranslationEnabled(DependencyObject obj, bool value)
+ {
+ ElementCompositionPreview.SetIsTranslationEnabled((UIElement)obj, value);
+ ((UIElement)obj).SetValue(IsTranslationEnabledProperty, value);
+ }
+}
diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs
index bd33a12e3..f045cc4cb 100644
--- a/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs
+++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.ThemeExtensions.cs
@@ -8,7 +8,7 @@
#nullable enable
namespace CollapseLauncher.Extension
{
- internal static partial class UIElementExtensions
+ public static partial class UIElementExtensions
{
private static string CurrentReversedThemeKey => InnerLauncherConfig.IsAppThemeLight ? "Dark" : "Light";
diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs
index 40a9d8432..efbeff7e4 100644
--- a/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs
+++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.UnsafeAccessorExtensions.cs
@@ -5,7 +5,7 @@
#nullable enable
namespace CollapseLauncher.Extension
{
- internal static partial class UIElementExtensions
+ public static partial class UIElementExtensions
{
///
/// Set the cursor for the element.
diff --git a/CollapseLauncher/Classes/Extension/UIElementExtensions.cs b/CollapseLauncher/Classes/Extension/UIElementExtensions.cs
index 08b471d43..57787320e 100644
--- a/CollapseLauncher/Classes/Extension/UIElementExtensions.cs
+++ b/CollapseLauncher/Classes/Extension/UIElementExtensions.cs
@@ -5,6 +5,7 @@
using Hi3Helper.CommunityToolkit.WinUI.Controls;
using Hi3Helper.SentryHelper;
using Microsoft.UI;
+using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
@@ -20,6 +21,8 @@
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using System.Xml.Linq;
using Windows.UI;
using Windows.UI.Text;
using WinRT;
@@ -36,7 +39,7 @@ internal class NavigationViewItemLocaleTextProperty
public string LocalePropertyName { get; init; }
}
- internal static partial class UIElementExtensions
+ public static partial class UIElementExtensions
{
#nullable enable
///
@@ -188,6 +191,22 @@ internal static void ApplyNavigationViewItemLocaleTextBindings(this NavigationVi
navViewControl.UpdateLayout();
}
+ internal static void BindProperty(this FrameworkElement element,
+ object? source,
+ string propertyName,
+ DependencyProperty dependencyProperty,
+ BindingMode bindingMode,
+ IValueConverter? converter = null)
+ {
+ element.SetBinding(dependencyProperty, new Binding
+ {
+ Mode = bindingMode,
+ Source = source,
+ Path = new PropertyPath(propertyName),
+ Converter = converter
+ });
+ }
+
internal static void BindProperty(
this T element,
DependencyProperty dependencyProperty,
@@ -237,13 +256,18 @@ internal static TButtonBase CreateButtonWithIcon(string text = null
string buttonStyle = "DefaultButtonStyle", double iconSize = 16d, double? textSize = null, CornerRadius? cornerRadius = null, FontWeight? textWeight = null)
where TButtonBase : ButtonBase, new()
{
- Grid contentPanel = CreateIconTextGrid(text, iconGlyph, iconFontFamily, iconSize, textSize, textWeight);
- TButtonBase buttonReturn = new TButtonBase();
+ return RunFunctionReturnFromUIThread(Impl);
- buttonReturn.CornerRadius = cornerRadius ?? AttachRoundedKindCornerRadius(buttonReturn);
- buttonReturn.Content = contentPanel;
- buttonReturn.Style = GetApplicationResource
+
\ No newline at end of file
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs
new file mode 100644
index 000000000..d60cce46a
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImageExtensions.cs
@@ -0,0 +1,390 @@
+using Hi3Helper.Win32.WinRT.WindowsStream;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media.Imaging;
+using PhotoSauce.MagicScaler;
+using PhotoSauce.MagicScaler.Transforms;
+using PhotoSauce.NativeCodecs.Libheif;
+using PhotoSauce.NativeCodecs.Libjxl;
+using PhotoSauce.NativeCodecs.Libwebp;
+using System;
+using System.IO;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Windows.Storage.Streams;
+
+// ReSharper disable SwitchStatementHandlesSomeKnownEnumValuesWithDefault
+// ReSharper disable ConvertIfStatementToSwitchStatement
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.LayeredBackgroundImage;
+
+internal static class LayeredBackgroundImageExtensions
+{
+ private static readonly HttpClient Client;
+
+ static LayeredBackgroundImageExtensions()
+ {
+ // Initialize support for MagicScaler's WebP decoding
+ CodecManager.Configure(InitializeMagicScalerCodecs);
+ Client = CreateHttpClient();
+ }
+
+ private static void InitializeMagicScalerCodecs(CodecCollection codecs)
+ {
+ codecs.UseWicCodecs(WicCodecPolicy.All);
+ codecs.UseLibwebp();
+ codecs.UseLibheif();
+ codecs.UseLibjxl();
+ }
+
+ private static HttpClient CreateHttpClient()
+ {
+ SocketsHttpHandler handler = new()
+ {
+ AllowAutoRedirect = true,
+ MaxConnectionsPerServer = Environment.ProcessorCount * 2
+ };
+ return new HttpClient(handler, false);
+ }
+
+ internal static async ValueTask LoadImageAsync(
+ this Image image,
+ Uri? sourceFromPath,
+ Stream? sourceFromStream,
+ LayeredBackgroundImage instance,
+ DependencyProperty useCacheProperty,
+ IPixelTransform? pixelTransform = null)
+ {
+ IMediaCacheHandler? cacheHandler = instance.MediaCacheHandler;
+ bool isDisposeStream = sourceFromStream == null;
+ bool forceUseInternalDecoder = false;
+
+ // Try get cached source from cache handler
+ if (cacheHandler != null)
+ {
+ object? source = sourceFromPath;
+ source ??= sourceFromStream;
+ MediaCacheResult cacheResult = await cacheHandler.LoadCachedSource(source);
+
+ forceUseInternalDecoder = cacheResult.ForceUseInternalDecoder;
+ isDisposeStream = cacheResult.DisposeStream;
+
+ if (cacheResult.CachedSource is Uri sourceAsPath)
+ {
+ sourceFromPath = sourceAsPath;
+ sourceFromStream = null;
+ }
+ else if (cacheResult.CachedSource is Stream sourceAsStream)
+ {
+ sourceFromPath = null;
+ sourceFromStream = sourceAsStream;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ try
+ {
+ if (sourceFromPath != null)
+ {
+ return await image.LoadImageFromUriPathSourceAsync(sourceFromPath,
+ forceUseInternalDecoder,
+ instance,
+ useCacheProperty,
+ pixelTransform);
+ }
+
+ if (sourceFromStream != null)
+ {
+ return await image.LoadImageFromStreamSourceAsync(sourceFromStream,
+ forceUseInternalDecoder,
+ instance,
+ useCacheProperty,
+ pixelTransform);
+ }
+
+ return false;
+ }
+ finally
+ {
+ if (isDisposeStream && sourceFromStream != null)
+ {
+ await sourceFromStream.DisposeAsync();
+ }
+ }
+ }
+
+ private static async ValueTask LoadImageFromUriPathSourceAsync(
+ this Image image,
+ Uri sourceFromPath,
+ bool forceUseInternalDecoder,
+ LayeredBackgroundImage instance,
+ DependencyProperty useCacheProperty,
+ IPixelTransform? pixelTransform = null)
+ {
+ string extension = Path.GetExtension(sourceFromPath.ToString());
+ bool isInternalFormat = LayeredBackgroundImage
+ .SupportedImageBitmapExtensionsLookup
+ .Contains(extension);
+ bool isSvgFormat = LayeredBackgroundImage
+ .SupportedImageVectorExtensionsLookup
+ .Contains(extension);
+
+ if ((forceUseInternalDecoder ||
+ isInternalFormat ||
+ isSvgFormat) && pixelTransform == null)
+ {
+ if (isSvgFormat)
+ {
+ image.Source = new SvgImageSource(sourceFromPath);
+ return true;
+ }
+
+ image.Source = new BitmapImage(sourceFromPath)
+ {
+ CreateOptions = (bool)instance.GetValue(useCacheProperty)
+ ? BitmapCreateOptions.None
+ : BitmapCreateOptions.IgnoreImageCache
+ };
+ return true;
+ }
+
+ await using FileStream? fileStream = await TryGetStreamFromPathAsync(sourceFromPath);
+ if (fileStream == null)
+ {
+ return false;
+ }
+
+ // Borrow loading process from stream source loader.
+ // We gonna ignore internal decoder enforcement here because, uh... idk.
+ return await image
+ .LoadImageFromStreamSourceAsync(fileStream,
+ false,
+ instance,
+ useCacheProperty,
+ pixelTransform);
+ }
+
+ private static async ValueTask LoadImageFromStreamSourceAsync(
+ this Image image,
+ Stream sourceFromStream,
+ bool forceUseInternalDecoder,
+ LayeredBackgroundImage instance,
+ DependencyProperty useCacheProperty,
+ IPixelTransform? pixelTransform = null)
+ {
+ (Stream? stream, bool isTemporaryStream) =
+ await sourceFromStream.GetNativeOrCopiedStreamIfNotSeekable(CancellationToken.None);
+
+ if (stream == null)
+ {
+ return false;
+ }
+
+ try
+ {
+ // Reset position
+ stream.Position = 0;
+
+ // Guess codec type
+ ImageExternalCodecType codecType = await stream.GuessImageFormatFromStreamAsync();
+ if (codecType == ImageExternalCodecType.NotSupported)
+ {
+ return false;
+ }
+
+ // Reset position after format guessing
+ stream.Position = 0;
+
+ if ((forceUseInternalDecoder ||
+ codecType == ImageExternalCodecType.Default) &&
+ pixelTransform != null)
+ {
+ using IRandomAccessStream sourceRandomStream = stream.AsRandomAccessStream(true);
+ BitmapImage bitmapImage = new()
+ {
+ CreateOptions = (bool)instance.GetValue(useCacheProperty)
+ ? BitmapCreateOptions.None
+ : BitmapCreateOptions.IgnoreImageCache
+ };
+ await bitmapImage.SetSourceAsync(sourceRandomStream);
+ image.Source = bitmapImage;
+ return true;
+ }
+
+ if (codecType == ImageExternalCodecType.Svg)
+ {
+ using IRandomAccessStream sourceRandomStream = stream.AsRandomAccessStream(true);
+ SvgImageSource svgImageSource = new();
+ svgImageSource.SetSourceAsync(sourceRandomStream);
+ image.Source = svgImageSource;
+ return true;
+ }
+
+ // Use MagicScaler for external codec types
+ await using FileStream tempStream = CreateTemporaryStream();
+ await Task.Run(() =>
+ {
+ ProcessImageSettings settings = new();
+ settings.TrySetEncoderFormat(ImageMimeTypes.Png);
+
+ using ProcessingPipeline pipeline = MagicImageProcessor.BuildPipeline(stream, settings);
+ if (pixelTransform != null)
+ {
+ pipeline.AddTransform(pixelTransform);
+ }
+
+ pipeline.WriteOutput(tempStream);
+ });
+
+ tempStream.Position = 0;
+ using IRandomAccessStream tempRandomStream = tempStream.AsRandomAccessStream(true);
+ BitmapImage tempBitmapImage = new()
+ {
+ CreateOptions = (bool)instance.GetValue(useCacheProperty)
+ ? BitmapCreateOptions.None
+ : BitmapCreateOptions.IgnoreImageCache
+ };
+ await tempBitmapImage.SetSourceAsync(tempRandomStream);
+ image.Source = tempBitmapImage;
+ return true;
+ }
+ finally
+ {
+ if (isTemporaryStream)
+ {
+ await stream.DisposeAsync();
+ }
+ }
+ }
+
+ private static async Task TryGetStreamFromPathAsync(Uri? url)
+ {
+ if (url == null)
+ {
+ return null;
+ }
+
+ if (url.IsFile)
+ {
+ return File.Open(url.LocalPath, FileMode.Open, FileAccess.Read, FileShare.Read);
+ }
+
+ if (await GetFileLengthFromUrl(Client, url) is 0)
+ {
+ return null;
+ }
+
+ HttpRequestMessage requestMessage = new(HttpMethod.Get, url);
+ HttpResponseMessage responseMessage =
+ await Client.SendAsync(requestMessage,
+ HttpCompletionOption.ResponseHeadersRead);
+
+ if (!responseMessage.IsSuccessStatusCode)
+ {
+ responseMessage.Dispose();
+ requestMessage.Dispose();
+ return null;
+ }
+
+ FileStream tempStream = url.CreateTemporaryStreamFromUrl();
+ try
+ {
+ await using Stream networkStream = await responseMessage.Content.ReadAsStreamAsync();
+ await networkStream.CopyToAsync(tempStream);
+ return tempStream;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ await tempStream.DisposeAsync();
+ }
+
+ return null;
+ }
+
+ private static async Task GetFileLengthFromUrl(HttpClient client, Uri url)
+ {
+ HttpRequestMessage requestMessage = new(HttpMethod.Head, url);
+ HttpResponseMessage responseMessage =
+ await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
+
+ if (responseMessage.IsSuccessStatusCode)
+ {
+ return responseMessage.Content.Headers.ContentLength ?? 0;
+ }
+
+ responseMessage.Dispose();
+ requestMessage.Dispose();
+ return 0;
+ }
+
+ internal static double GetClampedVolume(this double thisVolume)
+ {
+ if (double.IsNaN(thisVolume) ||
+ double.IsInfinity(thisVolume))
+ {
+ thisVolume = 0;
+ }
+
+ return Math.Clamp(thisVolume, 0, 100d) / 100d;
+ }
+
+ private static async ValueTask<(Stream? Stream, bool IsTemporaryStream)>
+ GetNativeOrCopiedStreamIfNotSeekable(
+ this T stream,
+ CancellationToken token)
+ where T : Stream
+ {
+ // If it's seekable, then just return it
+ if (stream.CanSeek)
+ {
+ return (stream, false);
+ }
+
+ // Copy over
+ FileStream tempStream = CreateTemporaryStream();
+ try
+ {
+ await stream.CopyToAsync(tempStream, token);
+ return (tempStream, true);
+ }
+ catch
+ {
+ await tempStream.DisposeAsync();
+ return (null, false);
+ }
+ }
+
+ private static FileStream CreateTemporaryStreamFromUrl(this Uri url)
+ {
+ string extension = Path.GetExtension(url.AbsolutePath);
+ string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + extension);
+
+ return File.Open(path,
+ new FileStreamOptions
+ {
+ Mode = FileMode.Create,
+ Access = FileAccess.ReadWrite,
+ Share = FileShare.ReadWrite,
+ Options = FileOptions.DeleteOnClose
+ });
+ }
+
+ private static FileStream CreateTemporaryStream()
+ {
+ string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
+ return File.Open(path,
+ new FileStreamOptions
+ {
+ Mode = FileMode.Create,
+ Access = FileAccess.ReadWrite,
+ Share = FileShare.ReadWrite,
+ Options = FileOptions.DeleteOnClose
+ });
+ }
+}
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml
new file mode 100644
index 000000000..e6f44a0db
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/LayeredBackgroundImage/LayeredBackgroundImage_themeresources.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs
new file mode 100644
index 000000000..a8dc028e9
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/ManagedUIElementList.cs
@@ -0,0 +1,225 @@
+using Microsoft.UI.Xaml;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using WinRT;
+
+// ReSharper disable StaticMemberInGenericType
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls;
+
+[ProjectedRuntimeClass(typeof(IList))]
+[GeneratedBindableCustomProperty]
+public partial class ManagedUIElementList : IList, INotifyCollectionChanged, INotifyPropertyChanged
+{
+ private readonly List _backedList;
+
+ #region Cached Property Changes Arguments
+
+ private static readonly PropertyChangedEventArgs CountPropertyChanged = new(nameof(Count));
+ private static readonly PropertyChangedEventArgs IndexerPropertyChanged = new("Item[]");
+
+ #endregion
+
+ #region Events
+
+ ///
+ public event NotifyCollectionChangedEventHandler? CollectionChanged;
+
+ ///
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ #endregion
+
+ ///
+ /// Creates a new empty Observable List
+ ///
+ public ManagedUIElementList() => _backedList = [];
+
+ ///
+ /// Creates a new Observable List from the enumerable.
+ ///
+ ///
+ /// Borrow the current instance of instead of allocating new backed list if possible.
+ public ManagedUIElementList(IEnumerable enumerable, bool useBorrow = false)
+ {
+ if (enumerable is List borrowedList &&
+ useBorrow)
+ {
+ _backedList = borrowedList;
+ return;
+ }
+
+ _backedList = [.. enumerable];
+ }
+
+ ///
+ public IEnumerator GetEnumerator() => _backedList.GetEnumerator();
+
+ ///
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ ///
+ public void Add(UIElement item) => Add(item, true);
+
+ ///
+ /// Adds an item to the backed List and notify the changes.
+ ///
+ /// The object to add to the backed List.
+ /// Whether to notify the changes or not.
+ public void Add(UIElement item, bool notifyChanges)
+ {
+ _backedList.Add(item);
+ if (!notifyChanges)
+ {
+ return;
+ }
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
+ }
+
+ public void AddRange(IEnumerable items)
+ {
+ _backedList.AddRange(items);
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, items));
+ }
+
+ ///
+ public void Clear() => Clear(true);
+
+ ///
+ /// Removes all items from the backed List and notify the changes.
+ ///
+ /// Whether to notify the changes or not.
+ public void Clear(bool notifyChanges)
+ {
+ _backedList.Clear();
+ if (!notifyChanges)
+ {
+ return;
+ }
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ }
+
+ ///
+ public bool Contains(UIElement item) => _backedList.Contains(item);
+
+ ///
+ public void CopyTo(UIElement[] array, int arrayIndex) => _backedList.CopyTo(array, arrayIndex);
+
+ ///
+ public int Count => _backedList.Count;
+
+ ///
+ public bool IsReadOnly => false;
+
+ ///
+ public int IndexOf(UIElement item) => _backedList.IndexOf(item);
+
+ ///
+ public bool Remove(UIElement item) => Remove(item, true);
+
+ ///
+ /// Removes the first occurrence of a specific object from the backed List.
+ ///
+ /// The object to remove from the backed List.
+ /// Whether to notify the changes or not.
+ ///
+ /// if was successfully removed from the backed List; otherwise, .
+ /// This method also returns if is not found from the backed List.
+ ///
+ public bool Remove(UIElement item, bool notifyChanges)
+ {
+ bool isSuccess = _backedList.Remove(item);
+
+ if (!isSuccess)
+ {
+ return false;
+ }
+
+ if (!notifyChanges)
+ {
+ return true;
+ }
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
+ return true;
+ }
+
+ ///
+ public void Insert(int index, UIElement item) => Insert(index, item, true);
+
+ ///
+ /// Inserts an item to the backed List at the specified index.
+ ///
+ /// The zero-based index at which should be inserted.
+ /// The object to insert into the backed List.
+ /// Whether to notify the changes or not.
+ public void Insert(int index, UIElement item, bool notifyChanges)
+ {
+ _backedList.Insert(index, item);
+
+ if (!notifyChanges)
+ {
+ return;
+ }
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
+ }
+
+ ///
+ public void RemoveAt(int index) => RemoveAt(index, true);
+
+ ///
+ /// Removes the backed List item at the specified index.
+ ///
+ /// The zero-based index of the item to remove.
+ /// Whether to notify the changes or not.
+ public void RemoveAt(int index, bool notifyChanges)
+ {
+ UIElement item = _backedList[index];
+ _backedList.Remove(item);
+
+ if (!notifyChanges)
+ {
+ return;
+ }
+
+ NotifyCountPropertyChange();
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
+ }
+
+ ///
+ [IndexerName("Item")]
+ public UIElement this[int index]
+ {
+ get => _backedList[index];
+ set
+ {
+ UIElement oldItem = _backedList[index];
+ UIElement newItem = _backedList[index] = value;
+
+ NotifyIndexerPropertyChange();
+ CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItem, oldItem, index));
+ }
+ }
+
+ private void NotifyCountPropertyChange() => PropertyChanged?.Invoke(this, CountPropertyChanged);
+ private void NotifyIndexerPropertyChange() => PropertyChanged?.Invoke(this, IndexerPropertyChanged);
+}
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs
new file mode 100644
index 000000000..91ab0c973
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Converters.cs
@@ -0,0 +1,23 @@
+using Microsoft.UI.Xaml.Data;
+using System;
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager;
+
+internal partial class IndexAddOneConverter : IValueConverter
+{
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value is int asInt)
+ {
+ return asInt + 1;
+ }
+
+ return value;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs
new file mode 100644
index 000000000..22fa67adf
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Enums.cs
@@ -0,0 +1,14 @@
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager;
+
+public enum NewPipsPagerNavigationMode
+{
+ Auto,
+ Hidden,
+ Visible
+}
+
+public enum NewPipsPagerSelectionMode
+{
+ Click,
+ Hover
+}
\ No newline at end of file
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs
new file mode 100644
index 000000000..6dd8deafd
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Events.cs
@@ -0,0 +1,403 @@
+using Microsoft.UI.Input;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Input;
+using System;
+using System.Linq;
+using System.Numerics;
+using Windows.Foundation;
+using Windows.System;
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager;
+
+public partial class NewPipsPager
+{
+ #region Size Measure Override
+
+ protected override Size MeasureOverride(Size parentSize)
+ {
+ Orientation orientation = Orientation;
+ double pipsButtonSize = GetButtonSize(orientation);
+
+ Vector2 containerSize = _pipsPagerItemsRepeater.ActualSize;
+ double containerTotalWidth = containerSize.X;
+ double containerTotalHeight = containerSize.Y;
+
+ GetNavigationButtonTotalSize(PreviousNavigationButtonMode,
+ _previousPageButton,
+ out double buttonPrevSizeTotalWidth,
+ out double buttonPrevSizeTotalHeight);
+
+ GetNavigationButtonTotalSize(NextNavigationButtonMode,
+ _nextPageButton,
+ out double buttonNextSizeTotalWidth,
+ out double buttonNextSizeTotalHeight);
+
+ Vector2 scrollViewportSize = parentSize.ToVector2();
+ double scrollViewportTotalWidth = scrollViewportSize.X;
+ double scrollViewportTotalHeight = scrollViewportSize.Y;
+
+ Size selfSize = base.MeasureOverride(parentSize);
+ double totalCalculatedWidth = selfSize.Width;
+ double totalCalculatedHeight = selfSize.Height;
+
+ if (orientation == Orientation.Horizontal)
+ {
+ _pipsPagerScrollViewer.MaxWidth =
+ GetViewportSize(scrollViewportTotalWidth,
+ containerTotalWidth,
+ buttonPrevSizeTotalWidth,
+ buttonNextSizeTotalWidth,
+ pipsButtonSize,
+ out bool isContainerLarger);
+
+ totalCalculatedWidth = 0;
+ totalCalculatedWidth += !isContainerLarger
+ ? containerTotalWidth
+ : _pipsPagerScrollViewer.MaxWidth;
+ totalCalculatedWidth += buttonPrevSizeTotalWidth +
+ buttonNextSizeTotalWidth;
+ }
+ else
+ {
+ _pipsPagerScrollViewer.MaxHeight =
+ GetViewportSize(scrollViewportTotalHeight,
+ containerTotalHeight,
+ buttonPrevSizeTotalHeight,
+ buttonNextSizeTotalHeight,
+ pipsButtonSize,
+ out bool isContainerLarger);
+
+ totalCalculatedHeight = 0;
+ totalCalculatedHeight += !isContainerLarger
+ ? containerTotalHeight
+ : _pipsPagerScrollViewer.MaxHeight;
+ totalCalculatedHeight += buttonPrevSizeTotalHeight +
+ buttonNextSizeTotalHeight;
+ }
+
+ return new Size(totalCalculatedWidth, totalCalculatedHeight);
+ }
+
+ private static void GetNavigationButtonTotalSize(
+ NewPipsPagerNavigationMode mode,
+ Button element,
+ out double width,
+ out double height)
+ {
+ bool isVisible = mode != NewPipsPagerNavigationMode.Hidden;
+ Vector2 size = isVisible ? element.ActualSize : Vector2.Zero;
+ Thickness margin = isVisible ? element.Margin : default;
+ width = size.X + margin.Left + margin.Right;
+ height = size.Y + margin.Top + margin.Bottom;
+ }
+
+ private static double GetViewportSize(double initialViewportSize,
+ double initialContainerSize,
+ double previousSideElementSize,
+ double nextSideElementSize,
+ double perButtonSize,
+ out bool isContainerLarger)
+ {
+ // Decrease viewport based on total width of navigation buttons
+ initialViewportSize -= previousSideElementSize + nextSideElementSize;
+ isContainerLarger = initialContainerSize > initialViewportSize;
+
+ // Clamp to display only viewable pips
+ if (isContainerLarger)
+ {
+ double dividedPerButtonSize = Math.Floor(initialViewportSize / perButtonSize);
+ initialViewportSize = dividedPerButtonSize * perButtonSize;
+ int clampedNth = (int)dividedPerButtonSize;
+ if (clampedNth % 2 == 0)
+ {
+ initialViewportSize = (clampedNth - 1) * perButtonSize;
+ }
+
+ return Math.Max(initialViewportSize, 0);
+ }
+
+ return double.PositiveInfinity;
+ }
+
+ #endregion
+
+ #region UI Events - Navigation Buttons
+
+ private void PreviousPageButton_OnClick(object sender, RoutedEventArgs e) => ItemIndex--;
+
+ private void NextPageButton_OnClick(object sender, RoutedEventArgs e) => ItemIndex++;
+
+ private void KeyboardKeys_Pressed(object sender, KeyRoutedEventArgs e)
+ {
+ switch (e.Key)
+ {
+ case VirtualKey.Left:
+ case VirtualKey.Up:
+ PreviousPageButton_OnClick(sender, e);
+ break;
+ case VirtualKey.Right:
+ case VirtualKey.Down:
+ NextPageButton_OnClick(sender, e);
+ break;
+ }
+ }
+
+ #endregion
+
+ #region UI Events - Orientation
+
+ private static void Orientation_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ NewPipsPager pager = (NewPipsPager)d;
+ Orientation orientation = (Orientation)e.NewValue;
+
+ Orientation_OnChange(pager, orientation);
+ }
+
+ private static void Orientation_OnChange(NewPipsPager pager, Orientation orientation)
+ {
+ string state = orientation == Orientation.Vertical
+ ? "VerticalOrientationView"
+ : "HorizontalOrientationView";
+ VisualStateManager.GoToState(pager, state, true);
+ }
+
+ #endregion
+
+ #region Property Changes
+
+ private static void ItemsCount_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ if (d is not NewPipsPager pager)
+ {
+ return;
+ }
+
+ object obj = e.NewValue;
+ int value = 0;
+ if (obj is int asInt)
+ {
+ value = asInt;
+ }
+
+ pager.ItemsCount_OnChange(value);
+ }
+
+ private void ItemsCount_OnChange(int value)
+ {
+ if (!_isTemplateLoaded)
+ {
+ return;
+ }
+
+ if (value < 0)
+ {
+ throw new IndexOutOfRangeException("ItemsCount cannot be negative!");
+ }
+
+ int oldItemsCount = _itemsDummy.Length;
+
+ using (_atomicLock.EnterScope())
+ {
+ try
+ {
+
+ if (value == 0)
+ {
+ _itemsDummy = [];
+ return;
+ }
+
+ _itemsDummy = Enumerable.Range(0, value).ToArray();
+ }
+ finally
+ {
+ // Update ItemsSource if already assigned
+ _pipsPagerItemsRepeater.ItemsSource = _itemsDummy;
+ _pipsPagerItemsRepeater.UpdateLayout();
+
+ // Update index only if the count is invalid
+ int currentIndex = ItemIndex;
+ if (currentIndex > value ||
+ (value != 0 && currentIndex < 0))
+ {
+ ItemIndex = 0;
+ }
+
+ ItemsCountChanged?.Invoke(this, new ChangedStructItemArgs(oldItemsCount, value));
+ }
+ }
+ }
+
+ private static void ItemIndex_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ // Ignore if the old and new index are equal
+ if (e is not { NewValue: int asNewIndex, OldValue: int asOldIndex } ||
+ asNewIndex == asOldIndex)
+ {
+ return;
+ }
+
+ NewPipsPager pager = (NewPipsPager)d;
+ if (!pager.IsLoaded)
+ {
+ return;
+ }
+
+ // Update navigation buttons state
+ UpdatePreviousButtonVisualState(pager);
+ UpdateNextButtonVisualState(pager);
+
+ // Update pip buttons state
+ UpdateAndBringSelectedPipToView(pager, asNewIndex, asOldIndex);
+
+ // Update pager layout
+ pager.UpdateLayout();
+ }
+
+ #endregion
+
+ #region ItemsRepeater
+
+ private void ItemsRepeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs args)
+ {
+ if (args.Element is not Button asButton)
+ {
+ return;
+ }
+
+ if (asButton.Tag is not int asIndex)
+ {
+ return;
+ }
+
+ AssignPipButtonStyle(asButton,
+ asIndex != ItemIndex
+ ? NormalPipButtonStyle
+ : SelectedPipButtonStyle);
+
+ // Avoid redundant loaded + unloaded events assignment
+ if (asButton.IsLoaded)
+ {
+ return;
+ }
+
+ asButton.Loaded += ItemsRepeaterPipButton_LoadedEvent;
+ asButton.Unloaded += ItemsRepeaterPipButton_UnloadedEvent;
+ }
+
+ private void ItemsRepeater_OnSizeChanged(object sender, SizeChangedEventArgs e) => InvalidateMeasure();
+
+ private void ItemsRepeaterPipButton_UnloadedEvent(object sender, RoutedEventArgs e)
+ {
+ Button button = (Button)sender;
+ if (SelectionMode == NewPipsPagerSelectionMode.Click)
+ {
+ button.Click -= ItemsRepeaterPipButton_OnClick;
+ }
+ else
+ {
+ button.PointerEntered -= ItemsRepeaterPipButton_OnClick;
+ }
+
+ button.Loaded -= ItemsRepeaterPipButton_LoadedEvent;
+ button.Unloaded -= ItemsRepeaterPipButton_UnloadedEvent;
+ }
+
+ private void ItemsRepeaterPipButton_LoadedEvent(object sender, RoutedEventArgs e)
+ {
+ Button button = (Button)sender;
+ if (SelectionMode == NewPipsPagerSelectionMode.Click)
+ {
+ button.Click += ItemsRepeaterPipButton_OnClick;
+ }
+ else
+ {
+ button.PointerEntered += ItemsRepeaterPipButton_OnClick;
+ }
+ }
+
+ private void ItemsRepeaterPipButton_OnClick(object sender, RoutedEventArgs args)
+ {
+ ItemIndex = (int)((Button)sender).Tag;
+ }
+
+ #endregion
+
+ #region ScrollViewer
+
+ private void ScrollViewer_OnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
+ {
+ if (!e.Pointer.IsInRange ||
+ sender is not UIElement element)
+ {
+ return;
+ }
+
+ Orientation layoutOrientation = Orientation;
+ double pipsButtonSize = GetButtonSize(layoutOrientation);
+
+ PointerPoint pointer = e.GetCurrentPoint(element);
+ int orientation = pointer.Properties.MouseWheelDelta;
+ bool isHorizontal = layoutOrientation == Orientation.Horizontal;
+ double delta = pipsButtonSize * (orientation / 120d);
+
+ double toOffset = (isHorizontal
+ ? _pipsPagerScrollViewer.HorizontalOffset
+ : _pipsPagerScrollViewer.VerticalOffset) + -delta;
+ toOffset = Math.Round(toOffset / pipsButtonSize) * pipsButtonSize;
+
+ if (isHorizontal)
+ {
+ toOffset = Math.Clamp(toOffset, 0, _pipsPagerScrollViewer.ExtentWidth);
+ _pipsPagerScrollViewer.ChangeView(toOffset, _pipsPagerScrollViewer.VerticalOffset, _pipsPagerScrollViewer.ZoomFactor);
+ }
+ else
+ {
+ toOffset = Math.Clamp(toOffset, 0, _pipsPagerScrollViewer.ExtentHeight);
+ _pipsPagerScrollViewer.ChangeView(_pipsPagerScrollViewer.HorizontalOffset, toOffset, _pipsPagerScrollViewer.ZoomFactor);
+ }
+ }
+
+ private double GetButtonSize(Orientation orientation)
+ {
+ double pipsButtonSize = 0d;
+
+ if (_pipsPagerItemsRepeater.TryGetElement(0) is UIElement button)
+ {
+ var desiredSize = button.ActualSize;
+ pipsButtonSize = orientation == Orientation.Horizontal
+ ? desiredSize.X
+ : desiredSize.Y;
+ }
+
+ return pipsButtonSize;
+ }
+
+ #endregion
+
+ #region Loaded and Unloaded
+
+ private void NewPipsPager_Unloaded(object sender, RoutedEventArgs e)
+ {
+ UnapplyNavigationButtonEvents();
+ UnapplyKeyPressEvents();
+ UnapplyItemsRepeaterEvents();
+
+ _pipsPagerItemsRepeater.ItemsSource = null;
+ }
+
+ private void NewPipsPager_Loaded(object sender, RoutedEventArgs e)
+ {
+ ItemsCount_OnChange(ItemsCount);
+ UpdateAndBringSelectedPipToView(this, ItemIndex, -1);
+
+ // Update navigation buttons state
+ UpdatePreviousButtonVisualState(this);
+ UpdateNextButtonVisualState(this);
+ }
+
+ #endregion
+}
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs
new file mode 100644
index 000000000..59c3fdca3
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Properties.cs
@@ -0,0 +1,300 @@
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System;
+using System.Threading;
+using Windows.Foundation;
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager;
+
+public partial class NewPipsPager
+{
+ #region Events
+
+ public event TypedEventHandler>? ItemsCountChanged;
+ public event TypedEventHandler>? ItemIndexChanged;
+
+ #endregion
+
+ #region Properties
+
+ public Orientation Orientation
+ {
+ get => (Orientation)GetValue(OrientationProperty);
+ set => SetValue(OrientationProperty, value);
+ }
+
+ public int ItemsCount
+ {
+ get => (int)GetValue(ItemsCountProperty);
+ set => SetValue(ItemsCountProperty, value);
+ }
+
+ public int ItemIndex
+ {
+ get => (int)GetValue(ItemIndexProperty);
+ set
+ {
+ using (_atomicLock.EnterScope())
+ {
+ int itemsCount = ItemsCount;
+ if (itemsCount == 0)
+ {
+ return;
+ }
+
+ if (value < 0)
+ {
+ value = itemsCount - 1;
+ }
+
+ if (value >= itemsCount)
+ {
+ value = 0;
+ }
+
+ SetValue(ItemIndexProperty, value);
+ }
+ }
+ }
+
+ public NewPipsPagerSelectionMode SelectionMode
+ {
+ get => (NewPipsPagerSelectionMode)GetValue(SelectionModeProperty);
+ set => SetValue(SelectionModeProperty, value);
+ }
+
+ public NewPipsPagerNavigationMode PreviousNavigationButtonMode
+ {
+ get => (NewPipsPagerNavigationMode)GetValue(PreviousNavigationButtonModeProperty);
+ set => SetValue(PreviousNavigationButtonModeProperty, value);
+ }
+
+ public NewPipsPagerNavigationMode NextNavigationButtonMode
+ {
+ get => (NewPipsPagerNavigationMode)GetValue(NextNavigationButtonModeProperty);
+ set => SetValue(NextNavigationButtonModeProperty, value);
+ }
+
+ public Style PreviousButtonStyle
+ {
+ get => (Style)GetValue(PreviousButtonStyleProperty);
+ set => SetValue(PreviousButtonStyleProperty, value);
+ }
+
+ public Style NextButtonStyle
+ {
+ get => (Style)GetValue(NextButtonStyleProperty);
+ set => SetValue(NextButtonStyleProperty, value);
+ }
+
+ public Style NormalPipButtonStyle
+ {
+ get => (Style)GetValue(NormalPipButtonStyleProperty);
+ set => SetValue(NormalPipButtonStyleProperty, value);
+ }
+
+ public Style SelectedPipButtonStyle
+ {
+ get => (Style)GetValue(SelectedPipButtonStyleProperty);
+ set => SetValue(SelectedPipButtonStyleProperty, value);
+ }
+
+ #endregion
+
+ #region Fields
+
+ private readonly Lock _atomicLock = new();
+
+ private int[] _itemsDummy = [];
+
+ #endregion
+
+ #region Dependency Change Methods
+
+ private static void UpdatePreviousButtonVisualState(NewPipsPager pager)
+ {
+ UpdateButtonVisualState(pager,
+ pager._previousPageButton,
+ pager.ItemIndex > 0,
+ NavButtonStatePreviousPageButtonCollapsed,
+ NavButtonStatePreviousPageButtonVisible,
+ NavButtonStatePreviousPageButtonHidden,
+ pager.PreviousNavigationButtonMode);
+ }
+
+ private static void UpdateNextButtonVisualState(NewPipsPager pager)
+ {
+ UpdateButtonVisualState(pager,
+ pager._nextPageButton,
+ pager.ItemIndex + 1 < pager.ItemsCount,
+ NavButtonStateNextPageButtonCollapsed,
+ NavButtonStateNextPageButtonVisible,
+ NavButtonStateNextPageButtonHidden,
+ pager.NextNavigationButtonMode);
+ }
+
+ private static void UpdateButtonVisualState(
+ NewPipsPager instance,
+ Button? button,
+ bool conditionForAutoVisible,
+ string stateNameForCollapsed,
+ string stateNameForVisible,
+ string stateNameForHidden,
+ NewPipsPagerNavigationMode mode)
+ {
+ if (button == null)
+ {
+ return;
+ }
+
+ if (mode == NewPipsPagerNavigationMode.Hidden)
+ {
+ VisualStateManager.GoToState(instance, stateNameForCollapsed, true);
+ return;
+ }
+
+ VisualStateManager.GoToState(instance, stateNameForVisible, true);
+ button.IsEnabled = true;
+ if (mode == NewPipsPagerNavigationMode.Visible)
+ {
+ return;
+ }
+
+ if (conditionForAutoVisible)
+ {
+ return;
+ }
+
+ button.IsEnabled = false;
+ VisualStateManager.GoToState(instance, stateNameForHidden, true);
+ }
+
+ private static void UpdateAndBringSelectedPipToView(NewPipsPager pager, int newIndex, int oldIndex)
+ {
+ if (pager.UpdateSelectedPipStyle(newIndex, oldIndex) is not { } asButton)
+ {
+ return;
+ }
+
+ BringIntoViewOptions options = new()
+ {
+ AnimationDesired = true
+ };
+ if (pager.Orientation == Orientation.Horizontal)
+ {
+ options.HorizontalAlignmentRatio = 0.5d;
+ }
+ else
+ {
+ options.VerticalAlignmentRatio = 0.5d;
+ }
+ asButton.StartBringIntoView(options);
+ }
+
+ private Button? UpdateSelectedPipStyle(int newIndex, int oldIndex)
+ {
+ ItemsRepeater? repeater = _pipsPagerItemsRepeater;
+
+ try
+ {
+ if (!_isTemplateLoaded ||
+ repeater?.ItemsSourceView == null)
+ {
+ return null;
+ }
+
+ int childCount = repeater.ItemsSourceView.Count;
+ bool isUpdateNewChild = newIndex >= 0 && newIndex < childCount;
+ bool isUpdateOldChild = oldIndex >= 0 && oldIndex < childCount;
+
+ if (ItemsCount == 0)
+ {
+ return null;
+ }
+
+ Button? newIndexPipButton = repeater.GetOrCreateElement(newIndex) as Button;
+ Button? oldIndexPipButton = repeater.TryGetElement(oldIndex) as Button;
+
+ try
+ {
+ if (isUpdateOldChild)
+ {
+ AssignPipButtonStyle(oldIndexPipButton, NormalPipButtonStyle);
+ }
+
+ if (isUpdateNewChild)
+ {
+ return AssignPipButtonStyle(newIndexPipButton, SelectedPipButtonStyle);
+ }
+
+ return newIndexPipButton;
+ }
+ finally
+ {
+ if (newIndex != oldIndex)
+ {
+ ItemIndexChanged?.Invoke(this, new ChangedStructItemArgs(oldIndex, newIndex));
+ }
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+
+ return null;
+ }
+
+ private static Button? AssignPipButtonStyle(Button? button, Style? style)
+ {
+ if (button is null)
+ {
+ return button;
+ }
+
+ button.Style = style;
+ button.UpdateLayout();
+ VisualStateManager.GoToState(button, PipButtonStateNormal, true);
+ return button;
+ }
+
+ private static Style? TryGetStyle(string styleName)
+ {
+ if (Application.Current.Resources.TryGetValue(styleName, out object styleObj) &&
+ styleObj is Style asStyle)
+ {
+ return asStyle;
+ }
+
+ return null;
+ }
+
+ private static void PreviousNavigationButtonMode_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ UpdatePreviousButtonVisualState((NewPipsPager)d);
+ }
+
+ private static void NextNavigationButtonMode_OnChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ UpdateNextButtonVisualState((NewPipsPager)d);
+ }
+
+ #endregion
+
+ #region Dependency Properties
+
+ public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(NewPipsPager), new PropertyMetadata(Orientation.Vertical, Orientation_OnChange));
+ public static readonly DependencyProperty ItemsCountProperty = DependencyProperty.Register(nameof(ItemsCount), typeof(int), typeof(NewPipsPager), new PropertyMetadata(0, ItemsCount_OnChange));
+ public static readonly DependencyProperty ItemIndexProperty = DependencyProperty.Register(nameof(ItemIndex), typeof(int), typeof(NewPipsPager), new PropertyMetadata(-1, ItemIndex_OnChange));
+ public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register(nameof(SelectionMode), typeof(bool), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerSelectionMode.Click));
+ public static readonly DependencyProperty PreviousNavigationButtonModeProperty = DependencyProperty.Register(nameof(PreviousNavigationButtonMode), typeof(NewPipsPagerNavigationMode), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerNavigationMode.Auto, PreviousNavigationButtonMode_OnChange));
+ public static readonly DependencyProperty NextNavigationButtonModeProperty = DependencyProperty.Register(nameof(NextNavigationButtonMode), typeof(NewPipsPagerNavigationMode), typeof(NewPipsPager), new PropertyMetadata(NewPipsPagerNavigationMode.Auto, NextNavigationButtonMode_OnChange));
+
+ public static readonly DependencyProperty PreviousButtonStyleProperty = DependencyProperty.Register(nameof(PreviousButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!));
+ public static readonly DependencyProperty NextButtonStyleProperty = DependencyProperty.Register(nameof(NextButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!));
+ public static readonly DependencyProperty NormalPipButtonStyleProperty = DependencyProperty.Register(nameof(NormalPipButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!));
+ public static readonly DependencyProperty SelectedPipButtonStyleProperty = DependencyProperty.Register(nameof(SelectedPipButtonStyle), typeof(Style), typeof(NewPipsPager), new PropertyMetadata(null!));
+
+ #endregion
+}
diff --git a/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs
new file mode 100644
index 000000000..c23da0b70
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Theme/CustomControls/NewPipsPager/NewPipsPager.Templates.cs
@@ -0,0 +1,111 @@
+using CollapseLauncher.Extension;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System.Threading;
+
+#nullable enable
+namespace CollapseLauncher.XAMLs.Theme.CustomControls.NewPipsPager;
+
+[TemplatePart(Name = TemplateNamePreviousPageButton, Type = typeof(Button))]
+[TemplatePart(Name = TemplateNameNextPageButton, Type = typeof(Button))]
+[TemplatePart(Name = TemplateNamePipsPagerScrollViewer, Type = typeof(ScrollViewer))]
+[TemplatePart(Name = TemplateNamePipsPagerItemsRepeater, Type = typeof(ItemsRepeater))]
+public partial class NewPipsPager
+{
+ #region Constants
+
+ private const string TemplateNamePreviousPageButton = "PreviousPageButton";
+ private const string TemplateNameNextPageButton = "NextPageButton";
+ private const string TemplateNamePipsPagerScrollViewer = "PipsPagerScrollViewer";
+ private const string TemplateNamePipsPagerItemsRepeater = "PipsPagerItemsRepeater";
+
+ private const string PipButtonStateNormal = "Normal";
+
+ private const string NavButtonStatePreviousPageButtonCollapsed = "PreviousPageButtonCollapsed";
+ private const string NavButtonStatePreviousPageButtonVisible = "PreviousPageButtonVisible";
+ private const string NavButtonStatePreviousPageButtonHidden = "PreviousPageButtonHidden";
+ private const string NavButtonStateNextPageButtonCollapsed = "NextPageButtonCollapsed";
+ private const string NavButtonStateNextPageButtonVisible = "NextPageButtonVisible";
+ private const string NavButtonStateNextPageButtonHidden = "NextPageButtonHidden";
+
+ #endregion
+
+ #region Fields
+
+ private Button _previousPageButton = null!;
+ private Button _nextPageButton = null!;
+ private ScrollViewer _pipsPagerScrollViewer = null!;
+ private ItemsRepeater _pipsPagerItemsRepeater = null!;
+
+ private bool _isTemplateLoaded;
+
+ #endregion
+
+ #region Apply Template Methods
+
+ protected override void OnApplyTemplate()
+ {
+ if (Interlocked.Exchange(ref _isTemplateLoaded, true))
+ {
+ return;
+ }
+
+ base.OnApplyTemplate();
+
+ _previousPageButton = this.GetTemplateChild
-
+