init
all 视频 视频 视频 视频 视频 init
This commit is contained in:
commit
3b053c714c
128 files changed
+31559
No files matched your search
+102
@@ -0,0 +1,102 @@
|
||||
import "./styles/index.css";
|
||||
import { useEffect } from "react";
|
||||
import { X } from "lucide-react";
|
||||
import { DirectorDeskShell } from "./app/layout/DirectorDeskShell";
|
||||
import { DirectorCanvas } from "./editor/canvas/DirectorCanvas";
|
||||
import { initDirectorDeskHostBridge } from "./editor/io/hostBridge";
|
||||
import { useDirectorStore } from "./editor/store/directorStore";
|
||||
|
||||
function isEditableShortcutTarget(target: EventTarget | null) {
|
||||
if (!(target instanceof HTMLElement)) return false;
|
||||
|
||||
return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const viewMode = useDirectorStore((state) => state.viewMode);
|
||||
const setViewMode = useDirectorStore((state) => state.setViewMode);
|
||||
|
||||
useEffect(() => {
|
||||
initDirectorDeskHostBridge();
|
||||
window.parent?.postMessage({ type: "storyai:director-desk-ready" }, window.location.origin);
|
||||
}, []);
|
||||
|
||||
function handleClose() {
|
||||
window.parent?.postMessage({ type: "storyai:director-desk-close" }, window.location.origin);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (event.defaultPrevented || isEditableShortcutTarget(event.target)) return;
|
||||
if (!event.metaKey && !event.ctrlKey) return;
|
||||
|
||||
const key = event.key.toLowerCase();
|
||||
if (key === "c") {
|
||||
event.preventDefault();
|
||||
useDirectorStore.getState().copySelectedObjects();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === "v") {
|
||||
event.preventDefault();
|
||||
useDirectorStore.getState().pasteClipboardObjects();
|
||||
return;
|
||||
}
|
||||
|
||||
if (key === "z" && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
useDirectorStore.getState().undo();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<header className="top-bar">
|
||||
<div className="top-bar-left">
|
||||
<h1 className="top-bar-title">3D导演台</h1>
|
||||
</div>
|
||||
<div className="top-bar-center">
|
||||
<div className="mode-toggle ui-segmented" role="group" aria-label="视角切换">
|
||||
<button
|
||||
className={`mode-toggle-button ui-segmented-item ${viewMode === "director" ? "ui-segmented-item-active" : ""}`}
|
||||
aria-pressed={viewMode === "director"}
|
||||
type="button"
|
||||
onClick={() => setViewMode("director")}
|
||||
>
|
||||
导演视角
|
||||
</button>
|
||||
<button
|
||||
className={`mode-toggle-button ui-segmented-item ${viewMode === "camera" ? "ui-segmented-item-active" : ""}`}
|
||||
aria-pressed={viewMode === "camera"}
|
||||
type="button"
|
||||
onClick={() => setViewMode("camera")}
|
||||
>
|
||||
机位视角
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="top-bar-actions">
|
||||
<button
|
||||
className="top-bar-action-button"
|
||||
type="button"
|
||||
aria-label="关闭"
|
||||
title="关闭"
|
||||
onClick={handleClose}
|
||||
>
|
||||
<X aria-hidden="true" size={16} strokeWidth={1.8} />
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
<DirectorDeskShell>
|
||||
<DirectorCanvas />
|
||||
</DirectorDeskShell>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user