Skip to content

Commit 2dc43d9

Browse files
committed
Add event emitter
1 parent b4a0ca2 commit 2dc43d9

File tree

9 files changed

+132
-39
lines changed

9 files changed

+132
-39
lines changed

packages/react-native-reanimated/Common/cpp/reanimated/CSS/events/CSSAnimationEvent.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,23 @@
55

66
namespace reanimated::css {
77

8-
CSSAnimationEvent createAnimationStartEvent(
9-
const facebook::react::Tag viewTag,
10-
const std::shared_ptr<CSSAnimation> &animation) {
8+
CSSEvent createAnimationStartEvent(const facebook::react::Tag viewTag, const std::shared_ptr<CSSAnimation> &animation) {
119
const auto activeDuration = animation->getDuration() * animation->getIterationCount();
1210
const auto elapsedTime = std::min(std::max(-animation->getDelay(), 0.0), activeDuration);
13-
return {viewTag, CSSAnimationEventType::AnimationStart, animation->getName(), elapsedTime};
11+
return {viewTag, "animationstart", animation->getName(), elapsedTime};
1412
}
1513

16-
CSSAnimationEvent createAnimationIterationEvent(
14+
CSSEvent createAnimationIterationEvent(
1715
const facebook::react::Tag viewTag,
1816
const std::shared_ptr<CSSAnimation> &animation,
1917
const unsigned iteration) {
2018
const auto elapsedTime = static_cast<double>(iteration - 1) * animation->getDuration();
21-
return {viewTag, CSSAnimationEventType::AnimationIteration, animation->getName(), elapsedTime};
19+
return {viewTag, "animationiteration", animation->getName(), elapsedTime};
2220
}
2321

24-
CSSAnimationEvent createAnimationEndEvent(
25-
const facebook::react::Tag viewTag,
26-
const std::shared_ptr<CSSAnimation> &animation) {
22+
CSSEvent createAnimationEndEvent(const facebook::react::Tag viewTag, const std::shared_ptr<CSSAnimation> &animation) {
2723
const auto elapsedTime = animation->getDuration() * animation->getIterationCount();
28-
return {viewTag, CSSAnimationEventType::AnimationEnd, animation->getName(), elapsedTime};
24+
return {viewTag, "animationend", animation->getName(), elapsedTime};
2925
}
3026

3127
} // namespace reanimated::css
Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
#pragma once
22

3-
#include <react/renderer/core/ReactPrimitives.h>
3+
#include <reanimated/CSS/events/CSSEvent.h>
44

55
#include <cstdint>
66
#include <memory>
7-
#include <string>
87

98
namespace reanimated::css {
109

@@ -24,20 +23,11 @@ inline bool hasListener(CSSAnimationEventListeners listeners, CSSAnimationEventT
2423
return (listeners & static_cast<std::uint8_t>(type)) != 0;
2524
}
2625

27-
struct CSSAnimationEvent {
28-
facebook::react::Tag viewTag;
29-
CSSAnimationEventType type;
30-
std::string animationName;
31-
double elapsedTime; // in milliseconds (convert to seconds at dispatch time)
32-
};
33-
34-
CSSAnimationEvent createAnimationStartEvent(
35-
facebook::react::Tag viewTag,
36-
const std::shared_ptr<CSSAnimation> &animation);
37-
CSSAnimationEvent createAnimationIterationEvent(
26+
CSSEvent createAnimationStartEvent(facebook::react::Tag viewTag, const std::shared_ptr<CSSAnimation> &animation);
27+
CSSEvent createAnimationIterationEvent(
3828
facebook::react::Tag viewTag,
3929
const std::shared_ptr<CSSAnimation> &animation,
4030
unsigned iteration);
41-
CSSAnimationEvent createAnimationEndEvent(facebook::react::Tag viewTag, const std::shared_ptr<CSSAnimation> &animation);
31+
CSSEvent createAnimationEndEvent(facebook::react::Tag viewTag, const std::shared_ptr<CSSAnimation> &animation);
4232

4333
} // namespace reanimated::css
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include <react/renderer/core/ReactPrimitives.h>
4+
5+
#include <string>
6+
7+
namespace reanimated::css {
8+
9+
struct CSSEvent {
10+
facebook::react::Tag viewTag;
11+
std::string type; // e.g. "animationstart", "transitionend"
12+
std::string targetName; // animation name or property name
13+
double elapsedTime; // in milliseconds (convert to seconds at dispatch time)
14+
};
15+
16+
} // namespace reanimated::css
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <reanimated/CSS/events/CSSEventsEmitter.h>
2+
3+
#include <utility>
4+
5+
using namespace facebook;
6+
7+
namespace reanimated::css {
8+
9+
namespace {
10+
11+
jsi::Object eventToJSIObject(jsi::Runtime &rt, const CSSEvent &event) {
12+
auto obj = jsi::Object(rt);
13+
obj.setProperty(rt, "viewTag", event.viewTag);
14+
obj.setProperty(rt, "type", jsi::String::createFromUtf8(rt, event.type));
15+
obj.setProperty(rt, "animationName", jsi::String::createFromUtf8(rt, event.targetName));
16+
obj.setProperty(rt, "elapsedTime", event.elapsedTime);
17+
return obj;
18+
}
19+
20+
jsi::Array eventsToJSIArray(jsi::Runtime &rt, const std::vector<CSSEvent> &events) {
21+
auto array = jsi::Array(rt, events.size());
22+
for (size_t i = 0; i < events.size(); ++i) {
23+
array.setValueAtIndex(rt, i, eventToJSIObject(rt, events[i]));
24+
}
25+
return array;
26+
}
27+
28+
} // namespace
29+
30+
CSSEventsEmitter::CSSEventsEmitter(const std::shared_ptr<react::CallInvoker> &jsInvoker) : jsInvoker_(jsInvoker) {}
31+
32+
void CSSEventsEmitter::setEmitFunction(std::shared_ptr<jsi::Function> emitFunction) {
33+
emitFunction_ = std::move(emitFunction);
34+
}
35+
36+
void CSSEventsEmitter::schedule(CSSEvent event) {
37+
pendingEvents_.emplace_back(std::move(event));
38+
}
39+
40+
void CSSEventsEmitter::emit() {
41+
if (pendingEvents_.empty() || !emitFunction_) {
42+
return;
43+
}
44+
45+
auto events = std::make_shared<std::vector<CSSEvent>>();
46+
events->swap(pendingEvents_);
47+
auto emitFunction = emitFunction_;
48+
49+
jsInvoker_->invokeAsync([events = std::move(events), emitFunction = std::move(emitFunction)](jsi::Runtime &rt) {
50+
emitFunction->call(rt, eventsToJSIArray(rt, *events));
51+
});
52+
}
53+
54+
bool CSSEventsEmitter::hasEvents() const {
55+
return !pendingEvents_.empty();
56+
}
57+
58+
} // namespace reanimated::css
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#include <reanimated/CSS/events/CSSEvent.h>
4+
5+
#include <ReactCommon/CallInvoker.h>
6+
#include <jsi/jsi.h>
7+
8+
#include <memory>
9+
#include <vector>
10+
11+
using namespace facebook;
12+
13+
namespace reanimated::css {
14+
15+
class CSSEventsEmitter {
16+
public:
17+
explicit CSSEventsEmitter(const std::shared_ptr<react::CallInvoker> &jsInvoker);
18+
19+
void setEmitFunction(std::shared_ptr<jsi::Function> emitFunction);
20+
void schedule(CSSEvent event);
21+
void emit();
22+
bool hasEvents() const;
23+
24+
private:
25+
const std::shared_ptr<react::CallInvoker> jsInvoker_;
26+
std::shared_ptr<jsi::Function> emitFunction_;
27+
std::vector<CSSEvent> pendingEvents_;
28+
};
29+
30+
} // namespace reanimated::css

packages/react-native-reanimated/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
namespace reanimated::css {
1010

11+
CSSAnimationsRegistry::CSSAnimationsRegistry(const std::shared_ptr<CSSEventsEmitter> &eventsEmitter)
12+
: eventsEmitter_(eventsEmitter) {}
13+
1114
bool CSSAnimationsRegistry::isEmpty() const {
1215
// The registry is empty if has no registered animations and no updates
1316
// stored in the updates registry
@@ -92,12 +95,6 @@ void CSSAnimationsRegistry::update(const double timestamp) {
9295
}
9396
}
9497

95-
std::vector<CSSAnimationEvent> CSSAnimationsRegistry::flushEvents() {
96-
std::vector<CSSAnimationEvent> events;
97-
events.swap(pendingEvents_);
98-
return events;
99-
}
100-
10198
CSSAnimationsVector CSSAnimationsRegistry::buildAnimationsVector(
10299
jsi::Runtime &rt,
103100
const std::shared_ptr<const ShadowNode> &shadowNode,
@@ -211,7 +208,7 @@ void CSSAnimationsRegistry::updateViewAnimations(
211208

212209
if (detectEvents) {
213210
const AnimationStateSnapshot afterSnapshot = {newState, animation->getCurrentIteration()};
214-
detectAnimationEvents(viewTag, animation, beforeSnapshot, afterSnapshot);
211+
scheduleAnimationEvents(viewTag, animation, beforeSnapshot, afterSnapshot);
215212
}
216213

217214
if (newState == AnimationProgressState::Finished) {
@@ -344,7 +341,7 @@ void CSSAnimationsRegistry::handleAnimationsToRevert(const double timestamp) {
344341
animationsToRevertMap_.clear();
345342
}
346343

347-
void CSSAnimationsRegistry::detectAnimationEvents(
344+
void CSSAnimationsRegistry::scheduleAnimationEvents(
348345
const Tag viewTag,
349346
const std::shared_ptr<CSSAnimation> &animation,
350347
const AnimationStateSnapshot &before,
@@ -353,17 +350,17 @@ void CSSAnimationsRegistry::detectAnimationEvents(
353350

354351
if (hasListener(listeners, CSSAnimationEventType::AnimationStart) &&
355352
before.state == AnimationProgressState::Pending && after.state != AnimationProgressState::Pending) {
356-
pendingEvents_.emplace_back(createAnimationStartEvent(viewTag, animation));
353+
eventsEmitter_->schedule(createAnimationStartEvent(viewTag, animation));
357354
}
358355

359356
if (hasListener(listeners, CSSAnimationEventType::AnimationIteration) &&
360357
after.state == AnimationProgressState::Running && after.iteration > before.iteration) {
361-
pendingEvents_.emplace_back(createAnimationIterationEvent(viewTag, animation, after.iteration));
358+
eventsEmitter_->schedule(createAnimationIterationEvent(viewTag, animation, after.iteration));
362359
}
363360

364361
if (hasListener(listeners, CSSAnimationEventType::AnimationEnd) && before.state != AnimationProgressState::Finished &&
365362
after.state == AnimationProgressState::Finished) {
366-
pendingEvents_.emplace_back(createAnimationEndEvent(viewTag, animation));
363+
eventsEmitter_->schedule(createAnimationEndEvent(viewTag, animation));
367364
}
368365
}
369366

packages/react-native-reanimated/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <reanimated/CSS/configs/CSSAnimationConfig.h>
44
#include <reanimated/CSS/core/CSSAnimation.h>
55
#include <reanimated/CSS/events/CSSAnimationEvent.h>
6+
#include <reanimated/CSS/events/CSSEventsEmitter.h>
67
#include <reanimated/CSS/utils/DelayedItemsManager.h>
78
#include <reanimated/CSS/utils/props.h>
89
#include <reanimated/Fabric/updates/UpdatesRegistry.h>
@@ -24,6 +25,8 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
2425
public:
2526
using SettingsUpdates = std::vector<std::pair<size_t, PartialCSSAnimationSettings>>;
2627

28+
explicit CSSAnimationsRegistry(const std::shared_ptr<CSSEventsEmitter> &eventsEmitter);
29+
2730
bool isEmpty() const override;
2831
bool hasUpdates() const;
2932

@@ -38,7 +41,6 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
3841
void remove(Tag viewTag) override;
3942

4043
void update(double timestamp);
41-
std::vector<CSSAnimationEvent> flushEvents();
4244

4345
private:
4446
struct AnimationStateSnapshot {
@@ -56,14 +58,15 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
5658

5759
using Registry = std::unordered_map<Tag, RegistryEntry>;
5860

61+
const std::shared_ptr<CSSEventsEmitter> eventsEmitter_;
62+
5963
Registry registry_;
6064

6165
RunningAnimationIndicesMap runningAnimationIndicesMap_;
6266
AnimationsToRevertMap animationsToRevertMap_;
6367
DelayedItemsManager<std::shared_ptr<CSSAnimation>> delayedAnimationsManager_;
6468

6569
std::unordered_map<Tag, CSSAnimationEventListeners> eventListenersMap_;
66-
std::vector<CSSAnimationEvent> pendingEvents_;
6770

6871
CSSAnimationsVector buildAnimationsVector(
6972
jsi::Runtime &rt,
@@ -85,7 +88,7 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
8588
void activateDelayedAnimations(double timestamp);
8689
void handleAnimationsToRevert(double timestamp);
8790

88-
void detectAnimationEvents(
91+
void scheduleAnimationEvents(
8992
Tag viewTag,
9093
const std::shared_ptr<CSSAnimation> &animation,
9194
const AnimationStateSnapshot &before,

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
107107
updatesRegistryManager_(std::make_shared<UpdatesRegistryManager>(staticPropsRegistry_)),
108108
viewStylesRepository_(std::make_shared<ViewStylesRepository>(staticPropsRegistry_, animatedPropsRegistry_)),
109109
cssAnimationKeyframesRegistry_(std::make_shared<CSSKeyframesRegistry>(viewStylesRepository_)),
110-
cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>()),
110+
cssEventsEmitter_(std::make_shared<CSSEventsEmitter>(jsCallInvoker)),
111+
cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>(cssEventsEmitter_)),
111112
cssTransitionsRegistry_(std::make_shared<CSSTransitionsRegistry>(getAnimationTimestamp_, viewStylesRepository_)),
112113
synchronouslyUpdateUIPropsFunction_(platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction),
113114
#ifdef ANDROID

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <reanimated/AnimatedSensor/AnimatedSensorModule.h>
77
#include <reanimated/CSS/core/CSSAnimation.h>
88
#include <reanimated/CSS/core/CSSTransition.h>
9+
#include <reanimated/CSS/events/CSSEventsEmitter.h>
910
#include <reanimated/CSS/misc/ViewStylesRepository.h>
1011
#include <reanimated/CSS/registries/CSSAnimationsRegistry.h>
1112
#include <reanimated/CSS/registries/CSSKeyframesRegistry.h>
@@ -198,6 +199,7 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec,
198199
const std::shared_ptr<UpdatesRegistryManager> updatesRegistryManager_;
199200
const std::shared_ptr<ViewStylesRepository> viewStylesRepository_;
200201
const std::shared_ptr<CSSKeyframesRegistry> cssAnimationKeyframesRegistry_;
202+
const std::shared_ptr<CSSEventsEmitter> cssEventsEmitter_;
201203
const std::shared_ptr<CSSAnimationsRegistry> cssAnimationsRegistry_;
202204
const std::shared_ptr<CSSTransitionsRegistry> cssTransitionsRegistry_;
203205

0 commit comments

Comments
 (0)