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