0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2025-01-03 05:00:13 -05:00

Limit the undo stack size

Add an undo configuration.
If the document is larger than the configured threshold, then limit the
number of undo states that can be saved to the configured amount.
Defaults to no limit.

Merged for #200
This commit is contained in:
Andy Kauffman 2016-05-31 15:26:22 -04:00 committed by Neil Jenkins
parent bd4d377cf0
commit 8eea926e2b
3 changed files with 66 additions and 10 deletions

View file

@ -2435,6 +2435,10 @@ proto.setConfig = function ( config ) {
ol: null, ol: null,
li: null, li: null,
a: null a: null
},
undo: {
documentSizeThreshold: -1, // -1 means no threshold
undoLimit: -1 // -1 means no limit
} }
}, config ); }, config );
@ -2531,6 +2535,7 @@ proto.destroy = function () {
var l = instances.length; var l = instances.length;
var events = this._events; var events = this._events;
var type; var type;
for ( type in events ) { for ( type in events ) {
this.removeEventListener( type ); this.removeEventListener( type );
} }
@ -2542,6 +2547,11 @@ proto.destroy = function () {
instances.splice( l, 1 ); instances.splice( l, 1 );
} }
} }
// Destroy undo stack
this._undoIndex = -1;
this._undoStack = [];
this._undoStackLength = 0;
}; };
proto.handleEvent = function ( event ) { proto.handleEvent = function ( event ) {
@ -2974,19 +2984,37 @@ proto._recordUndoState = function ( range ) {
// Don't record if we're already in an undo state // Don't record if we're already in an undo state
if ( !this._isInUndoState ) { if ( !this._isInUndoState ) {
// Advance pointer to new position // Advance pointer to new position
var undoIndex = this._undoIndex += 1, var undoIndex = this._undoIndex += 1;
undoStack = this._undoStack; var undoStack = this._undoStack;
var undoConfig = this._config.undo;
var undoThreshold = undoConfig.documentSizeThreshold;
var undoLimit = undoConfig.undoLimit;
var html;
// Truncate stack if longer (i.e. if has been previously undone) // Truncate stack if longer (i.e. if has been previously undone)
if ( undoIndex < this._undoStackLength ) { if ( undoIndex < this._undoStackLength ) {
undoStack.length = this._undoStackLength = undoIndex; undoStack.length = this._undoStackLength = undoIndex;
} }
// Write out data // Get data
if ( range ) { if ( range ) {
this._saveRangeToBookmark( range ); this._saveRangeToBookmark( range );
} }
undoStack[ undoIndex ] = this._getHTML(); html = this._getHTML();
// If this document is above the configured size threshold,
// limit the number of saved undo states.
// Threshold is in bytes, JS uses 2 bytes per character
if ( undoThreshold > -1 && html.length * 2 > undoThreshold ) {
if ( undoLimit > -1 && undoIndex > undoLimit ) {
undoStack.splice( 0, undoIndex - undoLimit );
undoIndex = this._undoIndex = undoLimit;
this._undoStackLength = undoLimit;
}
}
// Save data
undoStack[ undoIndex ] = html;
this._undoStackLength += 1; this._undoStackLength += 1;
this._isInUndoState = true; this._isInUndoState = true;
} }

File diff suppressed because one or more lines are too long

View file

@ -167,6 +167,10 @@ proto.setConfig = function ( config ) {
ol: null, ol: null,
li: null, li: null,
a: null a: null
},
undo: {
documentSizeThreshold: -1, // -1 means no threshold
undoLimit: -1 // -1 means no limit
} }
}, config ); }, config );
@ -263,6 +267,7 @@ proto.destroy = function () {
var l = instances.length; var l = instances.length;
var events = this._events; var events = this._events;
var type; var type;
for ( type in events ) { for ( type in events ) {
this.removeEventListener( type ); this.removeEventListener( type );
} }
@ -274,6 +279,11 @@ proto.destroy = function () {
instances.splice( l, 1 ); instances.splice( l, 1 );
} }
} }
// Destroy undo stack
this._undoIndex = -1;
this._undoStack = [];
this._undoStackLength = 0;
}; };
proto.handleEvent = function ( event ) { proto.handleEvent = function ( event ) {
@ -706,19 +716,37 @@ proto._recordUndoState = function ( range ) {
// Don't record if we're already in an undo state // Don't record if we're already in an undo state
if ( !this._isInUndoState ) { if ( !this._isInUndoState ) {
// Advance pointer to new position // Advance pointer to new position
var undoIndex = this._undoIndex += 1, var undoIndex = this._undoIndex += 1;
undoStack = this._undoStack; var undoStack = this._undoStack;
var undoConfig = this._config.undo;
var undoThreshold = undoConfig.documentSizeThreshold;
var undoLimit = undoConfig.undoLimit;
var html;
// Truncate stack if longer (i.e. if has been previously undone) // Truncate stack if longer (i.e. if has been previously undone)
if ( undoIndex < this._undoStackLength ) { if ( undoIndex < this._undoStackLength ) {
undoStack.length = this._undoStackLength = undoIndex; undoStack.length = this._undoStackLength = undoIndex;
} }
// Write out data // Get data
if ( range ) { if ( range ) {
this._saveRangeToBookmark( range ); this._saveRangeToBookmark( range );
} }
undoStack[ undoIndex ] = this._getHTML(); html = this._getHTML();
// If this document is above the configured size threshold,
// limit the number of saved undo states.
// Threshold is in bytes, JS uses 2 bytes per character
if ( undoThreshold > -1 && html.length * 2 > undoThreshold ) {
if ( undoLimit > -1 && undoIndex > undoLimit ) {
undoStack.splice( 0, undoIndex - undoLimit );
undoIndex = this._undoIndex = undoLimit;
this._undoStackLength = undoLimit;
}
}
// Save data
undoStack[ undoIndex ] = html;
this._undoStackLength += 1; this._undoStackLength += 1;
this._isInUndoState = true; this._isInUndoState = true;
} }