diff --git a/packages/edit-post/src/components/layout/index.native.js b/packages/edit-post/src/components/layout/index.native.js index 36250cf27eb96f..44bef0e3bec51b 100644 --- a/packages/edit-post/src/components/layout/index.native.js +++ b/packages/edit-post/src/components/layout/index.native.js @@ -12,6 +12,7 @@ import { Component } from '@wordpress/element'; import { withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import { HTMLTextInput, KeyboardAvoidingView, ReadableContentView, withTheme } from '@wordpress/components'; +import { AutosaveMonitor } from '@wordpress/editor'; /** * Internal dependencies @@ -116,6 +117,7 @@ class Layout extends Component { return ( + { isHtmlView ? this.renderHTML() : this.renderVisual() } diff --git a/packages/editor/src/components/index.native.js b/packages/editor/src/components/index.native.js index 69035455d49f13..45156604efe6f4 100644 --- a/packages/editor/src/components/index.native.js +++ b/packages/editor/src/components/index.native.js @@ -1,5 +1,6 @@ // Post Related Components +export { default as AutosaveMonitor } from './autosave-monitor'; export { default as PostTitle } from './post-title'; export { default as EditorHistoryRedo } from './editor-history/redo'; export { default as EditorHistoryUndo } from './editor-history/undo'; diff --git a/packages/editor/src/store/actions.native.js b/packages/editor/src/store/actions.native.js index 51741ac9bc3b44..17733a0e47b408 100644 --- a/packages/editor/src/store/actions.native.js +++ b/packages/editor/src/store/actions.native.js @@ -1,3 +1,7 @@ +/** + * External dependencies + */ +import RNReactNativeGutenbergBridge from 'react-native-gutenberg-bridge'; export * from './actions.js'; @@ -14,3 +18,12 @@ export function togglePostTitleSelection( isSelected = true ) { isSelected, }; } + +/** + * Action generator used in signalling that the post should autosave. + * + * @param {Object?} options Extra flags to identify the autosave. + */ +export function* autosave( ) { + RNReactNativeGutenbergBridge.editorDidAutosave(); +} diff --git a/packages/editor/src/store/reducer.native.js b/packages/editor/src/store/reducer.native.js index 82b3689a98ead0..0c2c4e7d24e704 100644 --- a/packages/editor/src/store/reducer.native.js +++ b/packages/editor/src/store/reducer.native.js @@ -26,6 +26,10 @@ import { editorSettings, } from './reducer.js'; +import { EDITOR_SETTINGS_DEFAULTS } from './defaults.js'; + +EDITOR_SETTINGS_DEFAULTS.autosaveInterval = 2; // This is a way to override default on mobile + export * from './reducer.js'; /** diff --git a/packages/editor/src/store/selectors.native.js b/packages/editor/src/store/selectors.native.js index 8c6ead8e97ba2f..ae84e7b5afe5a1 100644 --- a/packages/editor/src/store/selectors.native.js +++ b/packages/editor/src/store/selectors.native.js @@ -1,3 +1,16 @@ +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { + isEditedPostDirty, + isEditedPostSaveable, + hasChangedContent, +} from './selectors.js'; export * from './selectors.js'; @@ -11,3 +24,32 @@ export * from './selectors.js'; export function isPostTitleSelected( state ) { return state.postTitle.isSelected; } + +/** + * Returns true if the post can be autosaved, or false otherwise. + * + * @param {Object} state Global application state. + * @param {Object} autosave A raw autosave object from the REST API. + * + * @return {boolean} Whether the post can be autosaved. + */ +export const isEditedPostAutosaveable = createRegistrySelector( ( ) => function( state ) { + // A post must contain a title, an excerpt, or non-empty content to be valid for autosaving. + if ( ! isEditedPostSaveable( state ) ) { + return false; + } + + // To avoid an expensive content serialization, use the content dirtiness + // flag in place of content field comparison against the known autosave. + // This is not strictly accurate, and relies on a tolerance toward autosave + // request failures for unnecessary saves. + if ( hasChangedContent( state ) ) { + return true; + } + + if ( isEditedPostDirty( state ) ) { + return true; + } + + return false; +} ); diff --git a/test/native/setup.js b/test/native/setup.js index c0e3e0942a9180..f34947ed9958c0 100644 --- a/test/native/setup.js +++ b/test/native/setup.js @@ -14,6 +14,7 @@ jest.mock( 'react-native-gutenberg-bridge', () => { subscribeUpdateHtml: jest.fn(), subscribeMediaAppend: jest.fn(), editorDidMount: jest.fn(), + editorDidAutosave: jest.fn(), subscribeMediaUpload: jest.fn(), requestMediaPickFromMediaLibrary: jest.fn(), requestMediaPickFromDeviceLibrary: jest.fn(),