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