-
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
Gallery block / media-placeholder - Preserve changes made while upload in progress. #19134
Gallery block / media-placeholder - Preserve changes made while upload in progress. #19134
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.
Thanks for the super detailed PR description! There were several times I had questions about the code that were answered in the description. Very nice :)
we are using ids of the media
This makes sense to me. Is there a reason why we use both ID and URL, or could we just use one of those?
there should be no change to how the gallery block works on native until this is similarly updated
I'm also not sure how to develop the changes for the react native side of things. My thought would be to merge this before looking into changes to native code.
This may not be necessary but has been done to ensure backwards compatibility with all other components that use this media-placeholder.
Ahh this makes a lot of sense. Do you know if we experience similar bugs on other components that would be fixed once remove this check?
I did notice one more bug which happens when I do the following:
- Start with an empty gallery
- Add several images at the same time
- When the first image finishes uploading but before the others have finished uploading, click into it and remove it.
- Once the other images upload, you'll see the removed image re-appear in the gallery.
Overall though, great bug fix. I think it's ready to merge unless you want to fix any of the nitpicks! :)
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
@noahtallen Yeah, now that you mention it we may not need the
I am not able to find any other components/blocks that use the
Yeah, there are a couple other odd bugs like this that exist. While this does not fix them, it does not create them either. I think at that point since it was triggered by a group upload, it is less likely that the user will want to remove it during the group upload. What is more likely is what we are fixing where a user may select a group upload and remove images (that were already on the gallery) while that upload is in progress. I think to fix the last of these bugs we may need to reorganize both how |
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.
@jorgefilipecosta do you have thoughts here?
I have updated the logic a little bit here. It is now a little more simplified and robust. This now also fixes the remaining issue I noted above in example 3.
Now, the second loader will no longer disappear once the first upload completes. Now when |
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.
nice changes! I think this is almost ready to go
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
packages/block-editor/src/components/media-placeholder/index.js
Outdated
Show resolved
Hide resolved
I think this might need a rebase to get the test passing again :) |
0d78e4a
to
1d39aa5
Compare
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.
Hi @Addison-Stavlo, I added a PR that removes the need to getValue, the difference compared to what we tried before was to reference this.props.value directly inside setMedia if we use a value variable captured before setMedia is defined the behavior is buggy.
Would you be able to confirm if things continue to work with this change? Thank you in advance :)
@jorgefilipecosta Thanks for taking a look and proposing a cleaner solution. This "mostly" works. There is a small behavioral regression on an edge case but it is still a good improvement to the functionality on master. Using proposed
Using That being said, this is an edge case that I would not expect many users to encounter, and it does end up with the expected state in the end. I'd be happy either way, the main reason this PR was opened was to handle the case where someone would try to remove existing images while another upload was in progress (the removed images would reappear once the upload completed). Beyond that, I have tried to address other edge cases that I have found along the way and have probably gotten a bit distracted trying to solve those as well. |
1d39aa5
to
d89cea8
Compare
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 solution addresses most of the issues and does not change anything on the public API. I guess we can go with this solution 👍
Thank you for all the work and for debugging on this PR @Addison-Stavlo!
Thanks for all of your time and help on this one @jorgefilipecosta ! Tested again, things work well! I updated a comment that was still referencing |
|
||
const mediaPlaceholder = ( | ||
<MediaPlaceholder | ||
addToGallery={ hasImagesWithId } | ||
addToGallery={ true } |
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.
It looks like this is the cause of #22338, that when first adding a gallery block the Media Library is always in addToGallery
mode with all images selected on the Insert Gallery page.
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.
Description
This PR aims to fix 3 bugs related to the Gallery block component.
Before - The bugs that exist.
1 - When Images are removed while another is uploading, they are re-added once upload is complete.
2 - When two images are uploaded separately, if the first finishes after the second then the second one is removed once the first finishes its upload.
3 - When two images are uploaded separately, if the first finishes before the second then the loader for the second disappears. Once the second finishes, "empty" loading image replaces the first.
How do we go about fixing the above bugs?
Currently, the
media-placeholder
component destructures thevalue
from props and adds this into thesetMedia
function ascurrentValue
. This is never updated during the lifetime of the function which is why the above issues exist. In case 1, since these images are initially added to the function incurrentValue
, they remain incurrentValue
even after they are deleted from the screen. Once thesetMedia
function runs when the uploading image completes, it returnscurrentValue
with those unwanted deleted images.To fix this, I have added another reference to
this.props.value
(namedcurrentMedia
) but declared inside thesetMedia
function itself. This allows us to comparecurrentValue
(the 'snapshot' of the gallery's images at the beginning of the upload, now renamedmediaToReturn
) with the values that are in the gallery at the time the function is run.This now allows us to do 2 important checks when the
setMedia
function runs:With these checks we are then able to add/remove items from
mediaToReturn
as necessary so that once the upload completes, we are able to return a state representative of changes that have happened since it started.Note: Why update
mediaToReturn
and not just use the current values inthis.props.value
altogether?You will find that
this.props.value
contains temporary items returned from thesetMedia
function, such as the loading placeholders. We don't want to return these placeholders with their corresponding completed uploads, so they would need to be filtered out in that case. Since currently there is not a good way to tell which placeholders correspond to which completed uploads, it is more simple to add items tomediaToReturn
than to remove the correctly corresponding ones from the current value of the gallery.After the described changes.
1 - When Images are removed while another is uploading, they are not re-added once the upload completes.
2 - When two images uploaded separately, if the first finishes after the second they will both remain in the gallery.
3 - When two images are uploaded separately, if the first finishes before the second the loader for the second still disappears. However, once it finishes its upload they both are present in the gallery with no empty loading placeholder.
Some comments on the code itself
There is an adjactent
*.native.js
file to themedia-placeholder
index file. This has yet to be updated as I am not currently set up to test functionality on native and wanted to get the discussion on this moving before then. None of the changes made should break any functionality on native, but since the logic in the native file has not been updated there should be no change to how the gallery block works on native until this is similarly updated. It may also be worth noting that cases 2 & 3 may be much less commonly experienced through the mobile workflow.For comparisons we are using
id
s (and in some casesurl
s) of the media. My first thought was to use lodashisEqual
to compare the objects, but noticed there could be some inconsistencies on which properties were present on the objects throughout the lifetime of the function (fullUrl: undefined
for example may be present in the values on the first pass of the function, but absent from the copies returned with the loading placeholder causingisEqual
to always returnfalse
on a second pass. ).How has this been tested?
Tested on local gutenberg docker environment.
Run this PR and test initiating different uploads simultaneously, removing images from the gallery during an upload, etc. Recreate the above scenarios listed and test with group uploads as well.
Types of changes
Bug fix (non-breaking change which fixes an issue)
Checklist: