Skip to content

Commit 3dd7bb3

Browse files
dario-piotrowiczAndrewKushnir
authored andcommitted
fix(animations): reset the start and done fns on player reset (#46364)
in the animation players, make sure than upon reset the _onStartFns and _onDoneFns are also re-applied so that they can be called again after resetting the animation also set the noop animation player's _finished to false when the player resets (needed to make sure that the _onDoneFns get called) resolves #26630 PR Close #46364
1 parent 79a973a commit 3dd7bb3

File tree

4 files changed

+87
-1
lines changed

4 files changed

+87
-1
lines changed

goldens/size-tracking/aio-payloads.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"aio-local": {
1313
"uncompressed": {
1414
"runtime": 4325,
15-
"main": 456412,
15+
"main": 456957,
1616
"polyfills": 33922,
1717
"styles": 72829,
1818
"light-theme": 78276,

packages/animations/browser/src/render/web_animations/web_animations_player.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ export class WebAnimationsPlayer implements AnimationPlayer {
2424
private _destroyed = false;
2525
private _finalKeyframe?: ɵStyleDataMap;
2626

27+
// the following original fns are persistent copies of the _onStartFns and _onDoneFns
28+
// and are used to reset the fns to their original values upon reset()
29+
// (since the _onStartFns and _onDoneFns get deleted after they are called)
30+
private _originalOnDoneFns: Function[] = [];
31+
private _originalOnStartFns: Function[] = [];
32+
2733
// TODO(issue/24571): remove '!'.
2834
public readonly domPlayer!: DOMAnimation;
2935
public time = 0;
@@ -89,10 +95,12 @@ export class WebAnimationsPlayer implements AnimationPlayer {
8995
}
9096

9197
onStart(fn: () => void): void {
98+
this._originalOnStartFns.push(fn);
9299
this._onStartFns.push(fn);
93100
}
94101

95102
onDone(fn: () => void): void {
103+
this._originalOnDoneFns.push(fn);
96104
this._onDoneFns.push(fn);
97105
}
98106

@@ -132,6 +140,8 @@ export class WebAnimationsPlayer implements AnimationPlayer {
132140
this._destroyed = false;
133141
this._finished = false;
134142
this._started = false;
143+
this._onStartFns = this._originalOnStartFns;
144+
this._onDoneFns = this._originalOnDoneFns;
135145
}
136146

137147
private _resetDomPlayerState() {

packages/animations/src/players/animation_player.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ export class NoopAnimationPlayer implements AnimationPlayer {
123123
private _onDoneFns: Function[] = [];
124124
private _onStartFns: Function[] = [];
125125
private _onDestroyFns: Function[] = [];
126+
private _originalOnDoneFns: Function[] = [];
127+
private _originalOnStartFns: Function[] = [];
126128
private _started = false;
127129
private _destroyed = false;
128130
private _finished = false;
@@ -140,9 +142,11 @@ export class NoopAnimationPlayer implements AnimationPlayer {
140142
}
141143
}
142144
onStart(fn: () => void): void {
145+
this._originalOnStartFns.push(fn);
143146
this._onStartFns.push(fn);
144147
}
145148
onDone(fn: () => void): void {
149+
this._originalOnDoneFns.push(fn);
146150
this._onDoneFns.push(fn);
147151
}
148152
onDestroy(fn: () => void): void {
@@ -188,6 +192,9 @@ export class NoopAnimationPlayer implements AnimationPlayer {
188192
}
189193
reset(): void {
190194
this._started = false;
195+
this._finished = false;
196+
this._onStartFns = this._originalOnStartFns;
197+
this._onDoneFns = this._originalOnDoneFns;
191198
}
192199
setPosition(position: number): void {
193200
this._position = this.totalTime ? position * this.totalTime : 1;

packages/platform-browser/animations/test/browser_animation_builder_spec.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,75 @@ import {NoopAnimationsModule, ɵBrowserAnimationBuilder as BrowserAnimationBuild
4545
expect(cmp.builder instanceof BrowserAnimationBuilder).toBeTruthy();
4646
});
4747

48+
it('should listen on start and done on the animation builder\'s player after it has been reset',
49+
fakeAsync(() => {
50+
@Component({
51+
selector: 'ani-cmp',
52+
template: '...',
53+
})
54+
class Cmp {
55+
@ViewChild('target') public target: any;
56+
57+
constructor(public builder: AnimationBuilder) {}
58+
59+
build() {
60+
const definition =
61+
this.builder.build([style({opacity: 0}), animate(1000, style({opacity: 1}))]);
62+
63+
return definition.create(this.target);
64+
}
65+
}
66+
67+
TestBed.configureTestingModule({declarations: [Cmp]});
68+
69+
const fixture = TestBed.createComponent(Cmp);
70+
const cmp = fixture.componentInstance;
71+
fixture.detectChanges();
72+
73+
const player = cmp.build();
74+
75+
let startedCount = 0;
76+
player.onStart(() => startedCount++);
77+
78+
let finishedCount = 0;
79+
player.onDone(() => finishedCount++);
80+
81+
player.init();
82+
flushMicrotasks();
83+
expect(startedCount).toEqual(0);
84+
expect(finishedCount).toEqual(0);
85+
86+
player.play();
87+
flushMicrotasks();
88+
expect(startedCount).toEqual(1);
89+
expect(finishedCount).toEqual(0);
90+
91+
player.finish();
92+
flushMicrotasks();
93+
expect(startedCount).toEqual(1);
94+
expect(finishedCount).toEqual(1);
95+
96+
player.play();
97+
player.finish();
98+
flushMicrotasks();
99+
expect(startedCount).toEqual(1);
100+
expect(finishedCount).toEqual(1);
101+
102+
[0, 1, 2, 3].forEach(i => {
103+
player.reset();
104+
105+
player.play();
106+
flushMicrotasks();
107+
expect(startedCount).toEqual(i + 2);
108+
expect(finishedCount).toEqual(i + 1);
109+
110+
player.finish();
111+
flushMicrotasks();
112+
expect(startedCount).toEqual(i + 2);
113+
expect(finishedCount).toEqual(i + 2);
114+
});
115+
}));
116+
48117
it('should listen on start and done on the animation builder\'s player', fakeAsync(() => {
49118
@Component({
50119
selector: 'ani-cmp',

0 commit comments

Comments
 (0)