Skip to content

Commit

Permalink
feat: let user interact with core player from react player
Browse files Browse the repository at this point in the history
  • Loading branch information
justusmattern27 committed Sep 10, 2024
1 parent 517efb7 commit 09caa1b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
9 changes: 6 additions & 3 deletions packages/2d/src/lib/scenes/Scene2D.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ export class Scene2D extends GeneratorScene<View2D> 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(
Expand Down
55 changes: 51 additions & 4 deletions packages/player-react/src/index.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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({
Expand All @@ -60,14 +70,19 @@ export function Player({

onDurationChange = () => {},
onTimeUpdate = () => {},
onPlayerReady = () => {},
onPlayerResize = () => {},
}: PlayerProps) {
const [playingState, setPlaying] = useState(playing);
const [isMouseOver, setIsMouseOver] = useState(false);
const [currentTimeState, setCurrentTime] = useState(currentTime);
const [duration, setDuration] = useState(-1);

const focus = useRef(false);
const playerRef = useRef<HTMLDivElement>(null);
const playerRef = useRef<HTMLDivElement | null>(null);
const wrapperRef = useRef<HTMLDivElement | null>(null);

const onClickHandler = controls ? () => setPlaying(prev => !prev) : undefined;

/**
* Sync the playing prop with the player's own state when it changes.
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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) {
Expand All @@ -149,6 +195,7 @@ export function Player({
return (
<div data-player="true" style={{display: 'contents'}}>
<div
ref={wrapperRef}
className="p-relative p-cursor-default p-focus:outline-none"
onFocus={() => (focus.current = true)}
onBlur={() => (focus.current = false)}
Expand All @@ -158,10 +205,10 @@ export function Player({
>
<div className="p-relative">
<revideo-player
ref={playerRef}
ref={playerRef as LegacyRef<HTMLDivElement>}
src={src}
playing={String(playingState)}
onClick={() => setPlaying(prev => !prev)}
onClick={onClickHandler}
variables={JSON.stringify(variables)}
looping={looping ? 'true' : 'false'}
width={width}
Expand Down
1 change: 1 addition & 0 deletions packages/player-react/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 09caa1b

Please sign in to comment.