Skip to content

Commit 1406d8a

Browse files
committed
Fix: improve selection handling in the Client.
1 parent cba3ab4 commit 1406d8a

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

client/src/CodeMirror-integration.mts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,17 +409,19 @@ export const deleteDocBlock = StateEffect.define<{ from: number }>({
409409
// Create a [widget](https://codemirror.net/docs/ref/#view.WidgetType) which
410410
// contains a doc block.
411411
class DocBlockWidget extends WidgetType {
412+
dom: null | HTMLDivElement;
412413
constructor(
413414
readonly indent: string,
414415
readonly delimiter: string,
415416
readonly contents: string,
417+
dom: null | HTMLDivElement
416418
// Only used in an update to avoid changing an already-modified doc
417419
// block.
418-
readonly dom: null | HTMLDivElement,
419420
) {
420421
// TODO: I don't understand why I don't need to store the provided
421422
// parameters in the object: `this.indent = indent;`, etc.
422423
super();
424+
this.dom = dom;
423425
}
424426

425427
eq(other: DocBlockWidget) {
@@ -446,6 +448,7 @@ class DocBlockWidget extends WidgetType {
446448
this.contents +
447449
"</div>";
448450
mathJaxTypeset(wrap);
451+
this.dom = wrap;
449452
return wrap;
450453
}
451454

@@ -473,6 +476,7 @@ class DocBlockWidget extends WidgetType {
473476
contents_div.innerHTML = this.contents;
474477
mathJaxTypeset(contents_div);
475478
}
479+
this.dom = dom as HTMLDivElement;
476480

477481
// Indicate the update was successful.
478482
return true;
@@ -502,6 +506,7 @@ class DocBlockWidget extends WidgetType {
502506
const tinymce_div = document.getElementById("TinyMCE-inst")!;
503507
codechat_body.insertBefore(tinymce_div, null);
504508
}
509+
this.dom = null;
505510
}
506511
}
507512

@@ -620,7 +625,28 @@ const on_dirty = (
620625
export const DocBlockPlugin = ViewPlugin.fromClass(
621626
class {
622627
constructor(view: EditorView) {}
623-
update(update: ViewUpdate) {}
628+
update(update: ViewUpdate) {
629+
// If the editor doesn't have focus, ignore selection changes. This
630+
// avoid the case where cursor movement in the IDE produces
631+
// selection changes in the Client, which then steals focus. TODO:
632+
// with the editor isn't focused, highlight the relevant line or
633+
// something similar.
634+
if (update.selectionSet && update.view.hasFocus) {
635+
// See if the new main selection falls within a doc block.
636+
const main_selection = update.state.selection.main;
637+
update.state
638+
.field(docBlockField)
639+
.between(
640+
main_selection.from,
641+
main_selection.to,
642+
(from: number, to: number, value: Decoration) => {
643+
// If so, give focus to the contents of the doc
644+
// block.
645+
value.spec.widget.dom?.childNodes[1].focus();
646+
},
647+
);
648+
}
649+
}
624650
},
625651
{
626652
eventHandlers: {

0 commit comments

Comments
 (0)