-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
index.js
133 lines (115 loc) · 3.79 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';
/**
* Internal dependencies
*/
import { store as editorStore } from '../../store';
export class AutosaveMonitor extends Component {
constructor( props ) {
super( props );
this.needsAutosave = !! ( props.isDirty && props.isAutosaveable );
}
componentDidMount() {
if ( ! this.props.disableIntervalChecks ) {
this.setAutosaveTimer();
}
}
componentDidUpdate( prevProps ) {
if ( this.props.disableIntervalChecks ) {
if ( this.props.editsReference !== prevProps.editsReference ) {
this.props.autosave();
}
return;
}
if ( this.props.interval !== prevProps.interval ) {
clearTimeout( this.timerId );
this.setAutosaveTimer();
}
if ( ! this.props.isDirty ) {
this.needsAutosave = false;
return;
}
if ( this.props.isAutosaving && ! prevProps.isAutosaving ) {
this.needsAutosave = false;
return;
}
if ( this.props.editsReference !== prevProps.editsReference ) {
this.needsAutosave = true;
}
}
componentWillUnmount() {
clearTimeout( this.timerId );
}
setAutosaveTimer( timeout = this.props.interval * 1000 ) {
this.timerId = setTimeout( () => {
this.autosaveTimerHandler();
}, timeout );
}
autosaveTimerHandler() {
if ( ! this.props.isAutosaveable ) {
this.setAutosaveTimer( 1000 );
return;
}
if ( this.needsAutosave ) {
this.needsAutosave = false;
this.props.autosave();
}
this.setAutosaveTimer();
}
render() {
return null;
}
}
/**
* Monitors the changes made to the edited post and triggers autosave if necessary.
*
* The logic is straightforward: a check is performed every `props.interval` seconds. If any changes are detected, `props.autosave()` is called.
* The time between the change and the autosave varies but is no larger than `props.interval` seconds. Refer to the code below for more details, such as
* the specific way of detecting changes.
*
* There are two caveats:
* * If `props.isAutosaveable` happens to be false at a time of checking for changes, the check is retried every second.
* * The timer may be disabled by setting `props.disableIntervalChecks` to `true`. In that mode, any change will immediately trigger `props.autosave()`.
*
* @param {Object} props - The properties passed to the component.
* @param {Function} props.autosave - The function to call when changes need to be saved.
* @param {number} props.interval - The maximum time in seconds between an unsaved change and an autosave.
* @param {boolean} props.isAutosaveable - If false, the check for changes is retried every second.
* @param {boolean} props.disableIntervalChecks - If true, disables the timer and any change will immediately trigger `props.autosave()`.
* @param {boolean} props.isDirty - Indicates if there are unsaved changes.
*
* @example
* ```jsx
* <AutosaveMonitor interval={30000} />
* ```
*/
export default compose( [
withSelect( ( select, ownProps ) => {
const { getReferenceByDistinctEdits } = select( coreStore );
const {
isEditedPostDirty,
isEditedPostAutosaveable,
isAutosavingPost,
getEditorSettings,
} = select( editorStore );
const { interval = getEditorSettings().autosaveInterval } = ownProps;
return {
editsReference: getReferenceByDistinctEdits(),
isDirty: isEditedPostDirty(),
isAutosaveable: isEditedPostAutosaveable(),
isAutosaving: isAutosavingPost(),
interval,
};
} ),
withDispatch( ( dispatch, ownProps ) => ( {
autosave() {
const { autosave = dispatch( editorStore ).autosave } = ownProps;
autosave();
},
} ) ),
] )( AutosaveMonitor );