mirror of https://github.com/vector-im/riot-web
add transform step during editor model update
parent
0e65f71a37
commit
f8f0e77bde
|
@ -19,6 +19,15 @@ import {diffAtCaret, diffDeletion} from "./diff";
|
|||
import DocumentPosition from "./position";
|
||||
import Range from "./range";
|
||||
|
||||
/**
|
||||
* @callback TransformCallback
|
||||
* @param {DocumentPosition?} caretPosition the position where the caret should be position
|
||||
* @param {string?} inputType the inputType of the DOM input event
|
||||
* @param {object?} diff an object with `removed` and `added` strings
|
||||
* @return {Number?} addedLen how many characters were added/removed (-) before the caret during the transformation step.
|
||||
This is used to adjust the caret position.
|
||||
*/
|
||||
|
||||
export default class EditorModel {
|
||||
constructor(parts, partCreator, updateCallback = null) {
|
||||
this._parts = parts;
|
||||
|
@ -26,7 +35,19 @@ export default class EditorModel {
|
|||
this._activePartIdx = null;
|
||||
this._autoComplete = null;
|
||||
this._autoCompletePartIdx = null;
|
||||
this._transformCallback = null;
|
||||
this.setUpdateCallback(updateCallback);
|
||||
this._updateInProgress = false;
|
||||
}
|
||||
|
||||
/** Set a callback for the transformation step.
|
||||
* While processing an update, right before calling the update callback,
|
||||
* a transform callback can be called, which serves to do modifications
|
||||
* on the model that can span multiple parts. Also see `startRange()`.
|
||||
* @param {TransformCallback} transformCallback
|
||||
*/
|
||||
setTransformCallback(transformCallback) {
|
||||
this._transformCallback = transformCallback;
|
||||
}
|
||||
|
||||
setUpdateCallback(updateCallback) {
|
||||
|
@ -133,6 +154,7 @@ export default class EditorModel {
|
|||
}
|
||||
|
||||
update(newValue, inputType, caret) {
|
||||
this._updateInProgress = true;
|
||||
const diff = this._diff(newValue, inputType, caret);
|
||||
const position = this.positionForOffset(diff.at, caret.atNodeEnd);
|
||||
let removedOffsetDecrease = 0;
|
||||
|
@ -147,11 +169,23 @@ export default class EditorModel {
|
|||
}
|
||||
this._mergeAdjacentParts();
|
||||
const caretOffset = diff.at - removedOffsetDecrease + addedLen;
|
||||
const newPosition = this.positionForOffset(caretOffset, true);
|
||||
let newPosition = this.positionForOffset(caretOffset, true);
|
||||
this._setActivePart(newPosition, canOpenAutoComplete);
|
||||
if (this._transformCallback) {
|
||||
const transformAddedLen = this._transform(newPosition, inputType, diff);
|
||||
if (transformAddedLen !== 0) {
|
||||
newPosition = this.positionForOffset(caretOffset + transformAddedLen, true);
|
||||
}
|
||||
}
|
||||
this._updateInProgress = false;
|
||||
this._updateCallback(newPosition, inputType, diff);
|
||||
}
|
||||
|
||||
_transform(newPosition, inputType, diff) {
|
||||
const result = this._transformCallback(newPosition, inputType, diff);
|
||||
return Number.isFinite(result) ? result : 0;
|
||||
}
|
||||
|
||||
_setActivePart(pos, canOpenAutoComplete) {
|
||||
const {index} = pos;
|
||||
const part = this._parts[index];
|
||||
|
@ -367,6 +401,8 @@ export default class EditorModel {
|
|||
insertIdx += 1;
|
||||
}
|
||||
this._mergeAdjacentParts();
|
||||
this._updateCallback();
|
||||
if (!this._updateInProgress) {
|
||||
this._updateCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue