Skip to content

Commit 6e0199c

Browse files
authored
Merge pull request #209 from wgqqqqq/fix/macos-monaco-undo-routing
fix(editor): improve markdown editor inline AI behavior
2 parents b492800 + a60b0dc commit 6e0199c

9 files changed

Lines changed: 260 additions & 104 deletions

File tree

src/web-ui/src/tools/editor/components/MarkdownEditor.scss

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,16 @@
107107

108108
h1 {
109109
font-size: $font-size-3xl;
110-
color: #111111;
111-
border-bottom: 1px solid rgba(17, 17, 17, 0.12);
110+
color: var(--color-text-primary);
111+
border-bottom: 1px solid $border-base;
112112
padding-bottom: $size-gap-3;
113113
text-align: center;
114114
letter-spacing: 0.5px;
115115
}
116116

117117
h2 {
118118
font-size: $font-size-2xl;
119-
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
119+
border-bottom: 1px solid $border-base;
120120
padding-bottom: $size-gap-2;
121121
}
122122

@@ -145,7 +145,7 @@
145145
padding: 0.2em 0.4em;
146146
margin: 0;
147147
font-size: 100%;
148-
background-color: rgba(255, 255, 255, 0.08);
148+
background-color: $element-bg-subtle;
149149
border-radius: $size-radius-sm;
150150
font-family: $font-family-mono;
151151
color: var(--color-accent-500);
@@ -157,7 +157,7 @@
157157
font-size: 100%;
158158
line-height: 1.45;
159159
background-color: $element-bg-subtle;
160-
border: 1px solid rgba(255, 255, 255, 0.03);
160+
border: 1px solid $border-base;
161161
border-radius: $size-radius-base;
162162
margin-bottom: $size-gap-4;
163163

@@ -175,7 +175,7 @@
175175
blockquote {
176176
padding: $size-gap-3 $size-gap-4;
177177
color: var(--color-text-muted);
178-
border-left: 3px solid rgba(255, 255, 255, 0.15);
178+
border-left: 3px solid $border-base;
179179
margin: 0 0 $size-gap-4 0;
180180
background: $element-bg-subtle;
181181
border-radius: 0 $size-radius-base $size-radius-base 0;
@@ -263,28 +263,28 @@
263263
margin-bottom: $size-gap-4;
264264
border-radius: $size-radius-base;
265265
overflow: hidden;
266-
border: 1px solid rgba(255, 255, 255, 0.04);
266+
border: 1px solid $border-base;
267267

268268
th {
269269
font-weight: $font-weight-semibold;
270270
padding: $size-gap-2 $size-gap-3;
271-
border: 1px solid rgba(255, 255, 255, 0.04);
271+
border: 1px solid $border-base;
272272
background: $element-bg-soft;
273273
color: var(--color-text-primary);
274274
}
275275

276276
td {
277277
padding: $size-gap-2 $size-gap-3;
278-
border: 1px solid rgba(255, 255, 255, 0.03);
278+
border: 1px solid $border-base;
279279
}
280280

281281
tr {
282282
background-color: transparent;
283-
border-top: 1px solid rgba(255, 255, 255, 0.03);
283+
border-top: 1px solid $border-base;
284284
transition: background-color $motion-fast $easing-standard;
285285

286286
&:nth-child(2n) {
287-
background-color: rgba(255, 255, 255, 0.01);
287+
background-color: color-mix(in srgb, var(--color-text-primary) 2%, transparent);
288288
}
289289

290290
&:hover {
@@ -306,8 +306,8 @@
306306
margin: $size-gap-6 0;
307307
background: linear-gradient(90deg,
308308
transparent 0%,
309-
rgba(255, 255, 255, 0.1) 20%,
310-
rgba(255, 255, 255, 0.1) 80%,
309+
color-mix(in srgb, var(--color-text-muted) 30%, transparent) 20%,
310+
color-mix(in srgb, var(--color-text-muted) 30%, transparent) 80%,
311311
transparent 100%);
312312
border: 0;
313313
border-radius: 1px;
@@ -358,7 +358,7 @@
358358
margin: $size-gap-4 0;
359359
padding: $size-gap-4;
360360
background: $element-bg-subtle;
361-
border: 1px solid rgba(255, 255, 255, 0.03);
361+
border: 1px solid $border-base;
362362
border-radius: $size-radius-base;
363363
overflow-x: auto;
364364

src/web-ui/src/tools/editor/components/MarkdownEditor.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
6262
const lastModifiedTimeRef = useRef<number>(0);
6363
const lastJumpPositionRef = useRef<{ filePath: string; line: number } | null>(null);
6464
const onContentChangeRef = useRef(onContentChange);
65+
const contentRef = useRef(content);
66+
const lastReportedDirtyRef = useRef<boolean | null>(null);
6567
onContentChangeRef.current = onContentChange;
68+
contentRef.current = content;
6669

6770
const basePath = React.useMemo(() => {
6871
if (!filePath) return undefined;
@@ -106,6 +109,7 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
106109
if (!isUnmountedRef.current) {
107110
setContent(fileContent);
108111
setHasChanges(false);
112+
lastReportedDirtyRef.current = false;
109113
setTimeout(() => {
110114
editorRef.current?.setInitialContent?.(fileContent);
111115
}, 0);
@@ -148,6 +152,7 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
148152
} else if (initialContent !== undefined) {
149153
setContent(initialContent);
150154
setHasChanges(false);
155+
lastReportedDirtyRef.current = false;
151156
setTimeout(() => {
152157
editorRef.current?.setInitialContent?.(initialContent);
153158
}, 0);
@@ -181,6 +186,7 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
181186
if (!isUnmountedRef.current) {
182187
editorRef.current?.markSaved?.();
183188
setHasChanges(false);
189+
lastReportedDirtyRef.current = false;
184190
if (onContentChangeRef.current) {
185191
onContentChangeRef.current(content, false);
186192
}
@@ -200,11 +206,18 @@ const MarkdownEditor: React.FC<MarkdownEditorProps> = ({
200206
}, [content, filePath, workspacePath, hasChanges, onSave, t]);
201207

202208
const handleContentChange = useCallback((newContent: string) => {
209+
contentRef.current = newContent;
203210
setContent(newContent);
204211
}, []);
205212

206213
const handleDirtyChange = useCallback((isDirty: boolean) => {
207214
setHasChanges(isDirty);
215+
if (lastReportedDirtyRef.current === isDirty) {
216+
return;
217+
}
218+
219+
lastReportedDirtyRef.current = isDirty;
220+
onContentChangeRef.current?.(contentRef.current, isDirty);
208221
}, []);
209222

210223
const handleSave = useCallback((_value: string) => {

src/web-ui/src/tools/editor/meditor/components/InlineAiPreviewBlock.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ export const InlineAiPreviewBlock: React.FC<InlineAiPreviewBlockProps> = ({
3838
onReject,
3939
onRetry,
4040
}) => {
41+
const handlePointerDown: React.PointerEventHandler<HTMLElement> = (event) => {
42+
// Keep ProseMirror from stealing focus and remounting the widget before click fires.
43+
event.preventDefault();
44+
event.stopPropagation();
45+
};
46+
47+
const handleMouseDown: React.MouseEventHandler<HTMLElement> = (event) => {
48+
event.preventDefault();
49+
event.stopPropagation();
50+
};
51+
4152
const statusText =
4253
status === 'submitting' || status === 'streaming'
4354
? labels.streaming
@@ -47,7 +58,11 @@ export const InlineAiPreviewBlock: React.FC<InlineAiPreviewBlockProps> = ({
4758
const previewStateClass = `m-editor-inline-ai-preview--${status}`;
4859

4960
return (
50-
<div className={`m-editor-inline-ai-preview m-editor-inline-ai-preview--inline ${previewStateClass}`}>
61+
<div
62+
className={`m-editor-inline-ai-preview m-editor-inline-ai-preview--inline ${previewStateClass}`}
63+
onPointerDownCapture={handlePointerDown}
64+
onMouseDownCapture={handleMouseDown}
65+
>
5166
<div className="m-editor-inline-ai-preview__header">
5267
<span className="m-editor-inline-ai-preview__title">{labels.title}</span>
5368
<span className="m-editor-inline-ai-preview__status">{statusText}</span>

src/web-ui/src/tools/editor/meditor/components/Preview.scss

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
margin: $size-gap-4 0;
3434
padding: $size-gap-4;
3535
background: $element-bg-subtle;
36-
border: 1px solid rgba(255, 255, 255, 0.03);
36+
border: 1px solid $border-base;
3737
border-radius: $size-radius-base;
3838
overflow-x: auto;
3939

@@ -70,7 +70,7 @@
7070

7171
&-divider {
7272
border: none;
73-
border-top: 1px dashed rgba(255, 255, 255, 0.08);
73+
border-top: 1px dashed $border-base;
7474
margin: $size-gap-1 0;
7575
}
7676

@@ -80,4 +80,3 @@
8080
word-break: break-word;
8181
}
8282
}
83-

src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585

8686
h1 {
8787
font-size: $font-size-3xl;
88-
color: #111111;
88+
color: var(--color-text-primary);
8989
text-align: center;
9090
}
9191

@@ -114,7 +114,7 @@
114114
blockquote {
115115
margin: 0;
116116
padding-left: $size-gap-3;
117-
border-left: 3px solid rgba(255, 255, 255, 0.15);
117+
border-left: 3px solid $border-base;
118118
}
119119

120120
pre {
@@ -309,8 +309,8 @@
309309
height: 3.5rem;
310310
padding-right: $size-gap-2;
311311
border-radius: 999px;
312-
background: rgba(255, 255, 255, 0.03);
313-
border-color: rgba(255, 255, 255, 0.1);
312+
background: $element-bg-subtle;
313+
border-color: $border-base;
314314
}
315315

316316
.bitfun-input {
@@ -330,7 +330,7 @@
330330
padding: 0 $size-gap-2;
331331
height: 2rem;
332332
border-radius: 999px;
333-
background: rgba(255, 255, 255, 0.05);
333+
background: $element-bg-subtle;
334334
color: var(--color-text-muted);
335335
font-size: $font-size-xs;
336336
white-space: nowrap;
@@ -389,8 +389,8 @@
389389
transition: background $motion-fast $easing-standard, border-color $motion-fast $easing-standard, color $motion-fast $easing-standard;
390390

391391
&:hover {
392-
background: rgba(255, 255, 255, 0.04);
393-
border-color: rgba(255, 255, 255, 0.08);
392+
background: $element-bg-subtle;
393+
border-color: $border-base;
394394
}
395395
}
396396

0 commit comments

Comments
 (0)