@@ -4,16 +4,21 @@ import {
44 SharedElementsStrictConfig ,
55 SharedElementAnimatedValue ,
66 SharedElementTransitionProps ,
7+ Route ,
78} from './types' ;
89import { normalizeSharedElementsConfig } from './utils' ;
910
1011export type SharedElementRendererUpdateHandler = ( ) => any ;
1112
1213export interface ISharedElementRendererData {
13- startTransition ( animValue : SharedElementAnimatedValue ) : void ;
14- endTransition ( ) : void ;
15- willActivateScene ( sceneData : SharedElementSceneData ) : void ;
16- didActivateScene ( sceneData : SharedElementSceneData ) : void ;
14+ startTransition (
15+ animValue : SharedElementAnimatedValue ,
16+ route : Route ,
17+ prevRoute : Route
18+ ) : void ;
19+ endTransition ( route : Route , prevRoute : Route ) : void ;
20+ willActivateScene ( sceneData : SharedElementSceneData , route : Route ) : void ;
21+ didActivateScene ( sceneData : SharedElementSceneData , route : Route ) : void ;
1722}
1823
1924function getSharedElements (
@@ -28,67 +33,138 @@ function getSharedElements(
2833 ) ;
2934}
3035
36+ const NO_SHARED_ELEMENTS : any [ ] = [ ] ;
37+
38+ type SceneRoute = {
39+ scene : SharedElementSceneData ;
40+ route : Route ;
41+ subscription : SharedElementEventSubscription | null ;
42+ } ;
43+
3144export default class SharedElementRendererData
3245 implements ISharedElementRendererData {
33- private sceneData : SharedElementSceneData | null = null ;
34- private prevSceneData : SharedElementSceneData | null = null ;
46+ private scenes : SceneRoute [ ] = [ ] ;
3547 private updateSubscribers = new Set < SharedElementRendererUpdateHandler > ( ) ;
36- private sceneSubscription : SharedElementEventSubscription | null = null ;
37- private sharedElements : SharedElementsStrictConfig = [ ] ;
48+ private sharedElements : SharedElementsStrictConfig | null = null ;
3849 private isShowing : boolean = true ;
3950 private animValue : SharedElementAnimatedValue ;
51+ private route : Route | null = null ;
52+ private prevRoute : Route | null = null ;
53+ private scene : SharedElementSceneData | null = null ;
54+ private prevScene : SharedElementSceneData | null = null ;
4055
41- startTransition ( animValue : SharedElementAnimatedValue ) {
56+ startTransition (
57+ animValue : SharedElementAnimatedValue ,
58+ route : Route ,
59+ // @ts -ignore
60+ prevRoute : Route //eslint-disable-line @typescript-eslint/no-unused-vars
61+ ) {
62+ //console.log('startTransition, route: ', route.key);
4263 this . animValue = animValue ;
64+ this . prevRoute = this . route ;
65+ this . route = route ;
66+ this . updateSceneListeners ( ) ;
67+ this . updateSharedElements ( ) ;
68+ }
69+
70+ endTransition (
71+ // @ts -ignore
72+ route : Route , //eslint-disable-line @typescript-eslint/no-unused-vars
73+ // @ts -ignore
74+ prevRoute : Route //eslint-disable-line @typescript-eslint/no-unused-vars
75+ ) {
76+ //console.log('endTransition, route: ', route.key);
77+ if ( this . prevRoute != null ) {
78+ this . prevRoute = null ;
79+ this . animValue = null ;
80+ this . updateSceneListeners ( ) ;
81+ this . updateSharedElements ( ) ;
82+ }
83+ }
84+
85+ willActivateScene ( sceneData : SharedElementSceneData , route : Route ) : void {
86+ //console.log('willActivateScene, route: ', route.key);
87+ this . registerScene ( sceneData , route ) ;
88+ }
89+
90+ didActivateScene ( sceneData : SharedElementSceneData , route : Route ) : void {
91+ //console.log('didActivateScene, route: ', route.key);
92+ this . prevRoute = null ;
93+ this . registerScene ( sceneData , route ) ;
4394 }
4495
45- endTransition ( ) {
46- // Nothing to do
96+ private registerScene ( sceneData : SharedElementSceneData , route : Route ) {
97+ this . scenes . push ( {
98+ scene : sceneData ,
99+ route,
100+ subscription : null ,
101+ } ) ;
102+ if ( this . scenes . length > 5 ) {
103+ const { subscription } = this . scenes [ 0 ] ;
104+ this . scenes . splice ( 0 , 1 ) ;
105+ if ( subscription ) subscription . remove ( ) ;
106+ }
107+ this . updateSceneListeners ( ) ;
108+ this . updateSharedElements ( ) ;
47109 }
48110
49- willActivateScene ( sceneData : SharedElementSceneData ) : void {
50- /*console.log(
51- 'SharedElementRendererData.willActivateScene: ',
52- sceneData.name,
53- ', previous: ',
54- this.prevSceneData ? this.prevSceneData.name : ''
55- );*/
56- if ( ! this . prevSceneData ) return ;
111+ private updateSceneListeners ( ) {
112+ this . scenes . forEach ( sceneRoute => {
113+ const { scene, route, subscription } = sceneRoute ;
114+ const isActive =
115+ ( this . route && this . route . key === route . key ) ||
116+ ( this . prevRoute && this . prevRoute . key === route . key ) ;
117+ if ( isActive && ! subscription ) {
118+ sceneRoute . subscription = scene . addUpdateListener ( ( ) => {
119+ // TODO optimize
120+ this . emitUpdateEvent ( ) ;
121+ } ) ;
122+ } else if ( ! isActive && subscription ) {
123+ sceneRoute . subscription = null ;
124+ subscription . remove ( ) ;
125+ }
126+ } ) ;
127+ }
128+
129+ private updateSharedElements ( ) {
130+ const { route, prevRoute, animValue } = this ;
131+ const sceneRoute = route
132+ ? this . scenes . find ( sc => sc . route . key === route . key )
133+ : undefined ;
134+ const prevSceneRoute = prevRoute
135+ ? this . scenes . find ( sc => sc . route . key === prevRoute . key )
136+ : undefined ;
137+ const scene = sceneRoute ? sceneRoute . scene : null ;
138+ const prevScene = prevSceneRoute ? prevSceneRoute . scene : null ;
139+
140+ // Update current scene & previous scene
141+ if ( scene === this . scene && prevScene === this . prevScene ) return ;
142+ this . scene = scene ;
143+ this . prevScene = prevScene ;
144+
145+ // Update shared elements
146+ let sharedElements : SharedElementsStrictConfig | null = null ;
57147 let isShowing = true ;
58- let sharedElements = getSharedElements ( sceneData , this . prevSceneData , true ) ;
59- if ( ! sharedElements ) {
60- isShowing = false ;
61- sharedElements = getSharedElements ( this . prevSceneData , sceneData , false ) ;
148+ if ( animValue && scene && prevScene ) {
149+ sharedElements = getSharedElements ( scene , prevScene , true ) ;
150+ if ( ! sharedElements ) {
151+ isShowing = false ;
152+ sharedElements = getSharedElements ( prevScene , scene , false ) ;
153+ }
62154 }
63- if ( sharedElements && sharedElements . length ) {
64- // console.log('sharedElements: ', sharedElements, sceneData);
65- this . sceneData = sceneData ;
155+ if ( this . sharedElements !== sharedElements ) {
66156 this . sharedElements = sharedElements ;
67157 this . isShowing = isShowing ;
68- this . sceneSubscription = this . sceneData . addUpdateListener ( ( ) => {
69- // TODO optimize
70- this . emitUpdateEvent ( ) ;
71- } ) ;
158+ /*console.log(
159+ 'updateSharedElements: ',
160+ sharedElements,
161+ ' ,isShowing: ',
162+ isShowing
163+ );*/
72164 this . emitUpdateEvent ( ) ;
73165 }
74166 }
75167
76- didActivateScene ( sceneData : SharedElementSceneData ) : void {
77- //console.log('SharedElementRendererData.didActivateScene: ', sceneData.name);
78- if ( this . sceneSubscription ) {
79- this . sceneSubscription . remove ( ) ;
80- this . sceneSubscription = null ;
81- }
82- this . prevSceneData = sceneData ;
83- if ( this . sceneData ) {
84- this . sceneData = null ;
85- if ( this . sharedElements . length ) {
86- this . sharedElements = [ ] ;
87- this . emitUpdateEvent ( ) ;
88- }
89- }
90- }
91-
92168 addUpdateListener (
93169 handler : SharedElementRendererUpdateHandler
94170 ) : SharedElementEventSubscription {
@@ -103,23 +179,21 @@ export default class SharedElementRendererData
103179 }
104180
105181 getTransitions ( ) : SharedElementTransitionProps [ ] {
106- const { sharedElements, prevSceneData , sceneData , isShowing } = this ;
182+ const { sharedElements, prevScene , scene , isShowing, animValue } = this ;
107183 // console.log('getTransitions: ', sharedElements);
184+ if ( ! sharedElements || ! scene || ! prevScene ) return NO_SHARED_ELEMENTS ;
108185 return sharedElements . map ( ( { id, otherId, ...other } ) => {
109186 const startId = isShowing ? otherId || id : id ;
110187 const endId = isShowing ? id : otherId || id ;
111188 return {
112- position : this . animValue ,
189+ position : animValue ,
113190 start : {
114- ancestor :
115- ( prevSceneData ? prevSceneData . getAncestor ( ) : undefined ) || null ,
116- node :
117- ( prevSceneData ? prevSceneData . getNode ( startId ) : undefined ) ||
118- null ,
191+ ancestor : ( prevScene ? prevScene . getAncestor ( ) : undefined ) || null ,
192+ node : ( prevScene ? prevScene . getNode ( startId ) : undefined ) || null ,
119193 } ,
120194 end : {
121- ancestor : ( sceneData ? sceneData . getAncestor ( ) : undefined ) || null ,
122- node : ( sceneData ? sceneData . getNode ( endId ) : undefined ) || null ,
195+ ancestor : ( scene ? scene . getAncestor ( ) : undefined ) || null ,
196+ node : ( scene ? scene . getNode ( endId ) : undefined ) || null ,
123197 } ,
124198 ...other ,
125199 } ;
0 commit comments