Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions src/editor/components/timeline/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
* The timeline runner that runs the animation when previewing.
*/
import InteractEditorRunner from './class-runner'
import { useRef, useMemo } from '@wordpress/element'
import {
useRef, useState, useEffect,
} from '@wordpress/element'
import { cloneDeep } from 'lodash'
import { getBlockClientId } from './with-tracked-anchors'
import { doAction } from '@wordpress/hooks'
import { select } from '@wordpress/data'

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

export const useTimelineRunnerRef = ( interaction, actions, timelineIndex ) => {
const runnerRef = useRef( null )
const [ initialStyles, setInitialStyles ] = useState( '' )

const renderingMode = select( 'core/editor' ).getRenderingMode()
const prevRenderingMode = useRef( renderingMode )

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

// This replaces all block anchors with the block's ID. The editor
// doesn't show block anchors, since it's always in the format of
// "block-clientId"
replaceBlockAnchorsForEditor( isolatedInteraction )
const initRunner = () => {
// This replaces all block anchors with the block's ID. The editor
// doesn't show block anchors, since it's always in the format of
// "block-clientId"
replaceBlockAnchorsForEditor( isolatedInteraction )
runnerRef.current?.configure( [ isolatedInteraction ] )
runnerRef.current?.init()
setInitialStyles( runnerRef.current?.getStartingActionStyles() || '' )
}

runnerRef.current?.configure( [ isolatedInteraction ] )
runnerRef.current?.init()
// If the rendering mode changed, we need to delay the init to
// avoid race condition tracking the anchors.
if ( prevRenderingMode.current !== renderingMode ) {
requestAnimationFrame( initRunner )
} else {
initRunner()
}

return runnerRef.current?.getStartingActionStyles() || ''
}, [ interaction, timelineIndex, actions ] )
prevRenderingMode.current = renderingMode
}, [ interaction, timelineIndex, actions, renderingMode ] )

return [ runnerRef, initialStyles ]
}
Expand Down
48 changes: 36 additions & 12 deletions src/editor/components/timeline/with-tracked-anchors.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from '@wordpress/element'
import { useEffect, useRef } from '@wordpress/element'
import { createHigherOrderComponent } from '@wordpress/compose'
import { addFilter } from '@wordpress/hooks'

Expand All @@ -10,22 +10,46 @@ const CLIENT_IDS = []
// ALL the time.
const withTrackedAnchors = createHigherOrderComponent( BlockEdit => {
return props => {
const prevAnchorRef = useRef()

useEffect( () => {
if ( props.attributes.anchor ) {
// Remove any previous anchor selector for this clientId.
const index = CLIENT_IDS.indexOf( props.clientId )
const anchor = props.attributes?.anchor
if ( ! anchor ) {
return
}

// If this block had a previous anchor, remove it.
if ( prevAnchorRef.current ) {
const oldIndex = ANCHORS.indexOf( prevAnchorRef.current )
if ( oldIndex !== -1 ) {
ANCHORS.splice( oldIndex, 1 )
CLIENT_IDS.splice( oldIndex, 1 )
}
}

// Remove any existing entry for this anchor.
// This ensures no duplication when the blocks are re-rendered.
const existingIndex = ANCHORS.indexOf( anchor )
if ( existingIndex !== -1 ) {
ANCHORS.splice( existingIndex, 1 )
CLIENT_IDS.splice( existingIndex, 1 )
}

ANCHORS.push( anchor )
CLIENT_IDS.push( props.clientId )

// Store anchor for next render
prevAnchorRef.current = anchor

// Cleanup when the block is unmounted
return () => {
const index = ANCHORS.indexOf( anchor )
if ( index !== -1 ) {
CLIENT_IDS.splice( index, 1 )
ANCHORS.splice( index, 1 )
CLIENT_IDS.splice( index, 1 )
}
// Keep track of the clientId-anchor pair
CLIENT_IDS.push( props.clientId )
ANCHORS.push( props.attributes.anchor )
}
}, [
props.clientId,
props.attributes?.anchor,
] )
}, [ props.clientId, props.attributes?.anchor ] )

return <BlockEdit { ...props } />
}
Expand Down