Skip to content

Commit

Permalink
Prevent content loss after refreshing an editor with unsaved auto-dra…
Browse files Browse the repository at this point in the history
…ft post (#23928)

* Add isPostNew flag to localAutosaveGet/localAutosaveSet/localAutosaveClear to make them work with brand new unsaved posts

* Clear the autosave storage once auto-draft is saved

* Move cache eviction to useAutosavePurge
  • Loading branch information
adamziel authored Jul 17, 2020
1 parent 6dba4c0 commit 95e4f3f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 19 deletions.
36 changes: 29 additions & 7 deletions packages/editor/src/components/local-autosave-monitor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { once, uniqueId, omit } from 'lodash';
* WordPress dependencies
*/
import { useCallback, useEffect, useRef } from '@wordpress/element';
import { ifCondition } from '@wordpress/compose';
import { ifCondition, usePrevious } from '@wordpress/compose';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { parse } from '@wordpress/blocks';
Expand Down Expand Up @@ -45,9 +45,15 @@ const hasSessionStorageSupport = once( () => {
* restore a local autosave, if one exists.
*/
function useAutosaveNotice() {
const { postId, getEditedPostAttribute, hasRemoteAutosave } = useSelect(
const {
postId,
isEditedPostNew,
getEditedPostAttribute,
hasRemoteAutosave,
} = useSelect(
( select ) => ( {
postId: select( 'core/editor' ).getCurrentPostId(),
isEditedPostNew: select( 'core/editor' ).isEditedPostNew(),
getEditedPostAttribute: select( 'core/editor' )
.getEditedPostAttribute,
hasRemoteAutosave: !! select( 'core/editor' ).getEditorSettings()
Expand All @@ -60,7 +66,7 @@ function useAutosaveNotice() {
const { editPost, resetEditorBlocks } = useDispatch( 'core/editor' );

useEffect( () => {
let localAutosave = localAutosaveGet( postId );
let localAutosave = localAutosaveGet( postId, isEditedPostNew );
if ( ! localAutosave ) {
return;
}
Expand All @@ -84,7 +90,7 @@ function useAutosaveNotice() {

if ( ! hasDifference ) {
// If there is no difference, it can be safely ejected from storage.
localAutosaveClear( postId );
localAutosaveClear( postId, isEditedPostNew );
return;
}
}
Expand Down Expand Up @@ -112,16 +118,23 @@ function useAutosaveNotice() {
],
}
);
}, [ postId ] );
}, [ isEditedPostNew, postId ] );
}

/**
* Custom hook which ejects a local autosave after a successful save occurs.
*/
function useAutosavePurge() {
const { postId, isDirty, isAutosaving, didError } = useSelect(
const {
postId,
isEditedPostNew,
isDirty,
isAutosaving,
didError,
} = useSelect(
( select ) => ( {
postId: select( 'core/editor' ).getCurrentPostId(),
isEditedPostNew: select( 'core/editor' ).isEditedPostNew(),
isDirty: select( 'core/editor' ).isEditedPostDirty(),
isAutosaving: select( 'core/editor' ).isAutosavingPost(),
didError: select( 'core/editor' ).didPostSaveRequestFail(),
Expand All @@ -138,12 +151,21 @@ function useAutosavePurge() {
( ( lastIsAutosaving.current && ! isAutosaving ) ||
( lastIsDirty.current && ! isDirty ) )
) {
localAutosaveClear( postId );
localAutosaveClear( postId, isEditedPostNew );
}

lastIsDirty.current = isDirty;
lastIsAutosaving.current = isAutosaving;
}, [ isDirty, isAutosaving, didError ] );

// Once the isEditedPostNew changes from true to false, let's clear the auto-draft autosave.
const wasEditedPostNew = usePrevious( isEditedPostNew );
const prevPostId = usePrevious( postId );
useEffect( () => {
if ( prevPostId === postId && wasEditedPostNew && ! isEditedPostNew ) {
localAutosaveClear( postId, true );
}
}, [ isEditedPostNew, postId ] );
}

function LocalAutosaveMonitor() {
Expand Down
2 changes: 2 additions & 0 deletions packages/editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ export function* autosave( options ) {

export function* __experimentalLocalAutosave() {
const post = yield select( STORE_KEY, 'getCurrentPost' );
const isPostNew = yield select( STORE_KEY, 'isEditedPostNew' );
const title = yield select( STORE_KEY, 'getEditedPostAttribute', 'title' );
const content = yield select(
STORE_KEY,
Expand All @@ -366,6 +367,7 @@ export function* __experimentalLocalAutosave() {
yield {
type: 'LOCAL_AUTOSAVE_SET',
postId: post.id,
isPostNew,
title,
content,
excerpt,
Expand Down
27 changes: 15 additions & 12 deletions packages/editor/src/store/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,23 @@ export function getRegistry() {
*
* @see https://github.com/WordPress/wordpress-develop/blob/6dad32d2aed47e6c0cf2aee8410645f6d7aba6bd/src/wp-login.php#L103
*
* @param {string} postId Post ID.
* @return {string} sessionStorage key
* @param {string} postId Post ID.
* @param {boolean} isPostNew Whether post new.
* @return {string} sessionStorage key
*/
function postKey( postId ) {
return `wp-autosave-block-editor-post-${ postId }`;
function postKey( postId, isPostNew ) {
return `wp-autosave-block-editor-post-${
isPostNew ? 'auto-draft' : postId
}`;
}

export function localAutosaveGet( postId ) {
return window.sessionStorage.getItem( postKey( postId ) );
export function localAutosaveGet( postId, isPostNew ) {
return window.sessionStorage.getItem( postKey( postId, isPostNew ) );
}

export function localAutosaveSet( postId, title, content, excerpt ) {
export function localAutosaveSet( postId, isPostNew, title, content, excerpt ) {
window.sessionStorage.setItem(
postKey( postId ),
postKey( postId, isPostNew ),
JSON.stringify( {
post_title: title,
content,
Expand All @@ -54,8 +57,8 @@ export function localAutosaveSet( postId, title, content, excerpt ) {
);
}

export function localAutosaveClear( postId ) {
window.sessionStorage.removeItem( postKey( postId ) );
export function localAutosaveClear( postId, isPostNew ) {
window.sessionStorage.removeItem( postKey( postId, isPostNew ) );
}

const controls = {
Expand All @@ -68,8 +71,8 @@ const controls = {
} )
),
GET_REGISTRY: createRegistryControl( ( registry ) => () => registry ),
LOCAL_AUTOSAVE_SET( { postId, title, content, excerpt } ) {
localAutosaveSet( postId, title, content, excerpt );
LOCAL_AUTOSAVE_SET( { postId, isPostNew, title, content, excerpt } ) {
localAutosaveSet( postId, isPostNew, title, content, excerpt );
},
};

Expand Down

0 comments on commit 95e4f3f

Please sign in to comment.