UNPKG

@remotion/studio

Version:

APIs for interacting with the Remotion Studio

248 lines (247 loc) 10.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PlayPause = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const player_1 = require("@remotion/player"); const react_1 = require("react"); const remotion_1 = require("remotion"); const is_current_selected_still_1 = require("../helpers/is-current-selected-still"); const use_keybinding_1 = require("../helpers/use-keybinding"); const jump_to_start_1 = require("../icons/jump-to-start"); const pause_1 = require("../icons/pause"); const play_1 = require("../icons/play"); const step_back_1 = require("../icons/step-back"); const step_forward_1 = require("../icons/step-forward"); const in_out_1 = require("../state/in-out"); const ControlButton_1 = require("./ControlButton"); const imperative_state_1 = require("./Timeline/imperative-state"); const timeline_scroll_logic_1 = require("./Timeline/timeline-scroll-logic"); const backStyle = { height: 18, color: 'white', }; const forwardBackStyle = { height: 16, color: 'white', }; const iconButton = { height: 14, width: 14, color: 'white', }; const PlayPause = ({ playbackRate, loop, bufferStateDelayInMilliseconds }) => { const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)(); const videoConfig = remotion_1.Internals.useUnsafeVideoConfig(); const [showBufferIndicator, setShowBufferState] = (0, react_1.useState)(false); const { playing, play, pause, pauseAndReturnToPlayStart, frameBack, seek, frameForward, isLastFrame, isFirstFrame, emitter, getCurrentFrame, } = player_1.PlayerInternals.usePlayer(); player_1.PlayerInternals.usePlayback({ loop, playbackRate, moveToBeginningWhenEnded: true, inFrame, outFrame, getCurrentFrame, browserMediaControlsBehavior: { mode: 'register-media-session', }, }); const isStill = (0, is_current_selected_still_1.useIsStill)(); (0, react_1.useEffect)(() => { if (isStill) { pause(); } }, [isStill, pause]); const onSpace = (0, react_1.useCallback)((e) => { if (playing) { pause(); } else { play(); } e.preventDefault(); }, [pause, play, playing]); const onEnter = (0, react_1.useCallback)((e) => { if (playing) { // Don't prevent keyboard navigation e.preventDefault(); pauseAndReturnToPlayStart(); } }, [pauseAndReturnToPlayStart, playing]); const onArrowLeft = (0, react_1.useCallback)((e) => { e.preventDefault(); if (e.altKey) { seek(0); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-left', durationInFrames: (0, imperative_state_1.getCurrentDuration)(), frame: 0, }); } else if (e.shiftKey) { frameBack((0, imperative_state_1.getCurrentFps)()); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-left', durationInFrames: (0, imperative_state_1.getCurrentDuration)(), frame: Math.max(0, getCurrentFrame() - (0, imperative_state_1.getCurrentFps)()), }); } else { frameBack(1); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-left', durationInFrames: (0, imperative_state_1.getCurrentDuration)(), frame: Math.max(0, getCurrentFrame() - 1), }); } }, [frameBack, seek, getCurrentFrame]); const onArrowRight = (0, react_1.useCallback)((e) => { if (e.altKey) { seek((0, imperative_state_1.getCurrentDuration)() - 1); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-right', durationInFrames: (0, imperative_state_1.getCurrentDuration)() - 1, frame: (0, imperative_state_1.getCurrentDuration)() - 1, }); } else if (e.shiftKey) { frameForward((0, imperative_state_1.getCurrentFps)()); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-right', durationInFrames: (0, imperative_state_1.getCurrentDuration)(), frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + (0, imperative_state_1.getCurrentFps)()), }); } else { frameForward(1); (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({ direction: 'fit-right', durationInFrames: (0, imperative_state_1.getCurrentDuration)(), frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + 1), }); } e.preventDefault(); }, [frameForward, seek, getCurrentFrame]); const oneFrameBack = (0, react_1.useCallback)(() => { frameBack(1); }, [frameBack]); const oneFrameForward = (0, react_1.useCallback)(() => { frameForward(1); }, [frameForward]); const jumpToStart = (0, react_1.useCallback)(() => { seek(inFrame !== null && inFrame !== void 0 ? inFrame : 0); }, [seek, inFrame]); const jumpToEnd = (0, react_1.useCallback)(() => { seek(outFrame !== null && outFrame !== void 0 ? outFrame : (0, imperative_state_1.getCurrentDuration)() - 1); }, [seek, outFrame]); const keybindings = (0, use_keybinding_1.useKeybinding)(); (0, react_1.useEffect)(() => { const arrowLeft = keybindings.registerKeybinding({ event: 'keydown', key: 'ArrowLeft', callback: onArrowLeft, commandCtrlKey: false, preventDefault: true, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); const arrowRight = keybindings.registerKeybinding({ event: 'keydown', key: 'ArrowRight', callback: onArrowRight, commandCtrlKey: false, preventDefault: true, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); const space = keybindings.registerKeybinding({ event: 'keydown', key: ' ', callback: onSpace, commandCtrlKey: false, preventDefault: true, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); const enter = keybindings.registerKeybinding({ event: 'keydown', key: 'enter', callback: onEnter, commandCtrlKey: false, preventDefault: false, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); const a = keybindings.registerKeybinding({ event: 'keydown', key: 'a', callback: jumpToStart, commandCtrlKey: false, preventDefault: true, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); const e = keybindings.registerKeybinding({ event: 'keydown', key: 'e', callback: jumpToEnd, commandCtrlKey: false, preventDefault: true, triggerIfInputFieldFocused: false, keepRegisteredWhenNotHighestContext: false, }); return () => { arrowLeft.unregister(); arrowRight.unregister(); space.unregister(); enter.unregister(); a.unregister(); e.unregister(); }; }, [ jumpToEnd, jumpToStart, keybindings, onArrowLeft, onArrowRight, onEnter, onSpace, ]); (0, react_1.useEffect)(() => { let timeout = null; let stopped = false; const onBuffer = () => { requestAnimationFrame(() => { stopped = false; timeout = setTimeout(() => { if (!stopped) { setShowBufferState(true); } }, bufferStateDelayInMilliseconds); }); }; const onResume = () => { requestAnimationFrame(() => { setShowBufferState(false); stopped = true; if (timeout) { clearTimeout(timeout); } }); }; emitter.addEventListener('waiting', onBuffer); emitter.addEventListener('resume', onResume); return () => { emitter.removeEventListener('waiting', onBuffer); emitter.removeEventListener('resume', onResume); setShowBufferState(false); if (timeout) { clearTimeout(timeout); } stopped = true; }; }, [bufferStateDelayInMilliseconds, emitter]); return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [ jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: !videoConfig || isFirstFrame, onClick: jumpToStart, children: jsx_runtime_1.jsx(jump_to_start_1.JumpToStart, { style: backStyle }) }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: !videoConfig || isFirstFrame, onClick: oneFrameBack, children: jsx_runtime_1.jsx(step_back_1.StepBack, { style: forwardBackStyle }) }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', onClick: playing ? pause : play, disabled: !videoConfig, children: playing ? (showBufferIndicator ? (jsx_runtime_1.jsx(player_1.PlayerInternals.BufferingIndicator, { type: "studio" })) : (jsx_runtime_1.jsx(pause_1.Pause, { style: iconButton }))) : (jsx_runtime_1.jsx(play_1.Play, { style: iconButton })) }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { "aria-label": "Step forward one frame", title: "Step forward one frame", disabled: !videoConfig || isLastFrame, onClick: oneFrameForward, children: jsx_runtime_1.jsx(step_forward_1.StepForward, { style: forwardBackStyle }) }) ] })); }; exports.PlayPause = PlayPause;