Skip to content

Commit

Permalink
feat: Add support for Determinate ProgressRing
Browse files Browse the repository at this point in the history
lottie wasm fixes
  • Loading branch information
kazo0 committed Dec 22, 2020
1 parent f31f750 commit eaa4e51
Show file tree
Hide file tree
Showing 14 changed files with 880 additions and 98 deletions.
4 changes: 4 additions & 0 deletions src/AddIns/Uno.UI.Lottie/LottieVisualSourceBase.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ public void SetProgress(double progress)
{
return;
}

//If setting Progress directly, we should have the full range to choose from
//Will be overridden in the Play method
_animation.SetMinAndMaxProgress(0f, 1f);
_animation.Progress = (float)progress;
}

Expand Down
153 changes: 80 additions & 73 deletions src/AddIns/Uno.UI.Lottie/LottieVisualSourceBase.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ partial class LottieVisualSourceBase
private static readonly string UNO_BOOTSTRAP_APP_BASE = global::System.Environment.GetEnvironmentVariable(nameof(UNO_BOOTSTRAP_APP_BASE));

private AnimatedVisualPlayer? _initializedPlayer;
private Uri? _lastSource;
private Size _compositionSize = new Size(0, 0);

private (double fromProgress, double toProgress, bool looped)? _playState;
private bool _isUpdating;
private bool _domLoaded;

private readonly SerialDisposable _animationDataSubscription = new SerialDisposable();

Expand All @@ -30,6 +32,7 @@ async Task InnerUpdate(CancellationToken ct)
{
_initializedPlayer = player;
player?.RegisterHtmlCustomEventHandler("lottie_state", OnStateChanged, isDetailJson: false);
player?.RegisterHtmlCustomEventHandler("animation_dom_loaded", OnAnimationDomLoaded);
}

if (player == null || _isUpdating)
Expand All @@ -40,93 +43,99 @@ async Task InnerUpdate(CancellationToken ct)
string[] js;

var sourceUri = UriSource;

if ((await TryLoadDownloadJson(sourceUri, ct)) is { } jsonStream)
if (_lastSource == null || !_lastSource.Equals(sourceUri))
{
var firstLoad = true;

var cacheKey = sourceUri.OriginalString;
_animationDataSubscription.Disposable = null;
_animationDataSubscription.Disposable =
LoadAndObserveAnimationData(jsonStream, cacheKey, OnJsonChanged);

void OnJsonChanged(string updatedJson, string updatedCacheKey)
_lastSource = sourceUri;

if ((await TryLoadDownloadJson(sourceUri, ct)) is { } jsonStream)
{
var play = _playState != null
|| (firstLoad && player.AutoPlay);
var firstLoad = true;

if (play && _playState == null)
{
_playState = (0, 1, true);
}
else if (!play)
var cacheKey = sourceUri.OriginalString;
_animationDataSubscription.Disposable = null;
_animationDataSubscription.Disposable =
LoadAndObserveAnimationData(jsonStream, cacheKey, OnJsonChanged);

void OnJsonChanged(string updatedJson, string updatedCacheKey)
{
_playState = null;
var play = _playState != null || (firstLoad && player.AutoPlay);
_domLoaded = false;

if (play && _playState == null)
{
_playState = (0, 1, true);
}
else if (!play)
{
_playState = null;
}

firstLoad = false;

js = new[]
{
"Uno.UI.Lottie.setAnimationProperties({",
"elementId:",
player.HtmlId.ToString(),
",jsonPath: null,autoplay:",
play ? "true" : "false",
",stretch:\"",
player.Stretch.ToString(),
"\",rate:",
player.PlaybackRate.ToStringInvariant(),
",cacheKey:\"",
updatedCacheKey,
"\"},",
updatedJson,
");"
};

ExecuteJs(js);

if (_playState != null && _domLoaded)
{
var (fromProgress, toProgress, looped) = _playState.Value;
Play(fromProgress, toProgress, looped);
}
}

firstLoad = false;
}
else
{
var documentPath = string.IsNullOrEmpty(UNO_BOOTSTRAP_APP_BASE)
? UriSource?.PathAndQuery
: UNO_BOOTSTRAP_APP_BASE + UriSource?.PathAndQuery;
_domLoaded = false;

js = new[]
{
"Uno.UI.Lottie.setAnimationProperties({",
"elementId:",
player.HtmlId.ToString(),
",jsonPath: null,autoplay:",
play ? "true" : "false",
",jsonPath:\"",
documentPath ?? "",
"\",autoplay:",
player.AutoPlay ? "true" : "false",
",stretch:\"",
player.Stretch.ToString(),
"\",rate:",
player.PlaybackRate.ToStringInvariant(),
",cacheKey:\"",
updatedCacheKey,
"\"},",
updatedJson,
");"
documentPath ?? "-n-",
"\"});"
};

ExecuteJs(js);

if (_playState != null)
if (player.AutoPlay)
{
_playState = (0, 1, true);
}
else
{
var (fromProgress, toProgress, looped) = _playState.Value;
Play(fromProgress, toProgress, looped);
_playState = null;
}
}
}
else
{
var documentPath = string.IsNullOrEmpty(UNO_BOOTSTRAP_APP_BASE)
? UriSource?.PathAndQuery
: UNO_BOOTSTRAP_APP_BASE + UriSource?.PathAndQuery;

js = new[]
{
"Uno.UI.Lottie.setAnimationProperties({",
"elementId:",
player.HtmlId.ToString(),
",jsonPath:\"",
documentPath ?? "",
"\",autoplay:",
player.AutoPlay ? "true" : "false",
",stretch:\"",
player.Stretch.ToString(),
"\",rate:",
player.PlaybackRate.ToStringInvariant(),
",cacheKey:\"",
documentPath ?? "-n-",
"\"});"
};

ExecuteJs(js);

if (player.AutoPlay)
{
_playState = (0, 1, true);
}
else
{
_playState = null;
}
ApplyPlayState();
}

void ExecuteJs(string[] js)
Expand All @@ -137,9 +146,6 @@ void ExecuteJs(string[] js)

_isUpdating = false;
}


ApplyPlayState();
}

private void ApplyPlayState()
Expand All @@ -151,6 +157,12 @@ private void ApplyPlayState()
}
}

private void OnAnimationDomLoaded(object sender, HtmlCustomEventArgs e)
{
_domLoaded = true;
ApplyPlayState();
}

private void OnStateChanged(object sender, HtmlCustomEventArgs e) => ParseStateString(e.Detail);

private void ParseStateString(string stateString)
Expand All @@ -166,11 +178,6 @@ private void ParseStateString(string stateString)
var loaded = parts[2].Equals("true", StringComparison.Ordinal);
var paused = parts[3].Equals("true", StringComparison.Ordinal);

if (paused && !_isUpdating)
{
_playState = null;
}

_player.SetValue(AnimatedVisualPlayer.IsAnimatedVisualLoadedProperty, loaded);
_player.SetValue(AnimatedVisualPlayer.IsPlayingProperty, !paused);
if (double.TryParse(parts[4], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var duration))
Expand All @@ -189,7 +196,7 @@ public void Play(double fromProgress, double toProgress, bool looped)
{
_playState = (fromProgress, toProgress, looped);

if (_player == null)
if (_player == null || !_domLoaded)
{
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/AddIns/Uno.UI.Lottie/WasmScripts/uno-lottie.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ declare namespace Uno.UI {
private static createAnimation;
private static getStateString;
private static raiseState;
private static raiseDataLoaded;
private static getPlayerConfig;
private static withPlayer;
}
Expand Down
21 changes: 18 additions & 3 deletions src/AddIns/Uno.UI.Lottie/WasmScripts/uno-lottie.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ var Uno;
a.loop = looped;
const fromFrame = fromProgress * Lottie._numberOfFrames;
const toFrame = toProgress * Lottie._numberOfFrames;
a.playSegments([fromFrame, toFrame], false);
a.playSegments([fromFrame, toFrame], true);
Lottie.raiseState(a);
});
return "ok";
Expand Down Expand Up @@ -61,8 +61,13 @@ var Uno;
static setProgress(elementId, progress) {
Lottie.withPlayer(p => {
const animation = Lottie._runningAnimations[elementId].animation;
const frames = animation.getDuration(true);
const frame = frames * progress;
var frame = Lottie._numberOfFrames * progress;
if (frame < animation.firstFrame) {
frame = frame - animation.firstFrame;
}
else {
frame = animation.getDuration(true) * progress;
}
animation.goToAndStop(frame, true);
Lottie.raiseState(animation);
});
Expand Down Expand Up @@ -122,6 +127,12 @@ var Uno;
animation.addEventListener("data_ready", (e) => {
Lottie._numberOfFrames = animation.totalFrames;
Lottie.raiseState(animation);
Lottie.raiseDataLoaded(animation);
});
animation.addEventListener("DOMLoaded", (e) => {
Lottie._numberOfFrames = animation.totalFrames;
Lottie.raiseState(animation);
Lottie.raiseDataLoaded(animation);
});
Lottie.raiseState(animation);
return runningAnimation;
Expand All @@ -137,6 +148,10 @@ var Uno;
const state = Lottie.getStateString(animation);
element.dispatchEvent(new CustomEvent("lottie_state", { detail: state }));
}
static raiseDataLoaded(animation) {
const element = animation.wrapper;
element.dispatchEvent(new CustomEvent("animation_dom_loaded"));
}
static getPlayerConfig(properties, animationData) {
let scaleMode = "none";
switch (properties.stretch) {
Expand Down
21 changes: 18 additions & 3 deletions src/AddIns/Uno.UI.Lottie/ts/Uno.UI.Lottie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace Uno.UI {
const fromFrame = fromProgress * Lottie._numberOfFrames;
const toFrame = toProgress * Lottie._numberOfFrames;

a.playSegments([fromFrame, toFrame], false);
a.playSegments([fromFrame, toFrame], true);
Lottie.raiseState(a);
});

Expand Down Expand Up @@ -100,8 +100,12 @@ namespace Uno.UI {
public static setProgress(elementId: number, progress: number): string {
Lottie.withPlayer(p => {
const animation = Lottie._runningAnimations[elementId].animation;
const frames = animation.getDuration(true);
const frame = frames * progress;
var frame = Lottie._numberOfFrames * progress;
if (frame < (animation as any).firstFrame) {
frame = frame - (animation as any).firstFrame
} else {
frame = animation.getDuration(true) * progress;
}
animation.goToAndStop(frame, true);
Lottie.raiseState(animation);

Expand Down Expand Up @@ -183,8 +187,14 @@ namespace Uno.UI {
(animation as any).addEventListener("data_ready", (e: any) => {
Lottie._numberOfFrames = animation.totalFrames;
Lottie.raiseState(animation);
Lottie.raiseDataLoaded(animation);
});

(animation as any).addEventListener("DOMLoaded", (e: any) => {
Lottie._numberOfFrames = animation.totalFrames;
Lottie.raiseState(animation);
Lottie.raiseDataLoaded(animation);
});
Lottie.raiseState(animation);

return runningAnimation;
Expand All @@ -205,6 +215,11 @@ namespace Uno.UI {
element.dispatchEvent(new CustomEvent("lottie_state", { detail: state }));
}

private static raiseDataLoaded(animation: Lottie.AnimationItem) {
const element = animation.wrapper;
element.dispatchEvent(new CustomEvent("animation_dom_loaded"));
}

private static getPlayerConfig(properties: LottieAnimationProperties, animationData?: AnimationData): Lottie.AnimationConfig {
let scaleMode = "none";
switch (properties.stretch) {
Expand Down
Loading

0 comments on commit eaa4e51

Please sign in to comment.