1 /*
2  * Copyright (c) 2024 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 #include "core/components_ng/manager/navigation/navigation_manager.h"
17 
18 #include <string>
19 
20 #include "base/log/dump_log.h"
21 #include "base/thread/task_executor.h"
22 #include "core/common/thread_checker.h"
23 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
24 #include "core/components_ng/pattern/navigation/navigation_stack.h"
25 
26 
27 namespace OHOS::Ace::NG {
AddNavigationDumpCallback(int32_t nodeId,int32_t depth,const DumpCallback & callback)28 void NavigationManager::AddNavigationDumpCallback(int32_t nodeId, int32_t depth, const DumpCallback& callback)
29 {
30     CHECK_RUN_ON(UI);
31     dumpMap_.emplace(DumpMapKey(nodeId, depth), callback);
32 }
33 
RemoveNavigationDumpCallback(int32_t nodeId,int32_t depth)34 void NavigationManager::RemoveNavigationDumpCallback(int32_t nodeId, int32_t depth)
35 {
36     CHECK_RUN_ON(UI);
37     auto it = dumpMap_.find(DumpMapKey(nodeId, depth));
38     if (it != dumpMap_.end()) {
39         dumpMap_.erase(it);
40     }
41 }
42 
OnDumpInfo()43 void NavigationManager::OnDumpInfo()
44 {
45     constexpr int NAVIGATION_DUMP_DEPTH = 2;
46     CHECK_RUN_ON(UI);
47     DumpLog::GetInstance().Print("Navigation number: " + std::to_string(dumpMap_.size()));
48     int navIdx = 0;
49     for (auto it = dumpMap_.begin(); it != dumpMap_.end(); ++it) {
50         DumpLog::GetInstance().Print(1, "Navigation[" + std::to_string(navIdx) + "] ID: " +
51             std::to_string(it->first.nodeId) + ", Depth: " + std::to_string(it->first.depth) + ", NavPathStack:");
52         if (it->second) {
53             it->second(NAVIGATION_DUMP_DEPTH);
54         }
55         navIdx++;
56     }
57 }
58 
FireNavigationUpdateCallback()59 void NavigationManager::FireNavigationUpdateCallback()
60 {
61     for (const auto& func : updateCallbacks_) {
62         func();
63     }
64     updateCallbacks_.clear();
65 }
66 
GetNavigationInfo(const RefPtr<AceType> & node)67 std::shared_ptr<NavigationInfo> NavigationManager::GetNavigationInfo(const RefPtr<AceType>& node)
68 {
69     RefPtr<UINode> current = nullptr;
70     auto customNode = AceType::DynamicCast<CustomNode>(node);
71     if (customNode) {
72         current = customNode->GetNavigationNode().Upgrade();
73     }
74 
75     if (!current) {
76         current = AceType::DynamicCast<UINode>(node);
77         while (current) {
78             if (current->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
79                 break;
80             }
81             current = current->GetParent();
82         }
83     }
84 
85     if (!current) {
86         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "find parent navigation node failed");
87         return nullptr;
88     }
89 
90     auto navigation = AceType::DynamicCast<NavigationGroupNode>(current);
91     CHECK_NULL_RETURN(navigation, nullptr);
92     auto pattern = navigation->GetPattern<NavigationPattern>();
93     CHECK_NULL_RETURN(pattern, nullptr);
94     auto stack = pattern->GetNavigationStack();
95     CHECK_NULL_RETURN(stack, nullptr);
96     return std::make_shared<NavigationInfo>(navigation->GetInspectorId().value_or(""), stack);
97 }
98 
AddInteractiveAnimation(const std::function<void ()> & addCallback)99 bool NavigationManager::AddInteractiveAnimation(const std::function<void()>& addCallback)
100 {
101     if (!isInteractive_) {
102         return false;
103     }
104     auto navigationGroupNode = AceType::DynamicCast<NavigationGroupNode>(
105         FrameNode::GetFrameNode(V2::NAVIGATION_VIEW_ETS_TAG, interactiveAnimationId_));
106     CHECK_NULL_RETURN(navigationGroupNode, false);
107     auto pattern = navigationGroupNode->GetPattern<NavigationPattern>();
108     CHECK_NULL_RETURN(pattern, false);
109     auto proxy = pattern->GetTopNavigationProxy();
110     CHECK_NULL_RETURN(proxy, false);
111     proxy->AddInteractiveAnimation(addCallback);
112     return true;
113 }
114 
AddRecoverableNavigation(std::string id,RefPtr<AceType> navigationNode)115 bool NavigationManager::AddRecoverableNavigation(std::string id, RefPtr<AceType> navigationNode)
116 {
117     auto navigation = AceType::DynamicCast<NavigationGroupNode>(navigationNode);
118     CHECK_NULL_RETURN(navigation, false);
119     if (!navigation->CanRecovery() || id != navigation->GetCurId()) {
120         return false;
121     }
122     recoverableNavigationMap_[id] = navigationNode;
123     return true;
124 }
125 
GetNavigationJsonInfo()126 std::unique_ptr<JsonValue> NavigationManager::GetNavigationJsonInfo()
127 {
128     auto allNavigationInfo = JsonUtil::CreateArray(true);
129     for (auto iter : recoverableNavigationMap_) {
130         auto node = iter.second.Upgrade();
131         if (!node) {
132             continue;
133         }
134         auto navigation = AceType::DynamicCast<NavigationGroupNode>(node);
135         if (!navigation->CanRecovery()) {
136             continue;
137         }
138         auto navigationPattern = navigation->GetPattern<NavigationPattern>();
139         if (!navigationPattern) {
140             continue;
141         }
142         auto navigationInfo = JsonUtil::Create(true);
143         navigationInfo->Put("id", iter.first.c_str());
144         navigationInfo->Put("stack", navigationPattern->GetNavdestinationJsonArray());
145         allNavigationInfo->Put(navigationInfo);
146     }
147     return allNavigationInfo;
148 }
149 
StorageNavigationRecoveryInfo(std::unique_ptr<JsonValue> navigationRecoveryInfo)150 void NavigationManager::StorageNavigationRecoveryInfo(std::unique_ptr<JsonValue> navigationRecoveryInfo)
151 {
152     auto allNavigationInfo = std::move(navigationRecoveryInfo);
153     if (!allNavigationInfo || !allNavigationInfo->IsArray()) {
154         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "Navigation recovery info invalid, can not restore!");
155         return;
156     }
157     auto arraySize = allNavigationInfo->GetArraySize();
158     for (int32_t i = 0; i < arraySize; ++ i) {
159         auto navigationInfo = allNavigationInfo->GetArrayItem(i);
160         auto navigationId = navigationInfo->GetString("id");
161         auto stackInfo = navigationInfo->GetValue("stack");
162         if (!stackInfo->IsArray()) {
163             continue;
164         }
165         std::vector<NavdestinationRecoveryInfo> navdestinationsInfo;
166         auto stackSize = stackInfo->GetArraySize();
167         for (int32_t j = 0; j < stackSize; ++ j) {
168             auto navdestinationInfo = stackInfo->GetArrayItem(j);
169             auto name = navdestinationInfo->GetString("name");
170             auto param = navdestinationInfo->GetString("param");
171             auto mode = navdestinationInfo->GetInt("mode");
172             navdestinationsInfo.emplace_back(NavdestinationRecoveryInfo(name, param, mode));
173         }
174         navigationRecoveryInfo_[navigationId] = navdestinationsInfo;
175     }
176 }
177 
GetNavigationRecoveryInfo(std::string navigationId)178 const std::vector<NavdestinationRecoveryInfo> NavigationManager::GetNavigationRecoveryInfo(std::string navigationId)
179 {
180     if (navigationRecoveryInfo_.find(navigationId) == navigationRecoveryInfo_.end()) {
181         return {};
182     }
183     auto ret = navigationRecoveryInfo_[navigationId];
184     navigationRecoveryInfo_.erase(navigationId);
185     return ret;
186 }
187 } // namespace OHOS::Ace::NG
188