Loading state when requesting a Frame Preview (#356)

- Spinner on Editor canvas when requesting a Frame Preview
- if Frame Preview returns an error, pop a toast

Co-authored-by: wil <wil@storyteller.ai>
This commit is contained in:
wilandwil authored and GitHub committed 2024-05-08 19:03:31 -07:00
1 parent 71efadc106
commit 69f92c88a1
6 files changed
+105 -33

No files matched your search

+11 -27
View File
@@ -1,40 +1,37 @@
import React, { useContext, useEffect } from "react";
import { useSignals } from "@preact/signals-react/runtime";
import { LoadingDots } from "~/components";
import { SidePanel } from "~/modules/SidePanel";
import { TopBar } from "~/modules/TopBar";
import { Controls3D } from "./comps/Controls3D";
import { ControlsTopButtons } from "./comps/ControlsTopButtons";
import { ControlsVideo } from "./comps/ControlsVideo";
import { ControlPanelSceneObject } from "./comps/ControlPanelSceneObject";
import { PreviewEngineCamera } from "./comps/PreviewEngineCamera";
import { PreviewFrameImage } from "./comps/PreviewFrameImage";
import { ViewSideBySide } from "./comps/ViewSideBySide";
import { Timeline } from "./comps/Timeline";
// import { AssetType } from "~/pages/PageEnigma/models";
import { AppUiContext } from "~/contexts/AppUiContext";
import { APPUI_VIEW_MODES } from "../../reducers";
import { pageHeight, pageWidth } from "~/store";
import {
timelineHeight,
sidePanelWidth,
sidePanelVisible,
dndSidePanelWidth,
dndTimelineHeight,
dragItem,
canDrop,
// dragItem,
// canDrop,
} from "~/pages/PageEnigma/store";
import { useSignals } from "@preact/signals-react/runtime";
import { AppUiContext } from "~/contexts/AppUiContext";
import { pageHeight, pageWidth } from "~/store";
import { TopBar } from "~/modules/TopBar";
import {
editorState,
EditorStates,
previewSrc,
} from "~/pages/PageEnigma/store/engine";
import { AssetType } from "~/pages/PageEnigma/models";
export const PageEditor = () => {
useSignals();
const [appUiState] = useContext(AppUiContext);
//To prevent the click event from propagating to the canvas: TODO: HANDLE THIS BETTER?
@@ -92,20 +89,7 @@ export const PageEditor = () => {
height: pageHeight.value - timelineHeight.value - 68,
}}>
<canvas id="video-scene" width="1280px" height="720px" />
{editorState.value === EditorStates.PREVIEW && (
<img
className="absolute inset-0"
src={previewSrc.value}
id="video-scene"
style={{
width:
pageWidth.value -
(sidePanelVisible.value ? sidePanelWidth.value : 0) -
84,
height: pageHeight.value - timelineHeight.value - 68,
}}
/>
)}
<PreviewFrameImage />
</div>
{/* Top controls */}
+11 -1
View File
@@ -9,23 +9,33 @@ import {
} from "~/pages/PageEnigma/models";
import { toTimelineActions } from "./toTimelineActions";
import { ClipUI } from "../datastructures/clips/clip_ui";
import { ToastTypes } from "~/contexts/ToasterContext";
export type ToastDataType = {
type: ToastTypes;
message: string;
}
type UnionedActionTypes =
| fromEngineActions
| toEngineActions
| toTimelineActions;
type UnionedDataTypes =
| QueueClip
| UpdateTime
| QueueKeyframe
| ClipUI[]
| MediaItem
| ToastDataType
| null;
export type QueueSubscribeType = {
action: UnionedActionTypes;
data: UnionedDataTypes;
};
import { ClipUI } from "../datastructures/clips/clip_ui";
class Queue {
private _queue: Record<
string,
@@ -7,5 +7,6 @@ export enum fromEngineActions {
UPDATE_CHARACTER_ID = "update_character_id",
UPDATE_TIME = "update_time",
UPDATE_TIME_LINE = "update_timeline",
POP_A_TOAST = "pop_a_toast",
// data={currentTime: number}
}
@@ -0,0 +1,61 @@
import { useSignals } from "@preact/signals-react/runtime";
import { faSpinnerThird } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
editorState,
EditorStates,
previewSrc,
} from "~/pages/PageEnigma/store/engine";
import {
timelineHeight,
sidePanelWidth,
sidePanelVisible,
} from "~/pages/PageEnigma/store";
import { pageHeight, pageWidth } from "~/store";
import { H3 } from "~/components";
export const PreviewFrameImage = ()=>{
useSignals();
if( editorState.value === EditorStates.PREVIEW ){
if ( previewSrc.value === "" ){
return (
<div
className="absolute inset-0"
style={{
width:
pageWidth.value -
(sidePanelVisible.value ? sidePanelWidth.value : 0) -
84,
height: pageHeight.value - timelineHeight.value - 68,
}}
>
<div
className="relative w-full h-full flex flex-col justify-center items-center gap-8">
<span className="absolute w-full h-full bg-black opacity-50"/>
<FontAwesomeIcon icon={faSpinnerThird} spin size="9x" />
<H3 className="text-white z-20">Generating Preview...</H3>
</div>
</div>
);
}else{
return(
<img
className="absolute inset-0"
src={previewSrc.value}
id="video-scene"
style={{
width:
pageWidth.value -
(sidePanelVisible.value ? sidePanelWidth.value : 0) -
84,
height: pageHeight.value - timelineHeight.value - 68,
}}
/>
);
}
}
return null;
}
@@ -11,7 +11,7 @@ import {
loadObjectData,
selectedObject,
} from "~/pages/PageEnigma/store";
import Queue from "~/pages/PageEnigma/Queue/Queue";
import Queue, { ToastDataType } from "~/pages/PageEnigma/Queue/Queue";
import { QueueNames } from "~/pages/PageEnigma/Queue/QueueNames";
import { toEngineActions } from "~/pages/PageEnigma/Queue/toEngineActions";
import {
@@ -22,12 +22,14 @@ import {
UpdateTime,
} from "~/pages/PageEnigma/models";
import { TrackContext } from "~/pages/PageEnigma/contexts/TrackContext/TrackContext";
import { ToasterContext } from "~/contexts/ToasterContext";
import { ToastTypes } from "~/contexts/ToasterContext";
import { toTimelineActions } from "~/pages/PageEnigma/Queue/toTimelineActions";
import { ClipUI } from "~/pages/PageEnigma/datastructures/clips/clip_ui";
interface Arguments {
action: fromEngineActions | toEngineActions | toTimelineActions;
data: QueueClip | UpdateTime | QueueKeyframe | ClipUI[] | MediaItem | null;
data: QueueClip | UpdateTime | QueueKeyframe | ClipUI[] | MediaItem | ToastDataType | null;
}
const LOADING_FUNCTIONS: Record<ClipGroup, (item: ClipUI) => void> = {
@@ -41,6 +43,7 @@ export function useQueueHandler() {
useSignals();
const { addKeyframe, clearExistingData, deleteObjectOrCharacter } =
useContext(TrackContext);
const { addToast } = useContext(ToasterContext);
const handleFromEngineActions = useCallback(
({ action, data }: Arguments) => {
@@ -79,6 +82,11 @@ export function useQueueHandler() {
LOADING_FUNCTIONS[item.group](item);
});
break;
case fromEngineActions.POP_A_TOAST:{
const message = (data as ToastDataType).message;
addToast(ToastTypes.ERROR, message);
break;
}
default:
throw new Error(`Unknown action ${action}`);
}
+11 -3
View File
@@ -43,6 +43,7 @@ import {
import { AuthState } from "~/contexts/Authentication/types";
import { hotkeysStatus } from "~/pages/PageEnigma/store";
import { SceneSignal } from "~/store";
import { ToastTypes } from "~/contexts/ToasterContext";
// Main editor class that will call everything else all you need to call is " initialize() ".
@@ -1333,11 +1334,18 @@ class Editor {
);
previewSrc.value = url;
return Promise.resolve(url);
} catch (err: any) {
console.log(err.message);
return Promise.resolve("");
Queue.publish({
queueName: QueueNames.FROM_ENGINE,
action: fromEngineActions.POP_A_TOAST,
data: {
type: ToastTypes.ERROR,
message: err.message
},
})
// return Promise.resolve("");
}
}
}