@@ -12,14 +12,13 @@ import './agent-cursor.js';
1212
1313// ProseMirror imports
1414import { EditorView } from 'prosemirror-view' ;
15- import { EditorState , Transaction , Plugin , PluginKey , TextSelection } from 'prosemirror-state' ;
15+ import { EditorState , Plugin , PluginKey , TextSelection } from 'prosemirror-state' ;
1616import { Schema , Node as PMNode } from 'prosemirror-model' ;
1717import { schema as basicSchema } from 'prosemirror-schema-basic' ;
1818import { addListNodes } from 'prosemirror-schema-list' ;
1919import { history , undo , redo } from 'prosemirror-history' ;
2020import { keymap } from 'prosemirror-keymap' ;
2121import { exampleSetup } from 'prosemirror-example-setup' ;
22- import { defaultMarkdownParser , defaultMarkdownSerializer } from 'prosemirror-markdown' ;
2322
2423import {
2524 AgentSelection ,
@@ -758,6 +757,15 @@ export class SynPmEditor extends LitElement {
758757 // console.log('Updating editor from Syn - text changed');
759758 this . isUpdatingFromSyn = true ;
760759
760+ // IMPORTANT: Capture the current cursor position BEFORE rebuilding
761+ // We must use the current editor selection, not read from ephemeral state,
762+ // to avoid cursor jumping when multiple users edit simultaneously
763+ const currentSelection = this . view . state . selection ;
764+ const currentPmPos = currentSelection . anchor ;
765+
766+ // Convert current ProseMirror position to markdown position
767+ const currentMarkdownPos = this . proseMirrorPosToMarkdownPos ( currentPmPos ) ;
768+
761769 const lines = stateText . split ( '\n' ) ;
762770 // console.log('Split into lines:', lines.length, 'lines:', JSON.stringify(lines));
763771
@@ -772,23 +780,16 @@ export class SynPmEditor extends LitElement {
772780 newDoc . content
773781 ) ;
774782
775- // Try to preserve cursor position
776- const cursors = this . _cursors . value ;
777- const myAgentSelection = cursors [ encodeHashToBase64 ( this . slice . myPubKey ) ] ;
778- if ( myAgentSelection && state . text . length > 0 ) {
779- const position = elemIdToPosition (
780- myAgentSelection . left ,
781- myAgentSelection . position ,
782- state . text
783- ) ;
784- if ( position !== null && position !== undefined ) {
785- const docSize = tr . doc . content . size ;
786- const safePos = Math . max ( 0 , Math . min ( position , docSize ) ) ;
787- try {
788- tr . setSelection ( TextSelection . near ( tr . doc . resolve ( safePos ) ) ) ;
789- } catch ( e ) {
790- // Selection might be invalid, ignore
791- }
783+ // Restore cursor position using the captured markdown position
784+ // Convert back from markdown to new ProseMirror position
785+ if ( currentMarkdownPos !== null && currentMarkdownPos !== undefined ) {
786+ const newPmPos = this . markdownPosToProseMirrorPos ( currentMarkdownPos ) ;
787+ const docSize = tr . doc . content . size ;
788+ const safePos = Math . max ( 0 , Math . min ( newPmPos , docSize ) ) ;
789+ try {
790+ tr . setSelection ( TextSelection . near ( tr . doc . resolve ( safePos ) ) ) ;
791+ } catch ( e ) {
792+ // Selection might be invalid, ignore
792793 }
793794 }
794795
0 commit comments