-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed-schedule AutosaveMonitor #23962
Changes from all commits
be271b3
27315d7
6bc161e
9d9d47a
384d321
5ea86aa
993077e
5fc2211
b763c19
c059ef3
a54ccec
83e78bd
dcc4549
e117434
c109577
025de0f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,63 +6,53 @@ import { compose } from '@wordpress/compose'; | |
import { withSelect, withDispatch } from '@wordpress/data'; | ||
|
||
export class AutosaveMonitor extends Component { | ||
componentDidUpdate( prevProps ) { | ||
const { | ||
isDirty, | ||
editsReference, | ||
isAutosaveable, | ||
isAutosaving, | ||
} = this.props; | ||
constructor( props ) { | ||
super( props ); | ||
this.needsAutosave = !! ( props.isDirty && props.isAutosaveable ); | ||
} | ||
|
||
// The edits reference is held for comparison to avoid scheduling an | ||
// autosave if an edit has not been made since the last autosave | ||
// completion. This is assigned when the autosave completes, and reset | ||
// when an edit occurs. | ||
// | ||
// See: https://github.com/WordPress/gutenberg/issues/12318 | ||
componentDidMount() { | ||
this.setAutosaveTimer(); | ||
} | ||
|
||
if ( editsReference !== prevProps.editsReference ) { | ||
this.didAutosaveForEditsReference = false; | ||
componentDidUpdate( prevProps ) { | ||
if ( ! this.props.isDirty && prevProps.isDirty ) { | ||
this.needsAutosave = false; | ||
return; | ||
} | ||
|
||
if ( ! isAutosaving && prevProps.isAutosaving ) { | ||
this.didAutosaveForEditsReference = true; | ||
if ( this.props.isAutosaving && ! prevProps.isAutosaving ) { | ||
this.needsAutosave = false; | ||
return; | ||
} | ||
|
||
if ( | ||
prevProps.isDirty !== isDirty || | ||
prevProps.isAutosaveable !== isAutosaveable || | ||
prevProps.editsReference !== editsReference | ||
) { | ||
this.toggleTimer( | ||
isDirty && isAutosaveable && ! this.didAutosaveForEditsReference | ||
); | ||
if ( this.props.editsReference !== prevProps.editsReference ) { | ||
this.needsAutosave = true; | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
this.toggleTimer( false ); | ||
clearTimeout( this.timerId ); | ||
} | ||
|
||
toggleTimer( isPendingSave ) { | ||
const { interval, shouldThrottle = false } = this.props; | ||
setAutosaveTimer( timeout = this.props.interval * 1000 ) { | ||
this.timerId = setTimeout( () => { | ||
this.autosaveTimerHandler(); | ||
}, timeout ); | ||
} | ||
|
||
// By default, AutosaveMonitor will wait for a pause in editing before | ||
// autosaving. In other words, its action is "debounced". | ||
// | ||
// The `shouldThrottle` props allows overriding this behaviour, thus | ||
// making the autosave action "throttled". | ||
if ( ! shouldThrottle && this.pendingSave ) { | ||
clearTimeout( this.pendingSave ); | ||
delete this.pendingSave; | ||
autosaveTimerHandler() { | ||
if ( ! this.props.isAutosaveable ) { | ||
this.setAutosaveTimer( 1000 ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this fixed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be either A case for
A case for
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, no bug, just looked weird. I was working on something unrelated requiring disabling autosave when I found it. Thanks for the explanation, it makes sense. |
||
return; | ||
} | ||
|
||
if ( isPendingSave && ! ( shouldThrottle && this.pendingSave ) ) { | ||
this.pendingSave = setTimeout( () => { | ||
this.props.autosave(); | ||
delete this.pendingSave; | ||
}, interval * 1000 ); | ||
if ( this.needsAutosave ) { | ||
this.needsAutosave = false; | ||
this.props.autosave(); | ||
} | ||
|
||
this.setAutosaveTimer(); | ||
} | ||
|
||
render() { | ||
|
@@ -84,9 +74,9 @@ export default compose( [ | |
const { interval = getEditorSettings().autosaveInterval } = ownProps; | ||
|
||
return { | ||
editsReference: getReferenceByDistinctEdits(), | ||
isDirty: isEditedPostDirty(), | ||
isAutosaveable: isEditedPostAutosaveable(), | ||
editsReference: getReferenceByDistinctEdits(), | ||
isAutosaving: isAutosavingPost(), | ||
interval, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this change the selector is not being updated in response to continued typing within the same paragraph block. This means the AutosaveMonitor is unaware of unsaved edits. It seems like a bug to me but I'm curious about your thoughts @youknowriad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, it's a weird way to detect dirtiness though, I wonder if the component should rely on
__experimentalGetDirtyEntityRecords
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a weird way. I suppose it was invented to account for the fact that autosaving doesn't make the post "not dirty" which also affects the
isDirty
prop this component receives. I just tested and the same is true for__experimentalGetDirtyEntityRecords
- after an autosave completes, it still returns a non-empty list.