1*4440fb50SKudo Chien #include "LayoutAnimationsManager.h"
2*4440fb50SKudo Chien #include "CollectionUtils.h"
3*4440fb50SKudo Chien #include "Shareables.h"
4*4440fb50SKudo Chien 
5*4440fb50SKudo Chien #include <utility>
6*4440fb50SKudo Chien 
7*4440fb50SKudo Chien namespace reanimated {
8*4440fb50SKudo Chien 
configureAnimation(int tag,LayoutAnimationType type,const std::string & sharedTransitionTag,std::shared_ptr<Shareable> config)9*4440fb50SKudo Chien void LayoutAnimationsManager::configureAnimation(
10*4440fb50SKudo Chien     int tag,
11*4440fb50SKudo Chien     LayoutAnimationType type,
12*4440fb50SKudo Chien     const std::string &sharedTransitionTag,
13*4440fb50SKudo Chien     std::shared_ptr<Shareable> config) {
14*4440fb50SKudo Chien   auto lock = std::unique_lock<std::mutex>(animationsMutex_);
15*4440fb50SKudo Chien   getConfigsForType(type)[tag] = config;
16*4440fb50SKudo Chien   if (type == SHARED_ELEMENT_TRANSITION) {
17*4440fb50SKudo Chien     sharedTransitionGroups_[sharedTransitionTag].push_back(tag);
18*4440fb50SKudo Chien     viewTagToSharedTag_[tag] = sharedTransitionTag;
19*4440fb50SKudo Chien   }
20*4440fb50SKudo Chien }
21*4440fb50SKudo Chien 
hasLayoutAnimation(int tag,LayoutAnimationType type)22*4440fb50SKudo Chien bool LayoutAnimationsManager::hasLayoutAnimation(
23*4440fb50SKudo Chien     int tag,
24*4440fb50SKudo Chien     LayoutAnimationType type) {
25*4440fb50SKudo Chien   auto lock = std::unique_lock<std::mutex>(animationsMutex_);
26*4440fb50SKudo Chien   return collection::contains(getConfigsForType(type), tag);
27*4440fb50SKudo Chien }
28*4440fb50SKudo Chien 
clearLayoutAnimationConfig(int tag)29*4440fb50SKudo Chien void LayoutAnimationsManager::clearLayoutAnimationConfig(int tag) {
30*4440fb50SKudo Chien   auto lock = std::unique_lock<std::mutex>(animationsMutex_);
31*4440fb50SKudo Chien   enteringAnimations_.erase(tag);
32*4440fb50SKudo Chien   exitingAnimations_.erase(tag);
33*4440fb50SKudo Chien   layoutAnimations_.erase(tag);
34*4440fb50SKudo Chien 
35*4440fb50SKudo Chien   sharedTransitionAnimations_.erase(tag);
36*4440fb50SKudo Chien   auto const &groupName = viewTagToSharedTag_[tag];
37*4440fb50SKudo Chien   auto &group = sharedTransitionGroups_[groupName];
38*4440fb50SKudo Chien   auto position = std::find(group.begin(), group.end(), tag);
39*4440fb50SKudo Chien   if (position != group.end()) {
40*4440fb50SKudo Chien     group.erase(position);
41*4440fb50SKudo Chien   }
42*4440fb50SKudo Chien   if (group.size() == 0) {
43*4440fb50SKudo Chien     sharedTransitionGroups_.erase(groupName);
44*4440fb50SKudo Chien   }
45*4440fb50SKudo Chien   viewTagToSharedTag_.erase(tag);
46*4440fb50SKudo Chien }
47*4440fb50SKudo Chien 
startLayoutAnimation(jsi::Runtime & rt,int tag,LayoutAnimationType type,const jsi::Object & values)48*4440fb50SKudo Chien void LayoutAnimationsManager::startLayoutAnimation(
49*4440fb50SKudo Chien     jsi::Runtime &rt,
50*4440fb50SKudo Chien     int tag,
51*4440fb50SKudo Chien     LayoutAnimationType type,
52*4440fb50SKudo Chien     const jsi::Object &values) {
53*4440fb50SKudo Chien   std::shared_ptr<Shareable> config, viewShareable;
54*4440fb50SKudo Chien   {
55*4440fb50SKudo Chien     auto lock = std::unique_lock<std::mutex>(animationsMutex_);
56*4440fb50SKudo Chien     config = getConfigsForType(type)[tag];
57*4440fb50SKudo Chien   }
58*4440fb50SKudo Chien   // TODO: cache the following!!
59*4440fb50SKudo Chien   jsi::Value layoutAnimationRepositoryAsValue =
60*4440fb50SKudo Chien       rt.global()
61*4440fb50SKudo Chien           .getPropertyAsObject(rt, "global")
62*4440fb50SKudo Chien           .getProperty(rt, "LayoutAnimationsManager");
63*4440fb50SKudo Chien   jsi::Function startAnimationForTag =
64*4440fb50SKudo Chien       layoutAnimationRepositoryAsValue.getObject(rt).getPropertyAsFunction(
65*4440fb50SKudo Chien           rt, "start");
66*4440fb50SKudo Chien   startAnimationForTag.call(
67*4440fb50SKudo Chien       rt,
68*4440fb50SKudo Chien       jsi::Value(tag),
69*4440fb50SKudo Chien       jsi::Value(static_cast<int>(type)),
70*4440fb50SKudo Chien       values,
71*4440fb50SKudo Chien       config->getJSValue(rt));
72*4440fb50SKudo Chien }
73*4440fb50SKudo Chien 
cancelLayoutAnimation(jsi::Runtime & rt,int tag,LayoutAnimationType type,bool cancelled=true,bool removeView=true)74*4440fb50SKudo Chien void LayoutAnimationsManager::cancelLayoutAnimation(
75*4440fb50SKudo Chien     jsi::Runtime &rt,
76*4440fb50SKudo Chien     int tag,
77*4440fb50SKudo Chien     LayoutAnimationType type,
78*4440fb50SKudo Chien     bool cancelled = true,
79*4440fb50SKudo Chien     bool removeView = true) {
80*4440fb50SKudo Chien   jsi::Value layoutAnimationRepositoryAsValue =
81*4440fb50SKudo Chien       rt.global()
82*4440fb50SKudo Chien           .getPropertyAsObject(rt, "global")
83*4440fb50SKudo Chien           .getProperty(rt, "LayoutAnimationsManager");
84*4440fb50SKudo Chien   jsi::Function cancelLayoutAnimation =
85*4440fb50SKudo Chien       layoutAnimationRepositoryAsValue.getObject(rt).getPropertyAsFunction(
86*4440fb50SKudo Chien           rt, "stop");
87*4440fb50SKudo Chien   std::shared_ptr<Shareable> config;
88*4440fb50SKudo Chien   {
89*4440fb50SKudo Chien     auto lock = std::unique_lock<std::mutex>(animationsMutex_);
90*4440fb50SKudo Chien     config = sharedTransitionAnimations_[tag];
91*4440fb50SKudo Chien   }
92*4440fb50SKudo Chien   if (config != nullptr) {
93*4440fb50SKudo Chien     cancelLayoutAnimation.call(
94*4440fb50SKudo Chien         rt, jsi::Value(tag), config->getJSValue(rt), cancelled, removeView);
95*4440fb50SKudo Chien   }
96*4440fb50SKudo Chien }
97*4440fb50SKudo Chien 
98*4440fb50SKudo Chien /*
99*4440fb50SKudo Chien   The top screen on the stack triggers the animation, so we need to find
100*4440fb50SKudo Chien   the sibling view registered in the past. This method finds view
101*4440fb50SKudo Chien   registered in the same transition group (with the same transition tag)
102*4440fb50SKudo Chien   which has been added to that group directly before the one that we
103*4440fb50SKudo Chien   provide as an argument.
104*4440fb50SKudo Chien */
findPrecedingViewTagForTransition(int tag)105*4440fb50SKudo Chien int LayoutAnimationsManager::findPrecedingViewTagForTransition(int tag) {
106*4440fb50SKudo Chien   auto const &groupName = viewTagToSharedTag_[tag];
107*4440fb50SKudo Chien   auto const &group = sharedTransitionGroups_[groupName];
108*4440fb50SKudo Chien   auto position = std::find(group.begin(), group.end(), tag);
109*4440fb50SKudo Chien   if (position != group.end() && position != group.begin()) {
110*4440fb50SKudo Chien     return *std::prev(position);
111*4440fb50SKudo Chien   }
112*4440fb50SKudo Chien   return -1;
113*4440fb50SKudo Chien }
114*4440fb50SKudo Chien 
115*4440fb50SKudo Chien std::unordered_map<int, std::shared_ptr<Shareable>>
getConfigsForType(LayoutAnimationType type)116*4440fb50SKudo Chien     &LayoutAnimationsManager::getConfigsForType(LayoutAnimationType type) {
117*4440fb50SKudo Chien   switch (type) {
118*4440fb50SKudo Chien     case ENTERING:
119*4440fb50SKudo Chien       return enteringAnimations_;
120*4440fb50SKudo Chien     case EXITING:
121*4440fb50SKudo Chien       return exitingAnimations_;
122*4440fb50SKudo Chien     case LAYOUT:
123*4440fb50SKudo Chien       return layoutAnimations_;
124*4440fb50SKudo Chien     case SHARED_ELEMENT_TRANSITION:
125*4440fb50SKudo Chien       return sharedTransitionAnimations_;
126*4440fb50SKudo Chien     default:
127*4440fb50SKudo Chien       assert(false);
128*4440fb50SKudo Chien   }
129*4440fb50SKudo Chien }
130*4440fb50SKudo Chien 
131*4440fb50SKudo Chien } // namespace reanimated
132