Add delete clip with modal

This commit is contained in:
FromTheLOLAshes committed 2024-03-27 14:17:42 +07:00
1 parent e36ec9317f
commit 985de175a5
8 files changed
+172 -3

No files matched your search

+54
View File
@@ -0,0 +1,54 @@
import { Dialog } from "@headlessui/react";
interface Props {
text: string;
title: string;
open: boolean;
onClose: () => void;
onOk?: () => void;
okText?: string;
okColor?: string;
onCancel?: () => void;
cancelText?: string;
}
export const ConfirmationModal = ({
text,
title,
open,
onClose,
onOk,
okText = "OK",
okColor = "bg-brand-success",
onCancel,
cancelText = "Cancel",
}: Props) => {
return (
<Dialog open={open} onClose={onClose}>
<div className="fixed inset-0 flex w-screen items-center justify-center bg-white p-4 opacity-35" />
<div className="fixed inset-0 flex w-screen items-center justify-center p-4">
<Dialog.Panel className="bg-black p-4">
<Dialog.Title>{title}</Dialog.Title>
<p className="my-6">{text}</p>
<div className="flex justify-end gap-4">
{!!onCancel && (
<button onClick={onCancel} className="rounded-lg px-3 py-2">
{cancelText}
</button>
)}
{!!onOk && (
<button
onClick={onOk}
className={[okColor, "rounded-lg px-3 py-2"].join(" ")}
>
{okText}
</button>
)}
</div>
</Dialog.Panel>
</div>
</Dialog>
);
};
-1
View File
@@ -23,7 +23,6 @@ export const LowerPanel = ({ children, timelineHeight }: LowerPanelPropsI) => {
].join(" ")}
style={{ height: timelineHeight }}
onPointerOver={() => {
console.log("over");
setOverTimeline(true);
}}
onPointerLeave={() => setOverTimeline(false)}
@@ -1,4 +1,4 @@
import { Fragment, useContext } from "react";
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
import { LowerPanel } from "~/modules/LowerPanel";
import { Character } from "./Character";
@@ -9,19 +9,61 @@ import { Objects } from "./Objects";
import { useMouseEventsAnimation } from "./utils/useMouseEventsAnimation";
import { faSortDown } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { ConfirmationModal } from "~/components/ConfirmationModal";
interface Props {
timelineHeight: number;
}
export const Timeline = ({ timelineHeight }: Props) => {
const { characters, objects, scale, length } = useContext(TrackContext);
const {
characters,
objects,
scale,
length,
selectedClip,
deleteCharacterClip,
deleteAudioClip,
deleteCameraClip,
deleteObjectClip,
} = useContext(TrackContext);
const { onPointerDown, time } = useMouseEventsAnimation();
const [dialogOpen, setDialogOpen] = useState(false);
const sectionWidth = 60 * 4 * scale;
const fullHeight =
characters.length * 200 + objects.objects.length * 80 + 248 + 96;
const onDeleteAsk = useCallback(
(event: KeyboardEvent) => {
if (["Backspace", "Delete"].indexOf(event.key) > -1 && selectedClip) {
setDialogOpen(true);
}
},
[selectedClip],
);
const onDelete = useCallback(() => {
deleteCharacterClip(selectedClip!);
deleteCameraClip(selectedClip!);
deleteAudioClip(selectedClip!);
deleteObjectClip(selectedClip!);
}, [
selectedClip,
deleteAudioClip,
deleteCharacterClip,
deleteCameraClip,
deleteObjectClip,
]);
useEffect(() => {
document.addEventListener("keydown", onDeleteAsk);
return () => {
document.addEventListener("keydown", onDeleteAsk);
};
}, [onDeleteAsk]);
return (
<>
<LowerPanel timelineHeight={timelineHeight}>
@@ -102,6 +144,19 @@ export const Timeline = ({ timelineHeight }: Props) => {
/>
</div>
</LowerPanel>
<ConfirmationModal
title="Delete Clip"
text="Are you sure you want to delete the selected clip?"
open={dialogOpen}
onClose={() => setDialogOpen(false)}
onOk={() => {
onDelete();
setDialogOpen(false);
}}
okText="Delete"
okColor="bg-brand-primary"
onCancel={() => setDialogOpen(false)}
/>
</>
);
};
@@ -32,6 +32,7 @@ export const TrackContext = createContext<{
offset: number;
}) => void;
selectCharacterClip: (clipId: string) => void;
deleteCharacterClip: (clipId: string) => void;
// timeline camera group
camera: CameraGroup | null;
@@ -41,6 +42,7 @@ export const TrackContext = createContext<{
offset: number;
}) => void;
selectCameraClip: (clipId: string) => void;
deleteCameraClip: (clipId: string) => void;
// timeline global audio group
audio: AudioGroup | null;
@@ -52,6 +54,7 @@ export const TrackContext = createContext<{
toggleAudioMute: () => void;
addGlobalAudio: (clipId: string, animationClips: BaseClip[]) => void;
selectAudioClip: (clipId: string) => void;
deleteAudioClip: (clipId: string) => void;
// timeline objects group
objects: ObjectGroup;
@@ -61,6 +64,7 @@ export const TrackContext = createContext<{
offset: number;
}) => void;
selectObjectClip: (clipId: string) => void;
deleteObjectClip: (clipId: string) => void;
// current - only select one item - will be replaced
selectedClip: string | null;
@@ -103,20 +107,24 @@ export const TrackContext = createContext<{
addCharacterAnimation: () => {},
addCharacterAudio: () => {},
selectCharacterClip: () => {},
deleteCharacterClip: () => {},
camera: null,
updateCamera: () => {},
selectCameraClip: () => {},
deleteCameraClip: () => {},
audio: null,
updateAudio: () => {},
toggleAudioMute: () => {},
selectAudioClip: () => {},
addGlobalAudio: () => {},
deleteAudioClip: () => {},
objects: { id: "", objects: [] },
updateObject: () => {},
selectObjectClip: () => {},
deleteObjectClip: () => {},
selectedClip: null,
selectClip: () => {},
@@ -91,11 +91,21 @@ export default function useUpdateAudio() {
});
}, []);
const deleteAudioClip = useCallback((clipId: string) => {
setAudio((oldAudio) => {
return {
...oldAudio,
clips: [...oldAudio.clips.filter((clip) => clip.id !== clipId)],
};
});
}, []);
return {
audio,
updateAudio,
toggleAudioMute,
selectAudioClip,
addGlobalAudio,
deleteAudioClip,
};
}
@@ -64,9 +64,19 @@ export default function useUpdateCamera() {
});
}, []);
const deleteCameraClip = useCallback((clipId: string) => {
setCamera((oldCamera) => {
return {
...oldCamera,
clips: [...oldCamera.clips.filter((clip) => clip.id !== clipId)],
};
});
}, []);
return {
camera,
updateCamera,
selectCameraClip,
deleteCameraClip,
};
}
@@ -203,6 +203,25 @@ export default function useUpdateCharacters() {
});
}, []);
const deleteCharacterClip = useCallback((clipId: string) => {
setCharacters((oldCharacters) => {
return [
...oldCharacters.map((character) => ({
...character,
animationClips: character.animationClips.filter(
(clip) => clip.id !== clipId,
),
positionClips: character.positionClips.filter(
(clip) => clip.id !== clipId,
),
lipSyncClips: character.lipSyncClips.filter(
(clip) => clip.id !== clipId,
),
})),
];
});
}, []);
return {
characters,
updateCharacters,
@@ -210,5 +229,6 @@ export default function useUpdateCharacters() {
addCharacterAnimation,
addCharacterAudio,
selectCharacterClip,
deleteCharacterClip,
};
}
@@ -61,9 +61,22 @@ export default function useUpdateObject() {
});
}, []);
const deleteObjectClip = useCallback((clipId: string) => {
setObjects((oldObjectGroup) => {
return {
...oldObjectGroup,
objects: oldObjectGroup.objects.map((object) => ({
...object,
clips: object.clips.filter((clip) => clip.id !== clipId),
})),
};
});
}, []);
return {
objects,
updateObject,
selectObjectClip,
deleteObjectClip,
};
}