UNPKG

35.5 kBJavaScriptView Raw
1import { getPageStartDefaultsForType, getRectFromProps, getSpringFromProps, SharedTransition, SharedTransitionAnimationType } from './shared-transition';
2import { isNumber } from '../../utils/types';
3import { Screen } from '../../platform';
4import { CORE_ANIMATION_DEFAULTS } from '../../utils/common';
5import { ios as iOSUtils } from '../../utils/native-helper';
6export class SharedTransitionHelper {
7 static animate(state, transitionContext, type) {
8 const transition = state.instance;
9 setTimeout(async () => {
10 // Run on next tick
11 // ensures that existing UI state finishes before snapshotting
12 // (eg, button touch up state)
13 switch (state.activeType) {
14 case SharedTransitionAnimationType.present: {
15 // console.log('-- Transition present --');
16 SharedTransition.notifyEvent(SharedTransition.startedEvent, {
17 id: transition.id,
18 type,
19 action: 'present',
20 });
21 if (type === 'modal') {
22 transitionContext.containerView.addSubview(transition.presented.view);
23 }
24 else if (type === 'page') {
25 transitionContext.containerView.insertSubviewAboveSubview(transition.presented.view, transition.presenting.view);
26 }
27 transition.presented.view.layoutIfNeeded();
28 const { sharedElements, presented, presenting } = SharedTransition.getSharedElements(state.page, state.toPage);
29 const sharedElementTags = sharedElements.map((v) => v.sharedTransitionTag);
30 if (!transition.sharedElements) {
31 transition.sharedElements = {
32 presented: [],
33 presenting: [],
34 independent: [],
35 };
36 }
37 if (SharedTransition.DEBUG) {
38 console.log(` ${type}: Present`);
39 console.log(`1. Found sharedTransitionTags to animate:`, sharedElementTags);
40 console.log(`2. Take snapshots of shared elements and position them based on presenting view:`);
41 }
42 const pageOut = state.pageOut;
43 const pageStart = state.pageStart;
44 const startFrame = getRectFromProps(pageStart, getPageStartDefaultsForType(type));
45 const pageEnd = state.pageEnd;
46 const pageEndTags = pageEnd?.sharedTransitionTags || {};
47 // console.log('pageEndIndependentTags:', pageEndIndependentTags);
48 const positionSharedTags = async () => {
49 for (const presentingView of sharedElements) {
50 const presentingSharedElement = presentingView.ios;
51 // console.log('fromTarget instanceof UIImageView:', fromTarget instanceof UIImageView)
52 // TODO: discuss whether we should check if UIImage/UIImageView type to always snapshot images or if other view types could be duped/added vs. snapshotted
53 // Note: snapshot may be most efficient/simple
54 // console.log('---> ', presentingView.sharedTransitionTag, ': ', presentingSharedElement)
55 const presentedView = presented.find((v) => v.sharedTransitionTag === presentingView.sharedTransitionTag);
56 const presentedSharedElement = presentedView.ios;
57 const pageEndProps = pageEndTags[presentingView.sharedTransitionTag];
58 const snapshot = UIImageView.alloc().init();
59 if (pageEndProps?.callback) {
60 await pageEndProps?.callback(presentedView, 'present');
61 }
62 // treat images differently...
63 if (presentedSharedElement instanceof UIImageView) {
64 // in case the image is loaded async, we need to update the snapshot when it changes
65 // todo: remove listener on transition end
66 presentedView.on('imageSourceChange', () => {
67 snapshot.image = iOSUtils.snapshotView(presentedSharedElement, Screen.mainScreen.scale);
68 snapshot.tintColor = presentedSharedElement.tintColor;
69 });
70 snapshot.tintColor = presentedSharedElement.tintColor;
71 snapshot.contentMode = presentedSharedElement.contentMode;
72 }
73 iOSUtils.copyLayerProperties(snapshot, presentingSharedElement, pageEndProps?.propertiesToMatch);
74 snapshot.clipsToBounds = true;
75 // console.log('---> snapshot: ', snapshot);
76 const startFrame = presentingSharedElement.convertRectToView(presentingSharedElement.bounds, transitionContext.containerView);
77 const endFrame = presentedSharedElement.convertRectToView(presentedSharedElement.bounds, transitionContext.containerView);
78 snapshot.frame = startFrame;
79 if (SharedTransition.DEBUG) {
80 console.log('---> ', presentingView.sharedTransitionTag, ' frame:', iOSUtils.printCGRect(snapshot.frame));
81 }
82 transition.sharedElements.presenting.push({
83 view: presentingView,
84 startFrame,
85 endFrame,
86 snapshot,
87 startOpacity: presentingView.opacity,
88 endOpacity: isNumber(pageEndProps?.opacity) ? pageEndProps.opacity : presentedView.opacity,
89 propertiesToMatch: pageEndProps?.propertiesToMatch,
90 zIndex: isNumber(pageEndProps?.zIndex) ? pageEndProps.zIndex : 0,
91 });
92 transition.sharedElements.presented.push({
93 view: presentedView,
94 startFrame: endFrame,
95 endFrame: startFrame,
96 startOpacity: presentedView.opacity,
97 endOpacity: presentingView.opacity,
98 propertiesToMatch: pageEndProps?.propertiesToMatch,
99 });
100 // set initial opacity to match the source view opacity
101 snapshot.alpha = presentingView.opacity;
102 // hide both while animating within the transition context
103 presentingView.opacity = 0;
104 presentedView.opacity = 0;
105 }
106 };
107 const positionIndependentTags = async () => {
108 // independent tags
109 for (const tag in pageEndTags) {
110 // only handle if independent (otherwise it's shared between both pages and handled above)
111 if (!sharedElementTags.includes(tag)) {
112 // only consider start when there's a matching end
113 const pageStartIndependentProps = pageStart?.sharedTransitionTags ? pageStart?.sharedTransitionTags[tag] : null;
114 // console.log('start:', tag, pageStartIndependentProps);
115 const pageEndProps = pageEndTags[tag];
116 let independentView = presenting.find((v) => v.sharedTransitionTag === tag);
117 let isPresented = false;
118 if (!independentView) {
119 independentView = presented.find((v) => v.sharedTransitionTag === tag);
120 if (!independentView) {
121 break;
122 }
123 isPresented = true;
124 }
125 const independentSharedElement = independentView.ios;
126 if (pageEndProps?.callback) {
127 await pageEndProps?.callback(independentView, 'present');
128 }
129 // let snapshot: UIImageView;
130 // if (isPresented) {
131 // snapshot = UIImageView.alloc().init();
132 // } else {
133 const snapshot = UIImageView.alloc().initWithImage(iOSUtils.snapshotView(independentSharedElement, Screen.mainScreen.scale));
134 // }
135 if (independentSharedElement instanceof UIImageView) {
136 // in case the image is loaded async, we need to update the snapshot when it changes
137 // todo: remove listener on transition end
138 // if (isPresented) {
139 // independentView.on('imageSourceChange', () => {
140 // snapshot.image = iOSNativeHelper.snapshotView(independentSharedElement, Screen.mainScreen.scale);
141 // snapshot.tintColor = independentSharedElement.tintColor;
142 // });
143 // }
144 snapshot.tintColor = independentSharedElement.tintColor;
145 snapshot.contentMode = independentSharedElement.contentMode;
146 }
147 snapshot.clipsToBounds = true;
148 const startFrame = independentSharedElement.convertRectToView(independentSharedElement.bounds, transitionContext.containerView);
149 const startFrameRect = getRectFromProps(pageStartIndependentProps);
150 // adjust for any specified start positions
151 const startFrameAdjusted = CGRectMake(startFrame.origin.x + startFrameRect.x, startFrame.origin.y + startFrameRect.y, startFrame.size.width, startFrame.size.height);
152 // console.log('startFrameAdjusted:', tag, iOSNativeHelper.printCGRect(startFrameAdjusted));
153 // if (pageStartIndependentProps?.scale) {
154 // snapshot.transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(startFrameAdjusted.origin.x, startFrameAdjusted.origin.y), CGAffineTransformMakeScale(pageStartIndependentProps.scale.x, pageStartIndependentProps.scale.y))
155 // } else {
156 snapshot.frame = startFrame; //startFrameAdjusted;
157 // }
158 if (SharedTransition.DEBUG) {
159 console.log('---> ', independentView.sharedTransitionTag, ' frame:', iOSUtils.printCGRect(snapshot.frame));
160 }
161 const endFrameRect = getRectFromProps(pageEndProps);
162 const endFrame = CGRectMake(startFrame.origin.x + endFrameRect.x, startFrame.origin.y + endFrameRect.y, startFrame.size.width, startFrame.size.height);
163 // console.log('endFrame:', tag, iOSNativeHelper.printCGRect(endFrame));
164 transition.sharedElements.independent.push({
165 view: independentView,
166 isPresented,
167 startFrame,
168 snapshot,
169 endFrame,
170 startTransform: independentSharedElement.transform,
171 scale: pageEndProps.scale,
172 startOpacity: independentView.opacity,
173 endOpacity: isNumber(pageEndProps.opacity) ? pageEndProps.opacity : 0,
174 propertiesToMatch: pageEndProps?.propertiesToMatch,
175 zIndex: isNumber(pageEndProps?.zIndex) ? pageEndProps.zIndex : 0,
176 });
177 independentView.opacity = 0;
178 }
179 }
180 };
181 // position all sharedTransitionTag elements
182 await positionSharedTags();
183 await positionIndependentTags();
184 // combine to order by zIndex and add to transition context
185 const snapshotData = transition.sharedElements.presenting.concat(transition.sharedElements.independent);
186 snapshotData.sort((a, b) => (a.zIndex > b.zIndex ? 1 : -1));
187 if (SharedTransition.DEBUG) {
188 console.log(`zIndex settings:`, snapshotData.map((s) => {
189 return {
190 sharedTransitionTag: s.view.sharedTransitionTag,
191 zIndex: s.zIndex,
192 };
193 }));
194 }
195 for (const data of snapshotData) {
196 // add snapshot to animate
197 transitionContext.containerView.addSubview(data.snapshot);
198 }
199 // Important: always set after above shared element positions have had their start positions set
200 transition.presented.view.alpha = isNumber(pageStart?.opacity) ? pageStart?.opacity : 0;
201 transition.presented.view.frame = CGRectMake(startFrame.x, startFrame.y, startFrame.width, startFrame.height);
202 const cleanupPresent = () => {
203 for (const presented of transition.sharedElements.presented) {
204 presented.view.opacity = presented.startOpacity;
205 }
206 for (const presenting of transition.sharedElements.presenting) {
207 presenting.snapshot.removeFromSuperview();
208 }
209 for (const independent of transition.sharedElements.independent) {
210 independent.snapshot.removeFromSuperview();
211 if (independent.isPresented) {
212 independent.view.opacity = independent.startOpacity;
213 }
214 }
215 SharedTransition.updateState(transition.id, {
216 activeType: SharedTransitionAnimationType.dismiss,
217 });
218 if (type === 'page') {
219 transition.presenting.view.removeFromSuperview();
220 }
221 transitionContext.completeTransition(true);
222 SharedTransition.notifyEvent(SharedTransition.finishedEvent, {
223 id: transition.id,
224 type,
225 action: 'present',
226 });
227 };
228 const animateProperties = () => {
229 if (SharedTransition.DEBUG) {
230 console.log('3. Animating shared elements:');
231 }
232 transition.presented.view.alpha = isNumber(pageEnd?.opacity) ? pageEnd?.opacity : 1;
233 const endFrame = getRectFromProps(pageEnd);
234 transition.presented.view.frame = CGRectMake(endFrame.x, endFrame.y, endFrame.width, endFrame.height);
235 if (pageOut) {
236 if (isNumber(pageOut.opacity)) {
237 transition.presenting.view.alpha = pageOut?.opacity;
238 }
239 const outFrame = getRectFromProps(pageOut);
240 transition.presenting.view.frame = CGRectMake(outFrame.x, outFrame.y, outFrame.width, outFrame.height);
241 }
242 // animate page properties to the following:
243 // https://stackoverflow.com/a/27997678/1418981
244 // In order to have proper layout. Seems mostly needed when presenting.
245 // For instance during presentation, destination view doesn't account navigation bar height.
246 // Not sure if best to leave all the time?
247 // owner.presented.view.setNeedsLayout();
248 // owner.presented.view.layoutIfNeeded();
249 for (const presented of transition.sharedElements.presented) {
250 const presentingMatch = transition.sharedElements.presenting.find((v) => v.view.sharedTransitionTag === presented.view.sharedTransitionTag);
251 // Workaround wrong origin due ongoing layout process.
252 const updatedEndFrame = presented.view.ios.convertRectToView(presented.view.ios.bounds, transitionContext.containerView);
253 const correctedEndFrame = CGRectMake(updatedEndFrame.origin.x, updatedEndFrame.origin.y, presentingMatch.endFrame.size.width, presentingMatch.endFrame.size.height);
254 presentingMatch.snapshot.frame = correctedEndFrame;
255 // apply view and layer properties to the snapshot view to match the source/presented view
256 iOSUtils.copyLayerProperties(presentingMatch.snapshot, presented.view.ios, presented.propertiesToMatch);
257 // create a snapshot of the presented view
258 presentingMatch.snapshot.image = iOSUtils.snapshotView(presented.view.ios, Screen.mainScreen.scale);
259 // apply correct alpha
260 presentingMatch.snapshot.alpha = presentingMatch.endOpacity;
261 if (SharedTransition.DEBUG) {
262 console.log(`---> ${presentingMatch.view.sharedTransitionTag} animate to: `, iOSUtils.printCGRect(correctedEndFrame));
263 }
264 }
265 for (const independent of transition.sharedElements.independent) {
266 const endFrame = independent.endFrame;
267 // if (independent.isPresented) {
268 // const updatedEndFrame = independent.view.ios.convertRectToView(independent.view.ios.bounds, transitionContext.containerView);
269 // endFrame = CGRectMake(updatedEndFrame.origin.x, updatedEndFrame.origin.y, independent.endFrame.size.width, independent.endFrame.size.height);
270 // }
271 if (independent.scale) {
272 independent.snapshot.transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(endFrame.origin.x, endFrame.origin.y), CGAffineTransformMakeScale(independent.scale.x, independent.scale.y));
273 }
274 else {
275 independent.snapshot.frame = endFrame;
276 }
277 independent.snapshot.alpha = independent.endOpacity;
278 if (SharedTransition.DEBUG) {
279 console.log(`---> ${independent.view.sharedTransitionTag} animate to: `, iOSUtils.printCGRect(independent.endFrame));
280 }
281 }
282 };
283 if (isNumber(pageEnd?.duration)) {
284 // override spring and use only linear animation
285 UIView.animateWithDurationDelayOptionsAnimationsCompletion(pageEnd?.duration / 1000, 0, 0 /* UIViewAnimationOptions.CurveEaseInOut */, () => {
286 animateProperties();
287 }, () => {
288 cleanupPresent();
289 });
290 }
291 else {
292 iOSUtils.animateWithSpring({
293 ...getSpringFromProps(pageEnd?.spring),
294 animations: () => {
295 animateProperties();
296 },
297 completion: () => {
298 cleanupPresent();
299 },
300 });
301 }
302 break;
303 }
304 case SharedTransitionAnimationType.dismiss: {
305 // console.log('-- Transition dismiss --');
306 SharedTransition.notifyEvent(SharedTransition.startedEvent, {
307 id: transition.id,
308 type,
309 action: 'dismiss',
310 });
311 if (type === 'page') {
312 transitionContext.containerView.insertSubviewBelowSubview(transition.presenting.view, transition.presented.view);
313 }
314 // console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count);
315 if (SharedTransition.DEBUG) {
316 console.log(` ${type}: Dismiss`);
317 console.log(`1. Dismiss sharedTransitionTags to animate:`, transition.sharedElements.presented.map((p) => p.view.sharedTransitionTag));
318 console.log(`2. Add back previously stored sharedElements to dismiss:`);
319 }
320 const pageOut = state.pageOut;
321 const pageEnd = state.pageEnd;
322 const pageEndTags = pageEnd?.sharedTransitionTags || {};
323 const pageReturn = state.pageReturn;
324 for (const p of transition.sharedElements.presented) {
325 p.view.opacity = 0;
326 }
327 // combine to order by zIndex and add to transition context
328 const snapshotData = transition.sharedElements.presenting.concat(transition.sharedElements.independent);
329 snapshotData.sort((a, b) => (a.zIndex > b.zIndex ? 1 : -1));
330 if (SharedTransition.DEBUG) {
331 console.log(`zIndex settings:`, snapshotData.map((s) => {
332 return {
333 sharedTransitionTag: s.view.sharedTransitionTag,
334 zIndex: s.zIndex,
335 };
336 }));
337 }
338 // first loop through all the shared elements and fire the callback
339 for (const data of snapshotData) {
340 const pageEndProps = pageEndTags[data.view.sharedTransitionTag];
341 if (pageEndProps?.callback) {
342 await pageEndProps?.callback(data.view, 'dismiss');
343 }
344 }
345 // now that all the callbacks had their chance to run, we can take the snapshots
346 for (const data of snapshotData) {
347 const view = data.view.ios;
348 const currentAlpha = view.alpha;
349 if (pageReturn?.useStartOpacity) {
350 // when desired, reset the alpha to the start value so the view is visible in the snapshot
351 view.alpha = data.startOpacity;
352 }
353 // take a new snapshot
354 data.snapshot.image = iOSUtils.snapshotView(view, Screen.mainScreen.scale);
355 // find the currently visible view with the same sharedTransitionTag
356 const fromView = transition.sharedElements.presented.find((p) => p.view.sharedTransitionTag === data.view.sharedTransitionTag)?.view;
357 if (fromView) {
358 // match the snapshot frame to the current frame of the fromView
359 data.snapshot.frame = fromView.ios.convertRectToView(fromView.ios.bounds, transitionContext.containerView);
360 }
361 // snapshot has been taken, we can restore the alpha
362 view.alpha = currentAlpha;
363 // we recalculate the startFrame because the view might have changed its position in the background
364 data.startFrame = view.convertRectToView(view.bounds, transitionContext.containerView);
365 // add snapshot to animate
366 transitionContext.containerView.addSubview(data.snapshot);
367 }
368 const cleanupDismiss = () => {
369 for (const presenting of transition.sharedElements.presenting) {
370 presenting.view.opacity = presenting.startOpacity;
371 presenting.snapshot.removeFromSuperview();
372 }
373 for (const independent of transition.sharedElements.independent) {
374 independent.view.opacity = independent.startOpacity;
375 independent.snapshot.removeFromSuperview();
376 }
377 SharedTransition.finishState(transition.id);
378 transition.sharedElements = null;
379 transitionContext.completeTransition(true);
380 SharedTransition.notifyEvent(SharedTransition.finishedEvent, {
381 id: transition.id,
382 type,
383 action: 'dismiss',
384 });
385 };
386 const animateProperties = () => {
387 if (SharedTransition.DEBUG) {
388 console.log('3. Dismissing shared elements:');
389 }
390 transition.presented.view.alpha = isNumber(pageReturn?.opacity) ? pageReturn?.opacity : 0;
391 const endFrame = getRectFromProps(pageReturn, getPageStartDefaultsForType(type));
392 transition.presented.view.frame = CGRectMake(endFrame.x, endFrame.y, endFrame.width, endFrame.height);
393 if (pageOut) {
394 // always return to defaults if pageOut had been used
395 transition.presenting.view.alpha = 1;
396 const outFrame = getRectFromProps(null);
397 transition.presenting.view.frame = CGRectMake(0, 0, outFrame.width, outFrame.height);
398 }
399 for (const presenting of transition.sharedElements.presenting) {
400 iOSUtils.copyLayerProperties(presenting.snapshot, presenting.view.ios, presenting.propertiesToMatch);
401 presenting.snapshot.frame = presenting.startFrame;
402 presenting.snapshot.alpha = presenting.startOpacity;
403 if (SharedTransition.DEBUG) {
404 console.log(`---> ${presenting.view.sharedTransitionTag} animate to: `, iOSUtils.printCGRect(presenting.snapshot.frame));
405 }
406 }
407 for (const independent of transition.sharedElements.independent) {
408 independent.snapshot.alpha = independent.startOpacity;
409 if (independent.scale) {
410 independent.snapshot.transform = independent.startTransform;
411 }
412 else {
413 independent.snapshot.frame = independent.startFrame;
414 }
415 if (SharedTransition.DEBUG) {
416 console.log(`---> ${independent.view.sharedTransitionTag} animate to: `, iOSUtils.printCGRect(independent.snapshot.frame));
417 }
418 }
419 };
420 if (isNumber(pageReturn?.duration)) {
421 // override spring and use only linear animation
422 UIView.animateWithDurationDelayOptionsAnimationsCompletion(pageReturn?.duration / 1000, 0, 0 /* UIViewAnimationOptions.CurveEaseInOut */, () => {
423 animateProperties();
424 }, () => {
425 cleanupDismiss();
426 });
427 }
428 else {
429 iOSUtils.animateWithSpring({
430 ...getSpringFromProps(pageReturn?.spring),
431 animations: () => {
432 animateProperties();
433 },
434 completion: () => {
435 cleanupDismiss();
436 },
437 });
438 }
439 break;
440 }
441 }
442 });
443 }
444 static interactiveStart(state, interactiveState, type) {
445 SharedTransition.notifyEvent(SharedTransition.startedEvent, {
446 id: state.instance.id,
447 type,
448 action: 'interactiveStart',
449 });
450 switch (type) {
451 case 'page':
452 interactiveState.transitionContext.containerView.insertSubviewBelowSubview(state.instance.presenting.view, state.instance.presented.view);
453 break;
454 }
455 }
456 static interactiveUpdate(state, interactiveState, type, percent) {
457 if (interactiveState) {
458 if (!interactiveState.added) {
459 interactiveState.added = true;
460 for (const p of state.instance.sharedElements.presented) {
461 p.view.opacity = 0;
462 }
463 for (const p of state.instance.sharedElements.presenting) {
464 p.snapshot.alpha = p.endOpacity;
465 interactiveState.transitionContext.containerView.addSubview(p.snapshot);
466 }
467 const pageStart = state.pageStart;
468 const startFrame = getRectFromProps(pageStart, getPageStartDefaultsForType(type));
469 interactiveState.propertyAnimator = UIViewPropertyAnimator.alloc().initWithDurationDampingRatioAnimations(1, 1, () => {
470 for (const p of state.instance.sharedElements.presenting) {
471 p.snapshot.frame = p.startFrame;
472 iOSUtils.copyLayerProperties(p.snapshot, p.view.ios, p.propertiesToMatch);
473 p.snapshot.alpha = 1;
474 }
475 state.instance.presented.view.alpha = isNumber(state.pageReturn?.opacity) ? state.pageReturn?.opacity : 0;
476 state.instance.presented.view.frame = CGRectMake(startFrame.x, startFrame.y, state.instance.presented.view.bounds.size.width, state.instance.presented.view.bounds.size.height);
477 });
478 }
479 interactiveState.propertyAnimator.fractionComplete = percent;
480 SharedTransition.notifyEvent(SharedTransition.interactiveUpdateEvent, {
481 id: state?.instance?.id,
482 type,
483 percent,
484 });
485 }
486 }
487 static interactiveCancel(state, interactiveState, type) {
488 if (state?.instance && interactiveState?.added && interactiveState?.propertyAnimator) {
489 interactiveState.propertyAnimator.reversed = true;
490 const duration = isNumber(state.pageEnd?.duration) ? state.pageEnd?.duration / 1000 : CORE_ANIMATION_DEFAULTS.duration;
491 interactiveState.propertyAnimator.continueAnimationWithTimingParametersDurationFactor(null, duration);
492 setTimeout(() => {
493 for (const p of state.instance.sharedElements.presented) {
494 p.view.opacity = 1;
495 }
496 for (const p of state.instance.sharedElements.presenting) {
497 p.snapshot.removeFromSuperview();
498 }
499 state.instance.presented.view.alpha = 1;
500 interactiveState.propertyAnimator = null;
501 interactiveState.added = false;
502 interactiveState.transitionContext.cancelInteractiveTransition();
503 interactiveState.transitionContext.completeTransition(false);
504 SharedTransition.updateState(state?.instance?.id, {
505 interactiveBegan: false,
506 interactiveCancelled: true,
507 });
508 SharedTransition.notifyEvent(SharedTransition.interactiveCancelledEvent, {
509 id: state?.instance?.id,
510 type,
511 });
512 }, duration * 1000);
513 }
514 }
515 static interactiveFinish(state, interactiveState, type) {
516 if (state?.instance && interactiveState?.added && interactiveState?.propertyAnimator) {
517 interactiveState.propertyAnimator.reversed = false;
518 const duration = isNumber(state.pageReturn?.duration) ? state.pageReturn?.duration / 1000 : CORE_ANIMATION_DEFAULTS.duration;
519 interactiveState.propertyAnimator.continueAnimationWithTimingParametersDurationFactor(null, duration);
520 setTimeout(() => {
521 for (const presenting of state.instance.sharedElements.presenting) {
522 presenting.view.opacity = presenting.startOpacity;
523 presenting.snapshot.removeFromSuperview();
524 }
525 SharedTransition.finishState(state.instance.id);
526 interactiveState.propertyAnimator = null;
527 interactiveState.added = false;
528 interactiveState.transitionContext.finishInteractiveTransition();
529 interactiveState.transitionContext.completeTransition(true);
530 SharedTransition.notifyEvent(SharedTransition.finishedEvent, {
531 id: state?.instance?.id,
532 type,
533 action: 'interactiveFinish',
534 });
535 }, duration * 1000);
536 }
537 }
538}
539//# sourceMappingURL=shared-transition-helper.ios.js.map
\No newline at end of file