mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 01:18:34 +00:00
PageEnigma refactor Phase 5b: migrate error, myMovies, editorOverlays signal slices
Three more signal files retired in favour of the Zustand store. error.ts (deleted): - ErrorDialog (in ~/components/signaled): reads showErrorDialog / errorDialogTitle / errorDialogMessage from the store, calls setShowErrorDialog - SceneTitleInput (in TopBar): handleShowErrorDialog uses the store's setErrorDialog action myMovies.ts (deleted): - MyMoviesButton (in TopBar): writes via setGenerateMovieId / setViewMyMovies - GenerateModals: useEffect-on-store replaces useSignalEffect; reads generateMovieId from store - MyMovies and Sharing: read viewMyMovies from store, close via setViewMyMovies - Sharing also reads generateMovieId from store editorOverlays.ts (deleted): - PageEditor's LoadingDots: reads editorLoader from store - SceneContainer: reads editorLetterBox from store and passes through to Letterbox - PreviewEngineCamera: reads editorLetterBox + toggleEditorLetterBox from store - save_manager: showEditorLoader/hideEditorLoader become thin wrappers over the store actions, keeping the same call sites signals/index.ts no longer re-exports any of the three deleted files.
This commit is contained in:
1 parent
4b0618e50b
commit
11a0ac82b6
14 files changed
+81
-121
No files matched your search
@@ -1,32 +1,36 @@
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { faTriangleExclamation } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
|
||||
import { Modal } from "@storyteller/ui-modal";
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import {
|
||||
showErrorDialog,
|
||||
errorDialogMessage,
|
||||
errorDialogTitle,
|
||||
} from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
|
||||
export function ErrorDialog() {
|
||||
useSignals();
|
||||
const { showErrorDialog, errorDialogTitle, errorDialogMessage, setShowErrorDialog } =
|
||||
usePageEnigmaStore(
|
||||
useShallow((s) => ({
|
||||
showErrorDialog: s.showErrorDialog,
|
||||
errorDialogTitle: s.errorDialogTitle,
|
||||
errorDialogMessage: s.errorDialogMessage,
|
||||
setShowErrorDialog: s.setShowErrorDialog,
|
||||
})),
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={errorDialogTitle.value}
|
||||
title={errorDialogTitle}
|
||||
titleIcon={faTriangleExclamation}
|
||||
titleIconClassName="text-brand-primary"
|
||||
isOpen={showErrorDialog.value}
|
||||
onClose={() => (showErrorDialog.value = false)}
|
||||
isOpen={showErrorDialog}
|
||||
onClose={() => setShowErrorDialog(false)}
|
||||
showClose={false}
|
||||
>
|
||||
<div>
|
||||
{errorDialogMessage.value}
|
||||
{errorDialogMessage}
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => (showErrorDialog.value = false)}
|
||||
onClick={() => setShowErrorDialog(false)}
|
||||
variant="secondary"
|
||||
>
|
||||
Close
|
||||
|
||||
@@ -3,7 +3,7 @@ import { twMerge } from "tailwind-merge";
|
||||
import { faFilm } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Button } from "@storyteller/ui-button";
|
||||
import { generateMovieId, viewMyMovies } from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
|
||||
import { activeWorkflowJobs } from "~/signals";
|
||||
|
||||
@@ -18,8 +18,9 @@ export const MyMoviesButton = () => {
|
||||
<Button
|
||||
variant="action"
|
||||
onClick={() => {
|
||||
generateMovieId.value = "";
|
||||
viewMyMovies.value = true;
|
||||
const store = usePageEnigmaStore.getState();
|
||||
store.setGenerateMovieId("");
|
||||
store.setViewMyMovies(true);
|
||||
}}
|
||||
>
|
||||
<div className="relative flex items-center gap-2">
|
||||
|
||||
@@ -4,11 +4,7 @@ import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { faPencil, faSpinnerThird } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { scene, signalScene, authentication } from "~/signals";
|
||||
import {
|
||||
showErrorDialog,
|
||||
errorDialogMessage,
|
||||
errorDialogTitle,
|
||||
} from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
import { Input } from "@storyteller/ui-input";
|
||||
import { MediaFilesApi } from "~/Classes/ApiManager/MediaFilesApi";
|
||||
import { getCreatorIcon, ModelCreator } from "@storyteller/model-list";
|
||||
@@ -36,9 +32,7 @@ export const SceneTitleInput = ({ pageName }: Props) => {
|
||||
};
|
||||
|
||||
const handleShowErrorDialog = (errorMessage: string) => {
|
||||
errorDialogTitle.value = "Error";
|
||||
errorDialogMessage.value = errorMessage;
|
||||
showErrorDialog.value = true;
|
||||
usePageEnigmaStore.getState().setErrorDialog("Error", errorMessage);
|
||||
};
|
||||
|
||||
const handleChangeSceneTitle = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
@@ -4,11 +4,15 @@ import { StoryTellerProxyScene } from "../proxy/storyteller_proxy_scene";
|
||||
|
||||
import {
|
||||
setCameraAspectRatio,
|
||||
hideEditorLoader,
|
||||
restoreSceneGenerationMetadata,
|
||||
showEditorLoader,
|
||||
globalIPAMediaToken,
|
||||
} from "../signals";
|
||||
import { usePageEnigmaStore } from "../PageEnigmaStore";
|
||||
|
||||
const showEditorLoader = (message?: string) =>
|
||||
usePageEnigmaStore.getState().showEditorLoader(message);
|
||||
const hideEditorLoader = () =>
|
||||
usePageEnigmaStore.getState().hideEditorLoader();
|
||||
import Editor from "./editor";
|
||||
import { getArtStyle } from "~/enums";
|
||||
import { cameras, selectedCameraId, Camera } from "../signals/camera";
|
||||
|
||||
@@ -23,7 +23,6 @@ import { useStoryboardPageEnabled } from "@storyteller/ui-settings-modal";
|
||||
|
||||
import {
|
||||
sidePanelWidth,
|
||||
editorLoader,
|
||||
cameraAspectRatio,
|
||||
outlinerIsShowing,
|
||||
disableHotkeyInput,
|
||||
@@ -108,6 +107,7 @@ export const PageEditor = () => {
|
||||
const tabStore = useTabStore();
|
||||
const storyboardPageEnabled = useStoryboardPageEnabled();
|
||||
const camAspect = usePageEnigmaStore((s) => s.cameraAspectRatio);
|
||||
const editorLoader = usePageEnigmaStore((s) => s.editorLoader);
|
||||
const handleOverlayClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
@@ -540,9 +540,9 @@ export const PageEditor = () => {
|
||||
|
||||
<LoadingDots
|
||||
className="absolute left-0 top-0 z-50"
|
||||
isShowing={editorLoader.value.isShowing}
|
||||
isShowing={editorLoader.isShowing}
|
||||
type="bricks"
|
||||
message={editorLoader.value.message}
|
||||
message={editorLoader.message}
|
||||
/>
|
||||
|
||||
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-3">
|
||||
|
||||
+12
-11
@@ -1,9 +1,8 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { useSignals, useSignalEffect } from "@preact/signals-react/runtime";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { MediaFile } from "~/pages/PageEnigma/models";
|
||||
|
||||
import { generateMovieId } from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
import { ToastTypes } from "~/enums";
|
||||
import { addToast } from "~/signals";
|
||||
|
||||
@@ -12,8 +11,9 @@ import { Sharing } from "~/pages/PageEnigma/comps/GenerateModals/Sharing";
|
||||
import { MediaFilesApi } from "~/Classes/ApiManager/MediaFilesApi";
|
||||
|
||||
export function GenerateModals() {
|
||||
useSignals();
|
||||
const [mediaFile, setMediaFile] = useState<MediaFile | null>(null);
|
||||
const generateMovieId = usePageEnigmaStore((s) => s.generateMovieId);
|
||||
const setGenerateMovieId = usePageEnigmaStore((s) => s.setGenerateMovieId);
|
||||
|
||||
const GetMediaFileByToken = useCallback(async (movieId: string) => {
|
||||
const mediaFilesApi = new MediaFilesApi();
|
||||
@@ -30,14 +30,15 @@ export function GenerateModals() {
|
||||
`Unknown Error in Getting Movie (token=${movieId}`,
|
||||
);
|
||||
}, []);
|
||||
const setMovieId = useCallback((movieId: string) => {
|
||||
generateMovieId.value = movieId;
|
||||
}, []);
|
||||
useSignalEffect(() => {
|
||||
if (generateMovieId.value) {
|
||||
GetMediaFileByToken(generateMovieId.value);
|
||||
const setMovieId = useCallback(
|
||||
(movieId: string) => setGenerateMovieId(movieId),
|
||||
[setGenerateMovieId],
|
||||
);
|
||||
useEffect(() => {
|
||||
if (generateMovieId) {
|
||||
GetMediaFileByToken(generateMovieId);
|
||||
}
|
||||
});
|
||||
}, [generateMovieId, GetMediaFileByToken]);
|
||||
|
||||
if (!mediaFile) {
|
||||
return <MyMovies setMovieId={setMovieId} />;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { CompletedCard } from "~/pages/PageEnigma/comps/GenerateModals/CompletedCard";
|
||||
import { InProgressCard } from "~/pages/PageEnigma/comps/GenerateModals/InProgressCard";
|
||||
import { Modal } from "@storyteller/ui-modal";
|
||||
import { viewMyMovies } from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
import { activeWorkflowJobs, userMovies } from "~/signals";
|
||||
|
||||
interface Props {
|
||||
@@ -13,6 +13,8 @@ interface Props {
|
||||
|
||||
export function MyMovies({ setMovieId }: Props) {
|
||||
useSignals();
|
||||
const viewMyMovies = usePageEnigmaStore((s) => s.viewMyMovies);
|
||||
const setViewMyMovies = usePageEnigmaStore((s) => s.setViewMyMovies);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -20,10 +22,10 @@ export function MyMovies({ setMovieId }: Props) {
|
||||
titleIcon={faFilm}
|
||||
className="max-w-4xl"
|
||||
childPadding={false}
|
||||
isOpen={viewMyMovies.value}
|
||||
isOpen={viewMyMovies}
|
||||
onClose={() => {
|
||||
setMovieId("");
|
||||
viewMyMovies.value = false;
|
||||
setViewMyMovies(false);
|
||||
}}
|
||||
>
|
||||
<div className="h-[560px] overflow-y-auto overflow-x-hidden rounded-b-lg">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { useState } from "react";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { MediaFile } from "~/pages/PageEnigma/models";
|
||||
import { Input } from "@storyteller/ui-input";
|
||||
import { Label } from "@storyteller/ui-label";
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
faLink,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import SocialButton from "./SocialButton";
|
||||
import { generateMovieId, viewMyMovies } from "~/pages/PageEnigma/signals";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
import dayjs from "dayjs";
|
||||
import { downloadFile } from "~/pages/PageEnigma/comps/GenerateModals/utils/downloadFile";
|
||||
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
|
||||
@@ -24,7 +24,13 @@ interface Props {
|
||||
}
|
||||
|
||||
export function Sharing({ mediaFile, setMediaFile }: Props) {
|
||||
useSignals();
|
||||
const { generateMovieId, viewMyMovies, setViewMyMovies } = usePageEnigmaStore(
|
||||
useShallow((s) => ({
|
||||
generateMovieId: s.generateMovieId,
|
||||
viewMyMovies: s.viewMyMovies,
|
||||
setViewMyMovies: s.setViewMyMovies,
|
||||
})),
|
||||
);
|
||||
|
||||
const mediaTitle = mediaFile?.maybe_title ?? mediaFile?.token;
|
||||
// TODO: ApiManager should provide all endpoints
|
||||
@@ -56,17 +62,17 @@ export function Sharing({ mediaFile, setMediaFile }: Props) {
|
||||
return (
|
||||
<Modal
|
||||
title={generateTitle()}
|
||||
titleIcon={generateMovieId.value ? faChevronLeft : faFilm}
|
||||
titleIcon={generateMovieId ? faChevronLeft : faFilm}
|
||||
titleIconClassName="text-white/60 hover:text-white/80 transition-colors duration-150"
|
||||
onTitleIconClick={
|
||||
generateMovieId.value ? () => setMediaFile(null) : undefined
|
||||
generateMovieId ? () => setMediaFile(null) : undefined
|
||||
}
|
||||
className="max-w-6xl"
|
||||
childPadding={false}
|
||||
isOpen={viewMyMovies.value}
|
||||
isOpen={viewMyMovies}
|
||||
width={1049}
|
||||
onClose={() => {
|
||||
viewMyMovies.value = false;
|
||||
setViewMyMovies(false);
|
||||
setMediaFile(null);
|
||||
}}
|
||||
>
|
||||
|
||||
+10
-9
@@ -9,8 +9,6 @@ import {
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import {
|
||||
editorLetterBox,
|
||||
toggleEditorLetterBox,
|
||||
sidePanelHeight,
|
||||
outlinerIsShowing,
|
||||
} from "~/pages/PageEnigma/signals";
|
||||
@@ -25,12 +23,15 @@ import { useEffect } from "react";
|
||||
|
||||
export const PreviewEngineCamera = () => {
|
||||
useSignals();
|
||||
const { camAspect, editorState } = usePageEnigmaStore(
|
||||
useShallow((s) => ({
|
||||
camAspect: s.cameraAspectRatio,
|
||||
editorState: s.editorState,
|
||||
})),
|
||||
);
|
||||
const { camAspect, editorState, editorLetterBox, toggleEditorLetterBox } =
|
||||
usePageEnigmaStore(
|
||||
useShallow((s) => ({
|
||||
camAspect: s.cameraAspectRatio,
|
||||
editorState: s.editorState,
|
||||
editorLetterBox: s.editorLetterBox,
|
||||
toggleEditorLetterBox: s.toggleEditorLetterBox,
|
||||
})),
|
||||
);
|
||||
|
||||
const handleButtonCameraView = () => {
|
||||
// TODO: wire to editor.toggleCameraView() once editor.ts is migrated.
|
||||
@@ -113,7 +114,7 @@ export const PreviewEngineCamera = () => {
|
||||
{editorState === EditorStates.CAMERA_VIEW && (
|
||||
<Tooltip content="Toggle Letterbox" position={"top"}>
|
||||
<ButtonIcon
|
||||
icon={editorLetterBox.value ? faBlinds : faBlindsRaised}
|
||||
icon={editorLetterBox ? faBlinds : faBlindsRaised}
|
||||
onClick={() => toggleEditorLetterBox()}
|
||||
className="h-7 w-7"
|
||||
/>
|
||||
|
||||
+10
-13
@@ -1,24 +1,21 @@
|
||||
import { useCallback, useContext } from "react";
|
||||
import { useCallback } from "react";
|
||||
import { useSignals } from "@preact/signals-react/runtime";
|
||||
import { pageHeight, pageWidth } from "~/signals";
|
||||
import { editorLetterBox } from "~/pages/PageEnigma/signals";
|
||||
import { EngineContext, sceneContainerSignal } from "~/pages/PageEnigma/contexts/EngineContext";
|
||||
import { sceneContainerSignal } from "~/pages/PageEnigma/contexts/EngineContext";
|
||||
import { usePageEnigmaStore } from "~/pages/PageEnigma/PageEnigmaStore";
|
||||
import { Letterbox } from "./Letterbox";
|
||||
|
||||
export const SceneContainer = ({ children }: { children: React.ReactNode }) => {
|
||||
useSignals();
|
||||
const editorLetterBox = usePageEnigmaStore((s) => s.editorLetterBox);
|
||||
const containerWidth = pageWidth.value;
|
||||
|
||||
const containerHeight = pageHeight.value - 56;
|
||||
|
||||
const callbackRef = useCallback(
|
||||
(node: HTMLDivElement) => {
|
||||
if (node) {
|
||||
sceneContainerSignal.value = node;
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
const callbackRef = useCallback((node: HTMLDivElement) => {
|
||||
if (node) {
|
||||
sceneContainerSignal.value = node;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -32,7 +29,7 @@ export const SceneContainer = ({ children }: { children: React.ReactNode }) => {
|
||||
>
|
||||
{children}
|
||||
<Letterbox
|
||||
isShowing={editorLetterBox.value}
|
||||
isShowing={editorLetterBox}
|
||||
width={containerWidth}
|
||||
height={containerHeight}
|
||||
/>
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { signal } from "@preact/signals-core";
|
||||
|
||||
export const editorLoader = signal<{
|
||||
isShowing: boolean;
|
||||
message: string | undefined;
|
||||
}>({
|
||||
isShowing: false,
|
||||
message: "Loading Editor Engine 🦊",
|
||||
});
|
||||
|
||||
export const showEditorLoader = (message?: string) => {
|
||||
editorLoader.value = {
|
||||
isShowing: true,
|
||||
message,
|
||||
};
|
||||
};
|
||||
export const hideEditorLoader = () => {
|
||||
editorLoader.value = {
|
||||
isShowing: false,
|
||||
message: editorLoader.value.message,
|
||||
// it is important to keep the message so the loader fades out nicely
|
||||
};
|
||||
};
|
||||
|
||||
export const editorLetterBox = signal<boolean>(true);
|
||||
|
||||
export const toggleEditorLetterBox = (newState?: boolean) => {
|
||||
editorLetterBox.value =
|
||||
newState !== undefined ? newState : !editorLetterBox.value;
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import { signal } from "@preact/signals-core";
|
||||
|
||||
export const showErrorDialog = signal(false);
|
||||
export const errorDialogTitle = signal("Error!");
|
||||
export const errorDialogMessage = signal("Something went wrong.");
|
||||
|
||||
export function setErrorDialogTitle(errorTitle: string) {
|
||||
errorDialogTitle.value = errorTitle;
|
||||
}
|
||||
|
||||
export function setErrorDialogMessage(errorMessage: string) {
|
||||
errorDialogMessage.value = errorMessage;
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
export * from "./demoAssets";
|
||||
export * from "./editorOverlays";
|
||||
export * from "./engine";
|
||||
export * from "./dragAndDrop";
|
||||
export * from "./hotkeys";
|
||||
export * from "./myMovies";
|
||||
export * from "./objectPanel";
|
||||
export * from "./outliner";
|
||||
export * from "./selectedItem";
|
||||
export * from "./sidePanel";
|
||||
export * from "./sizing";
|
||||
export * from "./stylizeTab";
|
||||
export * from "./error";
|
||||
export * from "./assetModal";
|
||||
@@ -1,4 +0,0 @@
|
||||
import { signal } from "@preact/signals-core";
|
||||
|
||||
export const viewMyMovies = signal(false);
|
||||
export const generateMovieId = signal("");
|
||||
Reference in new issue
Block a user