-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Fix for Issue 4329: Updated dropzone provider to check hovered zones on dragover. #4604
Fix for Issue 4329: Updated dropzone provider to check hovered zones on dragover. #4604
Conversation
boundaries on dragover instead of dragenter/leave.
components/drop-zone/provider.js
Outdated
@@ -92,21 +83,29 @@ class DropZoneProvider extends Component { | |||
// Computing state | |||
const { onVerifyValidTransfer } = this.props; | |||
const isValidDrag = ! onVerifyValidTransfer || onVerifyValidTransfer( detail.dataTransfer ); | |||
|
|||
// Always true (onVerifyValidTransfer is not defined). |
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.
Can we remove it if it's always 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.
We can, although I can't tell what the original intention was to have this property in the first place. For the moment the property is not defined. Maybe @youknowriad can give us a bit more insight.
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'm fine removing this, this is a leftover since this component has been adapted from Calypso
components/drop-zone/provider.js
Outdated
this.setState( { | ||
isDraggingOverDocument, | ||
hoveredDropZone, | ||
position, | ||
} ); | ||
|
||
event.preventDefault(); | ||
event.stopPropagation(); |
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.
Reminder to check again and probably remove this last line. No need to stop propagation here.
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.
Any decision here?
@@ -162,14 +165,18 @@ class DropZoneProvider extends Component { | |||
// This seemingly useless line has been shown to resolve a Safari issue | |||
// where files dragged directly from the dock are not recognized | |||
event.dataTransfer && event.dataTransfer.files.length; // eslint-disable-line no-unused-expressions | |||
|
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.
Do we need those empty lines?
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.
Yes 😛
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.
jk! In general I prefer to keep declarations (const/let/var/etc) and conditionals separate from other statements. That's just personal preference though - I am more than happy to remove them. Do we have any general approach/convention that I can adopt for such details?
Good catch and works well for me. Added @youknowriad as a review to confirm whether we need |
Thanks @nb! I also pinged @youknowriad in the comments to shed some light on that missing |
onDragOver( event ) { | ||
event.preventDefault(); | ||
} | ||
|
||
toggleDraggingOverDocument( event ) { |
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 function is called so many times when dragging right now, do you think we should throttle it?
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.
Indeed. Great idea Riad. I am looking into this, currently trying something out with lodash. Sorry for the delayed response, I was just away since yesterday.
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 Riad, I've finally added throttling at 300ms using lodash. It feels ok to me at this value, but please have a go and let me know what you think. Also, this is the best I could come up with code-wise to get the event.preventDefault
call working. Tested it in Chrome/Firefox/Safari/IE11. :-)
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.
So this change can create performance issues when dragging files in theory but I'm not seeing the performance issues we had when we first tried this.
I think we optimized the blocks to avoid rerendering without changes which makes this strategy possible now.
cc @jasmussen for sanity check (performance wise) but in general, this is looking good.
In my quick tests here, dragging and dropping both single and multiple images into a long document caused no performance issues for me and was simply a delight. |
Indeed. I noticed some smart checks in there to only update the dropzones that need to be updated. Last I remember it was I believe 2 state updates as we drag something over a block top to bottom. I will run a few more checks to be sure and clean up that |
…property onVerifyValidTransfer.
- The top/bottom negative offsets of the block dropzones allow for the top/bottom borders shown when on hover to overlap, hence visualy appearing as one (or not changing). This was off by 1px, which this commit fixes.
@jasmussen when/if you get a chance, can you please take a look at my very last commit here? There is a brief description there - not sure if you noticed it, but if you look closer there is a 1px difference in overlap of the top/bottom blue borders of stacked dropzones. These are supposed to overlap exactly when you drag something from one block to the next. This seemingly simple change fixes it, but I can't determine what the cause was. Any ideas? shall we just call it fixed and not worry? Thanks! 😄 |
Sure thing, I'll take a look first thing tomorrow morning. |
Thanks :-) |
Checked out your branch, tried to drag and drop some images in, tried to create some reusable blocks, tried dragging and dropping again. I can't seem to find any visual regressions in this change. If you see the same, then let's call it fixed for now, and we can revisit if any issues pop up. |
This comment #4604 (comment) doesn't seem resolved yet. Any thoughts about this? |
Thanks @jasmussen ! I was just puzzled why I had to reduce the bottom offset by 1px to get the blue borders aligned when you drag across blocks -but yeah, it's such a minor issue, don't worry about it if it's looking fine. Thanks for checking 😄 |
components/drop-zone/provider.js
Outdated
@@ -17,6 +17,13 @@ class DropZoneProvider extends Component { | |||
this.isWithinZoneBounds = this.isWithinZoneBounds.bind( this ); | |||
this.onDrop = this.onDrop.bind( this ); | |||
|
|||
const throttledAction = throttle( this.toggleDraggingOverDocument, 500 ); | |||
|
|||
this.dragOverListener = ( event ) => { |
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.
Minor: I guess it's just a preference of mine but what do you think about something like this:
this.toggleDraggingOverDocument = throttle( this.toggleDraggingOverDocument.bind( this ), 500 );
this.dragOverListener = this.dragOverListener.bind( this );
and move the dragOverListener
declaration as a regular method (not defined in the constructor).
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.
Also wondering if 500
is not too high :) maybe 200?
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.
Indeed, 200
is a lot better.
Minor: I guess it's just a preference of mine but what do you think about something like this:...
Definitely. That is a lot cleaner/better. Just updated now. :-)
Also, you'll notice I make the call to the throttled method as this.toggleDraggingOverDocument.call( this, event );
- it's not necessary - we can just this.toggleDraggingOverDocument( event )
- lodash uses the last this
value on each call. I don't know why but I feel safer to have it this way instead? Should I just revert to the normal invocation?
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 this is going back/forth so many times... :-)
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.
No worries, thanks for handling all these details :)
I'd be in favor of a regular this.toggleDraggingOverDocument( event )
I'll give it a last spin tomorrow morning and approve
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.
Awesome! Updated. Let me know if you spot anything else :-)
…d throttle interval to 200.
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 work here 👍 Thanks for addressing all the concerns
Hey @chriskmnds I'm seeing a small bug on master where there's a lingering placeholder at the end of the post when drag and dropping a file. I wonder if it's related to this PR |
Hey @youknowriad I notice that too. It doesn't look like it's related to this PR. I've checked the commit before it (d8e13bf) and I can still see the lingering placeholder. This is what you are referring to right: I sense this is related to the latest changes with the sibling inserter. I can look into this first thing tomorrow in any case. Shall I create a ticket for it? :-) |
Description
This is a fix for issue 4329.
To my understanding, there is an issue with the top/bottom dropzones. Initially the dropzones were checked and activated on the dragenter and dragleave events - which fire once each, when we enter an area while dragging and when we leave that area. So when we are already dragging somewhere in the bottom part of the top dropzone and drag the item towards the top of it - the positioning is never updated (since nothing keeps track of the cursor position), and once we drag passed the dropzone then we are not within the zone bounds for the update logic to fire - hence we need to come back into the dropzone area to re-activate the top/first dropzone.
With
dragover
(the fix), we keep track of the cursor position and do our checks constantly + as this was written in a way that only the dropzones that need to be updated will change their state, then the overhead is not severe. This way we have the update logic fire when we drag from the bottom half to the top half of the first dropzone (and vice versa for the bottom one), hence the activation of the topmost and bottommost goes through as we are on our way to leave the dropzone area.Another Approach
Another possibility to investigate for a different solution may be to pad the top part of the blocks list with an additional dropzone in order to have the
dragenter
handler fire when leaving the topmost dropzone (so we never really leave the dropzone area, even though we won't be hovering over one of the visible blocks). This may not require changes to the provider.How Has This Been Tested?
Manually. Dragging an image from the desktop into a block and image gallery dropzone - confirming insert.
Screenshots (jpeg or gifs if applicable):
A gif has been added to the issue referenced above.
Types of changes
Updated handler to check on dragover instead of once on dragenter/leave. Reasoning: we need to tell when the cursor goes from the bottom to the top of the same block, otherwise we can't activate the top/bottom dropzones in the block list unless we drag something out and into the top/bottom dropzones respectively.
Checklist: