matrix-react-sdk
Version:
SDK for matrix.org using React
143 lines (137 loc) • 17.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.MAX_STEP_LENGTH = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2019 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
const MAX_STEP_LENGTH = exports.MAX_STEP_LENGTH = 10;
class HistoryManager {
constructor() {
(0, _defineProperty2.default)(this, "stack", []);
(0, _defineProperty2.default)(this, "newlyTypedCharCount", 0);
(0, _defineProperty2.default)(this, "currentIndex", -1);
(0, _defineProperty2.default)(this, "changedSinceLastPush", false);
(0, _defineProperty2.default)(this, "lastCaret", void 0);
(0, _defineProperty2.default)(this, "nonWordBoundarySinceLastPush", false);
(0, _defineProperty2.default)(this, "addedSinceLastPush", false);
(0, _defineProperty2.default)(this, "removedSinceLastPush", false);
}
clear() {
this.stack = [];
this.newlyTypedCharCount = 0;
this.currentIndex = -1;
this.changedSinceLastPush = false;
this.lastCaret = undefined;
this.nonWordBoundarySinceLastPush = false;
this.addedSinceLastPush = false;
this.removedSinceLastPush = false;
}
shouldPush(inputType, diff) {
// right now we can only push a step after
// the input has been applied to the model,
// so we can't push the state before something happened.
// not ideal but changing this would be harder to fit cleanly into
// the editor model.
const isNonBulkInput = inputType === "insertText" || inputType === "deleteContentForward" || inputType === "deleteContentBackward";
if (diff && isNonBulkInput) {
if (diff.added) {
this.addedSinceLastPush = true;
}
if (diff.removed) {
this.removedSinceLastPush = true;
}
// as long as you've only been adding or removing since the last push
if (this.addedSinceLastPush !== this.removedSinceLastPush) {
// add steps by word boundary, up to MAX_STEP_LENGTH characters
const str = diff.added ? diff.added : diff.removed;
const isWordBoundary = str === " " || str === "\t" || str === "\n";
if (this.nonWordBoundarySinceLastPush && isWordBoundary) {
return true;
}
if (!isWordBoundary) {
this.nonWordBoundarySinceLastPush = true;
}
this.newlyTypedCharCount += str.length;
return this.newlyTypedCharCount > MAX_STEP_LENGTH;
} else {
// if starting to remove while adding before, or the opposite, push
return true;
}
} else {
// bulk input (paste, ...) should be pushed every time
return true;
}
}
pushState(model, caret) {
// remove all steps after current step
while (this.currentIndex < this.stack.length - 1) {
this.stack.pop();
}
const parts = model.serializeParts();
this.stack.push({
parts,
caret
});
this.currentIndex = this.stack.length - 1;
this.lastCaret = undefined;
this.changedSinceLastPush = false;
this.newlyTypedCharCount = 0;
this.nonWordBoundarySinceLastPush = false;
this.addedSinceLastPush = false;
this.removedSinceLastPush = false;
}
// needs to persist parts and caret position
tryPush(model, caret, inputType, diff) {
// ignore state restoration echos.
// these respect the inputType values of the input event,
// but are actually passed in from MessageEditor calling model.reset()
// in the keydown event handler.
if (inputType === "historyUndo" || inputType === "historyRedo") {
return false;
}
const shouldPush = this.shouldPush(inputType, diff);
if (shouldPush) {
this.pushState(model, caret);
} else {
this.lastCaret = caret;
this.changedSinceLastPush = true;
}
return shouldPush;
}
ensureLastChangesPushed(model) {
if (this.changedSinceLastPush && this.lastCaret) {
this.pushState(model, this.lastCaret);
}
}
canUndo() {
return this.currentIndex >= 1 || this.changedSinceLastPush;
}
canRedo() {
return this.currentIndex < this.stack.length - 1;
}
// returns state that should be applied to model
undo(model) {
if (this.canUndo()) {
this.ensureLastChangesPushed(model);
this.currentIndex -= 1;
return this.stack[this.currentIndex];
}
}
// returns state that should be applied to model
redo() {
if (this.canRedo()) {
this.changedSinceLastPush = false;
this.currentIndex += 1;
return this.stack[this.currentIndex];
}
}
}
exports.default = HistoryManager;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNQVhfU1RFUF9MRU5HVEgiLCJleHBvcnRzIiwiSGlzdG9yeU1hbmFnZXIiLCJjb25zdHJ1Y3RvciIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJkZWZhdWx0IiwiY2xlYXIiLCJzdGFjayIsIm5ld2x5VHlwZWRDaGFyQ291bnQiLCJjdXJyZW50SW5kZXgiLCJjaGFuZ2VkU2luY2VMYXN0UHVzaCIsImxhc3RDYXJldCIsInVuZGVmaW5lZCIsIm5vbldvcmRCb3VuZGFyeVNpbmNlTGFzdFB1c2giLCJhZGRlZFNpbmNlTGFzdFB1c2giLCJyZW1vdmVkU2luY2VMYXN0UHVzaCIsInNob3VsZFB1c2giLCJpbnB1dFR5cGUiLCJkaWZmIiwiaXNOb25CdWxrSW5wdXQiLCJhZGRlZCIsInJlbW92ZWQiLCJzdHIiLCJpc1dvcmRCb3VuZGFyeSIsImxlbmd0aCIsInB1c2hTdGF0ZSIsIm1vZGVsIiwiY2FyZXQiLCJwb3AiLCJwYXJ0cyIsInNlcmlhbGl6ZVBhcnRzIiwicHVzaCIsInRyeVB1c2giLCJlbnN1cmVMYXN0Q2hhbmdlc1B1c2hlZCIsImNhblVuZG8iLCJjYW5SZWRvIiwidW5kbyIsInJlZG8iXSwic291cmNlcyI6WyIuLi8uLi9zcmMvZWRpdG9yL2hpc3RvcnkudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cblxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFHUEwtMy4wLW9ubHkgT1IgR1BMLTMuMC1vbmx5XG5QbGVhc2Ugc2VlIExJQ0VOU0UgZmlsZXMgaW4gdGhlIHJlcG9zaXRvcnkgcm9vdCBmb3IgZnVsbCBkZXRhaWxzLlxuKi9cblxuaW1wb3J0IEVkaXRvck1vZGVsIGZyb20gXCIuL21vZGVsXCI7XG5pbXBvcnQgeyBJRGlmZiB9IGZyb20gXCIuL2RpZmZcIjtcbmltcG9ydCB7IFNlcmlhbGl6ZWRQYXJ0IH0gZnJvbSBcIi4vcGFydHNcIjtcbmltcG9ydCB7IENhcmV0IH0gZnJvbSBcIi4vY2FyZXRcIjtcblxuZXhwb3J0IGludGVyZmFjZSBJSGlzdG9yeSB7XG4gICAgcGFydHM6IFNlcmlhbGl6ZWRQYXJ0W107XG4gICAgY2FyZXQ/OiBDYXJldDtcbn1cblxuZXhwb3J0IGNvbnN0IE1BWF9TVEVQX0xFTkdUSCA9IDEwO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBIaXN0b3J5TWFuYWdlciB7XG4gICAgcHJpdmF0ZSBzdGFjazogSUhpc3RvcnlbXSA9IFtdO1xuICAgIHByaXZhdGUgbmV3bHlUeXBlZENoYXJDb3VudCA9IDA7XG4gICAgcHJpdmF0ZSBjdXJyZW50SW5kZXggPSAtMTtcbiAgICBwcml2YXRlIGNoYW5nZWRTaW5jZUxhc3RQdXNoID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBsYXN0Q2FyZXQ/OiBDYXJldDtcbiAgICBwcml2YXRlIG5vbldvcmRCb3VuZGFyeVNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICBwcml2YXRlIGFkZGVkU2luY2VMYXN0UHVzaCA9IGZhbHNlO1xuICAgIHByaXZhdGUgcmVtb3ZlZFNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjbGVhcigpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zdGFjayA9IFtdO1xuICAgICAgICB0aGlzLm5ld2x5VHlwZWRDaGFyQ291bnQgPSAwO1xuICAgICAgICB0aGlzLmN1cnJlbnRJbmRleCA9IC0xO1xuICAgICAgICB0aGlzLmNoYW5nZWRTaW5jZUxhc3RQdXNoID0gZmFsc2U7XG4gICAgICAgIHRoaXMubGFzdENhcmV0ID0gdW5kZWZpbmVkO1xuICAgICAgICB0aGlzLm5vbldvcmRCb3VuZGFyeVNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hZGRlZFNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW1vdmVkU2luY2VMYXN0UHVzaCA9IGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2hvdWxkUHVzaChpbnB1dFR5cGU/OiBzdHJpbmcsIGRpZmY/OiBJRGlmZik6IGJvb2xlYW4ge1xuICAgICAgICAvLyByaWdodCBub3cgd2UgY2FuIG9ubHkgcHVzaCBhIHN0ZXAgYWZ0ZXJcbiAgICAgICAgLy8gdGhlIGlucHV0IGhhcyBiZWVuIGFwcGxpZWQgdG8gdGhlIG1vZGVsLFxuICAgICAgICAvLyBzbyB3ZSBjYW4ndCBwdXNoIHRoZSBzdGF0ZSBiZWZvcmUgc29tZXRoaW5nIGhhcHBlbmVkLlxuICAgICAgICAvLyBub3QgaWRlYWwgYnV0IGNoYW5naW5nIHRoaXMgd291bGQgYmUgaGFyZGVyIHRvIGZpdCBjbGVhbmx5IGludG9cbiAgICAgICAgLy8gdGhlIGVkaXRvciBtb2RlbC5cbiAgICAgICAgY29uc3QgaXNOb25CdWxrSW5wdXQgPVxuICAgICAgICAgICAgaW5wdXRUeXBlID09PSBcImluc2VydFRleHRcIiB8fCBpbnB1dFR5cGUgPT09IFwiZGVsZXRlQ29udGVudEZvcndhcmRcIiB8fCBpbnB1dFR5cGUgPT09IFwiZGVsZXRlQ29udGVudEJhY2t3YXJkXCI7XG4gICAgICAgIGlmIChkaWZmICYmIGlzTm9uQnVsa0lucHV0KSB7XG4gICAgICAgICAgICBpZiAoZGlmZi5hZGRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkZWRTaW5jZUxhc3RQdXNoID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChkaWZmLnJlbW92ZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZWRTaW5jZUxhc3RQdXNoID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGFzIGxvbmcgYXMgeW91J3ZlIG9ubHkgYmVlbiBhZGRpbmcgb3IgcmVtb3Zpbmcgc2luY2UgdGhlIGxhc3QgcHVzaFxuICAgICAgICAgICAgaWYgKHRoaXMuYWRkZWRTaW5jZUxhc3RQdXNoICE9PSB0aGlzLnJlbW92ZWRTaW5jZUxhc3RQdXNoKSB7XG4gICAgICAgICAgICAgICAgLy8gYWRkIHN0ZXBzIGJ5IHdvcmQgYm91bmRhcnksIHVwIHRvIE1BWF9TVEVQX0xFTkdUSCBjaGFyYWN0ZXJzXG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gZGlmZi5hZGRlZCA/IGRpZmYuYWRkZWQgOiBkaWZmLnJlbW92ZWQhO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlzV29yZEJvdW5kYXJ5ID0gc3RyID09PSBcIiBcIiB8fCBzdHIgPT09IFwiXFx0XCIgfHwgc3RyID09PSBcIlxcblwiO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm5vbldvcmRCb3VuZGFyeVNpbmNlTGFzdFB1c2ggJiYgaXNXb3JkQm91bmRhcnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghaXNXb3JkQm91bmRhcnkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ub25Xb3JkQm91bmRhcnlTaW5jZUxhc3RQdXNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5uZXdseVR5cGVkQ2hhckNvdW50ICs9IHN0ci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmV3bHlUeXBlZENoYXJDb3VudCA+IE1BWF9TVEVQX0xFTkdUSDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgc3RhcnRpbmcgdG8gcmVtb3ZlIHdoaWxlIGFkZGluZyBiZWZvcmUsIG9yIHRoZSBvcHBvc2l0ZSwgcHVzaFxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gYnVsayBpbnB1dCAocGFzdGUsIC4uLikgc2hvdWxkIGJlIHB1c2hlZCBldmVyeSB0aW1lXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgcHVzaFN0YXRlKG1vZGVsOiBFZGl0b3JNb2RlbCwgY2FyZXQ/OiBDYXJldCk6IHZvaWQge1xuICAgICAgICAvLyByZW1vdmUgYWxsIHN0ZXBzIGFmdGVyIGN1cnJlbnQgc3RlcFxuICAgICAgICB3aGlsZSAodGhpcy5jdXJyZW50SW5kZXggPCB0aGlzLnN0YWNrLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHRoaXMuc3RhY2sucG9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGFydHMgPSBtb2RlbC5zZXJpYWxpemVQYXJ0cygpO1xuICAgICAgICB0aGlzLnN0YWNrLnB1c2goeyBwYXJ0cywgY2FyZXQgfSk7XG4gICAgICAgIHRoaXMuY3VycmVudEluZGV4ID0gdGhpcy5zdGFjay5sZW5ndGggLSAxO1xuICAgICAgICB0aGlzLmxhc3RDYXJldCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5jaGFuZ2VkU2luY2VMYXN0UHVzaCA9IGZhbHNlO1xuICAgICAgICB0aGlzLm5ld2x5VHlwZWRDaGFyQ291bnQgPSAwO1xuICAgICAgICB0aGlzLm5vbldvcmRCb3VuZGFyeVNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5hZGRlZFNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZW1vdmVkU2luY2VMYXN0UHVzaCA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8vIG5lZWRzIHRvIHBlcnNpc3QgcGFydHMgYW5kIGNhcmV0IHBvc2l0aW9uXG4gICAgcHVibGljIHRyeVB1c2gobW9kZWw6IEVkaXRvck1vZGVsLCBjYXJldD86IENhcmV0LCBpbnB1dFR5cGU/OiBzdHJpbmcsIGRpZmY/OiBJRGlmZik6IGJvb2xlYW4ge1xuICAgICAgICAvLyBpZ25vcmUgc3RhdGUgcmVzdG9yYXRpb24gZWNob3MuXG4gICAgICAgIC8vIHRoZXNlIHJlc3BlY3QgdGhlIGlucHV0VHlwZSB2YWx1ZXMgb2YgdGhlIGlucHV0IGV2ZW50LFxuICAgICAgICAvLyBidXQgYXJlIGFjdHVhbGx5IHBhc3NlZCBpbiBmcm9tIE1lc3NhZ2VFZGl0b3IgY2FsbGluZyBtb2RlbC5yZXNldCgpXG4gICAgICAgIC8vIGluIHRoZSBrZXlkb3duIGV2ZW50IGhhbmRsZXIuXG4gICAgICAgIGlmIChpbnB1dFR5cGUgPT09IFwiaGlzdG9yeVVuZG9cIiB8fCBpbnB1dFR5cGUgPT09IFwiaGlzdG9yeVJlZG9cIikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNob3VsZFB1c2ggPSB0aGlzLnNob3VsZFB1c2goaW5wdXRUeXBlLCBkaWZmKTtcbiAgICAgICAgaWYgKHNob3VsZFB1c2gpIHtcbiAgICAgICAgICAgIHRoaXMucHVzaFN0YXRlKG1vZGVsLCBjYXJldCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmxhc3RDYXJldCA9IGNhcmV0O1xuICAgICAgICAgICAgdGhpcy5jaGFuZ2VkU2luY2VMYXN0UHVzaCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNob3VsZFB1c2g7XG4gICAgfVxuXG4gICAgcHVibGljIGVuc3VyZUxhc3RDaGFuZ2VzUHVzaGVkKG1vZGVsOiBFZGl0b3JNb2RlbCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5jaGFuZ2VkU2luY2VMYXN0UHVzaCAmJiB0aGlzLmxhc3RDYXJldCkge1xuICAgICAgICAgICAgdGhpcy5wdXNoU3RhdGUobW9kZWwsIHRoaXMubGFzdENhcmV0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBjYW5VbmRvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50SW5kZXggPj0gMSB8fCB0aGlzLmNoYW5nZWRTaW5jZUxhc3RQdXNoO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5SZWRvKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jdXJyZW50SW5kZXggPCB0aGlzLnN0YWNrLmxlbmd0aCAtIDE7XG4gICAgfVxuXG4gICAgLy8gcmV0dXJucyBzdGF0ZSB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIHRvIG1vZGVsXG4gICAgcHVibGljIHVuZG8obW9kZWw6IEVkaXRvck1vZGVsKTogSUhpc3RvcnkgfCB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY2FuVW5kbygpKSB7XG4gICAgICAgICAgICB0aGlzLmVuc3VyZUxhc3RDaGFuZ2VzUHVzaGVkKG1vZGVsKTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEluZGV4IC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFja1t0aGlzLmN1cnJlbnRJbmRleF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZXR1cm5zIHN0YXRlIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgdG8gbW9kZWxcbiAgICBwdWJsaWMgcmVkbygpOiBJSGlzdG9yeSB8IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5jYW5SZWRvKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2hhbmdlZFNpbmNlTGFzdFB1c2ggPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudEluZGV4ICs9IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFja1t0aGlzLmN1cnJlbnRJbmRleF07XG4gICAgICAgIH1cbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBWU8sTUFBTUEsZUFBZSxHQUFBQyxPQUFBLENBQUFELGVBQUEsR0FBRyxFQUFFO0FBRWxCLE1BQU1FLGNBQWMsQ0FBQztFQUFBQyxZQUFBO0lBQUEsSUFBQUMsZ0JBQUEsQ0FBQUMsT0FBQSxpQkFDSixFQUFFO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQSwrQkFDQSxDQUFDO0lBQUEsSUFBQUQsZ0JBQUEsQ0FBQUMsT0FBQSx3QkFDUixDQUFDLENBQUM7SUFBQSxJQUFBRCxnQkFBQSxDQUFBQyxPQUFBLGdDQUNNLEtBQUs7SUFBQSxJQUFBRCxnQkFB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