Skip to content

Commit 5cbb047

Browse files
committed
v1.0.4
修复编辑器高危风险
1 parent 64b4cc1 commit 5cbb047

File tree

5 files changed

+44
-8
lines changed

5 files changed

+44
-8
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "DeepLab",
33
"private": true,
4-
"version": "1.0.3",
4+
"version": "1.0.4",
55
"type": "module",
66
"packageManager": "pnpm@10.30.1",
77
"scripts": {

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "deeplab"
3-
version = "1.0.3"
3+
version = "1.0.4"
44
description = "AI科研辅助平台"
55
authors = ["timechess"]
66
edition = "2021"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "DeepLab",
4-
"version": "1.0.3",
4+
"version": "1.0.4",
55
"identifier": "deeplab",
66
"build": {
77
"beforeDevCommand": "pnpm dev:next",

src/components/note/detail/NoteDetailEditor.tsx

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
128128
const targetQueryInputRef = useRef<HTMLInputElement | null>(null);
129129
const editorSurfaceRef = useRef<HTMLDivElement | null>(null);
130130
const normalizingMathRef = useRef(false);
131+
const loadingSeqRef = useRef(0);
132+
const hydratingContentRef = useRef(false);
133+
const pendingDirtyWhileSavingRef = useRef(false);
131134

132135
const refreshContext = useCallback(async () => {
133136
if (!noteId) {
@@ -236,6 +239,10 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
236239
},
237240
},
238241
onUpdate: ({ editor: activeEditor }) => {
242+
if (hydratingContentRef.current) {
243+
hydratingContentRef.current = false;
244+
return;
245+
}
239246
if (!normalizingMathRef.current) {
240247
const normalized = normalizeDisplayMathParagraphs(activeEditor);
241248
if (normalized) {
@@ -250,7 +257,13 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
250257
return;
251258
}
252259

253-
setSaveState((current) => (current === "saving" ? current : "dirty"));
260+
setSaveState((current) => {
261+
if (current === "saving") {
262+
pendingDirtyWhileSavingRef.current = true;
263+
return current;
264+
}
265+
return "dirty";
266+
});
254267
syncSlashTrigger(activeEditor);
255268
},
256269
onSelectionUpdate: ({ editor: activeEditor }) => {
@@ -331,6 +344,7 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
331344
if (!editor || !noteId || !loaded) {
332345
return;
333346
}
347+
pendingDirtyWhileSavingRef.current = false;
334348
setSaveState("saving");
335349
setError(null);
336350
setNotice(null);
@@ -342,9 +356,11 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
342356
links: extractNoteLinks(json),
343357
});
344358
setTitle(response.title);
345-
setSaveState("saved");
359+
setSaveState(pendingDirtyWhileSavingRef.current ? "dirty" : "saved");
360+
pendingDirtyWhileSavingRef.current = false;
346361
await refreshContext();
347362
} catch (saveError) {
363+
pendingDirtyWhileSavingRef.current = false;
348364
setSaveState("failed");
349365
setError(
350366
saveError instanceof Error ? saveError.message : String(saveError),
@@ -356,22 +372,40 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
356372
if (!editor || !noteId) {
357373
return;
358374
}
375+
const currentLoadSeq = loadingSeqRef.current + 1;
376+
loadingSeqRef.current = currentLoadSeq;
377+
setLoaded(false);
378+
setSaveState("saved");
379+
setError(null);
380+
setTitle("");
359381
void (async () => {
360382
try {
361383
const detail = await getNoteDetail(noteId);
384+
if (loadingSeqRef.current !== currentLoadSeq) {
385+
return;
386+
}
362387
setTitle(detail.title);
363388
const parsed = safeJsonParse(detail.content) as JSONContent;
364389
const normalized = normalizeLegacyMathNodes(parsed)[0] ?? parsed;
390+
hydratingContentRef.current = true;
365391
editor.commands.setContent(normalized);
392+
if (loadingSeqRef.current !== currentLoadSeq) {
393+
return;
394+
}
366395
setLoaded(true);
367396
setSaveState("saved");
368397
setError(null);
369398
} catch (loadError) {
399+
if (loadingSeqRef.current !== currentLoadSeq) {
400+
return;
401+
}
370402
setError(
371403
loadError instanceof Error ? loadError.message : String(loadError),
372404
);
373405
}
374-
await refreshContext();
406+
if (loadingSeqRef.current === currentLoadSeq) {
407+
await refreshContext();
408+
}
375409
})();
376410
}, [editor, noteId, refreshContext]);
377411

@@ -676,7 +710,9 @@ export function NoteDetailEditor({ noteId }: NoteDetailEditorProps) {
676710
value={title}
677711
onChange={(event) => {
678712
setTitle(event.target.value);
679-
setSaveState("dirty");
713+
if (loaded) {
714+
setSaveState("dirty");
715+
}
680716
}}
681717
placeholder="笔记标题"
682718
className="w-full rounded-2xl border border-[#243651] bg-[#0f1724] px-4 py-3 text-xl font-semibold text-[#e5ecff] shadow-[0_10px_26px_rgba(0,0,0,0.25)] outline-none transition-colors focus:border-[#4f7dff]"

0 commit comments

Comments
 (0)