(
before: InputEditorSnapshot,
after: InputEditorSnapshot,
timestamp: number,
groupable = false,
)
| 508 | private readonly redo: InputUndoEntry[] = []; |
| 509 | |
| 510 | push( |
| 511 | before: InputEditorSnapshot, |
| 512 | after: InputEditorSnapshot, |
| 513 | timestamp: number, |
| 514 | groupable = false, |
| 515 | ): void { |
| 516 | if ( |
| 517 | before.value === after.value && |
| 518 | before.cursor === after.cursor && |
| 519 | before.selectionStart === after.selectionStart && |
| 520 | before.selectionEnd === after.selectionEnd |
| 521 | ) { |
| 522 | return; |
| 523 | } |
| 524 | |
| 525 | const t = Number.isFinite(timestamp) ? Math.trunc(timestamp) : 0; |
| 526 | const last = this.undo[this.undo.length - 1]; |
| 527 | if ( |
| 528 | groupable && |
| 529 | last && |
| 530 | last.groupable && |
| 531 | t - last.timestamp <= INPUT_UNDO_GROUP_WINDOW_MS && |
| 532 | t >= last.timestamp |
| 533 | ) { |
| 534 | this.undo[this.undo.length - 1] = Object.freeze({ |
| 535 | before: last.before, |
| 536 | after, |
| 537 | timestamp: t, |
| 538 | groupable: true, |
| 539 | }); |
| 540 | this.redo.length = 0; |
| 541 | return; |
| 542 | } |
| 543 | |
| 544 | this.undo.push( |
| 545 | Object.freeze({ |
| 546 | before, |
| 547 | after, |
| 548 | timestamp: t, |
| 549 | groupable, |
| 550 | }), |
| 551 | ); |
| 552 | if (this.undo.length > INPUT_UNDO_STACK_CAP) this.undo.shift(); |
| 553 | this.redo.length = 0; |
| 554 | } |
| 555 | |
| 556 | undoSnapshot(): InputEditorSnapshot | null { |
| 557 | const entry = this.undo.pop(); |
no outgoing calls