From e3e0994189aee7e276def90a95a0a7a87f097d50 Mon Sep 17 00:00:00 2001 From: Steven He Date: Sat, 20 Aug 2022 17:26:54 +0900 Subject: [PATCH 1/7] Remove reflection usage on animators --- src/Avalonia.Base/Animation/Animation.cs | 60 ++++++++++--------- .../Animation/AnimatorKeyFrame.cs | 7 ++- .../Animation/Animators/Animator`1.cs | 4 +- .../Animation/Animators/BaseBrushAnimator.cs | 17 +++--- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/Avalonia.Base/Animation/Animation.cs b/src/Avalonia.Base/Animation/Animation.cs index 6bb06367de..c5c76f4929 100644 --- a/src/Avalonia.Base/Animation/Animation.cs +++ b/src/Avalonia.Base/Animation/Animation.cs @@ -179,14 +179,14 @@ namespace Avalonia.Animation public KeyFrames Children { get; } = new KeyFrames(); // Store values for the Animator attached properties for IAnimationSetter objects. - private static readonly Dictionary s_animators = new Dictionary(); + private static readonly Dictionary Factory)> s_animators = new(); /// /// Gets the value of the Animator attached property for a setter. /// /// The animation setter. /// The property animator type. - public static Type? GetAnimator(IAnimationSetter setter) + public static (Type, Func)? GetAnimator(IAnimationSetter setter) { if (s_animators.TryGetValue(setter, out var type)) { @@ -199,25 +199,25 @@ namespace Avalonia.Animation /// Sets the value of the Animator attached property for a setter. /// /// The animation setter. - /// The property animator value. - public static void SetAnimator(IAnimationSetter setter, Type value) + public static void SetAnimator(IAnimationSetter setter) + where TAnimator : IAnimator, new() { - s_animators[setter] = value; + s_animators[setter] = (typeof(TAnimator), () => new TAnimator()); } - private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)> + private readonly static List<(Func Condition, Type Animator, Func Factory)> Animators = new() { - ( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator) ), - ( prop => typeof(byte).IsAssignableFrom(prop.PropertyType), typeof(ByteAnimator) ), - ( prop => typeof(Int16).IsAssignableFrom(prop.PropertyType), typeof(Int16Animator) ), - ( prop => typeof(Int32).IsAssignableFrom(prop.PropertyType), typeof(Int32Animator) ), - ( prop => typeof(Int64).IsAssignableFrom(prop.PropertyType), typeof(Int64Animator) ), - ( prop => typeof(UInt16).IsAssignableFrom(prop.PropertyType), typeof(UInt16Animator) ), - ( prop => typeof(UInt32).IsAssignableFrom(prop.PropertyType), typeof(UInt32Animator) ), - ( prop => typeof(UInt64).IsAssignableFrom(prop.PropertyType), typeof(UInt64Animator) ), - ( prop => typeof(float).IsAssignableFrom(prop.PropertyType), typeof(FloatAnimator) ), - ( prop => typeof(double).IsAssignableFrom(prop.PropertyType), typeof(DoubleAnimator) ), - ( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator) ), + ( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator), () => new BoolAnimator() ), + ( prop => typeof(byte).IsAssignableFrom(prop.PropertyType), typeof(ByteAnimator), () => new ByteAnimator() ), + ( prop => typeof(Int16).IsAssignableFrom(prop.PropertyType), typeof(Int16Animator), () => new Int16Animator() ), + ( prop => typeof(Int32).IsAssignableFrom(prop.PropertyType), typeof(Int32Animator), () => new Int32Animator() ), + ( prop => typeof(Int64).IsAssignableFrom(prop.PropertyType), typeof(Int64Animator), () => new Int64Animator() ), + ( prop => typeof(UInt16).IsAssignableFrom(prop.PropertyType), typeof(UInt16Animator), () => new UInt16Animator() ), + ( prop => typeof(UInt32).IsAssignableFrom(prop.PropertyType), typeof(UInt32Animator), () => new UInt32Animator() ), + ( prop => typeof(UInt64).IsAssignableFrom(prop.PropertyType), typeof(UInt64Animator), () => new UInt64Animator() ), + ( prop => typeof(float).IsAssignableFrom(prop.PropertyType), typeof(FloatAnimator), () => new FloatAnimator() ), + ( prop => typeof(double).IsAssignableFrom(prop.PropertyType), typeof(DoubleAnimator), () => new DoubleAnimator() ), + ( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator), () => new DecimalAnimator() ), }; /// @@ -232,18 +232,18 @@ namespace Avalonia.Animation /// The type of the animator to instantiate. /// public static void RegisterAnimator(Func condition) - where TAnimator : IAnimator + where TAnimator : IAnimator, new() { - Animators.Insert(0, (condition, typeof(TAnimator))); + Animators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator())); } - private static Type? GetAnimatorType(AvaloniaProperty property) + private static (Type Type, Func Factory)? GetAnimatorType(AvaloniaProperty property) { - foreach (var (condition, type) in Animators) + foreach (var (condition, type, factory) in Animators) { if (condition(property)) { - return type; + return (type, factory); } } return null; @@ -251,7 +251,7 @@ namespace Avalonia.Animation private (IList Animators, IList subscriptions) InterpretKeyframes(Animatable control) { - var handlerList = new List<(Type type, AvaloniaProperty property)>(); + var handlerList = new Dictionary<(Type type, AvaloniaProperty Property), Func>(); var animatorKeyFrames = new List(); var subscriptions = new List(); @@ -271,8 +271,10 @@ namespace Avalonia.Animation throw new InvalidOperationException($"No animator registered for the property {setter.Property}. Add an animator to the Animation.Animators collection that matches this property to animate it."); } - if (!handlerList.Contains((handler, setter.Property))) - handlerList.Add((handler, setter.Property)); + var (type, factory) = handler.Value; + + if (!handlerList.ContainsKey((type, setter.Property))) + handlerList[(type, setter.Property)] = factory; var cue = keyframe.Cue; @@ -281,7 +283,7 @@ namespace Avalonia.Animation cue = new Cue(keyframe.KeyTime.TotalSeconds / Duration.TotalSeconds); } - var newKF = new AnimatorKeyFrame(handler, cue, keyframe.KeySpline); + var newKF = new AnimatorKeyFrame(type, factory, cue, keyframe.KeySpline); subscriptions.Add(newKF.BindSetter(setter, control)); @@ -291,10 +293,10 @@ namespace Avalonia.Animation var newAnimatorInstances = new List(); - foreach (var (handlerType, property) in handlerList) + foreach (var handler in handlerList) { - var newInstance = (IAnimator)Activator.CreateInstance(handlerType)!; - newInstance.Property = property; + var newInstance = handler.Value(); + newInstance.Property = handler.Key.Property; newAnimatorInstances.Add(newInstance); } diff --git a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs index 8af31f2948..0356723f00 100644 --- a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs +++ b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs @@ -20,22 +20,25 @@ namespace Avalonia.Animation } - public AnimatorKeyFrame(Type? animatorType, Cue cue) + public AnimatorKeyFrame(Type? animatorType, Func? animatorFactory, Cue cue) { AnimatorType = animatorType; + AnimatorFactory = animatorFactory; Cue = cue; KeySpline = null; } - public AnimatorKeyFrame(Type? animatorType, Cue cue, KeySpline? keySpline) + public AnimatorKeyFrame(Type? animatorType, Func? animatorFactory, Cue cue, KeySpline? keySpline) { AnimatorType = animatorType; + AnimatorFactory = animatorFactory; Cue = cue; KeySpline = keySpline; } internal bool isNeutral; public Type? AnimatorType { get; } + public Func? AnimatorFactory { get; } public Cue Cue { get; } public KeySpline? KeySpline { get; } public AvaloniaProperty? Property { get; private set; } diff --git a/src/Avalonia.Base/Animation/Animators/Animator`1.cs b/src/Avalonia.Base/Animation/Animators/Animator`1.cs index 248ca61c1d..8765cfb4c9 100644 --- a/src/Avalonia.Base/Animation/Animators/Animator`1.cs +++ b/src/Avalonia.Base/Animation/Animators/Animator`1.cs @@ -171,12 +171,12 @@ namespace Avalonia.Animation.Animators { if (!hasStartKey) { - _convertedKeyframes.Insert(0, new AnimatorKeyFrame(null, new Cue(0.0d)) { Value = default(T), isNeutral = true }); + _convertedKeyframes.Insert(0, new AnimatorKeyFrame(null, null, new Cue(0.0d)) { Value = default(T), isNeutral = true }); } if (!hasEndKey) { - _convertedKeyframes.Add(new AnimatorKeyFrame(null, new Cue(1.0d)) { Value = default(T), isNeutral = true }); + _convertedKeyframes.Add(new AnimatorKeyFrame(null, null, new Cue(1.0d)) { Value = default(T), isNeutral = true }); } } } diff --git a/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs index 5f22254fb5..07c147ef6d 100644 --- a/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs +++ b/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs @@ -17,8 +17,7 @@ namespace Avalonia.Animation.Animators /// public class BaseBrushAnimator : Animator { - private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators = - new List<(Func Match, Type AnimatorType)>(); + private static readonly List<(Func Match, Type AnimatorType, Func AnimatorFactory)> _brushAnimators = new(); /// /// Register an that handles a specific @@ -34,7 +33,7 @@ namespace Avalonia.Animation.Animators public static void RegisterBrushAnimator(Func condition) where TAnimator : IAnimator, new() { - _brushAnimators.Insert(0, (condition, typeof(TAnimator))); + _brushAnimators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator())); } /// @@ -85,14 +84,14 @@ namespace Avalonia.Animation.Animators { if (keyframe.Value is ISolidColorBrush solidColorBrush) { - gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), keyframe.Cue, keyframe.KeySpline) + gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), () => new GradientBrushAnimator(), keyframe.Cue, keyframe.KeySpline) { Value = GradientBrushAnimator.ConvertSolidColorBrushToGradient(firstGradient, solidColorBrush) }); } else if (keyframe.Value is IGradientBrush) { - gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), keyframe.Cue, keyframe.KeySpline) + gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), () => new GradientBrushAnimator(), keyframe.Cue, keyframe.KeySpline) { Value = keyframe.Value }); @@ -117,7 +116,7 @@ namespace Avalonia.Animation.Animators { if (keyframe.Value is ISolidColorBrush) { - solidColorBrushAnimator.Add(new AnimatorKeyFrame(typeof(ISolidColorBrushAnimator), keyframe.Cue, keyframe.KeySpline) + solidColorBrushAnimator.Add(new AnimatorKeyFrame(typeof(ISolidColorBrushAnimator), () => new ISolidColorBrushAnimator(), keyframe.Cue, keyframe.KeySpline) { Value = keyframe.Value }); @@ -137,18 +136,18 @@ namespace Avalonia.Animation.Animators { if (_brushAnimators.Count > 0 && this[0].Value?.GetType() is Type firstKeyType) { - foreach (var (match, animatorType) in _brushAnimators) + foreach (var (match, animatorType, animatorFactory) in _brushAnimators) { if (!match(firstKeyType)) continue; - animator = (IAnimator?)Activator.CreateInstance(animatorType); + animator = animatorFactory(); if (animator != null) { animator.Property = Property; foreach (var keyframe in this) { - animator.Add(new AnimatorKeyFrame(animatorType, keyframe.Cue, keyframe.KeySpline) + animator.Add(new AnimatorKeyFrame(animatorType, animatorFactory, keyframe.Cue, keyframe.KeySpline) { Value = keyframe.Value }); From 5cce7e0a841643db6ab7718abe5346dae623c3ff Mon Sep 17 00:00:00 2001 From: Steve Date: Sat, 20 Aug 2022 17:46:21 +0900 Subject: [PATCH 2/7] Update Animation.cs --- src/Avalonia.Base/Animation/Animation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Base/Animation/Animation.cs b/src/Avalonia.Base/Animation/Animation.cs index c5c76f4929..b2382b656c 100644 --- a/src/Avalonia.Base/Animation/Animation.cs +++ b/src/Avalonia.Base/Animation/Animation.cs @@ -186,7 +186,7 @@ namespace Avalonia.Animation /// /// The animation setter. /// The property animator type. - public static (Type, Func)? GetAnimator(IAnimationSetter setter) + public static (Type Type, Func Factory)? GetAnimator(IAnimationSetter setter) { if (s_animators.TryGetValue(setter, out var type)) { From 5ff46b88577da62f773fca2fa7de8d190c4c8e69 Mon Sep 17 00:00:00 2001 From: Steven He Date: Sat, 20 Aug 2022 18:13:05 +0900 Subject: [PATCH 3/7] Fixes --- src/Avalonia.Base/Animation/Animation.cs | 11 ++++++++--- src/Avalonia.Base/Avalonia.Base.csproj | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Animation/Animation.cs b/src/Avalonia.Base/Animation/Animation.cs index c5c76f4929..7c03c988f8 100644 --- a/src/Avalonia.Base/Animation/Animation.cs +++ b/src/Avalonia.Base/Animation/Animation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -199,10 +200,14 @@ namespace Avalonia.Animation /// Sets the value of the Animator attached property for a setter. /// /// The animation setter. - public static void SetAnimator(IAnimationSetter setter) - where TAnimator : IAnimator, new() + /// The property animator value. + public static void SetAnimator(IAnimationSetter setter, +#if NET6_0_OR_GREATER + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)] +#endif + Type value) { - s_animators[setter] = (typeof(TAnimator), () => new TAnimator()); + s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!); } private readonly static List<(Func Condition, Type Animator, Func Factory)> Animators = new() diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index 15feed388b..d091b9072d 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -6,6 +6,7 @@ True true $(BaseIntermediateOutputPath)\GeneratedFiles + true From bf0b79fd329c3d051c0516251080d65beacddc46 Mon Sep 17 00:00:00 2001 From: Jan Lukas Gernert Date: Mon, 22 Aug 2022 17:09:35 +0200 Subject: [PATCH 4/7] update SkiaSharp to 2.88.1 --- build/SkiaSharp.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props index cc573825cd..31619399f9 100644 --- a/build/SkiaSharp.props +++ b/build/SkiaSharp.props @@ -1,7 +1,7 @@  - - - + + + From 2831ff5ad168caff947463f6d59c5b44e2fc82c9 Mon Sep 17 00:00:00 2001 From: Takoooooo Date: Tue, 23 Aug 2022 14:06:58 +0300 Subject: [PATCH 5/7] Fix Fluent theme port bugs --- src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml | 1 - src/Avalonia.Themes.Fluent/Controls/ButtonSpinner.xaml | 1 + src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml | 7 ------- src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml | 7 ------- 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml index 5ae83427b5..364a2a52e3 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml @@ -53,7 +53,6 @@ - diff --git a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml index bc47f3892e..e9c60570c7 100644 --- a/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml @@ -56,18 +56,11 @@ - - diff --git a/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml index 0d1b416d7a..fb02071c3f 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml @@ -55,18 +55,11 @@ - - From 7fb99a39817777c4887b7c157fd93391de979200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 24 Aug 2022 12:55:48 +0200 Subject: [PATCH 6/7] Update Avalonia.Web.Blazor dependencies --- src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj index 1531c95830..2d598687a9 100644 --- a/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj +++ b/src/Web/Avalonia.Web.Blazor/Avalonia.Web.Blazor.csproj @@ -45,8 +45,8 @@ - - + + From f86b74c136b78d3e2d5d3720a51b5b155a73f10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 24 Aug 2022 13:24:36 +0200 Subject: [PATCH 7/7] Fix build --- .../Interop/Typescript/StorageProvider.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Web/Avalonia.Web.Blazor/Interop/Typescript/StorageProvider.ts b/src/Web/Avalonia.Web.Blazor/Interop/Typescript/StorageProvider.ts index aee74b9067..1ee055eff9 100644 --- a/src/Web/Avalonia.Web.Blazor/Interop/Typescript/StorageProvider.ts +++ b/src/Web/Avalonia.Web.Blazor/Interop/Typescript/StorageProvider.ts @@ -8,7 +8,6 @@ declare global { type PermissionsMode = "read" | "readwrite"; interface FileSystemFileHandle { name: string, - kind: "file" | "directory", getFile(): Promise; createWritable(options?: { keepExistingData?: boolean }): Promise; @@ -169,10 +168,6 @@ class StorageItem { } public async getItems(): Promise { - if (this.handle.kind !== "directory"){ - return new StorageItems([]); - } - const items: StorageItem[] = []; for await (const [key, value] of this.handle.entries()) { items.push(new StorageItem(value));