From 09caa1bb5c62d8e239faf5c426c178da50d57a39 Mon Sep 17 00:00:00 2001 From: justusmattern27 Date: Tue, 10 Sep 2024 22:15:25 +0200 Subject: [PATCH 1/3] feat: let user interact with core player from react player --- packages/2d/src/lib/scenes/Scene2D.ts | 9 +++-- packages/player-react/src/index.tsx | 55 +++++++++++++++++++++++++-- packages/player-react/src/internal.ts | 1 + 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/packages/2d/src/lib/scenes/Scene2D.ts b/packages/2d/src/lib/scenes/Scene2D.ts index 5921a0f1..5a50e82a 100644 --- a/packages/2d/src/lib/scenes/Scene2D.ts +++ b/packages/2d/src/lib/scenes/Scene2D.ts @@ -76,9 +76,12 @@ export class Scene2D extends GeneratorScene implements Inspectable { } public inspectPosition(x: number, y: number): InspectedElement | null { - return this.execute( - () => this.getView().hit(new Vector2(x, y))?.key ?? null, - ); + const node = this.getNodeByPosition(x, y); + return node?.key; + } + + public getNodeByPosition(x: number, y: number): Node | null { + return this.execute(() => this.getView().hit(new Vector2(x, y)) ?? null); } public validateInspection( diff --git a/packages/player-react/src/index.tsx b/packages/player-react/src/index.tsx index 5c676e07..ba19d6c1 100644 --- a/packages/player-react/src/index.tsx +++ b/packages/player-react/src/index.tsx @@ -1,5 +1,13 @@ 'use client'; -import {ComponentProps, useEffect, useRef, useState} from 'react'; +import {Player as CorePlayer} from '@revideo/core'; +import { + ComponentProps, + LegacyRef, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; import {Controls} from './controls'; import './styles.css'; import {shouldShowControls} from './utils'; @@ -41,6 +49,8 @@ interface PlayerProps { onDurationChange?: (duration: number) => void; onTimeUpdate?: (currentTime: number) => void; + onPlayerReady?: (player: CorePlayer) => void; + onPlayerResize?: (rect: DOMRectReadOnly) => void; } export function Player({ @@ -60,6 +70,8 @@ export function Player({ onDurationChange = () => {}, onTimeUpdate = () => {}, + onPlayerReady = () => {}, + onPlayerResize = () => {}, }: PlayerProps) { const [playingState, setPlaying] = useState(playing); const [isMouseOver, setIsMouseOver] = useState(false); @@ -67,7 +79,10 @@ export function Player({ const [duration, setDuration] = useState(-1); const focus = useRef(false); - const playerRef = useRef(null); + const playerRef = useRef(null); + const wrapperRef = useRef(null); + + const onClickHandler = controls ? () => setPlaying(prev => !prev) : undefined; /** * Sync the playing prop with the player's own state when it changes. @@ -114,6 +129,35 @@ export function Player({ } }; + const handlePlayerReady = (event: Event) => { + const player = (event as CustomEvent).detail; + if (player) { + onPlayerReady(player); + } + }; + + const handlePlayerResize = useCallback( + (entries: ResizeObserverEntry[]) => { + const [entry] = entries; + if (entry && wrapperRef.current) { + const boundingRect = wrapperRef.current.getBoundingClientRect(); + onPlayerResize?.(boundingRect); + } + }, + [onPlayerResize], + ); + + useEffect(() => { + if (!wrapperRef.current) return; + + const resizeObserver = new ResizeObserver(handlePlayerResize); + resizeObserver.observe(wrapperRef.current); + + return () => { + resizeObserver.disconnect(); + }; + }, [handlePlayerResize]); + /** * Import the player and add all event listeners. */ @@ -122,11 +166,13 @@ export function Player({ playerRef.current?.addEventListener('timeupdate', handleTimeUpdate); playerRef.current?.addEventListener('duration', handleDurationUpdate); + playerRef.current?.addEventListener('playerready', handlePlayerReady); document.addEventListener('keydown', handleKeyDown); return () => { playerRef.current?.removeEventListener('timeupdate', handleTimeUpdate); playerRef.current?.removeEventListener('duration', handleDurationUpdate); + playerRef.current?.removeEventListener('playerready', handlePlayerReady); document.removeEventListener('keydown', handleKeyDown); const frameElement = document.getElementById('revideo-2d-frame'); if (frameElement) { @@ -149,6 +195,7 @@ export function Player({ return (
(focus.current = true)} onBlur={() => (focus.current = false)} @@ -158,10 +205,10 @@ export function Player({ >
} src={src} playing={String(playingState)} - onClick={() => setPlaying(prev => !prev)} + onClick={onClickHandler} variables={JSON.stringify(variables)} looping={looping ? 'true' : 'false'} width={width} diff --git a/packages/player-react/src/internal.ts b/packages/player-react/src/internal.ts index 63889f40..95c9d228 100644 --- a/packages/player-react/src/internal.ts +++ b/packages/player-react/src/internal.ts @@ -177,6 +177,7 @@ class RevideoPlayer extends HTMLElement { this.player.togglePlayback(this.playing); this.setState(State.Ready); + this.dispatchEvent(new CustomEvent('playerready', {detail: this.player})); } public attributeChangedCallback(name: string, _: any, newValue: any) { From cd09c3796159a6750e1294bcb53dcadf68f63353 Mon Sep 17 00:00:00 2001 From: justusmattern27 Date: Fri, 13 Sep 2024 13:41:28 +0200 Subject: [PATCH 2/3] fix: avoid constantly handling resize --- packages/player-react/src/index.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/player-react/src/index.tsx b/packages/player-react/src/index.tsx index ba19d6c1..00f0fbad 100644 --- a/packages/player-react/src/index.tsx +++ b/packages/player-react/src/index.tsx @@ -140,13 +140,23 @@ export function Player({ (entries: ResizeObserverEntry[]) => { const [entry] = entries; if (entry && wrapperRef.current) { - const boundingRect = wrapperRef.current.getBoundingClientRect(); - onPlayerResize?.(boundingRect); + const newRect = entry.contentRect; + if ( + !lastRect.current || + newRect.width !== lastRect.current.width || + newRect.height !== lastRect.current.height + ) { + console.log('jo resize'); + lastRect.current = newRect; + onPlayerResize?.(newRect); + } } }, [onPlayerResize], ); + const lastRect = useRef(null); + useEffect(() => { if (!wrapperRef.current) return; From 1ab4818fb7431900b5c835bd0afb3fba75ad36c0 Mon Sep 17 00:00:00 2001 From: justusmattern27 Date: Sun, 22 Sep 2024 17:28:40 +0200 Subject: [PATCH 3/3] chore: address comments --- packages/player-react/src/index.tsx | 39 ++++++++++++----------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/player-react/src/index.tsx b/packages/player-react/src/index.tsx index 00f0fbad..43f0bff0 100644 --- a/packages/player-react/src/index.tsx +++ b/packages/player-react/src/index.tsx @@ -1,13 +1,6 @@ 'use client'; import {Player as CorePlayer} from '@revideo/core'; -import { - ComponentProps, - LegacyRef, - useCallback, - useEffect, - useRef, - useState, -} from 'react'; +import {ComponentProps, useCallback, useEffect, useRef, useState} from 'react'; import {Controls} from './controls'; import './styles.css'; import {shouldShowControls} from './utils'; @@ -81,6 +74,7 @@ export function Player({ const focus = useRef(false); const playerRef = useRef(null); const wrapperRef = useRef(null); + const lastRect = useRef(null); const onClickHandler = controls ? () => setPlaying(prev => !prev) : undefined; @@ -138,25 +132,24 @@ export function Player({ const handlePlayerResize = useCallback( (entries: ResizeObserverEntry[]) => { - const [entry] = entries; - if (entry && wrapperRef.current) { - const newRect = entry.contentRect; - if ( - !lastRect.current || - newRect.width !== lastRect.current.width || - newRect.height !== lastRect.current.height - ) { - console.log('jo resize'); - lastRect.current = newRect; - onPlayerResize?.(newRect); - } + const [firstEntry] = entries; + if (!firstEntry || !wrapperRef.current) { + return; + } + + const newRect = firstEntry.contentRect; + const sameWidth = newRect.width === lastRect.current.width; + const sameHeight = newRect.height === lastRect.current.height; + if (lastRect.current && sameWidth && sameHeight) { + return; } + + lastRect.current = newRect; + onPlayerResize(newRect); }, [onPlayerResize], ); - const lastRect = useRef(null); - useEffect(() => { if (!wrapperRef.current) return; @@ -215,7 +208,7 @@ export function Player({ >
} + ref={playerRef} src={src} playing={String(playingState)} onClick={onClickHandler}