Import functionality for wino accounts, calendar sync UI, bunch of shell improvements
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
//
|
||||
// LottieGen version:
|
||||
// 8.2.250604.1+b02a3ee244
|
||||
//
|
||||
// Command:
|
||||
// LottieGen -Language CSharp -Public -WinUIVersion 2.4 -InputFile sync.json
|
||||
//
|
||||
// Input file:
|
||||
// sync.json (2404 bytes created 20:18+02:00 Apr 4 2026)
|
||||
//
|
||||
// LottieGen source:
|
||||
// http://aka.ms/Lottie
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
// ___________________________________________________________
|
||||
// | Object stats | UAP v15 count | UAP v7 count |
|
||||
// |__________________________|_______________|______________|
|
||||
// | All CompositionObjects | 26 | 26 |
|
||||
// |--------------------------+---------------+--------------|
|
||||
// | Expression animators | 1 | 1 |
|
||||
// | KeyFrame animators | 1 | 1 |
|
||||
// | Reference parameters | 1 | 1 |
|
||||
// | Expression operations | 0 | 0 |
|
||||
// |--------------------------+---------------+--------------|
|
||||
// | Animated brushes | - | - |
|
||||
// | Animated gradient stops | - | - |
|
||||
// | ExpressionAnimations | 1 | 1 |
|
||||
// | PathKeyFrameAnimations | - | - |
|
||||
// |--------------------------+---------------+--------------|
|
||||
// | ContainerVisuals | 1 | 1 |
|
||||
// | ShapeVisuals | 1 | 1 |
|
||||
// |--------------------------+---------------+--------------|
|
||||
// | ContainerShapes | 1 | 1 |
|
||||
// | CompositionSpriteShapes | 2 | 2 |
|
||||
// |--------------------------+---------------+--------------|
|
||||
// | Brushes | 1 | 1 |
|
||||
// | Gradient stops | - | - |
|
||||
// | CompositionVisualSurface | - | - |
|
||||
// -----------------------------------------------------------
|
||||
using Microsoft.Graphics.Canvas.Geometry;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Windows.Graphics;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Composition;
|
||||
|
||||
namespace AnimatedVisuals
|
||||
{
|
||||
// Name: main_libary_shelf_icon_sync
|
||||
// Frame rate: 60 fps
|
||||
// Frame count: 61
|
||||
// Duration: 1016.7 mS
|
||||
sealed class Sync
|
||||
: Microsoft.UI.Xaml.Controls.IAnimatedVisualSource
|
||||
{
|
||||
// Animation duration: 1.017 seconds.
|
||||
internal const long c_durationTicks = 10166666;
|
||||
|
||||
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor)
|
||||
{
|
||||
object ignored = null;
|
||||
return TryCreateAnimatedVisual(compositor, out ignored);
|
||||
}
|
||||
|
||||
public Microsoft.UI.Xaml.Controls.IAnimatedVisual TryCreateAnimatedVisual(Compositor compositor, out object diagnostics)
|
||||
{
|
||||
diagnostics = null;
|
||||
|
||||
if (Sync_AnimatedVisual_UAPv15.IsRuntimeCompatible())
|
||||
{
|
||||
var res =
|
||||
new Sync_AnimatedVisual_UAPv15(
|
||||
compositor
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (Sync_AnimatedVisual_UAPv7.IsRuntimeCompatible())
|
||||
{
|
||||
var res =
|
||||
new Sync_AnimatedVisual_UAPv7(
|
||||
compositor
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of frames in the animation.
|
||||
/// </summary>
|
||||
public double FrameCount => 61d;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the frame rate of the animation.
|
||||
/// </summary>
|
||||
public double Framerate => 60d;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the animation.
|
||||
/// </summary>
|
||||
public TimeSpan Duration => TimeSpan.FromTicks(10166666);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a zero-based frame number to the corresponding progress value denoting the
|
||||
/// start of the frame.
|
||||
/// </summary>
|
||||
public double FrameToProgress(double frameNumber)
|
||||
{
|
||||
return frameNumber / 61d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a map from marker names to corresponding progress values.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, double> Markers =>
|
||||
new Dictionary<string, double>
|
||||
{
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Sets the color property with the given name, or does nothing if no such property
|
||||
/// exists.
|
||||
/// </summary>
|
||||
public void SetColorProperty(string propertyName, Color value)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the scalar property with the given name, or does nothing if no such property
|
||||
/// exists.
|
||||
/// </summary>
|
||||
public void SetScalarProperty(string propertyName, double value)
|
||||
{
|
||||
}
|
||||
|
||||
sealed class Sync_AnimatedVisual_UAPv15
|
||||
: Microsoft.UI.Xaml.Controls.IAnimatedVisual
|
||||
{
|
||||
const long c_durationTicks = 10166666;
|
||||
readonly Compositor _c;
|
||||
readonly ExpressionAnimation _reusableExpressionAnimation;
|
||||
AnimationController _animationController_0;
|
||||
CompositionColorBrush _colorBrush_AlmostDarkSlateGray_FF2D3846;
|
||||
ContainerVisual _root;
|
||||
|
||||
void BindProperty(
|
||||
CompositionObject target,
|
||||
string animatedPropertyName,
|
||||
string expression,
|
||||
string referenceParameterName,
|
||||
CompositionObject referencedObject)
|
||||
{
|
||||
_reusableExpressionAnimation.ClearAllParameters();
|
||||
_reusableExpressionAnimation.Expression = expression;
|
||||
_reusableExpressionAnimation.SetReferenceParameter(referenceParameterName, referencedObject);
|
||||
target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation);
|
||||
}
|
||||
|
||||
ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(float initialProgress, float initialValue, CompositionEasingFunction initialEasingFunction)
|
||||
{
|
||||
var result = _c.CreateScalarKeyFrameAnimation();
|
||||
result.Duration = TimeSpan.FromTicks(c_durationTicks);
|
||||
result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
|
||||
return result;
|
||||
}
|
||||
|
||||
CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2 transformMatrix, CompositionBrush fillBrush)
|
||||
{
|
||||
var result = _c.CreateSpriteShape(geometry);
|
||||
result.TransformMatrix = transformMatrix;
|
||||
result.FillBrush = fillBrush;
|
||||
return result;
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
AnimationController AnimationController_0()
|
||||
{
|
||||
var result = _animationController_0 = _c.CreateAnimationController();
|
||||
result.Pause();
|
||||
BindProperty(result, "Progress", "_.Progress", "_", _root);
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// - - ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
CanvasGeometry Geometry_0()
|
||||
{
|
||||
CanvasGeometry result;
|
||||
using (var builder = new CanvasPathBuilder(null))
|
||||
{
|
||||
builder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);
|
||||
builder.BeginFigure(new Vector2(11.7449999F, 5.09700012F));
|
||||
builder.AddCubicBezier(new Vector2(11.7449999F, -3.66000009F), new Vector2(4.56699991F, -10.9189997F), new Vector2(-4.25500011F, -10.9189997F));
|
||||
builder.AddCubicBezier(new Vector2(-8.6239996F, -10.9189997F), new Vector2(-12.7040005F, -9.20300007F), new Vector2(-15.7449999F, -6.08900023F));
|
||||
builder.AddLine(new Vector2(-12.8739996F, -3.32599998F));
|
||||
builder.AddCubicBezier(new Vector2(-10.5930004F, -5.66200018F), new Vector2(-7.53200006F, -6.94799995F), new Vector2(-4.25500011F, -6.94799995F));
|
||||
builder.AddCubicBezier(new Vector2(2.36199999F, -6.94799995F), new Vector2(7.74499989F, -1.47099996F), new Vector2(7.74499989F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(3.74499989F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(9.74499989F, 10.9189997F));
|
||||
builder.AddLine(new Vector2(15.7449999F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(11.7449999F, 5.09700012F));
|
||||
builder.EndFigure(CanvasFigureLoop.Closed);
|
||||
result = CanvasGeometry.CreatePath(builder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// - - ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
CanvasGeometry Geometry_1()
|
||||
{
|
||||
CanvasGeometry result;
|
||||
using (var builder = new CanvasPathBuilder(null))
|
||||
{
|
||||
builder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);
|
||||
builder.BeginFigure(new Vector2(4.25500011F, 6.94799995F));
|
||||
builder.AddCubicBezier(new Vector2(-2.36199999F, 6.94799995F), new Vector2(-7.74499989F, 1.472F), new Vector2(-7.74499989F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-3.74499989F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-9.74499989F, -10.9189997F));
|
||||
builder.AddLine(new Vector2(-15.7449999F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-11.7449999F, -5.09499979F));
|
||||
builder.AddCubicBezier(new Vector2(-11.7449999F, 3.66199994F), new Vector2(-4.56699991F, 10.9189997F), new Vector2(4.25500011F, 10.9189997F));
|
||||
builder.AddCubicBezier(new Vector2(8.6260004F, 10.9189997F), new Vector2(12.7060003F, 9.20300007F), new Vector2(15.7449999F, 6.08900023F));
|
||||
builder.AddLine(new Vector2(12.8739996F, 3.32500005F));
|
||||
builder.AddCubicBezier(new Vector2(10.5930004F, 5.66099977F), new Vector2(7.53200006F, 6.94799995F), new Vector2(4.25500011F, 6.94799995F));
|
||||
builder.EndFigure(CanvasFigureLoop.Closed);
|
||||
result = CanvasGeometry.CreatePath(builder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CompositionColorBrush ColorBrush_AlmostDarkSlateGray_FF2D3846()
|
||||
{
|
||||
return _colorBrush_AlmostDarkSlateGray_FF2D3846 = _c.CreateColorBrush(Color.FromArgb(0xFF, 0x2D, 0x38, 0x46));
|
||||
}
|
||||
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
CompositionContainerShape ContainerShape()
|
||||
{
|
||||
var result = _c.CreateContainerShape();
|
||||
result.CenterPoint = new Vector2(24F, 24F);
|
||||
var shapes = result.Shapes;
|
||||
// ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
shapes.Add(SpriteShape_0());
|
||||
// ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
shapes.Add(SpriteShape_1());
|
||||
result.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_0_to_360(), AnimationController_0());
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
CompositionPathGeometry PathGeometry_0()
|
||||
{
|
||||
return _c.CreatePathGeometry(new CompositionPath(Geometry_0()));
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
CompositionPathGeometry PathGeometry_1()
|
||||
{
|
||||
return _c.CreatePathGeometry(new CompositionPath(Geometry_1()));
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Path 1
|
||||
CompositionSpriteShape SpriteShape_0()
|
||||
{
|
||||
// Offset:<28.255, 18.903>
|
||||
var geometry = PathGeometry_0();
|
||||
var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 28.2549992F, 18.9029999F), ColorBrush_AlmostDarkSlateGray_FF2D3846());;
|
||||
return result;
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Path 1
|
||||
CompositionSpriteShape SpriteShape_1()
|
||||
{
|
||||
// Offset:<19.745, 29.096>
|
||||
var geometry = PathGeometry_1();
|
||||
var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 19.7450008F, 29.0960007F), _colorBrush_AlmostDarkSlateGray_FF2D3846);;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The root of the composition.
|
||||
ContainerVisual Root()
|
||||
{
|
||||
var result = _root = _c.CreateContainerVisual();
|
||||
var propertySet = result.Properties;
|
||||
propertySet.InsertScalar("Progress", 0F);
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
result.Children.InsertAtTop(ShapeVisual_0());
|
||||
return result;
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Rotation
|
||||
ScalarKeyFrameAnimation RotationAngleInDegreesScalarAnimation_0_to_360()
|
||||
{
|
||||
// Frame 0.
|
||||
var result = CreateScalarKeyFrameAnimation(0F, 0F, HoldThenStepEasingFunction());
|
||||
// Frame 61.
|
||||
result.InsertKeyFrame(1F, 360F, _c.CreateCubicBezierEasingFunction(new Vector2(0.314999998F, 0F), new Vector2(0.465000004F, 0.861999989F)));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
ShapeVisual ShapeVisual_0()
|
||||
{
|
||||
var result = _c.CreateShapeVisual();
|
||||
result.Size = new Vector2(48F, 48F);
|
||||
result.Shapes.Add(ContainerShape());
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// RotationAngleInDegrees
|
||||
StepEasingFunction HoldThenStepEasingFunction()
|
||||
{
|
||||
var result = _c.CreateStepEasingFunction();
|
||||
result.IsFinalStepSingleFrame = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Sync_AnimatedVisual_UAPv15(
|
||||
Compositor compositor
|
||||
)
|
||||
{
|
||||
_c = compositor;
|
||||
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
|
||||
Root();
|
||||
}
|
||||
|
||||
public Visual RootVisual => _root;
|
||||
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
|
||||
public Vector2 Size => new Vector2(48F, 48F);
|
||||
void IDisposable.Dispose() => _root?.Dispose();
|
||||
|
||||
internal static bool IsRuntimeCompatible()
|
||||
{
|
||||
return Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 15);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Sync_AnimatedVisual_UAPv7
|
||||
: Microsoft.UI.Xaml.Controls.IAnimatedVisual
|
||||
{
|
||||
const long c_durationTicks = 10166666;
|
||||
readonly Compositor _c;
|
||||
readonly ExpressionAnimation _reusableExpressionAnimation;
|
||||
CompositionColorBrush _colorBrush_AlmostDarkSlateGray_FF2D3846;
|
||||
ContainerVisual _root;
|
||||
|
||||
void BindProperty(
|
||||
CompositionObject target,
|
||||
string animatedPropertyName,
|
||||
string expression,
|
||||
string referenceParameterName,
|
||||
CompositionObject referencedObject)
|
||||
{
|
||||
_reusableExpressionAnimation.ClearAllParameters();
|
||||
_reusableExpressionAnimation.Expression = expression;
|
||||
_reusableExpressionAnimation.SetReferenceParameter(referenceParameterName, referencedObject);
|
||||
target.StartAnimation(animatedPropertyName, _reusableExpressionAnimation);
|
||||
}
|
||||
|
||||
ScalarKeyFrameAnimation CreateScalarKeyFrameAnimation(float initialProgress, float initialValue, CompositionEasingFunction initialEasingFunction)
|
||||
{
|
||||
var result = _c.CreateScalarKeyFrameAnimation();
|
||||
result.Duration = TimeSpan.FromTicks(c_durationTicks);
|
||||
result.InsertKeyFrame(initialProgress, initialValue, initialEasingFunction);
|
||||
return result;
|
||||
}
|
||||
|
||||
CompositionSpriteShape CreateSpriteShape(CompositionGeometry geometry, Matrix3x2 transformMatrix, CompositionBrush fillBrush)
|
||||
{
|
||||
var result = _c.CreateSpriteShape(geometry);
|
||||
result.TransformMatrix = transformMatrix;
|
||||
result.FillBrush = fillBrush;
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// - - ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
CanvasGeometry Geometry_0()
|
||||
{
|
||||
CanvasGeometry result;
|
||||
using (var builder = new CanvasPathBuilder(null))
|
||||
{
|
||||
builder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);
|
||||
builder.BeginFigure(new Vector2(11.7449999F, 5.09700012F));
|
||||
builder.AddCubicBezier(new Vector2(11.7449999F, -3.66000009F), new Vector2(4.56699991F, -10.9189997F), new Vector2(-4.25500011F, -10.9189997F));
|
||||
builder.AddCubicBezier(new Vector2(-8.6239996F, -10.9189997F), new Vector2(-12.7040005F, -9.20300007F), new Vector2(-15.7449999F, -6.08900023F));
|
||||
builder.AddLine(new Vector2(-12.8739996F, -3.32599998F));
|
||||
builder.AddCubicBezier(new Vector2(-10.5930004F, -5.66200018F), new Vector2(-7.53200006F, -6.94799995F), new Vector2(-4.25500011F, -6.94799995F));
|
||||
builder.AddCubicBezier(new Vector2(2.36199999F, -6.94799995F), new Vector2(7.74499989F, -1.47099996F), new Vector2(7.74499989F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(3.74499989F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(9.74499989F, 10.9189997F));
|
||||
builder.AddLine(new Vector2(15.7449999F, 5.09700012F));
|
||||
builder.AddLine(new Vector2(11.7449999F, 5.09700012F));
|
||||
builder.EndFigure(CanvasFigureLoop.Closed);
|
||||
result = CanvasGeometry.CreatePath(builder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// - - ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
CanvasGeometry Geometry_1()
|
||||
{
|
||||
CanvasGeometry result;
|
||||
using (var builder = new CanvasPathBuilder(null))
|
||||
{
|
||||
builder.SetFilledRegionDetermination(CanvasFilledRegionDetermination.Winding);
|
||||
builder.BeginFigure(new Vector2(4.25500011F, 6.94799995F));
|
||||
builder.AddCubicBezier(new Vector2(-2.36199999F, 6.94799995F), new Vector2(-7.74499989F, 1.472F), new Vector2(-7.74499989F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-3.74499989F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-9.74499989F, -10.9189997F));
|
||||
builder.AddLine(new Vector2(-15.7449999F, -5.09499979F));
|
||||
builder.AddLine(new Vector2(-11.7449999F, -5.09499979F));
|
||||
builder.AddCubicBezier(new Vector2(-11.7449999F, 3.66199994F), new Vector2(-4.56699991F, 10.9189997F), new Vector2(4.25500011F, 10.9189997F));
|
||||
builder.AddCubicBezier(new Vector2(8.6260004F, 10.9189997F), new Vector2(12.7060003F, 9.20300007F), new Vector2(15.7449999F, 6.08900023F));
|
||||
builder.AddLine(new Vector2(12.8739996F, 3.32500005F));
|
||||
builder.AddCubicBezier(new Vector2(10.5930004F, 5.66099977F), new Vector2(7.53200006F, 6.94799995F), new Vector2(4.25500011F, 6.94799995F));
|
||||
builder.EndFigure(CanvasFigureLoop.Closed);
|
||||
result = CanvasGeometry.CreatePath(builder);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CompositionColorBrush ColorBrush_AlmostDarkSlateGray_FF2D3846()
|
||||
{
|
||||
return _colorBrush_AlmostDarkSlateGray_FF2D3846 = _c.CreateColorBrush(Color.FromArgb(0xFF, 0x2D, 0x38, 0x46));
|
||||
}
|
||||
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
CompositionContainerShape ContainerShape()
|
||||
{
|
||||
var result = _c.CreateContainerShape();
|
||||
result.CenterPoint = new Vector2(24F, 24F);
|
||||
var shapes = result.Shapes;
|
||||
// ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
shapes.Add(SpriteShape_0());
|
||||
// ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
shapes.Add(SpriteShape_1());
|
||||
result.StartAnimation("RotationAngleInDegrees", RotationAngleInDegreesScalarAnimation_0_to_360());
|
||||
var controller = result.TryGetAnimationController("RotationAngleInDegrees");
|
||||
controller.Pause();
|
||||
BindProperty(controller, "Progress", "_.Progress", "_", _root);
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// ShapeGroup: Group 2 Offset:<28.255, 18.903>
|
||||
CompositionPathGeometry PathGeometry_0()
|
||||
{
|
||||
return _c.CreatePathGeometry(new CompositionPath(Geometry_0()));
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// ShapeGroup: Group 1 Offset:<19.745, 29.096>
|
||||
CompositionPathGeometry PathGeometry_1()
|
||||
{
|
||||
return _c.CreatePathGeometry(new CompositionPath(Geometry_1()));
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Path 1
|
||||
CompositionSpriteShape SpriteShape_0()
|
||||
{
|
||||
// Offset:<28.255, 18.903>
|
||||
var geometry = PathGeometry_0();
|
||||
var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 28.2549992F, 18.9029999F), ColorBrush_AlmostDarkSlateGray_FF2D3846());;
|
||||
return result;
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Path 1
|
||||
CompositionSpriteShape SpriteShape_1()
|
||||
{
|
||||
// Offset:<19.745, 29.096>
|
||||
var geometry = PathGeometry_1();
|
||||
var result = CreateSpriteShape(geometry, new Matrix3x2(1F, 0F, 0F, 1F, 19.7450008F, 29.0960007F), _colorBrush_AlmostDarkSlateGray_FF2D3846);;
|
||||
return result;
|
||||
}
|
||||
|
||||
// The root of the composition.
|
||||
ContainerVisual Root()
|
||||
{
|
||||
var result = _root = _c.CreateContainerVisual();
|
||||
var propertySet = result.Properties;
|
||||
propertySet.InsertScalar("Progress", 0F);
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
result.Children.InsertAtTop(ShapeVisual_0());
|
||||
return result;
|
||||
}
|
||||
|
||||
// - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// Rotation
|
||||
ScalarKeyFrameAnimation RotationAngleInDegreesScalarAnimation_0_to_360()
|
||||
{
|
||||
// Frame 0.
|
||||
var result = CreateScalarKeyFrameAnimation(0F, 0F, HoldThenStepEasingFunction());
|
||||
// Frame 61.
|
||||
result.InsertKeyFrame(1F, 360F, _c.CreateCubicBezierEasingFunction(new Vector2(0.314999998F, 0F), new Vector2(0.465000004F, 0.861999989F)));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
ShapeVisual ShapeVisual_0()
|
||||
{
|
||||
var result = _c.CreateShapeVisual();
|
||||
result.Size = new Vector2(48F, 48F);
|
||||
result.Shapes.Add(ContainerShape());
|
||||
return result;
|
||||
}
|
||||
|
||||
// - - Shape tree root for layer: main_library_shelf_icon_sync Outlines
|
||||
// RotationAngleInDegrees
|
||||
StepEasingFunction HoldThenStepEasingFunction()
|
||||
{
|
||||
var result = _c.CreateStepEasingFunction();
|
||||
result.IsFinalStepSingleFrame = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Sync_AnimatedVisual_UAPv7(
|
||||
Compositor compositor
|
||||
)
|
||||
{
|
||||
_c = compositor;
|
||||
_reusableExpressionAnimation = compositor.CreateExpressionAnimation();
|
||||
Root();
|
||||
}
|
||||
|
||||
public Visual RootVisual => _root;
|
||||
public TimeSpan Duration => TimeSpan.FromTicks(c_durationTicks);
|
||||
public Vector2 Size => new Vector2(48F, 48F);
|
||||
void IDisposable.Dispose() => _root?.Dispose();
|
||||
|
||||
internal static bool IsRuntimeCompatible()
|
||||
{
|
||||
return Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+147
-51
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -48,7 +49,8 @@ public partial class App : WinoApplication,
|
||||
IRecipient<NewCalendarSynchronizationRequested>,
|
||||
IRecipient<AccountCreatedMessage>,
|
||||
IRecipient<AccountRemovedMessage>,
|
||||
IRecipient<GetStartedFromWelcomeRequested>
|
||||
IRecipient<GetStartedFromWelcomeRequested>,
|
||||
IRecipient<WelcomeImportCompletedMessage>
|
||||
{
|
||||
private const int InboxSyncsPerFullSync = 20;
|
||||
private const string ToggleDefaultModeLaunchArgument = "--mode=toggle-default";
|
||||
@@ -63,7 +65,7 @@ public partial class App : WinoApplication,
|
||||
private bool _isExiting;
|
||||
private CancellationTokenSource? _autoSynchronizationLoopCts;
|
||||
private readonly SemaphoreSlim _autoSynchronizationSemaphore = new(1, 1);
|
||||
private readonly Dictionary<Guid, int> _inboxSyncCounters = [];
|
||||
private readonly ConcurrentDictionary<Guid, int> _inboxSyncCounters = [];
|
||||
private NativeTrayIcon? _trayIcon;
|
||||
|
||||
internal bool IsExiting => _isExiting;
|
||||
@@ -756,7 +758,9 @@ public partial class App : WinoApplication,
|
||||
/// Creates the main window without activating it.
|
||||
/// Used for both normal launch and startup task launch (tray only).
|
||||
/// </summary>
|
||||
private void CreateWindow(Microsoft.UI.Xaml.LaunchActivatedEventArgs? args, string? forcedLaunchArguments = null)
|
||||
private void CreateWindow(Microsoft.UI.Xaml.LaunchActivatedEventArgs? args,
|
||||
string? forcedLaunchArguments = null,
|
||||
ShellModeActivationContext? activationContextOverride = null)
|
||||
{
|
||||
LogActivation("Creating main window.");
|
||||
|
||||
@@ -769,14 +773,28 @@ public partial class App : WinoApplication,
|
||||
|
||||
windowManager.SetPrimaryNavigationFrame(WinoWindowKind.Shell, shellWindow.GetMainFrame());
|
||||
|
||||
var navigationService = Services.GetRequiredService<INavigationService>();
|
||||
var defaultMode = _preferencesService?.DefaultApplicationMode ?? WinoApplicationMode.Mail;
|
||||
var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
|
||||
if (activationContextOverride != null)
|
||||
{
|
||||
var targetMode = !string.IsNullOrWhiteSpace(forcedLaunchArguments)
|
||||
? AppModeActivationResolver.Resolve(forcedLaunchArguments, null, null, defaultMode)
|
||||
: TryResolveActivationMode(activationArgs, defaultMode, out var resolvedActivationMode)
|
||||
? resolvedActivationMode
|
||||
: AppModeActivationResolver.Resolve(args?.Arguments, GetCurrentLaunchTileId(), Environment.CommandLine, defaultMode);
|
||||
|
||||
navigationService.ChangeApplicationMode(targetMode, activationContextOverride);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(forcedLaunchArguments))
|
||||
{
|
||||
shellWindow.HandleAppActivation(forcedLaunchArguments);
|
||||
return;
|
||||
}
|
||||
|
||||
var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
|
||||
if (activationArgs.Kind == ExtendedActivationKind.Launch &&
|
||||
activationArgs.Data is ILaunchActivatedEventArgs launchArgs)
|
||||
{
|
||||
@@ -791,7 +809,7 @@ public partial class App : WinoApplication,
|
||||
return;
|
||||
}
|
||||
|
||||
if (TryResolveActivationMode(activationArgs, _preferencesService?.DefaultApplicationMode ?? WinoApplicationMode.Mail, out var activationMode))
|
||||
if (TryResolveActivationMode(activationArgs, defaultMode, out var activationMode))
|
||||
{
|
||||
shellWindow.HandleAppActivation(GetModeLaunchArgument(activationMode));
|
||||
return;
|
||||
@@ -859,6 +877,7 @@ public partial class App : WinoApplication,
|
||||
WeakReferenceMessenger.Default.Register<AccountCreatedMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<AccountRemovedMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<GetStartedFromWelcomeRequested>(this);
|
||||
WeakReferenceMessenger.Default.Register<WelcomeImportCompletedMessage>(this);
|
||||
}
|
||||
|
||||
public async void Receive(NewMailSynchronizationRequested message)
|
||||
@@ -882,6 +901,11 @@ public partial class App : WinoApplication,
|
||||
syncResult.CompletedState,
|
||||
message.Options.GroupedSynchronizationTrackingId));
|
||||
|
||||
if (syncResult.CompletedState is SynchronizationCompletedState.Success or SynchronizationCompletedState.PartiallyCompleted)
|
||||
{
|
||||
await ClearInvalidCredentialAttentionIfNeededAsync(message.Options.AccountId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (syncResult.CompletedState == SynchronizationCompletedState.Failed ||
|
||||
syncResult.CompletedState == SynchronizationCompletedState.PartiallyCompleted)
|
||||
{
|
||||
@@ -906,7 +930,12 @@ public partial class App : WinoApplication,
|
||||
var dialogService = Services.GetRequiredService<IMailDialogService>();
|
||||
dialogService.InfoBarMessage(
|
||||
Translator.Info_SyncFailedTitle,
|
||||
Translator.Exception_FailedToSynchronizeFolders,
|
||||
message.Options.Type switch
|
||||
{
|
||||
CalendarSynchronizationType.CalendarMetadata => Translator.Exception_FailedToSynchronizeCalendarMetadata,
|
||||
CalendarSynchronizationType.Strict => Translator.Exception_FailedToSynchronizeCalendarData,
|
||||
_ => Translator.Exception_FailedToSynchronizeCalendarEvents
|
||||
},
|
||||
InfoBarMessageType.Error);
|
||||
}
|
||||
}
|
||||
@@ -942,6 +971,47 @@ public partial class App : WinoApplication,
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(WelcomeImportCompletedMessage message)
|
||||
{
|
||||
_hasConfiguredAccounts = message.ImportedMailboxCount > 0;
|
||||
|
||||
var windowManager = Services.GetRequiredService<IWinoWindowManager>();
|
||||
if (windowManager.GetWindow(WinoWindowKind.Welcome) == null)
|
||||
return;
|
||||
|
||||
MainWindow?.DispatcherQueue?.TryEnqueue(async () =>
|
||||
{
|
||||
if (_preferencesService != null)
|
||||
{
|
||||
_preferencesService.PreferenceChanged -= PreferencesServiceChanged;
|
||||
_preferencesService.PreferenceChanged += PreferencesServiceChanged;
|
||||
}
|
||||
|
||||
CreateWindow(
|
||||
null,
|
||||
GetModeLaunchArgument(WinoApplicationMode.Mail),
|
||||
new ShellModeActivationContext
|
||||
{
|
||||
SuppressStartupFlows = true
|
||||
});
|
||||
|
||||
await LoadInitialWinoAccountAsync();
|
||||
CloseWelcomeWindowIfPresent();
|
||||
|
||||
if (MainWindow != null)
|
||||
{
|
||||
await ActivateWindowAsync(MainWindow);
|
||||
}
|
||||
|
||||
RestartAutoSynchronizationLoop();
|
||||
|
||||
Services.GetRequiredService<IMailDialogService>().InfoBarMessage(
|
||||
Translator.GeneralTitle_Info,
|
||||
Translator.WinoAccount_Management_ImportReloginReminder,
|
||||
InfoBarMessageType.Information);
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(AccountRemovedMessage message)
|
||||
{
|
||||
var windowManager = Services.GetRequiredService<IWinoWindowManager>();
|
||||
@@ -1078,52 +1148,16 @@ public partial class App : WinoApplication,
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
var currentAccountIds = accounts.Select(a => a.Id).ToHashSet();
|
||||
_inboxSyncCounters.Keys.Where(a => !currentAccountIds.Contains(a)).ToList().ForEach(a => _inboxSyncCounters.Remove(a));
|
||||
|
||||
foreach (var account in accounts)
|
||||
foreach (var staleAccountId in _inboxSyncCounters.Keys.Where(a => !currentAccountIds.Contains(a)).ToList())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (_synchronizationManager.IsAccountSynchronizing(account.Id))
|
||||
continue;
|
||||
|
||||
var inboxSyncOptions = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.InboxOnly
|
||||
};
|
||||
|
||||
var inboxSyncResult = await _synchronizationManager.SynchronizeMailAsync(inboxSyncOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (inboxSyncResult.CompletedState is SynchronizationCompletedState.Success or SynchronizationCompletedState.PartiallyCompleted)
|
||||
{
|
||||
_inboxSyncCounters.TryAdd(account.Id, 0);
|
||||
_inboxSyncCounters[account.Id]++;
|
||||
|
||||
if (_inboxSyncCounters[account.Id] >= InboxSyncsPerFullSync)
|
||||
{
|
||||
var fullSyncOptions = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
};
|
||||
|
||||
await _synchronizationManager.SynchronizeMailAsync(fullSyncOptions, cancellationToken).ConfigureAwait(false);
|
||||
_inboxSyncCounters[account.Id] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!account.IsCalendarAccessGranted)
|
||||
continue;
|
||||
|
||||
var calendarOptions = new CalendarSynchronizationOptions()
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = CalendarSynchronizationType.CalendarMetadata
|
||||
};
|
||||
|
||||
await _synchronizationManager.SynchronizeCalendarAsync(calendarOptions, cancellationToken).ConfigureAwait(false);
|
||||
_inboxSyncCounters.TryRemove(staleAccountId, out _);
|
||||
}
|
||||
|
||||
var synchronizationTasks = accounts
|
||||
.Select(account => ExecuteAutoSynchronizationForAccountAsync(account, cancellationToken))
|
||||
.ToList();
|
||||
|
||||
await Task.WhenAll(synchronizationTasks).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -1134,6 +1168,68 @@ public partial class App : WinoApplication,
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteAutoSynchronizationForAccountAsync(Wino.Core.Domain.Entities.Shared.MailAccount account, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_synchronizationManager == null)
|
||||
return;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (_synchronizationManager.IsAccountSynchronizing(account.Id))
|
||||
return;
|
||||
|
||||
var inboxSyncOptions = new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.InboxOnly
|
||||
};
|
||||
|
||||
var inboxSyncResult = await _synchronizationManager.SynchronizeMailAsync(inboxSyncOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (inboxSyncResult.CompletedState is SynchronizationCompletedState.Success or SynchronizationCompletedState.PartiallyCompleted)
|
||||
{
|
||||
await ClearInvalidCredentialAttentionIfNeededAsync(account.Id).ConfigureAwait(false);
|
||||
|
||||
var inboxSyncCount = _inboxSyncCounters.AddOrUpdate(account.Id, 1, (_, currentCount) => currentCount + 1);
|
||||
|
||||
if (inboxSyncCount >= InboxSyncsPerFullSync)
|
||||
{
|
||||
var fullSyncOptions = new MailSynchronizationOptions
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
};
|
||||
|
||||
await _synchronizationManager.SynchronizeMailAsync(fullSyncOptions, cancellationToken).ConfigureAwait(false);
|
||||
_inboxSyncCounters[account.Id] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!account.IsCalendarAccessGranted)
|
||||
return;
|
||||
|
||||
var calendarOptions = new CalendarSynchronizationOptions
|
||||
{
|
||||
AccountId = account.Id,
|
||||
Type = CalendarSynchronizationType.CalendarMetadata
|
||||
};
|
||||
|
||||
await _synchronizationManager.SynchronizeCalendarAsync(calendarOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task ClearInvalidCredentialAttentionIfNeededAsync(Guid accountId)
|
||||
{
|
||||
if (_accountService == null)
|
||||
return;
|
||||
|
||||
var account = await _accountService.GetAccountAsync(accountId).ConfigureAwait(false);
|
||||
|
||||
if (account?.AttentionReason != AccountAttentionReason.InvalidCredentials)
|
||||
return;
|
||||
|
||||
await _accountService.ClearAccountAttentionAsync(accountId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles activation redirected from another instance (single-instancing).
|
||||
/// This is called when a second instance tries to launch and redirects to this existing instance.
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
TargetType="Button">
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SystemColorControlAccentBrush}" />
|
||||
<!--<Setter Property="Foreground" Value="{ThemeResource SystemColorControlAccentBrush}" />-->
|
||||
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
@@ -27,7 +28,7 @@
|
||||
<Grid Margin="4,0,0,0" Background="Transparent">
|
||||
<Grid Background="Transparent" ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="64" />
|
||||
<ColumnDefinition Width="128" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<UserControl
|
||||
x:Class="Wino.Mail.WinUI.Controls.SyncAnimationControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animatedvisuals="using:Wino.Mail.WinUI.AnimatedVisuals">
|
||||
|
||||
<AnimatedVisualPlayer
|
||||
x:Name="AnimationPlayer"
|
||||
AutoPlay="True"
|
||||
Stretch="Uniform">
|
||||
<animatedvisuals:SyncRefreshAnimation />
|
||||
</AnimatedVisualPlayer>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,54 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Mail.WinUI.Controls;
|
||||
|
||||
public sealed partial class SyncAnimationControl : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(
|
||||
nameof(IsPlaying),
|
||||
typeof(bool),
|
||||
typeof(SyncAnimationControl),
|
||||
new PropertyMetadata(true, OnIsPlayingChanged));
|
||||
|
||||
public bool IsPlaying
|
||||
{
|
||||
get => (bool)GetValue(IsPlayingProperty);
|
||||
set => SetValue(IsPlayingProperty, value);
|
||||
}
|
||||
|
||||
public SyncAnimationControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (IsPlaying)
|
||||
{
|
||||
PlayAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnIsPlayingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = (SyncAnimationControl)d;
|
||||
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
control.PlayAnimation();
|
||||
}
|
||||
else
|
||||
{
|
||||
control.AnimationPlayer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayAnimation()
|
||||
{
|
||||
#pragma warning disable CS4014 // Fire-and-forget is intentional for looped animation playback.
|
||||
AnimationPlayer.PlayAsync(0, 1, looped: true);
|
||||
#pragma warning restore CS4014
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.WhatIsNewDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Wino.Mail.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">480</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">560</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">480</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">700</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<Grid RowSpacing="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<controls:UpdateNotesFlipViewControl x:Name="UpdateNotesControl" Sections="{x:Bind Sections, Mode=OneTime}" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Button
|
||||
x:Name="GetStartedButton"
|
||||
Click="OnGetStartedClicked"
|
||||
Content="{x:Bind domain:Translator.WhatIsNew_GetStartedButton}"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
Visibility="Collapsed" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -1,54 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Updates;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class WhatIsNewDialog : ContentDialog
|
||||
{
|
||||
private readonly IUpdateManager _updateManager;
|
||||
|
||||
public List<UpdateNoteSection> Sections { get; }
|
||||
|
||||
private bool _canClose = false;
|
||||
|
||||
public WhatIsNewDialog(UpdateNotes notes, IUpdateManager updateManager)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_updateManager = updateManager;
|
||||
Sections = notes.Sections;
|
||||
|
||||
// Show the Get Started button immediately when there is only one page.
|
||||
UpdateNotesControl.SelectedIndexChanged += OnUpdateSectionChanged;
|
||||
UpdateGetStartedButtonVisibility(UpdateNotesControl.SelectedIndex);
|
||||
Closing += OnDialogClosing;
|
||||
}
|
||||
|
||||
private void OnUpdateSectionChanged(object? sender, int selectedIndex)
|
||||
=> UpdateGetStartedButtonVisibility(selectedIndex);
|
||||
|
||||
private void UpdateGetStartedButtonVisibility(int selectedIndex)
|
||||
{
|
||||
GetStartedButton.Visibility = selectedIndex == Sections.Count - 1
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void OnDialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args)
|
||||
{
|
||||
// Only allow closing when Get Started button was clicked.
|
||||
if (!_canClose)
|
||||
args.Cancel = true;
|
||||
}
|
||||
|
||||
private void OnGetStartedClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
GetStartedButton.IsEnabled = false;
|
||||
_updateManager.MarkUpdateNotesAsSeen();
|
||||
_canClose = true;
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.WinoAccountSyncExportDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="ExportClicked"
|
||||
PrimaryButtonStyle="{ThemeResource AccentButtonStyle}"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Export, Mode=OneTime}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Close, Mode=OneTime}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
Title="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_Title, Mode=OneTime}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">520</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">520</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Spacing="16">
|
||||
<TextBlock
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_Description, Mode=OneTime}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
<CheckBox
|
||||
x:Name="PreferencesCheckBox"
|
||||
Checked="SelectionChanged"
|
||||
Content="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_IncludePreferences, Mode=OneTime}"
|
||||
IsChecked="True"
|
||||
Unchecked="SelectionChanged" />
|
||||
|
||||
<StackPanel Spacing="8">
|
||||
<CheckBox
|
||||
x:Name="AccountsCheckBox"
|
||||
Checked="SelectionChanged"
|
||||
Content="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_IncludeAccounts, Mode=OneTime}"
|
||||
IsChecked="True"
|
||||
Unchecked="SelectionChanged" />
|
||||
|
||||
<Border
|
||||
Padding="12"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
CornerRadius="10">
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_AccountsDisclaimer, Mode=OneTime}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_AccountsRelogin, Mode=OneTime}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
x:Name="ProgressPanel"
|
||||
Spacing="8"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Management_ExportDialog_InProgress, Mode=OneTime}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<ProgressBar IsIndeterminate="True" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class WinoAccountSyncExportDialog : ContentDialog
|
||||
{
|
||||
private readonly IWinoAccountDataSyncService _syncService;
|
||||
private bool _isBusy;
|
||||
|
||||
public WinoAccountSyncExportDialog(IWinoAccountDataSyncService syncService)
|
||||
{
|
||||
_syncService = syncService;
|
||||
InitializeComponent();
|
||||
UpdateButtonState();
|
||||
}
|
||||
|
||||
public WinoAccountSyncExportResult? Result { get; private set; }
|
||||
|
||||
public Exception? FailureException { get; private set; }
|
||||
|
||||
private async void ExportClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
args.Cancel = true;
|
||||
|
||||
if (!HasSelection())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var deferral = args.GetDeferral();
|
||||
|
||||
try
|
||||
{
|
||||
SetBusyState(true);
|
||||
FailureException = null;
|
||||
Result = await _syncService.ExportAsync(new WinoAccountSyncSelection(
|
||||
PreferencesCheckBox.IsChecked == true,
|
||||
AccountsCheckBox.IsChecked == true));
|
||||
Hide();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
FailureException = ex;
|
||||
Hide();
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetBusyState(false);
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectionChanged(object sender, RoutedEventArgs e)
|
||||
=> UpdateButtonState();
|
||||
|
||||
private void SetBusyState(bool isBusy)
|
||||
{
|
||||
_isBusy = isBusy;
|
||||
ProgressPanel.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
|
||||
IsSecondaryButtonEnabled = !isBusy;
|
||||
UpdateButtonState();
|
||||
}
|
||||
|
||||
private void UpdateButtonState()
|
||||
=> IsPrimaryButtonEnabled = !_isBusy && HasSelection();
|
||||
|
||||
private bool HasSelection()
|
||||
=> PreferencesCheckBox.IsChecked == true || AccountsCheckBox.IsChecked == true;
|
||||
}
|
||||
@@ -23,7 +23,9 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
IRecipient<CalendarListAdded>,
|
||||
IRecipient<CalendarListUpdated>,
|
||||
IRecipient<CalendarListDeleted>,
|
||||
IRecipient<AccountRemovedMessage>
|
||||
IRecipient<AccountRemovedMessage>,
|
||||
IRecipient<AccountUpdatedMessage>,
|
||||
IRecipient<AccountCalendarSynchronizationStateChanged>
|
||||
{
|
||||
private readonly object _calendarStateLock = new();
|
||||
|
||||
@@ -41,6 +43,9 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
[ObservableProperty]
|
||||
public partial ReadOnlyObservableGroupedCollection<MailAccount, AccountCalendarViewModel> GroupedCalendars { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsAnySynchronizationInProgress { get; set; }
|
||||
|
||||
public IEnumerable<AccountCalendarViewModel> ActiveCalendars
|
||||
{
|
||||
get
|
||||
@@ -84,6 +89,8 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
Messenger.Register<CalendarListUpdated>(this);
|
||||
Messenger.Register<CalendarListDeleted>(this);
|
||||
Messenger.Register<AccountRemovedMessage>(this);
|
||||
Messenger.Register<AccountUpdatedMessage>(this);
|
||||
Messenger.Register<AccountCalendarSynchronizationStateChanged>(this);
|
||||
}
|
||||
|
||||
private void SingleGroupCalendarCollectiveStateChanged(object? sender, EventArgs e)
|
||||
@@ -114,6 +121,8 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
group.Add(calendar);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAggregateSynchronizationState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +149,8 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
_internalGroupedCalendars.Remove(group);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAggregateSynchronizationState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,4 +351,60 @@ public partial class AccountCalendarStateService : ObservableRecipient,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(AccountUpdatedMessage message)
|
||||
{
|
||||
if (Dispatcher != null)
|
||||
{
|
||||
await Dispatcher.ExecuteOnUIThread(() => UpdateGroupedAccount(message.Account));
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateGroupedAccount(message.Account);
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(AccountCalendarSynchronizationStateChanged message)
|
||||
{
|
||||
if (Dispatcher != null)
|
||||
{
|
||||
await Dispatcher.ExecuteOnUIThread(() => UpdateCalendarSynchronizationState(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateCalendarSynchronizationState(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGroupedAccount(MailAccount updatedAccount)
|
||||
{
|
||||
GroupedAccountCalendarViewModel? groupedAccount;
|
||||
lock (_calendarStateLock)
|
||||
{
|
||||
groupedAccount = _internalGroupedAccountCalendars.FirstOrDefault(a => a.Account.Id == updatedAccount.Id);
|
||||
}
|
||||
|
||||
groupedAccount?.UpdateAccount(updatedAccount);
|
||||
}
|
||||
|
||||
private void UpdateCalendarSynchronizationState(AccountCalendarSynchronizationStateChanged message)
|
||||
{
|
||||
GroupedAccountCalendarViewModel? groupedAccount;
|
||||
lock (_calendarStateLock)
|
||||
{
|
||||
groupedAccount = _internalGroupedAccountCalendars.FirstOrDefault(a => a.Account.Id == message.AccountId);
|
||||
}
|
||||
|
||||
if (groupedAccount == null)
|
||||
return;
|
||||
|
||||
groupedAccount.IsSynchronizationInProgress = message.IsSynchronizationInProgress;
|
||||
groupedAccount.SynchronizationStatus = message.SynchronizationStatus;
|
||||
UpdateAggregateSynchronizationState();
|
||||
}
|
||||
|
||||
private void UpdateAggregateSynchronizationState()
|
||||
{
|
||||
IsAnySynchronizationInProgress = _internalGroupedAccountCalendars.Any(a => a.IsSynchronizationInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,14 +28,16 @@ namespace Wino.Services;
|
||||
public class DialogService : DialogServiceBase, IMailDialogService
|
||||
{
|
||||
private readonly IWinoAccountProfileService _winoAccountProfileService;
|
||||
private readonly IWinoAccountDataSyncService _winoAccountDataSyncService;
|
||||
|
||||
public DialogService(INewThemeService themeService,
|
||||
IConfigurationService configurationService,
|
||||
IApplicationResourceManager<ResourceDictionary> applicationResourceManager,
|
||||
IUpdateManager updateManager,
|
||||
IWinoAccountProfileService winoAccountProfileService) : base(themeService, configurationService, applicationResourceManager, updateManager)
|
||||
IWinoAccountProfileService winoAccountProfileService,
|
||||
IWinoAccountDataSyncService winoAccountDataSyncService) : base(themeService, configurationService, applicationResourceManager)
|
||||
{
|
||||
_winoAccountProfileService = winoAccountProfileService;
|
||||
_winoAccountDataSyncService = winoAccountDataSyncService;
|
||||
}
|
||||
|
||||
public async Task<ICreateAccountAliasDialog> ShowCreateAccountAliasDialogAsync()
|
||||
@@ -279,4 +281,21 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
||||
|
||||
return dialog.Result;
|
||||
}
|
||||
|
||||
public async Task<WinoAccountSyncExportResult?> ShowWinoAccountExportDialogAsync()
|
||||
{
|
||||
var dialog = new WinoAccountSyncExportDialog(_winoAccountDataSyncService)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
if (dialog.FailureException != null)
|
||||
{
|
||||
throw dialog.FailureException;
|
||||
}
|
||||
|
||||
return dialog.Result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.Domain.Models.Common;
|
||||
using Wino.Core.Domain.Models.Printing;
|
||||
using Wino.Core.Domain.Models.Updates;
|
||||
using Wino.Dialogs;
|
||||
using Wino.Mail.WinUI.Dialogs;
|
||||
using Wino.Mail.WinUI.Extensions;
|
||||
@@ -31,16 +30,13 @@ public class DialogServiceBase : IDialogServiceBase
|
||||
|
||||
protected INewThemeService ThemeService { get; }
|
||||
protected IConfigurationService ConfigurationService { get; }
|
||||
protected IUpdateManager UpdateManager { get; }
|
||||
|
||||
protected IApplicationResourceManager<ResourceDictionary> ApplicationResourceManager { get; }
|
||||
|
||||
public DialogServiceBase(INewThemeService themeService, IConfigurationService configurationService, IApplicationResourceManager<ResourceDictionary> applicationResourceManager, IUpdateManager updateManager)
|
||||
public DialogServiceBase(INewThemeService themeService, IConfigurationService configurationService, IApplicationResourceManager<ResourceDictionary> applicationResourceManager)
|
||||
{
|
||||
ThemeService = themeService;
|
||||
ConfigurationService = configurationService;
|
||||
ApplicationResourceManager = applicationResourceManager;
|
||||
UpdateManager = updateManager;
|
||||
}
|
||||
|
||||
protected XamlRoot? GetXamlRoot()
|
||||
@@ -392,14 +388,4 @@ public class DialogServiceBase : IDialogServiceBase
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ShowWhatIsNewDialogAsync(UpdateNotes notes)
|
||||
{
|
||||
var dialog = new WhatIsNewDialog(notes, UpdateManager)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,10 +219,13 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
public bool ChangeApplicationMode(WinoApplicationMode mode)
|
||||
=> ExecuteOnNavigationThread(() => ChangeApplicationModeInternal(mode));
|
||||
|
||||
public bool ChangeApplicationMode(WinoApplicationMode mode, ShellModeActivationContext activationContext)
|
||||
=> ExecuteOnNavigationThread(() => ChangeApplicationModeInternal(mode, activationContext));
|
||||
|
||||
public bool CanGoBack()
|
||||
=> ExecuteOnNavigationThread(CanGoBackInternal);
|
||||
|
||||
private bool ChangeApplicationModeInternal(WinoApplicationMode mode, object? activationParameter = null)
|
||||
private bool ChangeApplicationModeInternal(WinoApplicationMode mode, ShellModeActivationContext? activationContext = null)
|
||||
{
|
||||
var coreFrame = GetCoreFrameInternal(NavigationReferenceFrame.ShellFrame);
|
||||
|
||||
@@ -254,7 +257,8 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
shell.ActivateMode(mode, new ShellModeActivationContext
|
||||
{
|
||||
IsInitialActivation = isInitialShellNavigation,
|
||||
Parameter = activationParameter
|
||||
SuppressStartupFlows = activationContext?.SuppressStartupFlows ?? false,
|
||||
Parameter = activationContext?.Parameter
|
||||
});
|
||||
|
||||
ResetCurrentModeBackStackState();
|
||||
@@ -280,7 +284,10 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
{
|
||||
if (_statePersistanceService.ApplicationMode != WinoApplicationMode.Settings)
|
||||
{
|
||||
return ChangeApplicationModeInternal(WinoApplicationMode.Settings, settingsTarget);
|
||||
return ChangeApplicationModeInternal(WinoApplicationMode.Settings, new ShellModeActivationContext
|
||||
{
|
||||
Parameter = settingsTarget
|
||||
});
|
||||
}
|
||||
|
||||
page = WinoPage.SettingsPage;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,9 +10,9 @@
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel
|
||||
MaxWidth="860"
|
||||
Padding="36,28,36,36"
|
||||
HorizontalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
|
||||
Spacing="24">
|
||||
|
||||
<!-- Page Header -->
|
||||
|
||||
@@ -219,6 +219,11 @@
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="Manage account settings" />
|
||||
<TextBlock Margin="20,0,0,12" Text="Add new account or manage individidual account settings." />
|
||||
<Button
|
||||
Margin="20,0,0,12"
|
||||
HorizontalAlignment="Left"
|
||||
Click="ManageAccountsClicked"
|
||||
Content="{x:Bind domain:Translator.MenuManageAccounts}" />
|
||||
<ListView
|
||||
x:Name="AccountsList"
|
||||
IsItemClickEnabled="False"
|
||||
|
||||
@@ -51,6 +51,11 @@ public sealed partial class SettingOptionsPage : SettingOptionsPageAbstract
|
||||
ViewModel.NavigateToAddAccount();
|
||||
}
|
||||
|
||||
private void ManageAccountsClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.NavigateToManageAccounts();
|
||||
}
|
||||
|
||||
private void SettingsSearchTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||
{
|
||||
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput || string.IsNullOrWhiteSpace(sender.Text))
|
||||
|
||||
@@ -130,6 +130,34 @@
|
||||
MaxWidth="600"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="8">
|
||||
<HyperlinkButton
|
||||
HorizontalAlignment="Center"
|
||||
Command="{x:Bind ViewModel.ImportFromWinoAccountCommand}"
|
||||
Content="{x:Bind domain:Translator.WelcomeWindow_ImportFromWinoAccount}" />
|
||||
|
||||
<StackPanel
|
||||
x:Name="ImportProgressPanel"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="8"
|
||||
Visibility="{x:Bind ViewModel.IsImportInProgress, Mode=OneWay}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.WelcomeWindow_ImportInProgress}" />
|
||||
<ProgressBar IsIndeterminate="True" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
x:Name="ImportStatusTextBlock"
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind ViewModel.ImportStatusMessage, Mode=OneWay}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="{x:Bind ViewModel.HasImportStatus, Mode=OneWay}" />
|
||||
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
|
||||
@@ -92,17 +92,22 @@
|
||||
Visibility="{x:Bind IsSynchronizationProgressVisible, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
|
||||
<PathIcon
|
||||
x:Name="AttentionIcon"
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="8,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
x:Load="{x:Bind IsAttentionRequired, Mode=OneWay}"
|
||||
Data="F1 M 2.021484 18.769531 C 1.767578 18.769531 1.52832 18.720703 1.303711 18.623047 C 1.079102 18.525391 0.880534 18.391928 0.708008 18.222656 C 0.535482 18.053385 0.398763 17.856445 0.297852 17.631836 C 0.19694 17.407227 0.146484 17.167969 0.146484 16.914062 C 0.146484 16.614584 0.211589 16.328125 0.341797 16.054688 L 7.695312 1.347656 C 7.851562 1.035156 8.082682 0.784506 8.388672 0.595703 C 8.694661 0.406902 9.023438 0.3125 9.375 0.3125 C 9.726562 0.3125 10.055338 0.406902 10.361328 0.595703 C 10.667317 0.784506 10.898438 1.035156 11.054688 1.347656 L 18.408203 16.054688 C 18.53841 16.328125 18.603516 16.614584 18.603516 16.914062 C 18.603516 17.167969 18.553059 17.407227 18.452148 17.631836 C 18.351236 17.856445 18.216145 18.053385 18.046875 18.222656 C 17.877604 18.391928 17.679035 18.525391 17.451172 18.623047 C 17.223307 18.720703 16.982422 18.769531 16.728516 18.769531 Z M 16.728516 17.519531 C 16.884766 17.519531 17.027994 17.460938 17.158203 17.34375 C 17.28841 17.226562 17.353516 17.086588 17.353516 16.923828 C 17.353516 16.806641 17.330729 16.702475 17.285156 16.611328 L 9.931641 1.904297 C 9.879557 1.793621 9.80306 1.708984 9.702148 1.650391 C 9.601236 1.591797 9.492188 1.5625 9.375 1.5625 C 9.257812 1.5625 9.148763 1.593426 9.047852 1.655273 C 8.946939 1.717123 8.870442 1.800131 8.818359 1.904297 L 1.464844 16.611328 C 1.419271 16.702475 1.396484 16.803387 1.396484 16.914062 C 1.396484 17.083334 1.459961 17.226562 1.586914 17.34375 C 1.713867 17.460938 1.858724 17.519531 2.021484 17.519531 Z M 8.75 11.875 L 8.75 6.875 C 8.75 6.705729 8.811849 6.559245 8.935547 6.435547 C 9.059244 6.31185 9.205729 6.25 9.375 6.25 C 9.544271 6.25 9.690755 6.31185 9.814453 6.435547 C 9.93815 6.559245 10 6.705729 10 6.875 L 10 11.875 C 10 12.044271 9.93815 12.190756 9.814453 12.314453 C 9.690755 12.438151 9.544271 12.5 9.375 12.5 C 9.205729 12.5 9.059244 12.438151 8.935547 12.314453 C 8.811849 12.190756 8.75 12.044271 8.75 11.875 Z M 8.4375 14.375 C 8.4375 14.114584 8.528646 13.893229 8.710938 13.710938 C 8.893229 13.528646 9.114583 13.4375 9.375 13.4375 C 9.635416 13.4375 9.856771 13.528646 10.039062 13.710938 C 10.221354 13.893229 10.3125 14.114584 10.3125 14.375 C 10.3125 14.635417 10.221354 14.856771 10.039062 15.039062 C 9.856771 15.221354 9.635416 15.3125 9.375 15.3125 C 9.114583 15.3125 8.893229 15.221354 8.710938 15.039062 C 8.528646 14.856771 8.4375 14.635417 8.4375 14.375 Z "
|
||||
Foreground="{ThemeResource InfoBarWarningSeverityIconBackground}" />
|
||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource InfoBarWarningSeverityIconBackground}"
|
||||
BorderThickness="1"
|
||||
Click="AttentionIconClicked"
|
||||
Foreground="{ThemeResource InfoBarWarningSeverityIconBackground}"
|
||||
ToolTipService.ToolTip="{x:Bind domain:Translator.Info_AccountAttentionRequiredClickableMessage, Mode=OneWay}"
|
||||
Visibility="{x:Bind IsAttentionRequired, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<PathIcon x:Name="AttentionIcon" Data="F1 M 2.021484 18.769531 C 1.767578 18.769531 1.52832 18.720703 1.303711 18.623047 C 1.079102 18.525391 0.880534 18.391928 0.708008 18.222656 C 0.535482 18.053385 0.398763 17.856445 0.297852 17.631836 C 0.19694 17.407227 0.146484 17.167969 0.146484 16.914062 C 0.146484 16.614584 0.211589 16.328125 0.341797 16.054688 L 7.695312 1.347656 C 7.851562 1.035156 8.082682 0.784506 8.388672 0.595703 C 8.694661 0.406902 9.023438 0.3125 9.375 0.3125 C 9.726562 0.3125 10.055338 0.406902 10.361328 0.595703 C 10.667317 0.784506 10.898438 1.035156 11.054688 1.347656 L 18.408203 16.054688 C 18.53841 16.328125 18.603516 16.614584 18.603516 16.914062 C 18.603516 17.167969 18.553059 17.407227 18.452148 17.631836 C 18.351236 17.856445 18.216145 18.053385 18.046875 18.222656 C 17.877604 18.391928 17.679035 18.525391 17.451172 18.623047 C 17.223307 18.720703 16.982422 18.769531 16.728516 18.769531 Z M 16.728516 17.519531 C 16.884766 17.519531 17.027994 17.460938 17.158203 17.34375 C 17.28841 17.226562 17.353516 17.086588 17.353516 16.923828 C 17.353516 16.806641 17.330729 16.702475 17.285156 16.611328 L 9.931641 1.904297 C 9.879557 1.793621 9.80306 1.708984 9.702148 1.650391 C 9.601236 1.591797 9.492188 1.5625 9.375 1.5625 C 9.257812 1.5625 9.148763 1.593426 9.047852 1.655273 C 8.946939 1.717123 8.870442 1.800131 8.818359 1.904297 L 1.464844 16.611328 C 1.419271 16.702475 1.396484 16.803387 1.396484 16.914062 C 1.396484 17.083334 1.459961 17.226562 1.586914 17.34375 C 1.713867 17.460938 1.858724 17.519531 2.021484 17.519531 Z M 8.75 11.875 L 8.75 6.875 C 8.75 6.705729 8.811849 6.559245 8.935547 6.435547 C 9.059244 6.31185 9.205729 6.25 9.375 6.25 C 9.544271 6.25 9.690755 6.31185 9.814453 6.435547 C 9.93815 6.559245 10 6.705729 10 6.875 L 10 11.875 C 10 12.044271 9.93815 12.190756 9.814453 12.314453 C 9.690755 12.438151 9.544271 12.5 9.375 12.5 C 9.205729 12.5 9.059244 12.438151 8.935547 12.314453 C 8.811849 12.190756 8.75 12.044271 8.75 11.875 Z M 8.4375 14.375 C 8.4375 14.114584 8.528646 13.893229 8.710938 13.710938 C 8.893229 13.528646 9.114583 13.4375 9.375 13.4375 C 9.635416 13.4375 9.856771 13.528646 10.039062 13.710938 C 10.221354 13.893229 10.3125 14.114584 10.3125 14.375 C 10.3125 14.635417 10.221354 14.856771 10.039062 15.039062 C 9.856771 15.221354 9.635416 15.3125 9.375 15.3125 C 9.114583 15.3125 8.893229 15.221354 8.710938 15.039062 C 8.528646 14.856771 8.4375 14.635417 8.4375 14.375 Z " />
|
||||
<TextBlock Text="{x:Bind domain:Translator.Info_AccountAttentionRequiredAction, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<muxc:ProgressRing
|
||||
x:Name="SynchronizationProgressBar"
|
||||
@@ -455,6 +460,7 @@
|
||||
Visibility="Collapsed">
|
||||
<Grid x:Name="CalendarPaneContent" Visibility="Collapsed">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
@@ -481,9 +487,31 @@
|
||||
Text="{x:Bind domain:Translator.CalendarEventCompose_NewEventButton, Mode=OneTime}" />
|
||||
</coreControls:WinoNavigationViewItem>
|
||||
|
||||
<coreControls:WinoNavigationViewItem
|
||||
x:Name="SynchronizeCalendarsNavigationItem"
|
||||
Grid.Row="1"
|
||||
Height="50"
|
||||
Margin="0,0,0,12"
|
||||
AutomationProperties.Name="{x:Bind domain:Translator.Buttons_Sync, Mode=OneTime}"
|
||||
IsEnabled="{x:Bind ViewModel.CalendarClient.CanSynchronizeCalendars, Mode=OneWay}"
|
||||
IsTabStop="True"
|
||||
KeyDown="SynchronizeCalendarsNavigationItemKeyDown"
|
||||
SelectsOnInvoked="False"
|
||||
Tapped="SynchronizeCalendarsNavigationItemTapped">
|
||||
<muxc:NavigationViewItem.Icon>
|
||||
<coreControls:WinoFontIcon Icon="Sync" />
|
||||
</muxc:NavigationViewItem.Icon>
|
||||
<TextBlock
|
||||
Margin="0,-2,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
Style="{StaticResource FlyoutPickerTitleTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.Buttons_Sync, Mode=OneTime}" />
|
||||
</coreControls:WinoNavigationViewItem>
|
||||
|
||||
<muxc:CalendarView
|
||||
x:Name="VisibleDateRangeCalendarView"
|
||||
Grid.Row="1"
|
||||
Grid.Row="2"
|
||||
Margin="12,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
SelectedDatesChanged="VisibleDateRangeCalendarViewSelectedDatesChanged"
|
||||
@@ -492,7 +520,7 @@
|
||||
|
||||
<ListView
|
||||
x:Name="CalendarHostListView"
|
||||
Grid.Row="2"
|
||||
Grid.Row="3"
|
||||
SelectionMode="None">
|
||||
<ListView.Header>
|
||||
<TextBlock
|
||||
@@ -509,6 +537,7 @@
|
||||
<muxc:Expander.Header>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
@@ -519,13 +548,29 @@
|
||||
IsChecked="{x:Bind IsCheckedState, Mode=TwoWay}"
|
||||
IsThreeState="True" />
|
||||
|
||||
<TextBlock
|
||||
<Ellipse
|
||||
Grid.Column="1"
|
||||
Width="12"
|
||||
Height="12"
|
||||
Margin="8,0,10,0"
|
||||
VerticalAlignment="Center"
|
||||
TextWrapping="Wrap">
|
||||
<Run FontWeight="SemiBold" Text="{x:Bind Account.Name}" />
|
||||
<Run FontSize="12" Text="(" /><Run FontSize="12" Text="{x:Bind Account.Address}" /><Run FontSize="12" Text=")" />
|
||||
</TextBlock>
|
||||
Fill="{x:Bind AccountColorHex, Converter={StaticResource HexToColorBrushConverter}, Mode=OneWay}" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<TextBlock VerticalAlignment="Center" TextWrapping="Wrap">
|
||||
<Run FontWeight="SemiBold" Text="{x:Bind Account.Name}" />
|
||||
<Run FontSize="12" Text=" (" /><Run FontSize="12" Text="{x:Bind Account.Address}" /><Run FontSize="12" Text=")" />
|
||||
</TextBlock>
|
||||
<ProgressBar
|
||||
Height="4"
|
||||
IsIndeterminate="True"
|
||||
ShowPaused="False"
|
||||
ShowError="False"
|
||||
Visibility="{x:Bind IsSynchronizationProgressVisible, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</muxc:Expander.Header>
|
||||
<muxc:Expander.Content>
|
||||
|
||||
@@ -277,6 +277,17 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
||||
await InvokeNewCalendarEventAsync();
|
||||
}
|
||||
|
||||
private async void AttentionIconClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is not FrameworkElement { DataContext: AccountMenuItem accountMenuItem })
|
||||
return;
|
||||
|
||||
if (ViewModel.MailClient is MailAppShellViewModel mailClient)
|
||||
{
|
||||
await mailClient.HandleAccountAttentionAsync(accountMenuItem.Parameter);
|
||||
}
|
||||
}
|
||||
|
||||
private async void NewCalendarEventNavigationItemKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key is not (VirtualKey.Enter or VirtualKey.Space))
|
||||
@@ -289,6 +300,31 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
||||
private Task InvokeNewCalendarEventAsync()
|
||||
=> ViewModel.CalendarClient.HandleNavigationItemInvokedAsync(new NewCalendarEventMenuItem());
|
||||
|
||||
private async void SynchronizeCalendarsNavigationItemTapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
await InvokeCalendarSynchronizationAsync();
|
||||
}
|
||||
|
||||
private async void SynchronizeCalendarsNavigationItemKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key is not (VirtualKey.Enter or VirtualKey.Space))
|
||||
return;
|
||||
|
||||
e.Handled = true;
|
||||
await InvokeCalendarSynchronizationAsync();
|
||||
}
|
||||
|
||||
private Task InvokeCalendarSynchronizationAsync()
|
||||
{
|
||||
if (ViewModel.CalendarClient.SyncCommand.CanExecute(null))
|
||||
{
|
||||
ViewModel.CalendarClient.SyncCommand.Execute(null);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void Receive(CalendarDisplayTypeChangedMessage message) => NotifyTitleBarContentChanged();
|
||||
|
||||
public void Receive(AccountCreatedMessage message)
|
||||
|
||||
@@ -200,6 +200,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.TabbedCommandBar" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Lottie" />
|
||||
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" />
|
||||
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" />
|
||||
|
||||
Reference in New Issue
Block a user