diff --git a/source/Component/CommandBar/CommandBar.tsx b/source/Component/CommandBar/CommandBar.tsx
index 23a1bb6..d0550f8 100644
--- a/source/Component/CommandBar/CommandBar.tsx
+++ b/source/Component/CommandBar/CommandBar.tsx
@@ -1,24 +1,30 @@
import { Component, ReactNode } from "react";
import { DirectionalHint, IconButton } from "@fluentui/react";
-import { useSetting, useSettingWithEvent, IMixinSettingProps } from "@Context/Setting";
+import { useSetting, IMixinSettingProps } from "@Context/Setting";
import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status";
import { BackgroundLevel, Theme } from "@Component/Theme/Theme";
import { LocalizationTooltipHost } from "@Component/Localization/LocalizationTooltipHost";
-import { AllI18nKeys, I18N } from "@Component/Localization/Localization";
+import { AllI18nKeys } from "@Component/Localization/Localization";
import { SettingPopup } from "@Component/SettingPopup/SettingPopup";
import { BehaviorPopup } from "@Component/BehaviorPopup/BehaviorPopup";
import { MouseMod } from "@GLRender/ClassicRenderer";
-import * as download from "downloadjs";
+import { ArchiveSave } from "@Context/Archive";
import "./CommandBar.scss";
const COMMAND_BAR_WIDTH = 45;
-function getRenderButton(param: {
+interface IRenderButtonParameter {
i18NKey: AllI18nKeys;
iconName?: string;
click?: () => void;
active?: boolean;
-}): ReactNode {
+}
+
+interface ICommandBarState {
+ isSaveRunning: boolean;
+}
+
+function getRenderButton(param: IRenderButtonParameter): ReactNode {
return
}
-
-@useSettingWithEvent("language")
-@useStatusWithEvent()
-class SaveCommandView extends Component {
-
- public render(): ReactNode {
- return getRenderButton({
- iconName: "Save",
- i18NKey: "Command.Bar.Save.Info",
- click: () => {
-
- let fileName: string = "";
- let isNewFile: boolean = true;
- let isSaved: boolean = false;
-
- if (this.props.status) {
- isNewFile = this.props.status.archive.isNewFile;
- fileName = this.props.status.archive.fileName ?? "";
- isSaved = this.props.status.archive.isSaved;
- }
-
- const file = this.props.status?.archive.save(this.props.status.model) ?? "";
- fileName = isNewFile ? I18N(this.props, "Header.Bar.New.File.Name") : fileName;
- download(file, fileName, "text/json");
- }
- })
- }
-}
-
@useSetting
@useStatusWithEvent("mouseModChange", "actuatorStartChange")
-class CommandBar extends Component {
+class CommandBar extends Component {
- render(): ReactNode {
+ public state: Readonly = {
+ isSaveRunning: false
+ };
+
+ public render(): ReactNode {
const mouseMod = this.props.status?.mouseMod ?? MouseMod.Drag;
@@ -80,7 +61,22 @@ class CommandBar extends Component {
>
-
+
{
+ this.setState({ isSaveRunning: false });
+ }}
+ />
+
+ {getRenderButton({
+ iconName: "Save",
+ i18NKey: "Command.Bar.Save.Info",
+ click: () => {
+ this.setState({
+ isSaveRunning: true
+ });
+ }
+ })}
{getRenderButton({
iconName: this.props.status?.actuator.start() ? "Pause" : "Play",
diff --git a/source/Context/Archive.tsx b/source/Context/Archive.tsx
new file mode 100644
index 0000000..cef0fe8
--- /dev/null
+++ b/source/Context/Archive.tsx
@@ -0,0 +1,91 @@
+import { FunctionComponent, useEffect } from "react";
+import * as download from "downloadjs";
+import { useSetting, IMixinSettingProps, Platform } from "@Context/Setting";
+import { useStatus, IMixinStatusProps } from "@Context/Status";
+import { I18N } from "@Component/Localization/Localization";
+
+interface IFileInfo {
+ fileName: string;
+ isNewFile: boolean;
+ isSaved: boolean;
+ fileUrl?: string;
+ fileData: () => Promise;
+}
+
+interface IRunnerProps {
+ running?: boolean;
+ afterRunning?: () => any;
+}
+
+interface ICallBackProps {
+ then: () => any;
+}
+
+const ArchiveSaveDownloadView: FunctionComponent = function ArchiveSave(props) {
+
+ const runner = async () => {
+ const file = await props.fileData();
+ setTimeout(() => {
+ download(file, props.fileName, "text/json");
+ props.then();
+ }, 100);
+ }
+
+ useEffect(() => { runner() }, []);
+
+ return <>>;
+}
+
+const ArchiveSaveDownload = ArchiveSaveDownloadView;
+
+/**
+ * 保存存档文件
+ */
+const ArchiveSaveView: FunctionComponent = function ArchiveSave(props) {
+
+ if (!props.running) {
+ return <>>;
+ }
+
+ const fileData: IFileInfo = {
+ fileName: "",
+ isNewFile: true,
+ isSaved: false,
+ fileUrl: undefined,
+ fileData: async () => `{"nextIndividualId":0,"objectPool":[],"labelPool":[],"behaviorPool":[]}`
+ }
+
+ if (props.status) {
+ fileData.isNewFile = props.status.archive.isNewFile;
+ fileData.fileName = props.status.archive.fileName ?? "";
+ fileData.isSaved = props.status.archive.isSaved;
+ fileData.fileUrl = props.status.archive.fileUrl;
+ }
+
+ if (fileData.isNewFile) {
+ fileData.fileName = I18N(props, "Header.Bar.New.File.Name");
+ }
+
+ // 生成存档文件
+ fileData.fileData = async () => {
+ return props.status?.archive.save(props.status.model) ?? "";
+ };
+
+ const callBack = () => {
+ if (props.afterRunning) {
+ props.afterRunning();
+ }
+ }
+
+ return <>
+ {
+ props.setting?.platform === Platform.web ?
+ :
+ <>>
+ }
+ >
+}
+
+const ArchiveSave = useSetting(useStatus(ArchiveSaveView));
+
+export { ArchiveSave };
\ No newline at end of file
diff --git a/source/Model/Archive.ts b/source/Model/Archive.ts
index edf5577..c4328e4 100644
--- a/source/Model/Archive.ts
+++ b/source/Model/Archive.ts
@@ -22,7 +22,7 @@ interface IArchiveObject {
behaviorPool: IArchiveBehavior[];
}
-class Archive extends Emitter {
+class Archive extends Emitter {
/**
* 是否为新文件
@@ -40,9 +40,9 @@ class Archive extends Emitter {
public isSaved: boolean = false;
/**
- * 文件数据
+ * 文件路径
*/
- public fileData?: M;
+ public fileUrl?: string;
/**
* 将模型转换为存档对象