-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Stop trying to autosave when title and classic block content both are empty. #10404
Stop trying to autosave when title and classic block content both are empty. #10404
Conversation
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.
👍 I've tested this locally and confirm autosave doesn't run until some text is entered in the post content.
I'll defer to @aduth or @youknowriad on the underlying JavaScript
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.
My suggestion noted at #6556 (comment) would avoid the need to inspect specific attributes of the block, rather relying on the existing serializer behavior to be performed, testing the result of which as being non-empty to determine whether a save can occur.
Pseudo-code:
const isEditedPostEmpty = ( state ) => ! hasKnownBlock( state ) && ! getEditedPostAttribute( state, 'content' )
const hasKnownBlock = ( state ) => getBlockOrder( state ).some( ( clientId ) => (
state.editor.current.blocksByClientId[ clientId ].name !== getUnknownTypeHandlerName()
) );
(In second function, I avoid getBlocks
because it has a non-trivial cost to execute)
const isSingleEmptyFreeformBlock = ( | ||
blocks.length === 1 && | ||
blocks[ 0 ].name === 'core/freeform' && | ||
( isEmpty( blocks[ 0 ].attributes ) || blocks[ 0 ].attributes.content === '' ) |
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.
This pierces the abstraction of blocks by duplicating the save implementation of the freeform block between block-library
and editor
. Something like the above isUnmodifiedDefaultBlock
(in blocks
) is a small improvement.
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.
Hey, I think I'm confused about this. Can you give me more( simple ) detail?
Sorry, Gutenberg and react is still new for me so I might not be doing this right.
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.
Sorry for being unclear. In short: We shouldn't pretend to know anything about what attributes do or don't exist here, because it will make our lives more difficult later if we ever need to change the attributes.
It's not entirely relevant if we consider the recommendation at #10404 (review)
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.
ok, yeah sure. Got it we should not use specific attribute name from a direct object and dependent on that. Also, this one is just checking for one empty block there might be more so it would be better if we check in all blocks in the current state. #10404 (review)
I'll update this occordingly.
// A single empty core/freeform block equivalent to an empty post. | ||
const isSingleEmptyFreeformBlock = ( | ||
blocks.length === 1 && | ||
blocks[ 0 ].name === 'core/freeform' && |
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.
The fallback block for which comment demarcation is omitted is not guaranteed to be explicitly 'core/freeform'
.
See:
gutenberg/packages/blocks/src/api/serializer.js
Lines 263 to 269 in 286317c
switch ( blockName ) { | |
case getUnknownTypeHandlerName(): | |
return saveContent; | |
default: | |
return getCommentDelimitedContent( blockName, saveAttributes, saveContent ); | |
} |
As in this snippet, it should be tested against the value returned by getUnknownTypeHandlerName
.
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.
Updated this with getUnknownTypeHandlerName
,
Sure @aduth, I'll look into this feedbacks and update this PR soon. |
@rahulsprajapati Any chance you can finish this up Thursday (10/17) IST so we can get this landed? |
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.
As of #8274, getUnknownTypeHandlerName
has been replaced by two functions getFreeformFallbackBlockName
and getUnregisteredFallbackBlockName
.
You'll need to update your branch to bring in the latest master
changes.
sure, will update this. |
@@ -360,6 +361,20 @@ export function isEditedPostSaveable( state ) { | |||
); | |||
} | |||
|
|||
/** |
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.
One of the test failures is due to the fact that documentation needs to be regenerated by npm run docs:build
.
@@ -375,7 +390,7 @@ export function isEditedPostEmpty( state ) { | |||
// operation by comparison. Since this function can be called frequently, | |||
// optimize for the fast case where saveable blocks are non-empty. | |||
return ( | |||
! getBlocksForSerialization( state ).length && |
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.
Hmm, in retrospect my original suggestion may have been made at a time before we'd considered the extra condition added by getBlocksForSerialization
to consider the empty paragraph (see #9808). I've got to imagine this change here regresses on that intended behavior.
Maybe we should update hasKnownBlocks
to accept blocks
as an argument, so we can pass the result of getBlocksForSerialization
to use in place of getBlockOrder
.
export function hasKnownBlocks( state ) { | ||
return getBlockOrder( state ).some( ( clientId ) => ( | ||
state.editor.present.blocksByClientId[ clientId ].name !== getFreeformContentHandlerName() && | ||
state.editor.present.blocksByClientId[ clientId ].name !== getUnregisteredTypeHandlerName() |
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.
The split of these two functions has me wondering if the semantics are meaningfully different enough to consider. "Unknown" would be truly a block, with demarcations, and thus non-empty for save. I think what we're really targeting is specifically freeform content.
Thus, I think we don't need this line and it could be dropped.
In doing so, and in reconsideration of targeting specifically freeform content, I wonder if the function name we've chosen hasKnownBlocks
is very accurate. I'll need to sit and think on this one...
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.
I wonder if the function name we've chosen hasKnownBlocks is very accurate. I'll need to sit and think on this one...
If we are just going to check that the post have any freeform block or not then hasFreeFromBlock
name will be more suitable for this.
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.
That name seems to suit the purpose, but it highlights to me that it's so specific to the isEditedPostEmpty
use-case that we might be better off to include the logic there, rather than to expose a new separate selector.
Thinking something like (haven't verified the logic):
export function isEditedPostEmpty( state ) {
const blocks = getBlocksForSerialization( state );
if ( ! blocks.length ) {
return true;
}
const freeformBlockName = getFreeformContentHandlerName();
if ( ! some( blocks, { name: freeformBlockName } ) ) {
return false;
}
// Content serialization is considered an expensive operation, and should
// only be considered after more trivial operations of assuming presence of
// non-freeform blocks as implying that serializable content exists.
return ! getEditedPostAttribute( state, 'content' );
}
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.
@aduth This works correctly.
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.
@rahulsprajapati @aduth : Yup, the code works correctly, but while writing test cases for this, existing test case should return false if edits include a non-empty content property
fails. So I think need to check for a more suitable solution. What do you guys say?
There appear to be some test failures for the impacted selectors. This is otherwise looking quite nice. |
Great. I'll look into tests failure. |
I looked over the tests and found that we had a few issues in their authoring:
I also discovered a completely separate bug in our optimization of blocks existing, in that a I've further revised the implementation to avoid |
Thank you @aduth for the explanation. 🙂 I was looking over the test only and was wondering why it's failing when the test case was correct and then just found that free-form was not detected with |
280f8ae
to
a25bc1a
Compare
… unregistered or empty content block is available in post.
a25bc1a
to
4c07ae6
Compare
I've manually verified that autosave doesn't fire when Title is empty and the post only has a Classic Block. Thanks for your work on this @rahulsprajapati, @aduth, @sanketio |
…rnmobile/port-quote-block-step-1 * 'master' of https://github.com/WordPress/gutenberg: (22 commits) Add removed periods to block descriptions. (#11367) Remove findDOMNode usage from the inserter (#11363) Remove deprecated componentWillReceiveProps from TinyMCE component (#11368) Create file blocks when dropping multiple files at once (#11297) Try avoiding the deprecated findDOMNode API from DropZone Provider (#11168) Fix: make meta+A behaviour of selecting all blocks work on safari and firefox. (#8180) Remove _wpGutenbergCodeEditorSettings and wp.codeEditor assets (#11342) Remove the Cloudflare warning (#11350) Image Block: Use source_url for media file link (#11254) Enhance styling of nextpage block using the Hr element (#11354) Embed block refactor and tidy (#10958) Nonce Middleware: Wrap the nonce middleware function into it's own function that isn't regenerated on every API request. (#11347) Fix RTL block alignments (#11293) RichText: fix buggy enter/delete behaviour (#11287) Remove code coverage setup (#11198) Parser: Runs all parser implementations against the same tests (#11320) Stop trying to autosave when title and classic block content both are empty. (#10404) Fix "Mac OS" typo + use fancy quotes consistently (#11310) Update documentation link paths (#11324) Editor: Reshape blocks state under own key (#11315) ... # Conflicts: # gutenberg-mobile
Description
Fixes: #6556
Add check in getBlocksForSerialization when single classic block ( core/freeform ) is available with empty content.
gutenberg/packages/editor/src/store/selectors.js
Lines 372 to 381 in 69ced17
How has this been tested?
Post autosave is not triggerd when one classic block content is availble and it's empty.
Screencast: https://drive.google.com/file/d/1p6HfNi7I6_57y8mbLhe9J8HTU4lAq--6/view
Screenshots
Types of changes
Bug fix (non-breaking change which fixes an issue)
Checklist: