Skip to content

Commit 39d444c

Browse files
committed
✨ 完善保存功能,但还有漏洞(快捷键保存总是变成另存为)
1 parent 7a6dd5b commit 39d444c

File tree

5 files changed

+84
-28
lines changed

5 files changed

+84
-28
lines changed

src/core/controller/Controller.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,10 @@ export namespace Controller {
676676
function keydown(event: KeyboardEvent) {
677677
const key = event.key.toLowerCase();
678678
pressingKeySet.add(key);
679+
if (key === "s" && pressingKeySet.has("control")) {
680+
// 保存
681+
console.log("Save");
682+
}
679683
if (keyMap[key]) {
680684
// 当按下某一个方向的时候,相当于朝着某个方向赋予一次加速度
681685
Camera.accelerateCommander = Camera.accelerateCommander
@@ -692,6 +696,7 @@ export namespace Controller {
692696
} else if (key === "enter") {
693697
// 开始编辑选中的连线
694698
}
699+
695700
}
696701

697702
function keyup(event: KeyboardEvent) {
@@ -711,6 +716,7 @@ export namespace Controller {
711716
.limitY(-1, 1);
712717
}
713718
setCursorName("default");
719+
714720
}
715721

716722
function touchstart(e: TouchEvent) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Color } from "../../Color";
2+
import { ProgressNumber } from "../../ProgressNumber";
3+
import { Effect } from "../effect";
4+
5+
/**
6+
* 屏幕闪颜色效果
7+
*/
8+
export class ViewFlashEffect extends Effect {
9+
constructor(
10+
public color: Color,
11+
public override timeProgress: ProgressNumber = new ProgressNumber(0, 100),
12+
) {
13+
super(timeProgress);
14+
}
15+
}

src/core/render/canvas2d/EffectRenderer.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import { CircleFlameEffect } from "../../effect/concrete/CircleFlameEffect";
44
import { LineCuttingEffect } from "../../effect/concrete/LineCuttingEffect";
55
import { LineEffect } from "../../effect/concrete/LineEffect";
66
import { TextRiseEffect } from "../../effect/concrete/TextRiseEffect";
7+
import { ViewFlashEffect } from "../../effect/concrete/ViewFlashEffect";
78
import { easeInOutSine } from "../../effect/easings";
9+
import { Rectangle } from "../../Rectangle";
810
import { Camera } from "../../stage/Camera";
911
import { Vector } from "../../Vector";
1012
import { Renderer } from "./renderer";
@@ -111,4 +113,19 @@ export namespace EffectRenderer {
111113
effect.lineWidth * effect.timeProgress.rate,
112114
);
113115
}
116+
export function renderViewFlashEffect(effect: ViewFlashEffect) {
117+
if (effect.timeProgress.isFull) {
118+
return;
119+
}
120+
RenderUtils.renderRect(
121+
new Rectangle(new Vector(-10000, -10000), new Vector(20000, 20000)),
122+
mixColors(
123+
effect.color,
124+
new Color(0, 0, 0, 0),
125+
effect.timeProgress.rate,
126+
),
127+
Color.Transparent,
128+
0,
129+
);
130+
}
114131
}

src/core/render/canvas2d/renderer.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { CircleFlameEffect } from "../../effect/concrete/CircleFlameEffect";
1414
import { LineCuttingEffect } from "../../effect/concrete/LineCuttingEffect";
1515
import { LineEffect } from "../../effect/concrete/LineEffect";
1616
import { Line } from "../../Line";
17+
import { ViewFlashEffect } from "../../effect/concrete/ViewFlashEffect";
1718

1819
/**
1920
* 渲染器
@@ -378,6 +379,8 @@ export namespace Renderer {
378379
EffectRenderer.renderLineEffect(effect);
379380
} else if (effect instanceof LineCuttingEffect) {
380381
EffectRenderer.renderLineCuttingEffect(effect);
382+
} else if (effect instanceof ViewFlashEffect) {
383+
EffectRenderer.renderViewFlashEffect(effect);
381384
}
382385
}
383386
}

src/pages/_app_menu.tsx

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from "react";
1+
import React, { useEffect } from "react";
22
import { cn } from "../utils/cn";
33
import {
44
AppWindow,
@@ -33,6 +33,9 @@ import { Camera } from "../core/stage/Camera";
3333
import { Edge } from "../core/Edge";
3434
import { NodeDumper } from "../core/NodeDumper";
3535
import { writeTextFile } from "@tauri-apps/plugin-fs";
36+
import { Stage } from "../core/stage/Stage";
37+
import { ViewFlashEffect } from "../core/effect/concrete/ViewFlashEffect";
38+
import { Color } from "../core/Color";
3639

3740
export default function AppMenu({
3841
className = "",
@@ -43,7 +46,7 @@ export default function AppMenu({
4346
}) {
4447
const navigate = useNavigate();
4548
const dialog = useDialog();
46-
const [, setFile] = useRecoilState(fileAtom);
49+
const [file, setFile] = useRecoilState(fileAtom);
4750

4851
const onNew = () => {
4952
NodeManager.destroy();
@@ -107,30 +110,21 @@ export default function AppMenu({
107110
};
108111

109112
const onSave = async () => {
110-
const path = await openFileDialog({
111-
title: "保存文件",
112-
directory: false,
113-
multiple: false,
114-
filters: [
115-
{
116-
name: "Project Graph",
117-
extensions: ["json"],
118-
},
119-
],
120-
});
113+
let path: string | null = file;
114+
console.log("准备保存,当前路径是", path);
121115

122-
if (!path) {
116+
if (file === "Project Graph") {
117+
// 如果文件名为 "Project Graph" 则说明是新建文件。
118+
// 要走另存为流程
119+
console.log("要走另存为流程");
120+
onSaveNew();
123121
return;
124122
}
125123

126124
try {
127125
const data = NodeDumper.dumpToV3(); // 获取当前节点和边的数据
128126
await writeTextFile(path, JSON.stringify(data, null, 2)); // 将数据写入文件
129-
dialog.show({
130-
title: "保存成功",
131-
content: `文件已保存到 ${path}`,
132-
type: "success",
133-
});
127+
Stage.effects.push(new ViewFlashEffect(Color.Black));
134128
} catch (e) {
135129
dialog.show({
136130
title: "保存失败",
@@ -173,6 +167,23 @@ export default function AppMenu({
173167
}
174168
};
175169

170+
useEffect(() => {
171+
// 绑定快捷键
172+
const keyDownFunction = (e: KeyboardEvent) => {
173+
if (e.ctrlKey && e.key === "n") {
174+
onNew();
175+
} else if (e.ctrlKey && e.key === "o") {
176+
onOpen();
177+
} else if (e.ctrlKey && e.key === "s") {
178+
onSave();
179+
}
180+
};
181+
document.addEventListener("keydown", keyDownFunction);
182+
return () => {
183+
document.removeEventListener("keydown", keyDownFunction);
184+
};
185+
}, []);
186+
176187
return (
177188
<div
178189
className={cn(
@@ -192,7 +203,7 @@ export default function AppMenu({
192203
打开
193204
</Col>
194205
<Col icon={<Save />} onClick={onSave}>
195-
覆盖保存
206+
保存
196207
</Col>
197208
<Col icon={<Save />} onClick={onSaveNew}>
198209
另存为
@@ -217,7 +228,7 @@ export default function AppMenu({
217228
<Col icon={<TestTube2 />} onClick={() => navigate("/test")}>
218229
测试
219230
</Col>
220-
{/* <Col
231+
<Col
221232
icon={<TestTube2 />}
222233
onClick={() =>
223234
dialog.show({
@@ -227,14 +238,18 @@ export default function AppMenu({
227238
})
228239
}
229240
>
230-
查看舞台序列化信息
241+
json
242+
</Col>
243+
<Col
244+
icon={<TestTube2 />}
245+
onClick={() => {
246+
console.log(NodeManager.nodes);
247+
console.log(NodeManager.edges);
248+
console.log(file);
249+
}}
250+
>
251+
print
231252
</Col>
232-
<Col icon={<TestTube2 />} onClick={() => {
233-
console.log(NodeManager.nodes);
234-
console.log(NodeManager.edges);
235-
}}>
236-
NodeManager log查看
237-
</Col> */}
238253
</Row>
239254
<Row icon={<AppWindow />} title="窗口">
240255
<Col icon={<RefreshCcw />} onClick={() => window.location.reload()}>

0 commit comments

Comments
 (0)