|
1 | | -import { v4 as uuidv4 } from "uuid"; |
2 | | -import { Dialog } from "../../../../components/dialog"; |
3 | 1 | import { Serialized } from "../../../../types/node"; |
4 | | -import { writeFileBase64 } from "../../../../utils/fs"; |
5 | | -import { PathString } from "../../../../utils/pathString"; |
6 | 2 | import { Rectangle } from "../../../dataStruct/shape/Rectangle"; |
7 | 3 | import { Vector } from "../../../dataStruct/Vector"; |
8 | 4 | import { Renderer } from "../../../render/canvas2d/renderer"; |
9 | | -import { Stage } from "../../../stage/Stage"; |
10 | 5 | import { StageDumper } from "../../../stage/StageDumper"; |
11 | 6 | import { StageSerializedAdder } from "../../../stage/stageManager/concreteMethods/StageSerializedAdder"; |
12 | 7 | import { StageManager } from "../../../stage/stageManager/StageManager"; |
13 | 8 | import { Entity } from "../../../stage/stageObject/abstract/StageEntity"; |
14 | 9 | import { ImageNode } from "../../../stage/stageObject/entity/ImageNode"; |
15 | 10 | import { TextNode } from "../../../stage/stageObject/entity/TextNode"; |
16 | | -import { UrlNode } from "../../../stage/stageObject/entity/UrlNode"; |
17 | 11 | import { MouseLocation } from "../../controlService/MouseLocation"; |
18 | | -import { SectionMethods } from "../../../stage/stageManager/basicMethods/SectionMethods"; |
19 | | -import { RectanglePushInEffect } from "../../feedbackService/effectEngine/concrete/RectanglePushInEffect"; |
| 12 | +import { copyEnginePasteImage } from "./pasteImage"; |
| 13 | +import { copyEnginePastePlainText } from "./pastePlainText"; |
20 | 14 |
|
21 | 15 | /** |
22 | 16 | * 专门用来管理节点复制的引擎 |
@@ -185,136 +179,14 @@ async function readClipboardItems(mouseLocation: Vector) { |
185 | 179 | navigator.clipboard.read().then(async (items) => { |
186 | 180 | for (const item of items) { |
187 | 181 | if (item.types.includes("image/png")) { |
188 | | - // 图片在草稿情况下不能粘贴 |
189 | | - if (Stage.path.isDraft()) { |
190 | | - Dialog.show({ |
191 | | - title: "草稿状态下不要粘贴图片", |
192 | | - content: "请先另存为,再粘贴图片,因为粘贴的图片会和保存的工程文件在同一目录下,而草稿在内存中,没有路径", |
193 | | - }); |
194 | | - return; |
195 | | - } |
196 | | - const blob = await item.getType(item.types[0]); // 获取 Blob 对象 |
197 | | - const imageUUID = uuidv4(); |
198 | | - const folder = PathString.dirPath(Stage.path.getFilePath()); |
199 | | - const imagePath = `${folder}${PathString.getSep()}${imageUUID}.png`; |
200 | | - |
201 | | - // 2024.12.31 测试发现这样的写法会导致读取时base64解码失败 |
202 | | - // writeFile(imagePath, new Uint8Array(await blob.arrayBuffer())); |
203 | | - // 下面这样的写法是没有问题的 |
204 | | - writeFileBase64(imagePath, await convertBlobToBase64(blob)); |
205 | | - |
206 | | - // 要延迟一下,等待保存完毕 |
207 | | - setTimeout(() => { |
208 | | - const imageNode = new ImageNode({ |
209 | | - uuid: imageUUID, |
210 | | - location: [mouseLocation.x, mouseLocation.y], |
211 | | - path: `${imageUUID}.png`, |
212 | | - }); |
213 | | - // imageNode.setBase64StringForced(base64String); |
214 | | - StageManager.addImageNode(imageNode); |
215 | | - }, 100); |
| 182 | + copyEnginePasteImage(item, mouseLocation); |
216 | 183 | } |
217 | 184 | if (item.types.includes("text/plain")) { |
218 | | - const blob = await item.getType("text/plain"); // 获取文本内容 |
219 | | - // const text = await blob.text(); |
220 | | - const clipboardText = await blobToText(blob); // 将 Blob 转换为文本 |
221 | | - if (PathString.isValidURL(clipboardText)) { |
222 | | - // 是URL类型 |
223 | | - const urlNode = new UrlNode({ |
224 | | - title: "链接", |
225 | | - uuid: uuidv4(), |
226 | | - url: clipboardText, |
227 | | - location: [mouseLocation.x, mouseLocation.y], |
228 | | - }); |
229 | | - StageManager.addUrlNode(urlNode); |
230 | | - |
231 | | - // 添加到section |
232 | | - const mouseSections = SectionMethods.getSectionsByInnerLocation(mouseLocation); |
233 | | - if (mouseSections.length > 0) { |
234 | | - StageManager.goInSection([urlNode], mouseSections[0]); |
235 | | - Stage.effectMachine.addEffect( |
236 | | - RectanglePushInEffect.sectionGoInGoOut( |
237 | | - urlNode.collisionBox.getRectangle(), |
238 | | - mouseSections[0].collisionBox.getRectangle(), |
239 | | - ), |
240 | | - ); |
241 | | - } |
242 | | - } else { |
243 | | - const { valid, text, url } = PathString.isMarkdownUrl(clipboardText); |
244 | | - if (valid) { |
245 | | - // 是Markdown链接类型 |
246 | | - const urlNode = new UrlNode({ |
247 | | - title: text, |
248 | | - uuid: uuidv4(), |
249 | | - url: url, |
250 | | - location: [mouseLocation.x, mouseLocation.y], |
251 | | - }); |
252 | | - StageManager.addUrlNode(urlNode); |
253 | | - |
254 | | - // 添加到section |
255 | | - const mouseSections = SectionMethods.getSectionsByInnerLocation(mouseLocation); |
256 | | - if (mouseSections.length > 0) { |
257 | | - StageManager.goInSection([urlNode], mouseSections[0]); |
258 | | - Stage.effectMachine.addEffect( |
259 | | - RectanglePushInEffect.sectionGoInGoOut( |
260 | | - urlNode.collisionBox.getRectangle(), |
261 | | - mouseSections[0].collisionBox.getRectangle(), |
262 | | - ), |
263 | | - ); |
264 | | - } |
265 | | - } else { |
266 | | - // 只是普通的文本 |
267 | | - const textNode = new TextNode({ |
268 | | - uuid: uuidv4(), |
269 | | - text: clipboardText, |
270 | | - location: [mouseLocation.x, mouseLocation.y], |
271 | | - size: [100, 100], |
272 | | - color: [0, 0, 0, 0], |
273 | | - }); |
274 | | - textNode.move(new Vector(-textNode.rectangle.size.x / 2, -textNode.rectangle.size.y / 2)); |
275 | | - StageManager.addTextNode(textNode); |
276 | | - |
277 | | - // 添加到section |
278 | | - const mouseSections = SectionMethods.getSectionsByInnerLocation(mouseLocation); |
279 | | - if (mouseSections.length > 0) { |
280 | | - StageManager.goInSection([textNode], mouseSections[0]); |
281 | | - Stage.effectMachine.addEffect( |
282 | | - RectanglePushInEffect.sectionGoInGoOut( |
283 | | - textNode.collisionBox.getRectangle(), |
284 | | - mouseSections[0].collisionBox.getRectangle(), |
285 | | - ), |
286 | | - ); |
287 | | - } |
288 | | - } |
289 | | - } |
| 185 | + copyEnginePastePlainText(item, mouseLocation); |
290 | 186 | } |
291 | 187 | } |
292 | 188 | }); |
293 | 189 | } catch (err) { |
294 | 190 | console.error("Failed to read clipboard contents: ", err); |
295 | 191 | } |
296 | 192 | } |
297 | | - |
298 | | -function blobToText(blob: Blob): Promise<string> { |
299 | | - return new Promise((resolve, reject) => { |
300 | | - const reader = new FileReader(); |
301 | | - reader.onload = () => resolve(reader.result as string); // 读取完成时返回结果 |
302 | | - reader.onerror = () => reject(reader.error); // 读取出错时返回错误 |
303 | | - reader.readAsText(blob); // 读取 Blob 对象作为文本 |
304 | | - }); |
305 | | -} |
306 | | - |
307 | | -async function convertBlobToBase64(blob: Blob): Promise<string> { |
308 | | - return new Promise((resolve, reject) => { |
309 | | - const reader = new FileReader(); |
310 | | - reader.onloadend = () => { |
311 | | - if (typeof reader.result === "string") { |
312 | | - resolve(reader.result.split(",")[1]); // 去掉"data:image/png;base64,"前缀 |
313 | | - } else { |
314 | | - reject(new Error("Invalid result type")); |
315 | | - } |
316 | | - }; |
317 | | - reader.onerror = reject; |
318 | | - reader.readAsDataURL(blob); |
319 | | - }); |
320 | | -} |
0 commit comments