Skip to content

Commit

Permalink
feat(lottie): Added the ability of LottieVisualSource to download its…
Browse files Browse the repository at this point in the history
… content and assign it locally.

This is required for a feature in a coming commit, adding theming support to lottie files.
  • Loading branch information
carldebilly committed Dec 2, 2020
1 parent 1114c7b commit b96d123
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 272 deletions.
101 changes: 55 additions & 46 deletions src/AddIns/Uno.UI.Lottie/LottieVisualSource.Android.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,57 @@
using System;
using System.Threading;
using Android.Animation;
using Android.Widget;
using Com.Airbnb.Lottie;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using Android.Views;
using Uno.Disposables;
using Uno.UI;
using ViewHelper = Uno.UI.ViewHelper;
using System.Threading.Tasks;

namespace Microsoft.Toolkit.Uwp.UI.Lottie
{
partial class LottieVisualSource
partial class LottieVisualSourceBase
{
private LottieAnimationView _animation;
private LottieAnimationView? _animation;

private LottieListener _listener;
private LottieListener? _listener;

private class LottieListener : AnimatorListenerAdapter
{
private readonly LottieVisualSource _lottieVisualSource;
private readonly LottieVisualSourceBase _lottieVisualSource;

public LottieListener(LottieVisualSource lottieVisualSource)
public LottieListener(LottieVisualSourceBase lottieVisualSource)
{
_lottieVisualSource = lottieVisualSource;
}

public override void OnAnimationCancel(Animator animation)
{
_lottieVisualSource.SetIsPlaying(false);
}
public override void OnAnimationCancel(Animator? animation) => _lottieVisualSource.SetIsPlaying(false);

public override void OnAnimationEnd(Animator animation)
{
_lottieVisualSource.SetIsPlaying(false);
}
public override void OnAnimationEnd(Animator? animation) => _lottieVisualSource.SetIsPlaying(false);

public override void OnAnimationPause(Animator animation)
{
_lottieVisualSource.SetIsPlaying(false);
}
public override void OnAnimationPause(Animator? animation) => _lottieVisualSource.SetIsPlaying(false);

public override void OnAnimationResume(Animator animation)
{
_lottieVisualSource.SetIsPlaying(true);
}
public override void OnAnimationResume(Animator? animation) => _lottieVisualSource.SetIsPlaying(true);

public override void OnAnimationStart(Animator animation)
{
_lottieVisualSource.SetIsPlaying(true);
}
public override void OnAnimationStart(Animator? animation) => _lottieVisualSource.SetIsPlaying(true);
}

public bool UseHardwareAcceleration { get; set; } = true;

private Uri _lastSource;
private Uri? _lastSource;
private (double fromProgress, double toProgress, bool looped)? _playState;

partial void InnerUpdate()
private readonly SerialDisposable _animationDataSubscription = new SerialDisposable();

async Task InnerUpdate(CancellationToken ct)
{
var player = _player;
if (!(_player is { } player))
{
return;
}

if (_animation == null)
{
Expand All @@ -69,29 +62,38 @@ partial void InnerUpdate()

_animation.AddAnimatorListener(_listener);

SetProperties();
await SetProperties();

// Add the player after
player.AddView(_animation);
}
else
{
SetProperties();
await SetProperties();
}

void SetProperties()
async Task SetProperties()
{
var source = UriSource;
if(_lastSource == null || !_lastSource.Equals(source))
var sourceUri = UriSource;
if(_lastSource == null || !_lastSource.Equals(sourceUri))
{
_lastSource = source;
_lastSource = sourceUri;

if (TryLoadEmbeddedJson(source, out var json))
if ((await TryLoadDownloadJson(sourceUri, ct)) is { } jsonStream)
{
_animation.SetAnimationFromJson(json, source.OriginalString);
var cacheKey = sourceUri.OriginalString;
_animationDataSubscription.Disposable = null;
_animationDataSubscription.Disposable =
LoadAndObserveAnimationData(jsonStream, cacheKey, OnJsonChanged);

void OnJsonChanged(string updatedJson, string updatedCacheKey)
{
_animation.SetAnimationFromJson(updatedJson, updatedCacheKey);
}
}
else
{
var path = source?.PathAndQuery ?? "";
var path = sourceUri?.PathAndQuery ?? "";
if (path.StartsWith("/"))
{
path = path.Substring(1);
Expand Down Expand Up @@ -137,17 +139,20 @@ partial void InnerMeasure(Size size)
{
var physicalSize = size.LogicalToPhysicalPixels();

_animation.Measure(
_animation?.Measure(
ViewHelper.MakeMeasureSpec((int)physicalSize.Width, MeasureSpecMode.AtMost),
ViewHelper.MakeMeasureSpec((int)physicalSize.Height, MeasureSpecMode.AtMost)
);
}

private void SetDuration()
{
var duration = TimeSpan.FromMilliseconds(_animation.Duration);
_player?.SetValue(AnimatedVisualPlayer.DurationProperty, duration);
_player?.SetValue(AnimatedVisualPlayer.IsAnimatedVisualLoadedProperty, duration > TimeSpan.Zero);
if (_animation is { } animation)
{
var duration = TimeSpan.FromMilliseconds(animation.Duration);
_player?.SetValue(AnimatedVisualPlayer.DurationProperty, duration);
_player?.SetValue(AnimatedVisualPlayer.IsAnimatedVisualLoadedProperty, duration > TimeSpan.Zero);
}
}

public void Play(double fromProgress, double toProgress, bool looped)
Expand All @@ -158,14 +163,18 @@ public void Play(double fromProgress, double toProgress, bool looped)
return;
}
SetIsPlaying(true);
if (_animation is { } animation)
{
#if __ANDROID_26__
_animation.RepeatCount = looped ? ValueAnimator.Infinite : 0; // Repeat count doesn't include first time.
animation.RepeatCount =
looped ? ValueAnimator.Infinite : 0; // Repeat count doesn't include first time.
#else
_animation.Loop(looped);
animation.Loop(looped);
#endif
_animation.SetMinProgress((float)fromProgress);
_animation.SetMaxProgress((float)toProgress);
_animation.PlayAnimation();
animation.SetMinProgress((float)fromProgress);
animation.SetMaxProgress((float)toProgress);
animation.PlayAnimation();
}
}

public void Stop()
Expand Down
Loading

0 comments on commit b96d123

Please sign in to comment.