Skip to content
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

[iOS] Fabric: Added ScrollEndDragEvent for scrollEndDrag event #48319

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,17 @@ - (BOOL)_shouldDisableScrollInteraction
return metrics;
}

- (ScrollViewEventEmitter::EndDragMetrics)_scrollViewMetricsWithVelocity:(CGPoint)velocity
andTargetContentOffset:(CGPoint)targetContentOffset
{
ScrollViewEventEmitter::EndDragMetrics metrics = [self _scrollViewMetrics];
metrics.targetContentOffset.x = targetContentOffset.x;
metrics.targetContentOffset.y = targetContentOffset.y;
metrics.velocity.x = velocity.x;
metrics.velocity.y = velocity.y;
return metrics;
}

- (void)_updateStateWithContentOffset
{
if (!_state) {
Expand Down Expand Up @@ -602,6 +613,14 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
targetContentOffset->y = scrollView.contentOffset.y + travel * _endDraggingSensitivityMultiplier;
}
}

if (!_eventEmitter) {
return;
}

auto metrics = [self _scrollViewMetricsWithVelocity:velocity andTargetContentOffset:*targetContentOffset];

static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag(metrics);
cipolleschi marked this conversation as resolved.
Show resolved Hide resolved
}

- (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view
Expand Down Expand Up @@ -672,8 +691,6 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL
return;
}

static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag([self _scrollViewMetrics]);

[self _updateStateWithContentOffset];

if (!decelerate) {
Expand Down Expand Up @@ -770,7 +787,9 @@ - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UI
return;
}

static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag([self _scrollViewMetrics]);
auto metrics = [self _scrollViewMetricsWithVelocity:{} andTargetContentOffset:{}];
static_cast<const ScrollViewEventEmitter &>(*_eventEmitter).onScrollEndDrag(metrics);

[self _updateStateWithContentOffset];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,39 @@ EventPayloadType ScrollEvent::getType() const {
return EventPayloadType::ScrollEvent;
}

jsi::Value ScrollEndDragEvent::asJSIValue(jsi::Runtime& runtime) const {
auto payload = ScrollEvent::asJSIValue(runtime).asObject(runtime);

{
auto targetContentOffsetObj = jsi::Object(runtime);
targetContentOffsetObj.setProperty(runtime, "x", targetContentOffset.x);
targetContentOffsetObj.setProperty(runtime, "y", targetContentOffset.y);
payload.setProperty(runtime, "targetContentOffset", targetContentOffsetObj);
}

{
auto velocityObj = jsi::Object(runtime);
velocityObj.setProperty(runtime, "x", velocity.x);
velocityObj.setProperty(runtime, "y", velocity.y);
payload.setProperty(runtime, "velocity", velocityObj);
}

return payload;
}

folly::dynamic ScrollEndDragEvent::asDynamic() const {
auto metrics = ScrollEvent::asDynamic();

auto targetContentOffsetObj = folly::dynamic::object(
"x", targetContentOffset.x)("y", targetContentOffset.y);
metrics["targetContentOffset"] = std::move(targetContentOffsetObj);

auto velocityObj = folly::dynamic::object("x", velocity.x)("y", velocity.y);
metrics["velocity"] = std::move(velocityObj);

return metrics;
};

#if RN_DEBUG_STRING_CONVERTIBLE

std::string getDebugName(const ScrollEvent& /*scrollEvent*/) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ struct ScrollEvent : public EventPayload {
EventPayloadType getType() const override;
};

struct ScrollEndDragEvent : public ScrollEvent {
Point targetContentOffset;
Point velocity;

ScrollEndDragEvent() = default;

ScrollEndDragEvent(const ScrollEvent& scrollEvent)
: ScrollEvent(scrollEvent), targetContentOffset({}), velocity({}) {}

folly::dynamic asDynamic() const;

/*
* EventPayload implementations
*/
jsi::Value asJSIValue(jsi::Runtime& runtime) const override;
};

#if RN_DEBUG_STRING_CONVERTIBLE

std::string getDebugName(const ScrollEvent& scrollEvent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ void ScrollViewEventEmitter::onScrollBeginDrag(

void ScrollViewEventEmitter::onScrollEndDrag(
const ScrollEvent& scrollEvent) const {
dispatchScrollViewEvent("scrollEndDrag", scrollEvent);
const auto* endDragScrollEvent =
dynamic_cast<const ScrollEndDragEvent*>(&scrollEvent);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cipolleschi Hi, this is the another way by dynamic_cast scrollEvent to ScrollEndDragEvent if we removed those changes.

Copy link
Contributor

@cipolleschi cipolleschi Dec 20, 2024

Choose a reason for hiding this comment

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

uhm... sorry for the extra back and forth.
I tested locally and actually I prefer the previous version with the properly typed methods and without the cast.
I haven't realized that even if the dispatchScrollViewEvent takes an endDragScrollEvent, it then creates a shared pointer of type ScrollEvent: creating the new event pointer with explicit ScrollEvent type makes us lose the information of the actual subclass and therefore we can't serialize the event properly. :(

I modified the imported code, nothing required to do on your side! 😉

if (endDragScrollEvent) {
dispatchEvent(
"scrollEndDrag",
std::make_shared<ScrollEndDragEvent>(*endDragScrollEvent));
} else {
dispatchScrollViewEvent("scrollEndDrag", scrollEvent);
}
}

void ScrollViewEventEmitter::onMomentumScrollBegin(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ScrollViewEventEmitter : public ViewEventEmitter {
using ViewEventEmitter::ViewEventEmitter;

using Metrics = ScrollEvent;
using EndDragMetrics = ScrollEndDragEvent;

void onScroll(const ScrollEvent& scrollEvent) const;
void onScrollBeginDrag(const ScrollEvent& scrollEvent) const;
Expand Down
Loading