Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/data/data-core-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,18 @@ Returns true if the post is autosaving, or false otherwise.

Whether the post is autosaving.

### isPreviewingPost

Returns true if the post is being previewed, or false otherwise.

*Parameters*

* state: Global application state.

*Returns*

Whether the post is being previewed.

### getSuggestedPostFormat

Returns a suggested post format for the current post, inferred only if there
Expand Down Expand Up @@ -1628,7 +1640,7 @@ Returns an action object to save the post.
*Parameters*

* options: Options for the save.
* options.autosave: Perform an autosave if true.
* options.isAutosave: Perform an autosave if true.

### mergeBlocks

Expand All @@ -1643,6 +1655,10 @@ Returns an action object used in signalling that two blocks should be merged

Returns an action object used in signalling that the post should autosave.

*Parameters*

* options: Extra flags to identify the autosave.

### redo

Returns an action object used in signalling that undo history should
Expand Down
5 changes: 4 additions & 1 deletion packages/edit-post/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ function Header( {
forceIsSaving={ isSaving }
/>
) }
<PostPreviewButton />
<PostPreviewButton
forceIsAutosaveable={ hasActiveMetaboxes }
forcePreviewLink={ isSaving ? null : undefined }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be refactored to:

forcePreviewLink={ isSaving }

and then we only would need to update the code later in the execution flow to:

previewLink: forcePreviewLink ? null : getAutosaveAttribute( 'preview_link' ),

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can't because we're forcing the null value from outside. The inner component don't know what value to put unless we rename the prop something like forceEmptyPreviewLink

/>
<PostPublishButtonOrToggle
forceIsDirty={ hasActiveMetaboxes }
forceIsSaving={ isSaving }
Expand Down
14 changes: 8 additions & 6 deletions packages/edit-post/src/store/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,26 @@ const effects = {

let wasSavingPost = select( 'core/editor' ).isSavingPost();
let wasAutosavingPost = select( 'core/editor' ).isAutosavingPost();
let wasPreviewingPost = select( 'core/editor' ).isPreviewingPost();
// Save metaboxes when performing a full save on the post.
subscribe( () => {
const isSavingPost = select( 'core/editor' ).isSavingPost();
const isAutosavingPost = select( 'core/editor' ).isAutosavingPost();
const isPreviewingPost = select( 'core/editor' ).isPreviewingPost();
const hasActiveMetaBoxes = select( 'core/edit-post' ).hasMetaBoxes();

// Save metaboxes on save completion when past save wasn't an autosave.
// Save metaboxes on save completion, except for autosaves that are not a post preview.
const shouldTriggerMetaboxesSave = (
hasActiveMetaBoxes &&
wasSavingPost &&
! wasAutosavingPost &&
! isSavingPost &&
! isAutosavingPost
hasActiveMetaBoxes && (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope it works 🙏 😅

( wasSavingPost && ! isSavingPost && ! wasAutosavingPost ) ||
( wasAutosavingPost && wasPreviewingPost && ! isPreviewingPost )
)
);

// Save current state for next inspection.
wasSavingPost = isSavingPost;
wasAutosavingPost = isAutosavingPost;
wasPreviewingPost = isPreviewingPost;

if ( shouldTriggerMetaboxesSave ) {
store.dispatch( requestMetaBoxUpdates() );
Expand Down
12 changes: 4 additions & 8 deletions packages/editor/src/components/post-preview-button/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ export class PostPreviewButton extends Component {
// unintentional forceful redirects.
if ( previewLink && ! prevProps.previewLink ) {
this.setPreviewWindowLink( previewLink );

// Once popup redirect is evaluated, even if already closed, delete
// reference to avoid later assignment of location in post update.
delete this.previewWindow;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aduth I removed this to be able to refresh the window without an autosave (once the metaboxes finish saving). I'm not aware of any downsides but let me know if I missed something.

}
}

Expand Down Expand Up @@ -152,7 +148,7 @@ export class PostPreviewButton extends Component {

// Request an autosave. This happens asynchronously and causes the component
// to update when finished.
this.props.autosave();
this.props.autosave( { isPreview: true } );

// Display a 'Generating preview' message in the Preview tab while we wait for the
// autosave to finish.
Expand Down Expand Up @@ -192,7 +188,7 @@ export class PostPreviewButton extends Component {
}

export default compose( [
withSelect( ( select ) => {
withSelect( ( select, { forcePreviewLink, forceIsAutosaveable } ) => {
const {
getCurrentPostId,
getCurrentPostAttribute,
Expand All @@ -215,9 +211,9 @@ export default compose( [
return {
postId: getCurrentPostId(),
currentPostLink: getCurrentPostAttribute( 'link' ),
previewLink,
previewLink: forcePreviewLink !== undefined ? forcePreviewLink : getAutosaveAttribute( 'preview_link' ),
isSaveable: isEditedPostSaveable(),
isAutosaveable: isEditedPostAutosaveable(),
isAutosaveable: forceIsAutosaveable || isEditedPostAutosaveable(),
isViewable: get( postType, [ 'viewable' ], false ),
};
} ),
Expand Down
8 changes: 5 additions & 3 deletions packages/editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ export function editPost( edits ) {
* Returns an action object to save the post.
*
* @param {Object} options Options for the save.
* @param {boolean} options.autosave Perform an autosave if true.
* @param {boolean} options.isAutosave Perform an autosave if true.
*
* @return {Object} Action object.
*/
Expand Down Expand Up @@ -439,10 +439,12 @@ export function mergeBlocks( firstBlockClientId, secondBlockClientId ) {
/**
* Returns an action object used in signalling that the post should autosave.
*
* @param {Object?} options Extra flags to identify the autosave.
*
* @return {Object} Action object.
*/
export function autosave() {
return savePost( { autosave: true } );
export function autosave( options ) {
return savePost( { isAutosave: true, ...options } );
}

/**
Expand Down
13 changes: 6 additions & 7 deletions packages/editor/src/store/effects/posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
getEditedPostContent,
getAutosave,
getCurrentPostType,
isEditedPostAutosaveable,
isEditedPostSaveable,
isEditedPostNew,
POST_UPDATE_TRANSACTION_ID,
Expand All @@ -51,12 +50,11 @@ export const requestPostUpdate = async ( action, store ) => {
const { dispatch, getState } = store;
const state = getState();
const post = getCurrentPost( state );
const isAutosave = !! action.options.autosave;
const isAutosave = !! action.options.isAutosave;

// Prevent save if not saveable.
const isSaveable = isAutosave ? isEditedPostAutosaveable : isEditedPostSaveable;

if ( ! isSaveable( state ) ) {
// We don't check for dirtiness here as this can be overriden in the UI.
if ( ! isEditedPostSaveable( state ) ) {
return;
}

Expand Down Expand Up @@ -91,7 +89,7 @@ export const requestPostUpdate = async ( action, store ) => {
dispatch( {
type: 'REQUEST_POST_UPDATE_START',
optimist: { type: BEGIN, id: POST_UPDATE_TRANSACTION_ID },
isAutosave,
options: action.options,
} );

// Optimistically apply updates under the assumption that the post
Expand Down Expand Up @@ -150,7 +148,7 @@ export const requestPostUpdate = async ( action, store ) => {
type: isRevision ? REVERT : COMMIT,
id: POST_UPDATE_TRANSACTION_ID,
},
isAutosave,
options: action.options,
postType,
} );
} catch ( error ) {
Expand All @@ -160,6 +158,7 @@ export const requestPostUpdate = async ( action, store ) => {
post,
edits,
error,
options: action.options,
} );
}
};
Expand Down
8 changes: 5 additions & 3 deletions packages/editor/src/store/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -967,21 +967,23 @@ export function saving( state = {}, action ) {
requesting: true,
successful: false,
error: null,
isAutosave: action.isAutosave,
options: action.options || {},
};

case 'REQUEST_POST_UPDATE_SUCCESS':
return {
requesting: false,
successful: true,
error: null,
options: action.options || {},
};

case 'REQUEST_POST_UPDATE_FAILURE':
return {
requesting: false,
successful: false,
error: action.error,
options: action.options || {},
};
}

Expand Down Expand Up @@ -1204,9 +1206,9 @@ export function autosave( state = null, action ) {
preview_link: post.preview_link,
};

case 'REQUEST_POST_UPDATE':
case 'REQUEST_POST_UPDATE_START':
// Invalidate known preview link when autosave starts.
if ( state && action.options.autosave ) {
if ( state && action.options.isAutosave ) {
return omit( state, 'preview_link' );
}
break;
Expand Down
13 changes: 12 additions & 1 deletion packages/editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,18 @@ export function didPostSaveRequestFail( state ) {
* @return {boolean} Whether the post is autosaving.
*/
export function isAutosavingPost( state ) {
return isSavingPost( state ) && state.saving.isAutosave;
return isSavingPost( state ) && !! state.saving.options.isAutosave;
}

/**
* Returns true if the post is being previewed, or false otherwise.
*
* @param {Object} state Global application state.
*
* @return {boolean} Whether the post is being previewed.
*/
export function isPreviewingPost( state ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's slightly weird that preview would have this side-effect but it wouldn't be evident from selector name. Though I guess it matches the expectation of the action itself.

return isSavingPost( state ) && !! state.saving.options.isPreview;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I don't think we need !! in this condition. If we need it, we should probably be consistent and add it in the previous selector that is updated in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. it's better to have it to ensure the return value is always a boolean.

}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/editor/src/store/test/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1943,6 +1943,7 @@ describe( 'state', () => {
requesting: true,
successful: false,
error: null,
options: {},
} );
} );

Expand All @@ -1954,6 +1955,7 @@ describe( 'state', () => {
requesting: false,
successful: true,
error: null,
options: {},
} );
} );

Expand All @@ -1972,6 +1974,7 @@ describe( 'state', () => {
code: 'pretend_error',
message: 'update failed',
},
options: {},
} );
} );
} );
Expand Down