Skip to content

Commit

Permalink
Read and save scenes in single document.
Browse files Browse the repository at this point in the history
  • Loading branch information
vinaymavi committed Mar 22, 2024
1 parent 228f9c6 commit 3caf6bb
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 33 deletions.
21 changes: 14 additions & 7 deletions app/auth/slides/create-new/[[...video_id]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useEffect } from "react";
import SceneEditor from "@/components/SceneEditor/SceneEditor";
import SceneList from "@/components/SceneList/SceneList";
import {
useMutationCreateScene,
useMutationPostTextToSpeech,
useMutationUpdateScene,
useQueryGetScenes,
useQueryGetVideo,
} from "@/src/query/video.query";
Expand All @@ -15,6 +15,7 @@ import { getLayoutContent } from "@/src/helpers";
import { Button, Spinner } from "@fluentui/react-components";
import AudioPlayer from "@/components/AudioPlayer/AudioPlayer";
import { ELanguage } from "@/src/types/video.types";
import { v4 as uuid } from "uuid";

export default function Page({ params }: { params: { video_id: string } }) {
const selectedLayoutId = useVideoStore((state) => state.selectedLayoutId);
Expand All @@ -24,7 +25,7 @@ export default function Page({ params }: { params: { video_id: string } }) {
isLoading: isScenesLoading,
} = useQueryGetScenes(params.video_id);
const { data: videoData } = useQueryGetVideo(params.video_id);
const { mutate: createScene, isPending } = useMutationCreateScene();
const { mutate: updateScene, isPending } = useMutationUpdateScene();
const {
isPending: isAudioPending,
data: audios,
Expand All @@ -35,21 +36,26 @@ export default function Page({ params }: { params: { video_id: string } }) {

// Store values
const selectedLayout = useVideoStore((state) => state.selectedLayoutId);
const scenes = scenesData?.[0]?.scenes || [];
const onCreateScene = () => {
const content = getLayoutContent(selectedLayoutId);
createScene({

if (videoData?.scenesId === undefined) return;

updateScene({
id: params.video_id,
name: "New Scene",
sceneId: videoData?.scenesId,
layoutId: selectedLayout,
data: {
id: uuid(),
content,
},
});
};

const playAll = () => {
if (!scenesData) return;
const texts = scenesData?.map((scene) => scene.description);
const texts = scenes.map((scene) => scene.description);
mutate({
text: texts,
audioLanguage: videoData?.audioLanguage || ELanguage.English,
Expand All @@ -69,7 +75,7 @@ export default function Page({ params }: { params: { video_id: string } }) {
<div className="flex h-screen w-full">
<div className="w-1/12 bg-red-200 text-center">Scene</div>
<div className="w-1/4 bg-green-200">
<SceneEditor />
<SceneEditor sceneDocId={videoData?.scenesId || ""} />
</div>
<div className="w-8/12 bg-white">
<div
Expand All @@ -91,10 +97,11 @@ export default function Page({ params }: { params: { video_id: string } }) {
</Button>
</div>
<SceneList
scenes={scenesData || []}
scenes={scenes || []}
audioLanguage={videoData?.audioLanguage}
createScene={onCreateScene}
isCreating={isPending}
sceneDocId={videoData?.scenesId || ""}
isLoading={isScenesFetching || isScenesLoading}
/>
</div>
Expand Down
14 changes: 12 additions & 2 deletions components/Scene/Scene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export const Scene = (props: ISceneProps) => {

mutateDebounce({
id: props.videoId,
sceneId: props.id,
sceneId: props.sceneDocId,
layoutId: props.layoutId,
sceneArrayIndex: props.sceneArrayIndex,
data: { [name]: e.target.value },
});
};
Expand Down Expand Up @@ -67,7 +69,13 @@ export const Scene = (props: ISceneProps) => {
}`}
id={props.id}
onClick={() =>
props.onClick && props.onClick(props.id, props.layoutId, props.content)
props.onClick &&
props.onClick(
props.id,
props.layoutId,
props.sceneArrayIndex,
props.content,
)
}
>
<div className={"flex"}>
Expand Down Expand Up @@ -108,6 +116,8 @@ export const Scene = (props: ISceneProps) => {

export interface ISceneProps extends IScene {
videoId: string;
sceneArrayIndex: number;
sceneDocId: string;
audioLanguage?: ELanguage;
}
export default Scene;
26 changes: 17 additions & 9 deletions components/SceneEditor/SceneEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ import { IInput } from "@/src/types/types";

let debounceContent: any = undefined;
let debounceImage: any = undefined;
const SceneEditor = (props: ISceneEditorProps) => {
const SceneEditor = ({ sceneDocId }: ISceneEditorProps) => {
const [activeTab, setActiveTab] = useState("1");
const selectedLayoutId = useVideoStore((state) => state.selectedLayoutId);
const selectedSceneId = useVideoStore((state) => state.selectedSceneId);
const sceneContent = useVideoStore((state) => state.sceneContent);
const sceneArrayIndex = useVideoStore((state) => state.sceneArrayIndex);
const setSceneContent = useVideoStore((state) => state.setSceneContent);
const params = useParams();

Expand All @@ -46,10 +47,10 @@ const SceneEditor = (props: ISceneEditorProps) => {
debounceContent.cancel();
}
debounceContent = debounce(updateScene, 1000);
console.log("sceneContent", sceneContent);
debounceContent({
id: params.video_id as string,
sceneId: selectedSceneId,
sceneId: sceneDocId,
sceneArrayIndex,
data: { content: content || sceneContent },
invalidate: false,
});
Expand All @@ -60,14 +61,19 @@ const SceneEditor = (props: ISceneEditorProps) => {
if (layoutId !== selectedLayoutId) {
const layout = layouts.find((layout) => layout.id === layoutId);
const newContentTemplate = JSON.parse(JSON.stringify(layout?.content));
setSceneContent(layoutId, selectedSceneId, newContentTemplate);
setSceneContent(
layoutId,
selectedSceneId,
sceneArrayIndex,
newContentTemplate,
);
}
};

// When image is uploaded to S3 update image URL to content template
const onUploadSuccess = (url: string, name: string) => {
console.log("url", url);
setSceneContent(selectedLayoutId, selectedSceneId, {
setSceneContent(selectedLayoutId, selectedSceneId, sceneArrayIndex, {
...sceneContent,
[name]: {
...sceneContent[name],
Expand Down Expand Up @@ -108,12 +114,12 @@ const SceneEditor = (props: ISceneEditorProps) => {
if (res.publicUrl) {
updateScene({
id: params.video_id as string,
sceneId: selectedSceneId,
sceneId: sceneDocId,
layoutId: selectedLayoutId,
sceneArrayIndex,
data: {
image: res.publicUrl,
},
isInvalidate: true,
});
}
});
Expand All @@ -124,7 +130,7 @@ const SceneEditor = (props: ISceneEditorProps) => {

// Listener for content data change and update the content in state
const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSceneContent(selectedLayoutId, selectedSceneId, {
setSceneContent(selectedLayoutId, selectedSceneId, sceneArrayIndex, {
...sceneContent,
[e.target.name]: {
...sceneContent[e.target.name],
Expand Down Expand Up @@ -243,7 +249,9 @@ const SceneEditor = (props: ISceneEditorProps) => {
);
};

export interface ISceneEditorProps {}
export interface ISceneEditorProps {
sceneDocId: string;
}

export { SceneEditor };
export default SceneEditor;
17 changes: 14 additions & 3 deletions components/SceneList/SceneList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useParams } from "next/navigation";
import { useVideoStore } from "@/src/stores/video.store";
import { useEffect } from "react";
import { IInput } from "@/src/types/types";
import { DEFAULT_LAYOUT } from "@/src/layouts";

export function SceneList(props: ISceneListProps) {
const params = useParams();
Expand All @@ -13,27 +14,36 @@ export function SceneList(props: ISceneListProps) {
const onSceneChange = (
sceneId: string,
layoutId: string,
sceneArrayIndex: number,
content?: Record<string, IInput>,
) => {
setSelectedContent(layoutId, sceneId, content);
setSelectedContent(layoutId, sceneId, sceneArrayIndex, content);
};

useEffect(() => {
if (props.scenes.length > 0 && !selectedSceneId) {
const scene = props.scenes[0];
setSelectedContent(scene.layoutId, scene.id, scene.content);
setSelectedContent(
scene.layoutId || DEFAULT_LAYOUT.id,
scene.id,
0,
scene.content || DEFAULT_LAYOUT.content,
);
}
}, [selectedSceneId, props.scenes, setSelectedContent]);
return (
<div className="flex- flex max-h-screen flex-col items-center overflow-auto pb-10 pt-10">
<div className="flex flex-col">
{props.scenes.map((scene) => (
{props.scenes.map((scene, index) => (
<Scene
{...scene}
videoId={params.video_id as string}
audioLanguage={props.audioLanguage}
key={scene.id}
onClick={onSceneChange}
sceneArrayIndex={index}
sceneDocId={props.sceneDocId}
layoutId={scene.layoutId || DEFAULT_LAYOUT.id}
isSelected={scene.id === selectedSceneId}
/>
))}
Expand All @@ -53,6 +63,7 @@ export interface ISceneListProps {
isCreating?: boolean;
isLoading?: boolean;
scenes: IScene[];
sceneDocId: string;
audioLanguage?: ELanguage;
}
export default SceneList;
16 changes: 12 additions & 4 deletions src/apis/video.client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { ServerClient } from "@/src/apis/server.client";
import { HttpMethod } from "@/src/constants";
import { ELanguage, IScene, IVideo } from "@/src/types/video.types";
import {
ELanguage,
IScene,
ISceneResponse,
IVideo,
} from "@/src/types/video.types";

export class VideoClient extends ServerClient {
public static async create(name: string): Promise<IVideo> {
Expand Down Expand Up @@ -65,7 +70,7 @@ export class VideoClient extends ServerClient {
return resp.json();
}

public static async getScenes(id: string): Promise<IScene[]> {
public static async getScenes(id: string): Promise<ISceneResponse[]> {
const resp = await VideoClient.sendToAPiServer(`videos/${id}/scenes`);
return resp.json();
}
Expand All @@ -75,14 +80,17 @@ export class VideoClient extends ServerClient {
sceneId: string,
layoutId: string,
data: Record<string, any>,
): Promise<IScene> {
sceneArrayIndex?: number,
): Promise<ISceneResponse[]> {
const body = {
...data,
layoutId,
};

const resp = await VideoClient.sendToAPiServer(
`videos/${id}/scenes/${sceneId}`,
`videos/${id}/scenes/${sceneId}/${
sceneArrayIndex === undefined ? "" : sceneArrayIndex
}`,
body,
HttpMethod.PUT,
);
Expand Down
1 change: 1 addition & 0 deletions src/layouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,5 @@ const layouts: Array<{
},
];

export const DEFAULT_LAYOUT = layouts[1];
export default layouts;
18 changes: 11 additions & 7 deletions src/query/video.query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,19 @@ export const useMutationUpdateScene = () => {
sceneId: string;
layoutId: string;
data: Record<string, any>;
isInvalidate?: boolean;
sceneArrayIndex?: number;
}) =>
VideoClient.updateScene(data.id, data.sceneId, data.layoutId, data.data),
VideoClient.updateScene(
data.id,
data.sceneId,
data.layoutId,
data.data,
data.sceneArrayIndex,
),
onSuccess: (data, variables) => {
if (variables.isInvalidate) {
queryClient.invalidateQueries({
queryKey: ["video", variables.id, "scenes"],
});
}
queryClient.invalidateQueries({
queryKey: ["video", variables.id, "scenes"],
});
},
});
};
Expand Down
4 changes: 3 additions & 1 deletion src/stores/video.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ export const useVideoStore = create<IVideoStore>()(
devtools((set, get) => ({
selectedLayoutId: "",
selectedSceneId: "",
sceneArrayIndex: -1,
sceneContent: {},
setSceneContent: (layoutId, sceneId, content) => {
setSceneContent: (layoutId, sceneId, sceneArrayIndex, content) => {
set((state) => ({
...state,
selectedLayoutId: layoutId,
selectedSceneId: sceneId,
sceneArrayIndex,
sceneContent: content,
}));
},
Expand Down
9 changes: 9 additions & 0 deletions src/types/video.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ export interface IVideoStore {
selectedLayoutId: string;
selectedSceneId: string;
sceneContent: Record<string, IInput>;
sceneArrayIndex: number;
setSceneContent: (
layoutId: string,
sceneId: string,
sceneArrayIndex: number,
content?: Record<string, IInput>,
) => void;
}
Expand All @@ -25,6 +27,7 @@ export interface IVideo {
createdAt: string;
updatedAt: string;
userId: string;
scenesId: string;
}

export interface IScene {
Expand All @@ -38,6 +41,12 @@ export interface IScene {
onClick?: (
sceneId: string,
layoutId: string,
sceneArrayIndex: number,
content?: Record<string, IInput>,
) => void;
}

export interface ISceneResponse {
videoId: string;
scenes: IScene[];
}

0 comments on commit 3caf6bb

Please sign in to comment.