convert some code to signals from context

This commit is contained in:
FromTheLOLAshes committed 2024-03-28 16:40:03 +07:00
1 parent bcb3acbc7f
commit f43d8bcdf5
23 files changed
+216 -186

No files matched your search

+12 -9
View File
@@ -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<HTMLDivElement>) => {
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}
>
<div
+7 -5
View File
@@ -1,4 +1,4 @@
import { useContext, useEffect, useReducer } from "react";
import { useEffect, useReducer } from "react";
import { faSparkles } from "@fortawesome/pro-solid-svg-icons";
@@ -17,11 +17,12 @@ import { AppUIProvider } from "./contexts/AppUiContext";
import { reducer, initialState, ACTION_TYPES } from "./reducer";
import { VIEW_MODES } from "./reducer/types";
import { ViewSideBySide } from "./comps/ViewSideBySide";
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
import { timelineHeight } from "~/pages/PageEnigma/store";
import { useSignals } from "@preact/signals-react/runtime";
export const PageEnigmaComponent = () => {
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 (
<div>
<TopBarHelmet>
@@ -46,8 +49,7 @@ export const PageEnigmaComponent = () => {
<div
id="CanvasUiWrapper"
className="flex"
style={{ height: `calc(100% - ${timelineHeight}px)` }}
// style={{ height: `calc(100% - 260px` }}
style={{ height: `calc(100% - ${lowerHeight}px)` }}
>
<div className="relative w-full overflow-hidden bg-transparent">
<div
@@ -1,6 +1,8 @@
import { useCallback, useContext, useEffect, useState } from "react";
import { BaseClip } from "~/pages/PageEnigma/models/track";
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
import { canDrop, dragId, overTimeline, scale } from "~/pages/PageEnigma/store";
import { useSignals } from "@preact/signals-react/runtime";
interface Props {
clip: BaseClip;
@@ -8,16 +10,8 @@ interface Props {
}
export const ClipElement = ({ clip, type }: Props) => {
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<HTMLDivElement>) => {
@@ -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}
>
@@ -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 (
<div
className="block rounded-lg bg-audio-groupBg pb-5 pl-2 pr-4"
style={{ width: fullWidth + 90 }}
style={{ width: fullWidth.value + 90 }}
>
<div className="prevent-select mb-5 pt-2 text-xs font-medium text-white">
Global Audio
@@ -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 (
<div
className="block rounded-lg bg-camera-groupBg pb-5 pl-2 pr-4"
style={{ width: fullWidth + 90 }}
style={{ width: fullWidth.value + 90 }}
>
<div className="mb-5 pt-2 text-xs font-medium text-white">Camera</div>
<div className="flex flex-col gap-4">
@@ -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 (
<div
className="block rounded-lg bg-character-groupBg pb-5 pl-2 pr-4"
style={{ width: fullWidth + 90 }}
style={{ width: fullWidth.value + 90 }}
>
<div className="prevent-select mb-5 pt-2 text-xs font-medium text-white">
Character
@@ -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 (
<div
className="block rounded-lg bg-objects-groupBg pb-5 pl-2 pr-4"
style={{ width: fullWidth + 90 }}
style={{ width: fullWidth.value + 90 }}
>
<div className="prevent-select mb-5 pt-2 text-xs font-medium text-white">
Objects
@@ -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) => (
<Fragment key={index}>
@@ -96,15 +103,18 @@ export const Timeline = () => {
))}
<div
className="absolute"
style={{ left: length * sectionWidth + 92 }}
style={{ left: filmLength.value * sectionWidth + 92 }}
>
00:{length < 10 ? "0" + length.toString() : length.toString()}
00:
{filmLength.value < 10
? "0" + filmLength.value.toString()
: filmLength.value.toString()}
</div>
<div
className="absolute block h-full bg-ui-divider"
style={{
width: 1,
left: length * sectionWidth + 88,
left: filmLength.value * sectionWidth + 88,
height: fullHeight,
}}
/>
@@ -125,7 +135,7 @@ export const Timeline = () => {
</div>
<div
className="absolute text-brand-primary"
style={{ top: 8, left: displayTime * 4 * scale + 88 }}
style={{ top: 8, left: displayTime * 4 * scale.value + 88 }}
onPointerDown={onPointerDown}
>
<FontAwesomeIcon
+19 -12
View File
@@ -2,8 +2,15 @@ import { TrackClip } from "~/pages/PageEnigma/comps/Timeline/TrackClip";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faVolume, faVolumeSlash } from "@fortawesome/pro-solid-svg-icons";
import { BaseClip } from "~/pages/PageEnigma/models/track";
import { PointerEvent, useContext } from "react";
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
import { PointerEvent } from "react";
import {
canDrop,
dragType,
dropId,
dropOffset,
filmLength,
scale,
} from "~/pages/PageEnigma/store";
interface Props {
id: string;
@@ -26,20 +33,18 @@ export const Track = ({
style,
type,
}: Props) => {
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<HTMLDivElement>) {
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}
@@ -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}
</div>
@@ -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")}
@@ -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<HTMLDivElement>) => {
if (event.button === 0) {
setClientX(event.clientX);
setIsActive("drag");
setTime(currentTime);
setTime(currentTime.value);
}
}, []),
time,
@@ -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(() => {
@@ -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<HTMLDivElement>) => {
if (event.button === 0) {
event.stopPropagation();
setClientY(event.clientY);
setIsActive(true);
setHeight(timelineHeight);
}
},
[timelineHeight],
),
onPointerDown: useCallback((event: React.PointerEvent<HTMLDivElement>) => {
if (event.button === 0) {
event.stopPropagation();
setClientY(event.clientY);
setIsActive(true);
setHeight(timelineHeight.value);
}
}, []),
height,
};
};
@@ -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: () => {},
});
@@ -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;
@@ -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<CharacterGroup[]>([
@@ -128,7 +129,10 @@ export default function useUpdateCharacters() {
}
return {
...character,
animationClips: [...character.animationClips, { ...clip, offset }],
animationClips: [
...character.animationClips,
{ ...clip, id: uuid.v4(), offset },
],
};
});
});
@@ -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,
};
}
@@ -0,0 +1,8 @@
import { signal } from "@preact/signals-core";
export const dragType = signal<"animations" | "lipSync" | null>(null);
export const dragId = signal<string | null>(null);
export const canDrop = signal(false);
export const overTimeline = signal(false);
export const dropId = signal("");
export const dropOffset = signal(0);
+3
View File
@@ -0,0 +1,3 @@
export * from "./dragAndDrop";
export * from "./sizing";
export * from "./timing";
+8
View File
@@ -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;
});
+3
View File
@@ -0,0 +1,3 @@
import { signal } from "@preact/signals-core";
export const currentTime = signal(0);
+41
View File
@@ -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",
+2
View File
@@ -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",