-
-
Notifications
You must be signed in to change notification settings - Fork 935
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!: Remove pointerId from Draggable callbacks #1313
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.
This is a positive change, it makes the API cleaner. However, several things need to be addressed:
-
This is a big breaking change ("big" meaning that it will definitely break the code for whoever uses Draggable components). Shouldn't we go via a more cautious deprecation route here?
-
The documentation is missing (I know it was missing before, but still). It's hard to figure out why the
onDrag*
methods return booleans, or what's the difference betweenonDragEnd
vsonDragCancel
. I think it's a great opportunity to add the missing doc-strings. -
With
pointerId
parameter gone, how can a user access this information if they really need it? Say, could it be stored inside theinfo
parameter?
|
/// Override this to handle the start of a drag/pan gesture that is within the | ||
/// boundaries (or hitboxes) of the component that this mixin is used on. | ||
/// Return `true` if you want this event to continue to be passed on to | ||
/// components underneath (lower priority) this component. |
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.
What's the use case for returning true
here? Do you want to be able to drag multiple components with a single finger?
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.
Either that, or just know that there is a drag event happening on top, you don't have to react to by moving the component.
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.
Not sure I understand your example -- this is an onDragStart
event, which means there can't be any other "drag event happening on top". Unless you mean a drag from another finger, but that sounds like an advanced use case that we defer to handleDragStart
?
@@ -8,18 +8,37 @@ mixin Draggable on Component { | |||
bool _isDragged = false; | |||
bool get isDragged => _isDragged; | |||
|
|||
/// Override this to handle the start of a drag/pan gesture that is within the | |||
/// boundaries (or hitboxes) of the component that this mixin is used on. |
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.
Maybe mention that "within boundaries" means as determined by [containsPoint] method, and remove mention of hitboxes (which may be confusing to someone who doesn't know about hitboxes).
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.
Good idea.
/// components underneath (lower priority) this component. | ||
/// | ||
/// This event is not that common, it can happen for example when the user | ||
/// is interrupted by a system-modal dialog in the middle of the drag. |
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.
If this event is uncommon, then I wonder if we could provide some default implementation that defers to onDragEnd
?
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 think that should be up to the user to decide, it will after all just be one line for them to do that if they want to.
Hmm, now that I took another look at Also, I don't see any mechanism for "capturing" the drag event by the component that started it. In particular, how do we know that the component that had captured |
Correct, this isn't a problem a problem though, this is just how it is designed since it isn't a mixin on a
Because it has stored the pointer id, check the |
Fair; but then it underscores the need for clear documentation, since the name of the class doesn't reflect its actual functionality. We could consider renaming it, or extend its functionality to match the current name, or both.
Ah ok, makes sense. But then what's the point in |
It could of course be clearer, but we do go through it here:
It can be "captured" by more than one component. |
Seems to me that dragging multiple components with a single gesture is an even more rare use case than multi-finger drag. |
They are not mutally exclusive, you can do both. The id is only removed from the callbacks, not the handle methods. I don't get your point here I think. |
The point of this PR is to simplify the API of At the same time, boolean return values are also very rarely needed (perhaps even more rarely), and removing them would provide an even better improvement to the API (improvement because the developer doesn't need to worry whether to return true or false or what does it all mean). |
These booleans are used all the time, or do you mean that the default should be false and that the events should always only affect the top most component? The feature to let an event propagate until you tell it to stop is not something that is unique to Flame. The boolean is perhaps used more in other events, like in the Tappable, but we want to have the API consistent. |
I know, this paradigm comes all the way from HTML. But, in HTML there is no explicit marking of components as tappable / draggable / etc -- all elements respond to all events; and also they don't support 2 levels of APIs "simple" and "advanced" as we do. So, yes, if a component is Tappable and is visually on top, then it should receive the tap event. If it is Draggable, it should receive the drag event, etc. At least in the "simple API" case. The cases where you'd need to pass the event through are so rare that I can't imagine a single example of a game where that could be useful. Can you? |
The second, "advanced" level, is mostly for internal use, but can be overridden if there really is a need for it, almost no use-cases need to do that.
Yes, I have seen it used in several games. One game for example was falling fruits where you should tap the correct fruits to gain points and these fruits could overlap, and one tap should give all the plus and minus points from all the fruits that were tapped. We can discuss this more in the chat, because this is not related to this PR. |
If we are going to add breaking changes for the Or does the |
It is possible, a little bit of a hassle in the gestures file though.
Yes, you can get the pointer in Do you want to try to do it? 😄 |
class |
It does, and it should. |
Description
Since
pointerId
is already handled by thehandle*
methods we don't have to expose it in theonDrag*
methods, this conforms with the standard set inTappable
.Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the
relevant checkboxes (
[x]
). This will ensure a smooth and quick review process.fix:
,feat:
,docs:
etc).docs
and added dartdoc comments with///
.examples
.Breaking Change
Does your PR require Flame users to manually update their apps to accommodate your change?
!
,e.g.
feat!:
,fix!:
).