From f43d8bcdf51686f288e1660f4073dc1f148b4e3b Mon Sep 17 00:00:00 2001 From: FromTheLOLAshes Date: Thu, 28 Mar 2024 16:40:03 +0700 Subject: [PATCH] convert some code to signals from context --- app/modules/LowerPanel/LowerPanel.tsx | 21 +++++---- app/pages/PageEnigma/PageEnigmaComponent.tsx | 12 ++--- .../comps/SidePanelTabs/ClipElement.tsx | 34 ++++++-------- app/pages/PageEnigma/comps/Timeline/Audio.tsx | 6 +-- .../PageEnigma/comps/Timeline/Camera.tsx | 5 ++- .../PageEnigma/comps/Timeline/Character.tsx | 5 ++- .../PageEnigma/comps/Timeline/Objects.tsx | 5 ++- .../PageEnigma/comps/Timeline/Timeline.tsx | 30 ++++++++----- app/pages/PageEnigma/comps/Timeline/Track.tsx | 31 ++++++++----- .../PageEnigma/comps/Timeline/TrackClip.tsx | 17 ++++--- .../Timeline/utils/useMouseEventsAnimation.ts | 17 ++++--- .../Timeline/utils/useMouseEventsClip.ts | 19 +++----- .../Timeline/utils/useMouseEventsHeight.ts | 33 +++++++------- .../contexts/TrackContext/TrackContext.tsx | 45 ------------------- .../contexts/TrackContext/TrackProvider.tsx | 20 ++++++--- .../TrackContext/utils/useUpdateCharacters.ts | 8 +++- .../TrackContext/utils/useUpdateDragDrop.ts | 29 +++--------- app/pages/PageEnigma/store/dragAndDrop.ts | 8 ++++ app/pages/PageEnigma/store/index.ts | 3 ++ app/pages/PageEnigma/store/sizing.ts | 8 ++++ app/pages/PageEnigma/store/timing.ts | 3 ++ package-lock.json | 41 +++++++++++++++++ package.json | 2 + 23 files changed, 216 insertions(+), 186 deletions(-) create mode 100644 app/pages/PageEnigma/store/dragAndDrop.ts create mode 100644 app/pages/PageEnigma/store/index.ts create mode 100644 app/pages/PageEnigma/store/sizing.ts create mode 100644 app/pages/PageEnigma/store/timing.ts diff --git a/app/modules/LowerPanel/LowerPanel.tsx b/app/modules/LowerPanel/LowerPanel.tsx index 7984fed262..6bf237da52 100644 --- a/app/modules/LowerPanel/LowerPanel.tsx +++ b/app/modules/LowerPanel/LowerPanel.tsx @@ -1,25 +1,28 @@ -import React, { useCallback, useContext } from "react"; -import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; +import React, { useCallback } from "react"; import { useMouseEventsHeight } from "~/pages/PageEnigma/comps/Timeline/utils/useMouseEventsHeight"; +import { + currentTime, + overTimeline, + scale, + timelineHeight, +} from "~/pages/PageEnigma/store"; interface LowerPanelPropsI { children: React.ReactNode; } export const LowerPanel = ({ children }: LowerPanelPropsI) => { - const { setOverTimeline, updateCurrentTime, scale, timelineHeight } = - useContext(TrackContext); const { onPointerDown, height } = useMouseEventsHeight(); - const displayHeight = height > -1 ? height : timelineHeight; + const displayHeight = height > -1 ? height : timelineHeight.value; const onTimelineClick = useCallback( (event: React.PointerEvent) => { if (event.button === 0) { - updateCurrentTime((Math.round(event.clientX) - 92) / 4 / scale); + currentTime.value = (Math.round(event.clientX) - 92) / 4 / scale.value; } }, - [updateCurrentTime, scale], + [], ); return ( @@ -31,9 +34,9 @@ export const LowerPanel = ({ children }: LowerPanelPropsI) => { ].join(" ")} style={{ height: displayHeight }} onPointerOver={() => { - setOverTimeline(true); + overTimeline.value = true; }} - onPointerLeave={() => setOverTimeline(false)} + onPointerLeave={() => (overTimeline.value = false)} onPointerDown={onTimelineClick} >
{ const [appUiState, dispatchAppUiState] = useReducer(reducer, initialState); - const { timelineHeight } = useContext(TrackContext); + useSignals(); useEffect(() => { setTimeout( @@ -33,6 +34,8 @@ export const PageEnigmaComponent = () => { ); }, []); + const lowerHeight = timelineHeight.value; + console.log("main", timelineHeight.value); return (
@@ -46,8 +49,7 @@ export const PageEnigmaComponent = () => {
{ - const { - startDrag, - dragId, - endDrag, - scale, - canDrop, - setCanDrop, - overTimeline, - dropId, - } = useContext(TrackContext); + useSignals(); + const { startDrag, endDrag } = useContext(TrackContext); const [initPosition, setInitPosition] = useState<{ initX: number; initY: number; @@ -37,7 +31,7 @@ export const ClipElement = ({ clip, type }: Props) => { useEffect(() => { const onPointerUp = () => { - if (dragId) { + if (dragId.value) { endDrag(); } }; @@ -60,7 +54,7 @@ export const ClipElement = ({ clip, type }: Props) => { window.removeEventListener("pointerup", onPointerUp); window.removeEventListener("pointermove", onMouseMove); }; - }, [dragId, startDrag, endDrag, initX, initY]); + }, [startDrag, endDrag, initX, initY]); const onPointerDown = useCallback( (event: React.PointerEvent) => { @@ -77,10 +71,10 @@ export const ClipElement = ({ clip, type }: Props) => { initX: position.x, initY: position.y + position.height + 1, }); - setCanDrop(false); + canDrop.value = false; } }, - [type, clip.id, startDrag, setCanDrop], + [type, clip.id, startDrag], ); return ( @@ -98,15 +92,15 @@ export const ClipElement = ({ clip, type }: Props) => { className={[ "absolute p-2", "rounded-lg", - !canDrop ? "bg-brand-primary" : "bg-brand-secondary-700", - dragId ? "block" : "hidden", + !canDrop.value ? "bg-brand-primary" : "bg-brand-secondary-700", + dragId.value ? "block" : "hidden", ].join(" ")} style={{ - top: overTimeline ? y + 24 : y, - left: overTimeline ? x : x, + top: overTimeline.value ? y + 24 : y, + left: overTimeline.value ? x : x, zIndex: 5000, - width: overTimeline ? clip.length * 4 * scale : 64, - height: overTimeline ? 32 : 64, + width: overTimeline.value ? clip.length * 4 * scale.value : 64, + height: overTimeline.value ? 32 : 64, }} onPointerDown={onPointerDown} > diff --git a/app/pages/PageEnigma/comps/Timeline/Audio.tsx b/app/pages/PageEnigma/comps/Timeline/Audio.tsx index ae652ec4e8..946bc56336 100644 --- a/app/pages/PageEnigma/comps/Timeline/Audio.tsx +++ b/app/pages/PageEnigma/comps/Timeline/Audio.tsx @@ -1,16 +1,16 @@ import { useContext } from "react"; import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; import { Track } from "~/pages/PageEnigma/comps/Timeline/Track"; +import { fullWidth } from "~/pages/PageEnigma/store"; export const Audio = () => { - const { audio, updateAudio, toggleAudioMute, fullWidth } = - useContext(TrackContext); + const { audio, updateAudio, toggleAudioMute } = useContext(TrackContext); const { clips } = audio!; return (
Global Audio diff --git a/app/pages/PageEnigma/comps/Timeline/Camera.tsx b/app/pages/PageEnigma/comps/Timeline/Camera.tsx index f09e8a7d71..1c786716f5 100644 --- a/app/pages/PageEnigma/comps/Timeline/Camera.tsx +++ b/app/pages/PageEnigma/comps/Timeline/Camera.tsx @@ -1,15 +1,16 @@ import { useContext } from "react"; import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; import { Track } from "~/pages/PageEnigma/comps/Timeline/Track"; +import { fullWidth } from "~/pages/PageEnigma/store"; export const Camera = () => { - const { camera, fullWidth, updateCamera } = useContext(TrackContext); + const { camera, updateCamera } = useContext(TrackContext); const { clips } = camera!; return (
Camera
diff --git a/app/pages/PageEnigma/comps/Timeline/Character.tsx b/app/pages/PageEnigma/comps/Timeline/Character.tsx index 83a09b2c88..97402781b7 100644 --- a/app/pages/PageEnigma/comps/Timeline/Character.tsx +++ b/app/pages/PageEnigma/comps/Timeline/Character.tsx @@ -1,6 +1,7 @@ import { useCallback, useContext, useMemo } from "react"; import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; import { Track } from "~/pages/PageEnigma/comps/Timeline/Track"; +import { fullWidth } from "~/pages/PageEnigma/store"; function buildUpdaters( updateCharacters: (options: { @@ -38,7 +39,7 @@ interface Props { } export const Character = ({ characterId }: Props) => { - const { characters, updateCharacters, toggleLipSyncMute, fullWidth } = + const { characters, updateCharacters, toggleLipSyncMute } = useContext(TrackContext); const character = characters.find((row) => (row.id = characterId)); @@ -56,7 +57,7 @@ export const Character = ({ characterId }: Props) => { return (
Character diff --git a/app/pages/PageEnigma/comps/Timeline/Objects.tsx b/app/pages/PageEnigma/comps/Timeline/Objects.tsx index 238a243709..8929658c99 100644 --- a/app/pages/PageEnigma/comps/Timeline/Objects.tsx +++ b/app/pages/PageEnigma/comps/Timeline/Objects.tsx @@ -1,14 +1,15 @@ import { useContext } from "react"; import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; import { Track } from "~/pages/PageEnigma/comps/Timeline/Track"; +import { fullWidth } from "~/pages/PageEnigma/store"; export const Objects = () => { - const { objects, updateObject, fullWidth } = useContext(TrackContext); + const { objects, updateObject } = useContext(TrackContext); return (
Objects diff --git a/app/pages/PageEnigma/comps/Timeline/Timeline.tsx b/app/pages/PageEnigma/comps/Timeline/Timeline.tsx index 73783a8b11..bf64e2cbc7 100644 --- a/app/pages/PageEnigma/comps/Timeline/Timeline.tsx +++ b/app/pages/PageEnigma/comps/Timeline/Timeline.tsx @@ -10,15 +10,18 @@ import { useMouseEventsAnimation } from "./utils/useMouseEventsAnimation"; import { faSortDown } from "@fortawesome/pro-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { ConfirmationModal } from "~/components/ConfirmationModal"; +import { + scale, + currentTime, + filmLength, + timelineHeight, +} from "~/pages/PageEnigma/store"; export const Timeline = () => { const { characters, objects, - scale, - length, selectedClip, - currentTime, deleteCharacterClip, deleteAudioClip, deleteCameraClip, @@ -27,10 +30,14 @@ export const Timeline = () => { const { onPointerDown, time } = useMouseEventsAnimation(); const [dialogOpen, setDialogOpen] = useState(false); - const sectionWidth = 60 * 4 * scale; + const sectionWidth = 60 * 4 * scale.value; const fullHeight = characters.length * 268 + objects.objects.length * 60 + 300 + 96; + useEffect(() => { + timelineHeight.value = window.outerHeight * 0.25; + }, []); + const onDeleteAsk = useCallback( (event: KeyboardEvent) => { if (["Backspace", "Delete"].indexOf(event.key) > -1 && selectedClip) { @@ -40,7 +47,7 @@ export const Timeline = () => { [selectedClip], ); - const displayTime = time === -1 ? currentTime : time; + const displayTime = time === -1 ? currentTime.value : time; const onDelete = useCallback(() => { deleteCharacterClip(selectedClip!); @@ -74,7 +81,7 @@ export const Timeline = () => { "text-xs text-white opacity-75", ].join(" ")} > - {Array(length) + {Array(filmLength.value) .fill(0) .map((_, index) => ( @@ -96,15 +103,18 @@ export const Timeline = () => { ))}
- 00:{length < 10 ? "0" + length.toString() : length.toString()} + 00: + {filmLength.value < 10 + ? "0" + filmLength.value.toString() + : filmLength.value.toString()}
@@ -125,7 +135,7 @@ export const Timeline = () => {
{ - const { length, scale, setCanDrop, dragType, setDropId, setDropOffset } = - useContext(TrackContext); const trackType = type ?? style; function onPointerOver() { - if (dragType !== trackType) { + if (dragType.value !== trackType) { return; } - setCanDrop(true); - setDropId(id); + canDrop.value = true; + dropId.value = id; } function onPointerMove(event: PointerEvent) { - if (dragType !== trackType) { + if (dragType.value !== trackType) { return; } const track = document.getElementById(`track-${trackType}-${id}`); @@ -47,13 +52,13 @@ export const Track = ({ return; } const position = track.getBoundingClientRect(); - setDropOffset((event.clientX - position.x) / 4 / scale); + dropOffset.value = (event.clientX - position.x) / 4 / scale.value; } function onPointerLeave() { - if (dragType !== trackType) { + if (dragType.value !== trackType) { return; } - setCanDrop(false); + canDrop.value = false; } return ( @@ -72,7 +77,9 @@ export const Track = ({ index > 0 ? clips[index - 1].offset + clips[index - 1].length : 0 } max={ - index < clips.length - 1 ? clips[index + 1].offset : length * 60 + index < clips.length - 1 + ? clips[index + 1].offset + : filmLength.value * 60 } style={style} updateClip={updateClip} diff --git a/app/pages/PageEnigma/comps/Timeline/TrackClip.tsx b/app/pages/PageEnigma/comps/Timeline/TrackClip.tsx index d99b8b5011..de24749444 100644 --- a/app/pages/PageEnigma/comps/Timeline/TrackClip.tsx +++ b/app/pages/PageEnigma/comps/Timeline/TrackClip.tsx @@ -2,6 +2,7 @@ import { useMouseEventsClip } from "./utils/useMouseEventsClip"; import { BaseClip } from "~/pages/PageEnigma/models/track"; import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; import { useContext, useState } from "react"; +import { scale } from "~/pages/PageEnigma/store"; interface Props { min: number; @@ -12,7 +13,7 @@ interface Props { } export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => { - const { selectClip, selectedClip, scale } = useContext(TrackContext); + const { selectClip, selectedClip } = useContext(TrackContext); const [state, setState] = useState({ length: clip.length, offset: clip.offset, @@ -41,7 +42,7 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => { "rounded", "prevent-select text-xs font-medium text-white", ].join(" ")} - style={{ top: -28, left: offset * 4 * scale + 2 }} + style={{ top: -28, left: offset * 4 * scale.value + 2 }} > {clip.name}
@@ -54,7 +55,11 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => { ? "border border-b-2 border-l-2 border-r-0 border-t-2 border-white focus-visible:outline-0" : "", ].join(" ")} - style={{ width: 15, left: offset * 4 * scale, cursor: "w-resize" }} + style={{ + width: 15, + left: offset * 4 * scale.value, + cursor: "w-resize", + }} onPointerDown={(event) => onPointerDown(event, "left")} onClick={() => selectClip(clip.id)} /> @@ -67,8 +72,8 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => { : "", ].join(" ")} style={{ - width: length * 4 * scale - 30, - left: offset * 4 * scale + 15, + width: length * 4 * scale.value - 30, + left: offset * 4 * scale.value + 15, cursor: "move", }} onPointerDown={(event) => onPointerDown(event, "drag")} @@ -85,7 +90,7 @@ export const TrackClip = ({ clip, min, max, style, updateClip }: Props) => { ].join(" ")} style={{ width: 15, - left: offset * 4 * scale + length * 4 * scale - 15, + left: offset * 4 * scale.value + length * 4 * scale.value - 15, cursor: "e-resize", }} onPointerDown={(event) => onPointerDown(event, "right")} diff --git a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsAnimation.ts b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsAnimation.ts index f525bd2a0a..ba3d9aa746 100644 --- a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsAnimation.ts +++ b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsAnimation.ts @@ -1,27 +1,26 @@ -import React, { useCallback, useContext, useEffect, useState } from "react"; -import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; +import React, { useCallback, useEffect, useState } from "react"; +import { currentTime, scale } from "~/pages/PageEnigma/store"; export const useMouseEventsAnimation = () => { - const { currentTime, updateCurrentTime, length, scale } = - useContext(TrackContext); const [isActive, setIsActive] = useState(""); const [clientX, setClientX] = useState(0); const [time, setTime] = useState(-1); useEffect(() => { - const max = length * 60 * 4 * scale; + const max = length * 60 * 4 * scale.value; const onPointerUp = () => { if (isActive) { - updateCurrentTime(Math.round(time)); + currentTime.value = Math.round(time); setIsActive(""); setTime(-1); } }; const onMouseMove = (event: MouseEvent) => { - const delta = (event.clientX - clientX) / 4 / scale + currentTime; + const delta = + (event.clientX - clientX) / 4 / scale.value + currentTime.value; if (isActive === "drag") { event.stopPropagation(); event.preventDefault(); @@ -40,14 +39,14 @@ export const useMouseEventsAnimation = () => { window.removeEventListener("pointerup", onPointerUp); window.removeEventListener("pointermove", onMouseMove); }; - }, [clientX, isActive, length, updateCurrentTime, scale, time, currentTime]); + }, [clientX, isActive, time]); return { onPointerDown: useCallback((event: React.PointerEvent) => { if (event.button === 0) { setClientX(event.clientX); setIsActive("drag"); - setTime(currentTime); + setTime(currentTime.value); } }, []), time, diff --git a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts index 35c82d795d..8d666599a2 100644 --- a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts +++ b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsClip.ts @@ -1,12 +1,7 @@ -import React, { - Dispatch, - useCallback, - useContext, - useEffect, - useRef, -} from "react"; +import React, { Dispatch, useCallback, useEffect, useRef } from "react"; import { BaseClip } from "~/pages/PageEnigma/models/track"; -import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; +import { canDrop, scale } from "~/pages/PageEnigma/store"; +import { useSignals } from "@preact/signals-react/runtime"; export const useMouseEventsClip = ( clip: BaseClip, @@ -15,6 +10,7 @@ export const useMouseEventsClip = ( updateClip: (args: { id: string; offset: number; length: number }) => void, setState: Dispatch<{ length: number; offset: number }>, ) => { + useSignals(); const currLength = useRef(clip.length); const currOffset = useRef(clip.offset); const initLength = useRef(clip.length); @@ -22,8 +18,6 @@ export const useMouseEventsClip = ( const isActive = useRef(""); const clientX = useRef(0); - const { scale } = useContext(TrackContext); - const onPointerUp = useCallback(() => { if (isActive.current) { updateClip({ @@ -32,12 +26,13 @@ export const useMouseEventsClip = ( length: Math.round(currLength.current), }); isActive.current = ""; + canDrop.value = false; } }, [updateClip, clip.id]); const onMouseMove = useCallback( (event: MouseEvent) => { - const delta = (event.clientX - clientX.current) / 4 / scale; + const delta = (event.clientX - clientX.current) / 4 / scale.value; const deltaOffset = delta + initOffset.current; if (isActive.current === "drag") { if (deltaOffset < min || deltaOffset + currLength.current > max) { @@ -63,7 +58,7 @@ export const useMouseEventsClip = ( } setState({ length: currLength.current, offset: currOffset.current }); }, - [max, min, scale, setState], + [max, min, setState], ); useEffect(() => { diff --git a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsHeight.ts b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsHeight.ts index 66410d9cf5..d1b1a79fd7 100644 --- a/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsHeight.ts +++ b/app/pages/PageEnigma/comps/Timeline/utils/useMouseEventsHeight.ts @@ -1,8 +1,7 @@ -import React, { useCallback, useContext, useEffect, useState } from "react"; -import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext"; +import React, { useCallback, useEffect, useState } from "react"; +import { timelineHeight } from "~/pages/PageEnigma/store"; export const useMouseEventsHeight = () => { - const { timelineHeight, setTimelineHeight } = useContext(TrackContext); const [isActive, setIsActive] = useState(false); const [clientY, setClientY] = useState(0); @@ -11,7 +10,8 @@ export const useMouseEventsHeight = () => { useEffect(() => { const onPointerUp = () => { if (isActive) { - setTimelineHeight(height); + console.log("up", height); + timelineHeight.value = Math.round(height); setIsActive(false); setHeight(-1); } @@ -22,10 +22,10 @@ export const useMouseEventsHeight = () => { const delta = event.clientY - clientY; event.stopPropagation(); event.preventDefault(); - if (timelineHeight - delta < 30) { + if (timelineHeight.value - delta < 30) { return; } - setHeight(timelineHeight - delta); + setHeight(timelineHeight.value - delta); return; } }; @@ -37,20 +37,17 @@ export const useMouseEventsHeight = () => { window.removeEventListener("pointerup", onPointerUp); window.removeEventListener("pointermove", onMouseMove); }; - }, [clientY, isActive, height, timelineHeight, setTimelineHeight]); + }, [clientY, isActive, height]); return { - onPointerDown: useCallback( - (event: React.PointerEvent) => { - if (event.button === 0) { - event.stopPropagation(); - setClientY(event.clientY); - setIsActive(true); - setHeight(timelineHeight); - } - }, - [timelineHeight], - ), + onPointerDown: useCallback((event: React.PointerEvent) => { + if (event.button === 0) { + event.stopPropagation(); + setClientY(event.clientY); + setIsActive(true); + setHeight(timelineHeight.value); + } + }, []), height, }; }; diff --git a/app/pages/PageEnigma/contexts/TrackContext/TrackContext.tsx b/app/pages/PageEnigma/contexts/TrackContext/TrackContext.tsx index 5f5a037a72..7115d4677d 100644 --- a/app/pages/PageEnigma/contexts/TrackContext/TrackContext.tsx +++ b/app/pages/PageEnigma/contexts/TrackContext/TrackContext.tsx @@ -79,35 +79,8 @@ export const TrackContext = createContext<{ audioClips: AudioClip[]; // drag and drop - dragType: "animations" | "lipSync" | null; - dragId: string | null; startDrag: (type: "animations" | "lipSync", id: string) => void; endDrag: () => void; - canDrop: boolean; - setCanDrop: (can: boolean) => void; - overTimeline: boolean; - setOverTimeline: (over: boolean) => void; - dropId: string; - setDropId: (id: string) => void; - dropOffset: number; - setDropOffset: (offset: number) => void; - - // scale of timeline displa - scale: number; - - // current time position - currentTime: number; - updateCurrentTime: (time: number) => void; - - // total length of the film clip - length: number; - - // height of the timeline section - timelineHeight: number; - setTimelineHeight: (height: number) => void; - - // computed width length * 60 * 4 * scale - fullWidth: number; }>({ characters: [], updateCharacters: () => {}, @@ -140,24 +113,6 @@ export const TrackContext = createContext<{ animationClips: [], audioClips: [], - dragType: null, - dragId: null, startDrag: () => {}, endDrag: () => {}, - dropId: "", - setDropId: () => {}, - canDrop: false, - setCanDrop: () => {}, - overTimeline: false, - setOverTimeline: () => {}, - dropOffset: 0, - setDropOffset: () => {}, - - scale: 1, - currentTime: 0, - updateCurrentTime: () => {}, - length: 12, - fullWidth: 0, - timelineHeight: 0, - setTimelineHeight: () => {}, }); diff --git a/app/pages/PageEnigma/contexts/TrackContext/TrackProvider.tsx b/app/pages/PageEnigma/contexts/TrackContext/TrackProvider.tsx index a61164aa5a..2559041981 100644 --- a/app/pages/PageEnigma/contexts/TrackContext/TrackProvider.tsx +++ b/app/pages/PageEnigma/contexts/TrackContext/TrackProvider.tsx @@ -6,6 +6,13 @@ import useUpdateAudio from "~/pages/PageEnigma/contexts/TrackContext/utils/useUp import useUpdateObject from "~/pages/PageEnigma/contexts/TrackContext/utils/useUpdateObject"; import { AnimationClip, AudioClip } from "~/pages/PageEnigma/models/track"; import useUpdateDragDrop from "~/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop"; +import { + canDrop, + dragId, + dragType, + dropId, + dropOffset, +} from "~/pages/PageEnigma/store"; interface Props { children: ReactNode; @@ -47,19 +54,18 @@ export const TrackProvider = ({ children }: Props) => { // cross group functions const dropClip = useCallback(() => { - const { canDrop, dragType, dropId, dragId, dropOffset } = dragDrop; - if (canDrop) { - if (dragType === "animations") { + if (canDrop.value) { + if (dragType.value === "animations") { characters.addCharacterAnimation({ - clipId: dragId!, - characterId: dropId, + clipId: dragId.value!, + characterId: dropId.value, animationClips, - offset: dropOffset, + offset: dropOffset.value, }); } } endDrag(); - }, [dragDrop, animationClips, characters, endDrag]); + }, [animationClips, characters, endDrag]); const fullWidth = useMemo(() => { return length * 60 * 4 * scale; diff --git a/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateCharacters.ts b/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateCharacters.ts index 546e3664cc..be2d39a290 100644 --- a/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateCharacters.ts +++ b/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateCharacters.ts @@ -1,5 +1,6 @@ -import { useCallback, useRef, useState } from "react"; +import { useCallback, useState } from "react"; import { BaseClip, CharacterGroup } from "~/pages/PageEnigma/models/track"; +import * as uuid from "uuid"; export default function useUpdateCharacters() { const [characters, setCharacters] = useState([ @@ -128,7 +129,10 @@ export default function useUpdateCharacters() { } return { ...character, - animationClips: [...character.animationClips, { ...clip, offset }], + animationClips: [ + ...character.animationClips, + { ...clip, id: uuid.v4(), offset }, + ], }; }); }); diff --git a/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop.ts b/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop.ts index 35bf92ccb8..529cf82152 100644 --- a/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop.ts +++ b/app/pages/PageEnigma/contexts/TrackContext/utils/useUpdateDragDrop.ts @@ -1,38 +1,23 @@ -import { useCallback, useState } from "react"; +import { useCallback } from "react"; +import { canDrop, dragId, dragType } from "~/pages/PageEnigma/store"; export default function useUpdateDragDrop() { - const [state, setState] = useState<{ - dragType: "animations" | "lipSync" | null; - dragId: string | null; - }>({ dragType: null, dragId: null }); const startDrag = useCallback( (type: "animations" | "lipSync", id: string) => { - setState({ dragId: id, dragType: type }); + dragId.value = id; + dragType.value = type; }, [], ); - const [canDrop, setCanDrop] = useState(false); - const [overTimeline, setOverTimeline] = useState(false); const endDrag = useCallback(() => { - setState({ dragId: null, dragType: null }); + dragId.value = null; + dragType.value = null; + canDrop.value = false; }, []); - const [dropId, setDropId] = useState(""); - const [dropOffset, setDropOffset] = useState(0); - return { - dragId: state.dragId, - dragType: state.dragType, startDrag, endDrag, - canDrop, - setCanDrop, - overTimeline, - setOverTimeline, - dropId, - setDropId, - dropOffset, - setDropOffset, }; } diff --git a/app/pages/PageEnigma/store/dragAndDrop.ts b/app/pages/PageEnigma/store/dragAndDrop.ts new file mode 100644 index 0000000000..dbc5018fd7 --- /dev/null +++ b/app/pages/PageEnigma/store/dragAndDrop.ts @@ -0,0 +1,8 @@ +import { signal } from "@preact/signals-core"; + +export const dragType = signal<"animations" | "lipSync" | null>(null); +export const dragId = signal(null); +export const canDrop = signal(false); +export const overTimeline = signal(false); +export const dropId = signal(""); +export const dropOffset = signal(0); diff --git a/app/pages/PageEnigma/store/index.ts b/app/pages/PageEnigma/store/index.ts new file mode 100644 index 0000000000..fb12ae01bb --- /dev/null +++ b/app/pages/PageEnigma/store/index.ts @@ -0,0 +1,3 @@ +export * from "./dragAndDrop"; +export * from "./sizing"; +export * from "./timing"; diff --git a/app/pages/PageEnigma/store/sizing.ts b/app/pages/PageEnigma/store/sizing.ts new file mode 100644 index 0000000000..778621080b --- /dev/null +++ b/app/pages/PageEnigma/store/sizing.ts @@ -0,0 +1,8 @@ +import { signal, computed } from "@preact/signals-core"; + +export const scale = signal(1); +export const filmLength = signal(12); +export const timelineHeight = signal(0); +export const fullWidth = computed(() => { + return filmLength.value * 60 * 4 * scale.value; +}); diff --git a/app/pages/PageEnigma/store/timing.ts b/app/pages/PageEnigma/store/timing.ts new file mode 100644 index 0000000000..d64bb7525a --- /dev/null +++ b/app/pages/PageEnigma/store/timing.ts @@ -0,0 +1,3 @@ +import { signal } from "@preact/signals-core"; + +export const currentTime = signal(0); diff --git a/package-lock.json b/package-lock.json index af9fdcb114..a1baf63896 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@netlify/edge-functions": "^2.3.1", "@netlify/remix-edge-adapter": "^3.2.0", "@netlify/remix-runtime": "^2.2.0", + "@preact/signals-react": "^2.0.1", "@remix-run/deno": "^2.8.1", "@remix-run/node": "^2.8.1", "@remix-run/react": "^2.8.1", @@ -37,6 +38,7 @@ "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/three": "^0.162.0", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.7.4", "autoprefixer": "^10.4.18", "eslint": "^8.38.0", @@ -1735,6 +1737,31 @@ "node": ">=14" } }, + "node_modules/@preact/signals-core": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.6.0.tgz", + "integrity": "sha512-O/XGxwP85h1F7+ouqTMOIZ3+V1whfaV9ToIVcuyGriD4JkSD00cQo54BKdqjvBJxbenvp7ynfqRHEwI6e+NIhw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/@preact/signals-react": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@preact/signals-react/-/signals-react-2.0.1.tgz", + "integrity": "sha512-QQoxAPiliH6oeZPF5OZHmyala5zyFya0ZCp/A0lR4y6R9wO4lT7GdtYg5UFlmKNWMcFN6PiAjNPMTiNFMmnCpw==", + "dependencies": { + "@preact/signals-core": "^1.6.0", + "use-sync-external-store": "^1.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x" + } + }, "node_modules/@remix-run/deno": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/@remix-run/deno/-/deno-2.8.1.tgz", @@ -2429,6 +2456,12 @@ "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", "dev": true }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/webxr": { "version": "0.5.14", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.14.tgz", @@ -12478,6 +12511,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util": { "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", diff --git a/package.json b/package.json index a40f2b10c2..e723262fc4 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@netlify/edge-functions": "^2.3.1", "@netlify/remix-edge-adapter": "^3.2.0", "@netlify/remix-runtime": "^2.2.0", + "@preact/signals-react": "^2.0.1", "@remix-run/deno": "^2.8.1", "@remix-run/node": "^2.8.1", "@remix-run/react": "^2.8.1", @@ -43,6 +44,7 @@ "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/three": "^0.162.0", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^6.7.4", "autoprefixer": "^10.4.18", "eslint": "^8.38.0",