mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
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:
1 parent
71efadc106
commit
69f92c88a1
6 files changed
+105
-33
No files matched your search
@@ -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 */}
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
@@ -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("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user