Mentions légales du service

Skip to content
Snippets Groups Projects

Resolve "Cursor moves at the end of the document"

Merged Yannick Li requested to merge 22-cursor-moves-at-the-end-of-the-document into dev
1 unresolved thread
+ 79
6
import { client } from '@concordant/c-client';
import { client } from '@concordant/c-client';
import React, { Component } from 'react';
import React, { Component, createRef } from 'react';
import MDEditor from '@uiw/react-md-editor';
import MDEditor from '@uiw/react-md-editor';
import Submit1Input from './Submit1Input';
import Submit1Input from './Submit1Input';
import DiffMatchPatch from 'diff-match-patch';
import DiffMatchPatch from 'diff-match-patch';
@@ -35,6 +35,11 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
@@ -35,6 +35,11 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
*/
*/
private rga: any;
private rga: any;
 
/**
 
* Ref to the main div DOM element, required for selection management
 
*/
 
private nodeRef = createRef<HTMLDivElement>();
 
public static defaultProps = {
public static defaultProps = {
docName: "Untitled-1"
docName: "Untitled-1"
}
}
@@ -92,17 +97,85 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
@@ -92,17 +97,85 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
});
});
}
}
 
/**
 
* Handler called when a new remote value is received.
 
* @param newvalue New value received
 
*/
 
private valueReceived(newvalue: string) {
 
let textarea = this.nodeRef.current
 
?.getElementsByClassName("w-md-editor-text-input")
 
?.item(0) as HTMLInputElement;
 
 
const dmp = new DiffMatchPatch.diff_match_patch();
 
const diffs = dmp.diff_main(this.state.value, newvalue);
 
var cursorStart = textarea.selectionStart
 
var cursorEnd = textarea.selectionEnd
 
 
this.setState({
 
value: newvalue,
 
});
 
 
if (cursorStart === null || cursorEnd === null) {
 
return
 
}
 
 
let idx = 0
 
for (let diff of diffs) {
 
switch (diff[0]) {
 
case DiffMatchPatch.DIFF_EQUAL:
 
idx += diff[1].length
 
break;
 
case DiffMatchPatch.DIFF_INSERT:
 
if (idx <= cursorStart) {
 
// Insertion before the selected text:
 
// Move the cursor forward
 
cursorStart += diff[1].length
 
cursorEnd += diff[1].length
 
} else if (idx < cursorEnd) {
 
// Insertion in the selected text
 
// Deselect and put the cursor at the beginning of the previously selected text
 
cursorEnd = cursorStart
 
}
 
idx += diff[1].length
 
break;
 
case DiffMatchPatch.DIFF_DELETE:
 
if (idx <= cursorStart) {
 
if (idx + diff[1].length <= cursorStart) {
 
// Deletion before the selected text:
 
// Move the cursor backward
 
cursorStart -= diff[1].length
 
cursorEnd -= diff[1].length
 
} else {
 
// Deletion starts before the selected text but selected text is affected:
 
// Deselect and put the cursor at the beginning of the deletion
 
[cursorStart, cursorEnd] = [idx, idx]
 
}
 
} else if (idx < cursorEnd) {
 
// Deletion starts in the selected text
 
// Deselect and put the cursor at the beginning of the previously selected text
 
cursorEnd = cursorStart
 
}
 
break;
 
}
 
if (idx > cursorEnd) {
 
break
 
}
 
}
 
[textarea.selectionStart, textarea.selectionEnd] = [cursorStart, cursorEnd]
 
}
 
/**
/**
* Called after the component is rendered.
* Called after the component is rendered.
* It set a timer to refresh cells values.
* It set a timer to refresh the contents of the editor.
*/
*/
componentDidMount() {
componentDidMount() {
this.timerID = setInterval(
this.timerID = setInterval(
() => {
() => {
this.props.session.transaction(client.utils.ConsistencyLevel.None, () => {
this.props.session.transaction(client.utils.ConsistencyLevel.None, () => {
this.setState({
let newvalue = this.rga.get().toArray().join("");
value: this.rga.get().toArray().join(""),
if (newvalue !== this.state.value) {
});
this.valueReceived(newvalue)
 
}
});
});
},
},
1000
1000
@@ -136,7 +209,7 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
@@ -136,7 +209,7 @@ export default class CMDEditor extends Component<CMDEditorProps, CMDEditorState>
*/
*/
render() {
render() {
return (
return (
<div>
<div ref={this.nodeRef}>
<div>Current document : {this.state.docName}</div>
<div>Current document : {this.state.docName}</div>
<Submit1Input inputName="Document" onSubmit={this.handleSubmit.bind(this)} /><br />
<Submit1Input inputName="Document" onSubmit={this.handleSubmit.bind(this)} /><br />
<MDEditor
<MDEditor
Loading