1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_NAVIGATION_TRANSITION_PROXY_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_NAVIGATION_TRANSITION_PROXY_H
18 
19 #include "base/memory/ace_type.h"
20 #include "frameworks/core/components_ng/pattern/navigation/navigation_declaration.h"
21 #include "frameworks/core/components_ng/pattern/navrouter/navdestination_group_node.h"
22 #include "frameworks/core/components_ng/pattern/navrouter/navdestination_pattern.h"
23 namespace OHOS::Ace::NG {
24 
25 namespace {
26 std::atomic<uint64_t> g_proxyNextAutoGenId = 0;
27 }
28 
29 using namespace Framework;
30 class NavigationTransitionProxy : public AceType {
31     DECLARE_ACE_TYPE(NavigationTransitionProxy, AceType);
32 
33 public:
NavigationTransitionProxy()34     NavigationTransitionProxy()
35     {
36         proxyId_ = g_proxyNextAutoGenId.fetch_add(1);
37     }
38     ~NavigationTransitionProxy() = default;
39 
GetPreDestinationContext()40     RefPtr<NG::NavDestinationContext> GetPreDestinationContext() const
41     {
42         return preContext_;
43     }
44 
GetTopDestinationContext()45     RefPtr<NG::NavDestinationContext> GetTopDestinationContext() const
46     {
47         return topContext_;
48     }
49 
SetPreDestination(const RefPtr<NavDestinationGroupNode> & preDestination)50     void SetPreDestination(const RefPtr<NavDestinationGroupNode>& preDestination)
51     {
52         CHECK_NULL_VOID(preDestination);
53         auto pattern = AceType::DynamicCast<NavDestinationPattern>(preDestination->GetPattern());
54         CHECK_NULL_VOID(pattern);
55         preContext_ = pattern->GetNavDestinationContext();
56         CHECK_NULL_VOID(preContext_);
57         preContext_->SetNavPathInfo(pattern->GetNavPathInfo());
58     }
59 
SetTopDestination(const RefPtr<NavDestinationGroupNode> & topDestination)60     void SetTopDestination(const RefPtr<NavDestinationGroupNode>& topDestination)
61     {
62         CHECK_NULL_VOID(topDestination);
63         auto pattern = AceType::DynamicCast<NavDestinationPattern>(topDestination->GetPattern());
64         CHECK_NULL_VOID(pattern);
65         topContext_ = pattern->GetNavDestinationContext();
66         CHECK_NULL_VOID(topContext_);
67         topContext_->SetNavPathInfo(pattern->GetNavPathInfo());
68     }
69 
SetFinishTransitionEvent(std::function<void ()> && event)70     void SetFinishTransitionEvent(std::function<void()>&& event)
71     {
72         finishCallback_ = std::move(event);
73     }
74 
FireFinishCallback()75     void FireFinishCallback()
76     {
77         if (interactive_) {
78             FinishInteractiveAnimation();
79             return;
80         }
81         if (hasFinished_ || !finishCallback_) {
82             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "not support to finish custom animation more than once");
83             return;
84         }
85         hasFinished_ = true;
86         finishCallback_();
87         if (endCallback_) {
88             endCallback_(true);
89         }
90     }
91 
SetIsSuccess(bool isSuccess)92     void SetIsSuccess(bool isSuccess)
93     {
94         isSuccess_ = isSuccess;
95     }
96 
SetIsFinished(bool isFinished)97     void SetIsFinished(bool isFinished)
98     {
99         hasFinished_ = isFinished;
100     }
101 
GetIsFinished()102     bool GetIsFinished() const
103     {
104         return hasFinished_;
105     }
106 
SetCancelAnimationCallback(std::function<void ()> && cancelAnimation)107     void SetCancelAnimationCallback(std::function<void()>&& cancelAnimation)
108     {
109         cancelAnimation_ = std::move(cancelAnimation);
110     }
111 
FireCancelAnimation()112     void FireCancelAnimation()
113     {
114         if (!cancelAnimation_ || hasFinished_ || !interactive_) {
115             return;
116         }
117         cancelAnimation_();
118     }
119 
SetInteractive(bool interactive)120     void SetInteractive(bool interactive)
121     {
122         interactive_ = interactive;
123     }
124 
GetInteractive()125     bool GetInteractive() const
126     {
127         return interactive_;
128     }
129 
SetEndCallback(std::function<void (bool)> && callback)130     void SetEndCallback(std::function<void(bool)>&& callback)
131     {
132         endCallback_ = std::move(callback);
133     }
134 
FireEndCallback()135     void FireEndCallback()
136     {
137         if (endCallback_) {
138             endCallback_(isSuccess_);
139         }
140     }
141 
GetIsSuccess()142     bool GetIsSuccess()
143     {
144         return isSuccess_;
145     }
146 
SetInteractiveAnimation(std::shared_ptr<AnimationUtils::InteractiveAnimation> interactiveAnimation,const std::function<void ()> & finishCallback)147     void SetInteractiveAnimation(
148         std::shared_ptr<AnimationUtils::InteractiveAnimation> interactiveAnimation,
149         const std::function<void()>& finishCallback)
150     {
151         interactiveAnimation_ = interactiveAnimation;
152         interactiveFinishCallback_ = finishCallback;
153     }
154 
StartAnimation()155     void StartAnimation()
156     {
157         if (!interactiveAnimation_) {
158             return;
159         }
160         // if error code is 0, start interactive success
161         int32_t errorCode = AnimationUtils::StartInteractiveAnimation(interactiveAnimation_);
162         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "update start interactive animation code is %{public}d", errorCode);
163         isStartAnimation_ = errorCode == 0;
164     }
165 
UpdateTransition(float progress)166     void UpdateTransition(float progress)
167     {
168         if (!interactive_ || hasFinished_) {
169             return;
170         }
171         AnimationUtils::UpdateInteractiveAnimation(interactiveAnimation_, progress);
172     }
173 
FinishInteractiveAnimation()174     void FinishInteractiveAnimation()
175     {
176         if (!interactive_ || hasFinished_) {
177             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "not support to finish interactive animation more than once");
178             return;
179         }
180         hasFinished_ = true;
181         isSuccess_ = true;
182         if (!isStartAnimation_) {
183             interactiveFinishCallback_();
184             if (endCallback_) {
185                 endCallback_(true);
186             }
187             return;
188         }
189         AnimationUtils::ContinueInteractiveAnimation(interactiveAnimation_);
190     }
191 
CancelInteractiveAnimation()192     void CancelInteractiveAnimation()
193     {
194         if (!interactive_ || hasFinished_) {
195             TAG_LOGE(AceLogTag::ACE_NAVIGATION, "not support to cancel interactive animation more than once");
196             return;
197         }
198         hasFinished_ = true;
199         isSuccess_ = false;
200         if (!isStartAnimation_) {
201             interactiveFinishCallback_();
202             if (endCallback_) {
203                 endCallback_(false);
204             }
205             return;
206         }
207         AnimationUtils::ReverseInteractiveAnimation(interactiveAnimation_);
208     }
209 
AddInteractiveAnimation(const std::function<void ()> & callback)210     void AddInteractiveAnimation(const std::function<void()>& callback)
211     {
212         if (!interactive_) {
213             return;
214         }
215         AnimationUtils::AddInteractiveAnimation(interactiveAnimation_, callback);
216     }
217 
GetProxyId()218     uint64_t GetProxyId() const
219     {
220         return proxyId_;
221     }
222 
223 private:
224     uint64_t proxyId_ = 0;
225     RefPtr<NavDestinationContext> preContext_;
226     RefPtr<NavDestinationContext> topContext_;
227     std::function<void()> finishCallback_; // finish transition callback to continue animation
228     std::function<void()> cancelAnimation_; // cancel transition callback to reverse animation
229     std::function<void(bool)> endCallback_;
230     std::function<void()> interactiveFinishCallback_;
231     std::shared_ptr<AnimationUtils::InteractiveAnimation> interactiveAnimation_;
232     bool hasFinished_ = false; // current transition is finish or not
233     bool isSuccess_ = true; // set current custom transition is start success or not
234     bool interactive_ = false; // set current interactive animation
235     bool isStartAnimation_ = false;
236 };
237 
238 struct NavigationTransition {
239     int32_t timeout = 1000;
240     std::function<void(const RefPtr<NavigationTransitionProxy>&)> transition;
241     std::function<void(bool)> endCallback;
242     bool isValid = true;
243     bool interactive = false;
244 };
245 } // namespace OHOS::Ace::NG
246 #endif