Skip to content

Commit d826ce5

Browse files
authored
fix: preview stops working when editor show template is enabled (#15)
* fix: ensure no duplication of anchor * fix: rerun the runner when changing renderingMode, since the blocks changed id; wait for anchor tracking * fix: change to useEffect to get initialStyles after init * fix: cleanup of anchors when the block is unmounted * fix: cleanup of anchors when the block is unmounted
1 parent a33a882 commit d826ce5

2 files changed

Lines changed: 63 additions & 22 deletions

File tree

src/editor/components/timeline/runner.js

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
* The timeline runner that runs the animation when previewing.
33
*/
44
import InteractEditorRunner from './class-runner'
5-
import { useRef, useMemo } from '@wordpress/element'
5+
import {
6+
useRef, useState, useEffect,
7+
} from '@wordpress/element'
68
import { cloneDeep } from 'lodash'
79
import { getBlockClientId } from './with-tracked-anchors'
810
import { doAction } from '@wordpress/hooks'
11+
import { select } from '@wordpress/data'
912

1013
// Create the runner.
1114
const runner = new InteractEditorRunner()
@@ -36,9 +39,13 @@ doAction( 'interact.interaction.types.loaded' )
3639

3740
export const useTimelineRunnerRef = ( interaction, actions, timelineIndex ) => {
3841
const runnerRef = useRef( null )
42+
const [ initialStyles, setInitialStyles ] = useState( '' )
43+
44+
const renderingMode = select( 'core/editor' ).getRenderingMode()
45+
const prevRenderingMode = useRef( renderingMode )
3946

4047
// Initialize the runner
41-
const initialStyles = useMemo( () => {
48+
useEffect( () => {
4249
// We will need to spawn a new runner for each timeline. Spawning will
4350
// create a new running with the same configuration.
4451
if ( ! runnerRef.current ) {
@@ -52,16 +59,26 @@ export const useTimelineRunnerRef = ( interaction, actions, timelineIndex ) => {
5259
actions: cloneDeep( actions ),
5360
} ]
5461

55-
// This replaces all block anchors with the block's ID. The editor
56-
// doesn't show block anchors, since it's always in the format of
57-
// "block-clientId"
58-
replaceBlockAnchorsForEditor( isolatedInteraction )
62+
const initRunner = () => {
63+
// This replaces all block anchors with the block's ID. The editor
64+
// doesn't show block anchors, since it's always in the format of
65+
// "block-clientId"
66+
replaceBlockAnchorsForEditor( isolatedInteraction )
67+
runnerRef.current?.configure( [ isolatedInteraction ] )
68+
runnerRef.current?.init()
69+
setInitialStyles( runnerRef.current?.getStartingActionStyles() || '' )
70+
}
5971

60-
runnerRef.current?.configure( [ isolatedInteraction ] )
61-
runnerRef.current?.init()
72+
// If the rendering mode changed, we need to delay the init to
73+
// avoid race condition tracking the anchors.
74+
if ( prevRenderingMode.current !== renderingMode ) {
75+
requestAnimationFrame( initRunner )
76+
} else {
77+
initRunner()
78+
}
6279

63-
return runnerRef.current?.getStartingActionStyles() || ''
64-
}, [ interaction, timelineIndex, actions ] )
80+
prevRenderingMode.current = renderingMode
81+
}, [ interaction, timelineIndex, actions, renderingMode ] )
6582

6683
return [ runnerRef, initialStyles ]
6784
}

src/editor/components/timeline/with-tracked-anchors.js

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect } from '@wordpress/element'
1+
import { useEffect, useRef } from '@wordpress/element'
22
import { createHigherOrderComponent } from '@wordpress/compose'
33
import { addFilter } from '@wordpress/hooks'
44

@@ -10,22 +10,46 @@ const CLIENT_IDS = []
1010
// ALL the time.
1111
const withTrackedAnchors = createHigherOrderComponent( BlockEdit => {
1212
return props => {
13+
const prevAnchorRef = useRef()
14+
1315
useEffect( () => {
14-
if ( props.attributes.anchor ) {
15-
// Remove any previous anchor selector for this clientId.
16-
const index = CLIENT_IDS.indexOf( props.clientId )
16+
const anchor = props.attributes?.anchor
17+
if ( ! anchor ) {
18+
return
19+
}
20+
21+
// If this block had a previous anchor, remove it.
22+
if ( prevAnchorRef.current ) {
23+
const oldIndex = ANCHORS.indexOf( prevAnchorRef.current )
24+
if ( oldIndex !== -1 ) {
25+
ANCHORS.splice( oldIndex, 1 )
26+
CLIENT_IDS.splice( oldIndex, 1 )
27+
}
28+
}
29+
30+
// Remove any existing entry for this anchor.
31+
// This ensures no duplication when the blocks are re-rendered.
32+
const existingIndex = ANCHORS.indexOf( anchor )
33+
if ( existingIndex !== -1 ) {
34+
ANCHORS.splice( existingIndex, 1 )
35+
CLIENT_IDS.splice( existingIndex, 1 )
36+
}
37+
38+
ANCHORS.push( anchor )
39+
CLIENT_IDS.push( props.clientId )
40+
41+
// Store anchor for next render
42+
prevAnchorRef.current = anchor
43+
44+
// Cleanup when the block is unmounted
45+
return () => {
46+
const index = ANCHORS.indexOf( anchor )
1747
if ( index !== -1 ) {
18-
CLIENT_IDS.splice( index, 1 )
1948
ANCHORS.splice( index, 1 )
49+
CLIENT_IDS.splice( index, 1 )
2050
}
21-
// Keep track of the clientId-anchor pair
22-
CLIENT_IDS.push( props.clientId )
23-
ANCHORS.push( props.attributes.anchor )
2451
}
25-
}, [
26-
props.clientId,
27-
props.attributes?.anchor,
28-
] )
52+
}, [ props.clientId, props.attributes?.anchor ] )
2953

3054
return <BlockEdit { ...props } />
3155
}

0 commit comments

Comments
 (0)